QGIS API Documentation 4.3.0-Master (0de80482b60)
Loading...
Searching...
No Matches
qgssortedrasterblockindex.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgssortedrasterblockindex.h
3 --------------------------------------
4 Date : September 2026
5 Copyright : (C) 2026 by Nyall Dawson
6 email : nyall.dawson@gmail.com
7 ***************************************************************************/
8
9/***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
19
20#include <algorithm>
21
22#include "qgsrasterblock.h"
23
24namespace
25{
26 template<typename ValueT, typename IndexT> struct SortPair
27 {
28 ValueT val;
29 IndexT idx;
30 bool operator<( const SortPair &other ) const { return val < other.val; }
31 };
32
33 template<typename ValueT, typename IndexT> std::vector<IndexT> createSortedIndices( const QgsRasterBlock *block, qgssize totalCells )
34 {
35 const ValueT *rawData = reinterpret_cast<const ValueT *>( block->constBits() );
36 const bool hasNoData = block->hasNoData();
37 const bool hasNoDataValue = block->hasNoDataValue();
38 const ValueT noDataVal = static_cast<ValueT>( block->noDataValue() );
39
40 std::vector<SortPair<ValueT, IndexT>> pairs;
41 if ( !hasNoData )
42 {
43 // here we know the total number of valid cells in advance, since there's no no-data cells
44 pairs.resize( totalCells );
45 std::for_each( pairs.begin(), pairs.end(), [rawData, &pairs]( SortPair<ValueT, IndexT> &pair ) {
46 const IndexT idx = static_cast<IndexT>( &pair - pairs.data() );
47 pair = SortPair<ValueT, IndexT> { rawData[idx], idx };
48 } );
49 }
50 else
51 {
52 // slower path, because we have to test for no-data cells...
53 pairs.reserve( totalCells );
54 for ( qgssize i = 0; i < totalCells; ++i )
55 {
56 if ( hasNoDataValue )
57 {
58 const ValueT v = rawData[i];
59 if ( std::isnan( static_cast<double>( v ) ) || v == noDataVal )
60 continue;
61 pairs.push_back( SortPair<ValueT, IndexT> { v, static_cast<IndexT>( i ) } );
62 }
63 else if ( !block->isNoData( i ) )
64 {
65 pairs.push_back( SortPair<ValueT, IndexT> { rawData[i], static_cast<IndexT>( i ) } );
66 }
67 }
68 }
69
70 std::sort( pairs.begin(), pairs.end() );
71
72 // copy sorted index array to a more compact structure
73 std::vector<IndexT> sortedIndices( pairs.size() );
74 std::transform( pairs.begin(), pairs.end(), sortedIndices.begin(), []( const SortPair<ValueT, IndexT> &p ) { return p.idx; } );
75
76 return sortedIndices;
77 }
78
79 template<typename IndexT> std::vector<IndexT> createSortedIndices( const QgsRasterBlock *block, qgssize totalCells )
80 {
81 switch ( block->dataType() )
82 {
84 return createSortedIndices<quint8, IndexT>( block, totalCells );
86 return createSortedIndices<qint8, IndexT>( block, totalCells );
88 return createSortedIndices<quint16, IndexT>( block, totalCells );
90 return createSortedIndices<qint16, IndexT>( block, totalCells );
92 return createSortedIndices<quint32, IndexT>( block, totalCells );
94 return createSortedIndices<qint32, IndexT>( block, totalCells );
96 return createSortedIndices<float, IndexT>( block, totalCells );
98 return createSortedIndices<double, IndexT>( block, totalCells );
106 return std::vector<IndexT>();
107 }
109 }
110
111} //namespace
112
114{
115 if ( !block || block->isEmpty() )
116 return;
117
118 mBlock = block;
119 mCols = block->width();
120 mRows = block->height();
121 const qgssize totalCells = static_cast<qgssize>( mCols ) * mRows;
122 if ( totalCells <= static_cast<qgssize>( std::numeric_limits<uint32_t>::max() ) )
123 {
124 mSortedIndices = createSortedIndices<uint32_t>( mBlock, totalCells );
125 }
126 else
127 {
128 mSortedIndices = createSortedIndices<qgssize>( mBlock, totalCells );
129 }
130}
131
133{
134 return std::visit( []( const auto &vec ) -> qgssize { return vec.size(); }, mSortedIndices );
135}
136
138{
139 return std::visit(
140 [rank, order]( const auto &vec ) -> qgssize {
141 const std::size_t mappedRank = ( order == Qt::AscendingOrder ) ? rank : ( vec.size() - 1 - rank );
142 return static_cast<qgssize>( vec[mappedRank] );
143 },
144 mSortedIndices
145 );
146}
147
148double QgsSortedRasterBlockIndex::sortedValue( qgssize rank, Qt::SortOrder order ) const
149{
150 return mBlock->value( sortedIndex( rank, order ) );
151}
152
153void QgsSortedRasterBlockIndex::sortedColumnRow( qgssize rank, int &column, int &row, Qt::SortOrder order ) const
154{
155 indexToColumnAndRow( sortedIndex( rank, order ), column, row );
156}
@ CInt32
Complex Int32.
Definition qgis.h:404
@ Float32
Thirty two bit floating point (float).
Definition qgis.h:401
@ CFloat64
Complex Float64.
Definition qgis.h:406
@ Int16
Sixteen bit signed integer (qint16).
Definition qgis.h:398
@ ARGB32_Premultiplied
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32_Premultiplied.
Definition qgis.h:408
@ Int8
Eight bit signed integer (qint8) (added in QGIS 3.30).
Definition qgis.h:396
@ UInt16
Sixteen bit unsigned integer (quint16).
Definition qgis.h:397
@ Byte
Eight bit unsigned integer (quint8).
Definition qgis.h:395
@ UnknownDataType
Unknown or unspecified type.
Definition qgis.h:394
@ ARGB32
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32.
Definition qgis.h:407
@ Int32
Thirty two bit signed integer (qint32).
Definition qgis.h:400
@ Float64
Sixty four bit floating point (double).
Definition qgis.h:402
@ CFloat32
Complex Float32.
Definition qgis.h:405
@ CInt16
Complex Int16.
Definition qgis.h:403
@ UInt32
Thirty two bit unsigned integer (quint32).
Definition qgis.h:399
Raster data container.
bool hasNoData() const
Returns true if the block may contain no data.
double noDataValue() const
Returns no data value.
const char * constBits(qgssize index) const
Returns a const pointer to block data.
bool isNoData(int row, int column) const
Checks if value at position is no data.
Qgis::DataType dataType() const
Returns data type.
bool hasNoDataValue() const
true if the block has no data value.
const QgsRasterBlock * block() const
Returns a pointer to source QgsRasterBlock.
double sortedValue(qgssize rank, Qt::SortOrder order=Qt::AscendingOrder) const
Returns the raster block value corresponding to the specified sorted rank.
qgssize sortedCount() const
Returns the number of valid (non-NoData) sorted cells.
qgssize sortedIndex(qgssize rank, Qt::SortOrder order=Qt::AscendingOrder) const
Returns the source raster block index corresponding to the specified sorted rank.
QgsSortedRasterBlockIndex(const QgsRasterBlock *block)
Constructor for QgsSortedRasterBlockIndex, indexing the specified raster block.
void sortedColumnRow(qgssize rank, int &column, int &row, Qt::SortOrder order=Qt::AscendingOrder) const
Retrieves the source raster block column and row corresponding to the specified sorted rank.
#define BUILTIN_UNREACHABLE
Definition qgis.h:8229
unsigned long long qgssize
Qgssize is used instead of size_t, because size_t is stdlib type, unknown by SIP, and it would be har...
Definition qgis.h:8174
bool operator<(const QVariant &v1, const QVariant &v2)
Compares two QVariant values and returns whether the first is less than the second.
Definition qgis.h:8085