QGIS API Documentation 4.1.0-Master (0cdd3ae6384)
Loading...
Searching...
No Matches
qgsrasterlayerutils.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsrasterlayerutils.cpp
3 -------------------------
4 begin : March 2024
5 copyright : (C) 2024 by Nyall Dawson
6 email : nyall dot dawson at gmail dot 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
18#include "qgsrasterlayerutils.h"
19
22#include "qgsrasterlayer.h"
26#include "qgsrectangle.h"
27#include "qgsthreadingutils.h"
28
29#include <QString>
30
31using namespace Qt::StringLiterals;
32
33int QgsRasterLayerUtils::renderedBandForElevationAndTemporalRange( QgsRasterLayer *layer, const QgsDateTimeRange &temporalRange, const QgsDoubleRange &elevationRange, bool &matched )
34{
35 if ( !layer )
36 {
37 matched = false;
38 return -1;
39 }
40
41 matched = true;
42 const QgsRasterLayerElevationProperties *elevationProperties = qobject_cast< QgsRasterLayerElevationProperties * >( layer->elevationProperties() );
43 const QgsRasterLayerTemporalProperties *temporalProperties = qobject_cast< QgsRasterLayerTemporalProperties *>( layer->temporalProperties() );
44
45 // neither active
46 if ( ( !temporalProperties->isActive() || temporalRange.isInfinite() ) && ( !elevationProperties->hasElevation() || elevationRange.isInfinite() ) )
47 {
48 return -1;
49 }
50
51 // only elevation properties enabled
52 if ( !temporalProperties->isActive() || temporalRange.isInfinite() )
53 {
54 const int band = elevationProperties->bandForElevationRange( layer, elevationRange );
55 matched = band > 0;
56 return band;
57 }
58
59 // only temporal properties enabled
60 if ( !elevationProperties->hasElevation() || elevationRange.isInfinite() )
61 {
62 const int band = temporalProperties->bandForTemporalRange( layer, temporalRange );
63 matched = band > 0;
64 return band;
65 }
66
67 // both elevation and temporal properties enabled
68
69 // first find bands matching the temporal range
70 QList< int > temporalBands;
71 switch ( temporalProperties->mode() )
72 {
78 {
79 temporalBands << temporalProperties->filteredBandsForTemporalRange( layer, temporalRange );
80 break;
81 }
82
84 {
85 temporalBands << temporalProperties->bandNumber();
86 break;
87 }
88 }
89
90 if ( temporalBands.empty() )
91 {
92 matched = false;
93 return -1;
94 }
95
96 switch ( elevationProperties->mode() )
97 {
100 return temporalBands.at( 0 );
101
103 {
104 // find the top-most band which matches the map range
105 int currentMatchingBand = -1;
106 matched = false;
107 QgsDoubleRange currentMatchingRange;
108 const QMap<int, QgsDoubleRange> rangePerBand = elevationProperties->fixedRangePerBand();
109 for ( int band : temporalBands )
110 {
111 const QgsDoubleRange rangeForBand = rangePerBand.value( band );
112 if ( rangeForBand.overlaps( elevationRange ) )
113 {
114 if ( currentMatchingRange.isInfinite()
115 || ( rangeForBand.includeUpper() && rangeForBand.upper() >= currentMatchingRange.upper() )
116 || ( !currentMatchingRange.includeUpper() && rangeForBand.upper() >= currentMatchingRange.upper() ) )
117 {
118 matched = true;
119 currentMatchingBand = band;
120 currentMatchingRange = rangeForBand;
121 }
122 }
123 }
124 return currentMatchingBand;
125 }
126
128 {
129 QgsExpressionContext context;
132 context.appendScope( bandScope );
133
136 lowerProperty.prepare( context );
137 upperProperty.prepare( context );
138
139 int currentMatchingBand = -1;
140 matched = false;
141 QgsDoubleRange currentMatchingRange;
142
143 for ( int band : temporalBands )
144 {
145 bandScope->setVariable( u"band"_s, band );
146 bandScope->setVariable( u"band_name"_s, layer->dataProvider()->displayBandName( band ) );
147 bandScope->setVariable( u"band_description"_s, layer->dataProvider()->bandDescription( band ) );
148
149 bool ok = false;
150 const double lower = lowerProperty.valueAsDouble( context, 0, &ok );
151 if ( !ok )
152 continue;
153 const double upper = upperProperty.valueAsDouble( context, 0, &ok );
154 if ( !ok )
155 continue;
156
157 const QgsDoubleRange bandRange = QgsDoubleRange( lower, upper );
158 if ( bandRange.overlaps( elevationRange ) )
159 {
160 if ( currentMatchingRange.isInfinite()
161 || ( bandRange.includeUpper() && bandRange.upper() >= currentMatchingRange.upper() )
162 || ( !currentMatchingRange.includeUpper() && bandRange.upper() >= currentMatchingRange.upper() ) )
163 {
164 currentMatchingBand = band;
165 currentMatchingRange = bandRange;
166 matched = true;
167 }
168 }
169 }
170 return currentMatchingBand;
171 }
172 }
174}
175
177 QgsRasterDataProvider *provider, int band, const QgsRasterMinMaxOrigin &mmo, Qgis::RasterRangeLimit limits, const QgsRectangle &extent, int sampleSize, double &min SIP_OUT, double &max SIP_OUT
178)
179{
180 min = std::numeric_limits<double>::quiet_NaN();
181 max = std::numeric_limits<double>::quiet_NaN();
182
183 if ( !provider )
184 return;
185
187
189 {
190 QgsRasterBandStats myRasterBandStats = provider->bandStatistics( band, Qgis::RasterBandStatistic::Min | Qgis::RasterBandStatistic::Max, extent, sampleSize );
191 // Check if statistics were actually gathered, None means a failure
192 if ( myRasterBandStats.statsGathered == static_cast< int >( Qgis::RasterBandStatistic::NoStatistic ) )
193 {
194 // Best guess we can do
195 switch ( provider->dataType( band ) )
196 {
198 {
199 myRasterBandStats.minimumValue = 0;
200 myRasterBandStats.maximumValue = 255;
201 break;
202 }
204 {
205 myRasterBandStats.minimumValue = std::numeric_limits<int8_t>::lowest();
206 myRasterBandStats.maximumValue = std::numeric_limits<int8_t>::max();
207 break;
208 }
210 {
211 myRasterBandStats.minimumValue = 0;
212 myRasterBandStats.maximumValue = std::numeric_limits<uint16_t>::max();
213 break;
214 }
216 {
217 myRasterBandStats.minimumValue = 0;
218 myRasterBandStats.maximumValue = std::numeric_limits<uint32_t>::max();
219 break;
220 }
223 {
224 myRasterBandStats.minimumValue = std::numeric_limits<int16_t>::lowest();
225 myRasterBandStats.maximumValue = std::numeric_limits<int16_t>::max();
226 break;
227 }
230 {
231 myRasterBandStats.minimumValue = std::numeric_limits<int32_t>::lowest();
232 myRasterBandStats.maximumValue = std::numeric_limits<int32_t>::max();
233 break;
234 }
237 {
238 myRasterBandStats.minimumValue = std::numeric_limits<float_t>::lowest();
239 myRasterBandStats.maximumValue = std::numeric_limits<float_t>::max();
240 break;
241 }
244 {
245 myRasterBandStats.minimumValue = std::numeric_limits<double_t>::lowest();
246 myRasterBandStats.maximumValue = std::numeric_limits<double_t>::max();
247 break;
248 }
252 {
253 // Nothing to guess
254 break;
255 }
256 }
257 }
258 min = myRasterBandStats.minimumValue;
259 max = myRasterBandStats.maximumValue;
260 }
261 else if ( limits == Qgis::RasterRangeLimit::StdDev )
262 {
263 const QgsRasterBandStats myRasterBandStats = provider->bandStatistics( band, Qgis::RasterBandStatistic::Mean | Qgis::RasterBandStatistic::StdDev, extent, sampleSize );
264 min = myRasterBandStats.mean - ( mmo.stdDevFactor() * myRasterBandStats.stdDev );
265 max = myRasterBandStats.mean + ( mmo.stdDevFactor() * myRasterBandStats.stdDev );
266 }
267 else if ( limits == Qgis::RasterRangeLimit::CumulativeCut )
268 {
269 const double myLower = mmo.cumulativeCutLower();
270 const double myUpper = mmo.cumulativeCutUpper();
271 QgsDebugMsgLevel( u"myLower = %1 myUpper = %2"_s.arg( myLower ).arg( myUpper ), 4 );
272 provider->cumulativeCut( band, myLower, myUpper, min, max, extent, sampleSize );
273 }
274 QgsDebugMsgLevel( u"band = %1 min = %2 max = %3"_s.arg( band ).arg( min ).arg( max ), 4 );
275}
276
277QgsRectangle QgsRasterLayerUtils::alignRasterExtent( const QgsRectangle &extent, const QgsPointXY &origin, double pixelSizeX, double pixelSizeY )
278{
279 // Return original extent if pixel sizes are zero (to avoid division by zero) or if the extent is empty
280 if ( qgsDoubleNear( pixelSizeX, 0.0 ) || qgsDoubleNear( pixelSizeY, 0.0 ) || extent.isEmpty() )
281 {
282 return extent;
283 }
284 // Y pixel size may be negative to indicate inverted NS axis: use absolute value for calculations
285 const double absPixelSizeY { std::abs( pixelSizeY ) };
286 const double minX { origin.x() + std::floor( ( extent.xMinimum() - origin.x() ) / pixelSizeX ) * pixelSizeX };
287 const double minY { origin.y() + std::floor( ( extent.yMinimum() - origin.y() ) / absPixelSizeY ) * absPixelSizeY };
288 const double maxX { origin.x() + std::ceil( ( extent.xMaximum() - origin.x() ) / pixelSizeX ) * pixelSizeX };
289 const double maxY { origin.y() + std::ceil( ( extent.yMaximum() - origin.y() ) / absPixelSizeY ) * absPixelSizeY };
290 return QgsRectangle( minX, minY, maxX, maxY );
291}
292
293QList<QgsRasterReliefColor> QgsRasterLayerUtils::calculateOptimizedReliefClasses( QgsRasterDataProvider *provider, int band )
294{
295 QList<QgsRasterReliefColor> resultList;
296
297 if ( !provider || !provider->isValid() || band < 1 || band > provider->bandCount() )
298 {
299 return resultList;
300 }
301
303
304 // store elevation frequency in 252 elevation classes
305 double frequency[252] = { 0 };
306 const double frequencyClassRange = ( stats.maximumValue - stats.minimumValue ) / 252.0;
307
308 // go through raster cells and get frequency of classes
309 QgsRasterIterator iter( provider );
310 iter.startRasterRead( band, provider->xSize(), provider->ySize(), provider->extent() );
311
312 int iterCols = 0;
313 int iterRows = 0;
314 int iterLeft = 0;
315 int iterTop = 0;
316 std::unique_ptr<QgsRasterBlock> block;
317
318 bool isNoData = false;
319 while ( iter.readNextRasterPart( band, iterCols, iterRows, block, iterLeft, iterTop ) )
320 {
321 for ( int row = 0; row < iterRows; ++row )
322 {
323 for ( int col = 0; col < iterCols; ++col )
324 {
325 const double elevation = block->valueAndNoData( row, col, isNoData );
326 if ( isNoData )
327 continue;
328
329 int elevationClass = frequencyClassForElevation( elevation, stats.minimumValue, frequencyClassRange );
330 elevationClass = std::max( std::min( elevationClass, 251 ), 0 );
331 frequency[elevationClass] += 1.0;
332 }
333 }
334 }
335
336 //log10 transformation for all frequency values
337 for ( int i = 0; i < 252; ++i )
338 {
339 frequency[i] = std::log10( frequency[i] );
340 }
341
342 //start with 9 uniformly distributed classes
343 QList<int> classBreaks;
344 classBreaks.append( 0 );
345 classBreaks.append( 28 );
346 classBreaks.append( 56 );
347 classBreaks.append( 84 );
348 classBreaks.append( 112 );
349 classBreaks.append( 140 );
350 classBreaks.append( 168 );
351 classBreaks.append( 196 );
352 classBreaks.append( 224 );
353 classBreaks.append( 252 );
354
355 for ( int i = 0; i < 10; ++i )
356 {
357 optimiseClassBreaks( classBreaks, frequency );
358 }
359
360#ifdef QGISDEBUG
361 //debug, print out all the classbreaks
362 for ( int breakValue : std::as_const( classBreaks ) )
363 {
364 QgsDebugMsgLevel( QString::number( breakValue ), 2 );
365 }
366#endif
367
368 //set colors according to optimised class breaks
369 QVector<QColor> colorList;
370 colorList.reserve( 9 );
371 colorList.push_back( QColor( 7, 165, 144 ) );
372 colorList.push_back( QColor( 12, 221, 162 ) );
373 colorList.push_back( QColor( 33, 252, 183 ) );
374 colorList.push_back( QColor( 247, 252, 152 ) );
375 colorList.push_back( QColor( 252, 196, 8 ) );
376 colorList.push_back( QColor( 252, 166, 15 ) );
377 colorList.push_back( QColor( 175, 101, 15 ) );
378 colorList.push_back( QColor( 255, 133, 92 ) );
379 colorList.push_back( QColor( 204, 204, 204 ) );
380
381 resultList.reserve( classBreaks.size() );
382 for ( int i = 1; i < classBreaks.size(); ++i )
383 {
384 const double minElevation = stats.minimumValue + classBreaks[i - 1] * frequencyClassRange;
385 const double maxElevation = stats.minimumValue + classBreaks[i] * frequencyClassRange;
386 resultList.push_back( QgsRasterReliefColor( colorList.at( i - 1 ), minElevation, maxElevation ) );
387 }
388
389 return resultList;
390}
391
392int QgsRasterLayerUtils::frequencyClassForElevation( double elevation, double minElevation, double elevationClassRange )
393{
394 return ( elevation - minElevation ) / elevationClassRange;
395}
396
397void QgsRasterLayerUtils::optimiseClassBreaks( QList<int> &breaks, double *frequencies )
398{
399 if ( breaks.empty() )
400 return;
401
402 const qsizetype nClasses = breaks.size() - 1;
403 std::vector< double > a( nClasses ); //slopes
404 std::vector< double > b( nClasses ); //y-offsets
405
406 for ( int i = 0; i < nClasses; ++i )
407 {
408 //get all the values between the class breaks into input
409 QList<QPair<int, double>> regressionInput;
410 regressionInput.reserve( breaks.at( i + 1 ) - breaks.at( i ) );
411 for ( int j = breaks.at( i ); j < breaks.at( i + 1 ); ++j )
412 {
413 regressionInput.push_back( qMakePair( j, frequencies[j] ) );
414 }
415
416 double aParam, bParam;
417 if ( !regressionInput.isEmpty() && calculateRegression( regressionInput, aParam, bParam ) )
418 {
419 a[i] = aParam;
420 b[i] = bParam;
421 }
422 else
423 {
424 a[i] = 0;
425 b[i] = 0; //better default value
426 }
427 }
428
429 //shift class boundaries or eliminate classes which fall together
430 for ( int i = 1; i < nClasses; ++i )
431 {
432 if ( breaks[i] == breaks[i - 1] )
433 {
434 continue;
435 }
436
437 if ( qgsDoubleNear( a[i - 1], a[i] ) )
438 {
439 continue;
440 }
441 else
442 {
443 int newX = static_cast< int >( ( b[i - 1] - b[i] ) / ( a[i] - a[i - 1] ) );
444
445 if ( newX <= breaks[i - 1] )
446 {
447 newX = breaks[i - 1];
448 }
449 else if ( i < nClasses - 1 && newX >= breaks[i + 1] )
450 {
451 newX = breaks[i + 1];
452 }
453
454 breaks[i] = newX;
455 }
456 }
457}
458
459bool QgsRasterLayerUtils::calculateRegression( const QList<QPair<int, double> > &input, double &a, double &b )
460{
461 double xMean, yMean;
462 double xSum = 0;
463 double ySum = 0;
464 QList<QPair<int, double>>::const_iterator inputIt = input.constBegin();
465 for ( ; inputIt != input.constEnd(); ++inputIt )
466 {
467 xSum += inputIt->first;
468 ySum += inputIt->second;
469 }
470 xMean = xSum / input.size();
471 yMean = ySum / input.size();
472
473 double sumCounter = 0;
474 double sumDenominator = 0;
475 inputIt = input.constBegin();
476 for ( ; inputIt != input.constEnd(); ++inputIt )
477 {
478 sumCounter += ( ( inputIt->first - xMean ) * ( inputIt->second - yMean ) );
479 sumDenominator += ( ( inputIt->first - xMean ) * ( inputIt->first - xMean ) );
480 }
481
482 a = sumCounter / sumDenominator;
483 b = yMean - a * xMean;
484
485 return true;
486}
RasterRangeLimit
Describes the limits used to compute raster ranges (min/max values).
Definition qgis.h:1665
@ CumulativeCut
Range is [ min + cumulativeCutLower() * (max - min), min + cumulativeCutUpper() * (max - min) ].
Definition qgis.h:1669
@ StdDev
Range is [ mean - stdDevFactor() * stddev, mean + stdDevFactor() * stddev ].
Definition qgis.h:1668
@ MinimumMaximum
Real min-max values.
Definition qgis.h:1667
@ FixedRangePerBand
Layer has a fixed (manually specified) elevation range per band.
Definition qgis.h:4209
@ FixedElevationRange
Layer has a fixed elevation range.
Definition qgis.h:4207
@ RepresentsElevationSurface
Pixel values represent an elevation surface.
Definition qgis.h:4208
@ DynamicRangePerBand
Layer has a elevation range per band, calculated dynamically from an expression.
Definition qgis.h:4210
@ RepresentsTemporalValues
Pixel values represent an datetime.
Definition qgis.h:2786
@ RedrawLayerOnly
Redraw the layer when temporal range changes, but don't apply any filtering. Useful when raster symbo...
Definition qgis.h:2783
@ FixedRangePerBand
Layer has a fixed temporal range per band.
Definition qgis.h:2785
@ TemporalRangeFromDataProvider
Mode when raster layer delegates temporal range handling to the dataprovider.
Definition qgis.h:2782
@ FixedTemporalRange
Mode when temporal properties have fixed start and end datetimes.
Definition qgis.h:2781
@ FixedDateTime
Layer has a fixed date time instant.
Definition qgis.h:2787
@ StdDev
Standard deviation.
Definition qgis.h:6571
@ NoStatistic
No statistic.
Definition qgis.h:6565
@ 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
virtual bool isValid() const =0
Returns true if this is a valid layer.
QgsRange which stores a range of double values.
Definition qgsrange.h:217
bool isInfinite() const
Returns true if the range consists of all possible values.
Definition qgsrange.h:266
Single scope for storing variables and functions for use within a QgsExpressionContext.
void setVariable(const QString &name, const QVariant &value, bool isStatic=false)
Convenience method for setting a variable in the context scope by name name and value.
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer's project and layer.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
void appendScopes(const QList< QgsExpressionContextScope * > &scopes)
Appends a list of scopes to the end of the context.
QgsPropertyCollection & dataDefinedProperties()
Returns a reference to the object's property collection, used for data defined overrides.
@ RasterPerBandUpperElevation
Upper elevation for each raster band.
@ RasterPerBandLowerElevation
Lower elevation for each raster band.
Represents a 2D point.
Definition qgspointxy.h:62
double y
Definition qgspointxy.h:66
double x
Definition qgspointxy.h:65
QgsProperty property(int key) const final
Returns a matching property from the collection, if one exists.
A store for object properties.
double valueAsDouble(const QgsExpressionContext &context, double defaultValue=0.0, bool *ok=nullptr) const
Calculates the current value of the property and interprets it as a double.
bool prepare(const QgsExpressionContext &context=QgsExpressionContext()) const
Prepares the property against a specified expression context.
bool includeUpper() const
Returns true if the upper bound is inclusive, or false if the upper bound is exclusive.
Definition qgsrange.h:102
bool overlaps(const QgsRange< T > &other) const
Returns true if this range overlaps another range.
Definition qgsrange.h:171
T upper() const
Returns the upper bound of the range.
Definition qgsrange.h:86
The RasterBandStats struct is a container for statistics about a single raster band.
double mean
The mean cell value for the band. NO_DATA values are excluded.
double stdDev
The standard deviation of the cell values.
double minimumValue
The minimum cell value in the raster band.
Qgis::RasterBandStatistics statsGathered
Collected statistics.
double maximumValue
The maximum cell value in the raster band.
Base class for raster data providers.
QgsRectangle extent() const override=0
Returns the extent of the layer.
Qgis::DataType dataType(int bandNo) const override=0
Returns data type for the band specified by number.
virtual QString bandDescription(int bandNumber)
Returns the description for band bandNumber, or an empty string if the band is not valid or has not d...
virtual void cumulativeCut(int bandNo, double lowerCount, double upperCount, double &lowerValue, double &upperValue, const QgsRectangle &extent=QgsRectangle(), int sampleSize=0)
Find values for cumulative pixel count cut.
virtual int xSize() const
Gets raster size.
Q_DECL_DEPRECATED QgsRasterBandStats bandStatistics(int bandNo, int stats, const QgsRectangle &extent=QgsRectangle(), int sampleSize=0, QgsRasterBlockFeedback *feedback=nullptr)
Returns the band statistics.
virtual int bandCount() const =0
Gets number of bands.
QString displayBandName(int bandNumber) const
Generates a friendly, descriptive name for the specified bandNumber.
virtual int ySize() const
Iterator for sequentially processing raster cells.
bool readNextRasterPart(int bandNumber, int &nCols, int &nRows, QgsRasterBlock **block, int &topLeftCol, int &topLeftRow)
Fetches next part of raster data, caller takes ownership of the block and caller should delete the bl...
void startRasterRead(int bandNumber, qgssize nCols, qgssize nRows, const QgsRectangle &extent, QgsRasterBlockFeedback *feedback=nullptr)
Start reading of raster band.
Raster layer specific subclass of QgsMapLayerElevationProperties.
Qgis::RasterElevationMode mode() const
Returns the elevation mode.
bool hasElevation() const override
Returns true if the layer has an elevation or z component.
int bandForElevationRange(QgsRasterLayer *layer, const QgsDoubleRange &range) const
Returns the band corresponding to the specified range.
QMap< int, QgsDoubleRange > fixedRangePerBand() const
Returns the fixed elevation range for each band.
Implementation of map layer temporal properties for raster layers.
QList< int > filteredBandsForTemporalRange(QgsRasterLayer *layer, const QgsDateTimeRange &range) const
Returns a filtered list of bands which match the specified range.
Qgis::RasterTemporalMode mode() const
Returns the temporal properties mode.
int bandForTemporalRange(QgsRasterLayer *layer, const QgsDateTimeRange &range) const
Returns the band corresponding to the specified range.
int bandNumber() const
Returns the band number from which temporal values should be taken.
static void computeMinMax(QgsRasterDataProvider *provider, int band, const QgsRasterMinMaxOrigin &mmo, Qgis::RasterRangeLimit limits, const QgsRectangle &extent, int sampleSize, double &min, double &max)
Compute the min max values for provider along band according to MinMaxOrigin parameters mmo and exten...
static int renderedBandForElevationAndTemporalRange(QgsRasterLayer *layer, const QgsDateTimeRange &temporalRange, const QgsDoubleRange &elevationRange, bool &matched)
Given a raster layer, returns the band which should be used for rendering the layer for a specified t...
static QList< QgsRasterReliefColor > calculateOptimizedReliefClasses(QgsRasterDataProvider *provider, int band)
Calculates optimized relief class breaks according with the method of Buenzli (2011) using an iterati...
static QgsRectangle alignRasterExtent(const QgsRectangle &extent, const QgsPointXY &origin, double pixelSizeX, double pixelSizeY)
Returns a new extent that includes the given extent with corners coordinates aligned to the pixel gri...
Represents a raster layer.
QgsMapLayerTemporalProperties * temporalProperties() override
Returns the layer's temporal properties.
QgsRasterDataProvider * dataProvider() override
Returns the source data provider.
QgsMapLayerElevationProperties * elevationProperties() override
Returns the layer's elevation properties.
Describes the origin of minimum and maximum values in a raster.
double cumulativeCutLower() const
Returns the lower bound of cumulative cut method (between 0 and 1).
double stdDevFactor() const
Returns the factor f so that the min/max range is [ mean - f * stddev , mean + f * stddev ].
double cumulativeCutUpper() const
Returns the upper bound of cumulative cut method (between 0 and 1).
Defines elevation range and color for raster relief coloring.
A rectangle specified with double values.
double xMinimum
double yMinimum
double xMaximum
double yMaximum
bool isActive() const
Returns true if the temporal property is active.
bool isInfinite() const
Returns true if the range consists of all possible values.
Definition qgsrange.h:444
#define BUILTIN_UNREACHABLE
Definition qgis.h:7974
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference).
Definition qgis.h:7340
#define SIP_OUT
Definition qgis_sip.h:57
#define QgsDebugMsgLevel(str, level)
Definition qgslogger.h:80
QgsTemporalRange< QDateTime > QgsDateTimeRange
QgsRange which stores a range of date times.
Definition qgsrange.h:705
#define QGIS_CHECK_OTHER_QOBJECT_THREAD_ACCESS(other)