QGIS API Documentation 3.99.0-Master (357b655ed83)
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
34 QgsRasterLayer *layer,
35 const QgsDateTimeRange &temporalRange,
36 const QgsDoubleRange &elevationRange,
37 bool &matched )
38{
39 if ( !layer )
40 {
41 matched = false;
42 return -1;
43 }
44
45 matched = true;
46 const QgsRasterLayerElevationProperties *elevationProperties = qobject_cast< QgsRasterLayerElevationProperties * >( layer->elevationProperties() );
47 const QgsRasterLayerTemporalProperties *temporalProperties = qobject_cast< QgsRasterLayerTemporalProperties *>( layer->temporalProperties() );
48
49 // neither active
50 if ( ( !temporalProperties->isActive() || temporalRange.isInfinite() )
51 && ( !elevationProperties->hasElevation() || elevationRange.isInfinite() ) )
52 {
53 return -1;
54 }
55
56 // only elevation properties enabled
57 if ( !temporalProperties->isActive() || temporalRange.isInfinite() )
58 {
59 const int band = elevationProperties->bandForElevationRange( layer, elevationRange );
60 matched = band > 0;
61 return band;
62 }
63
64 // only temporal properties enabled
65 if ( !elevationProperties->hasElevation() || elevationRange.isInfinite() )
66 {
67 const int band = temporalProperties->bandForTemporalRange( layer, temporalRange );
68 matched = band > 0;
69 return band;
70 }
71
72 // both elevation and temporal properties enabled
73
74 // first find bands matching the temporal range
75 QList< int > temporalBands;
76 switch ( temporalProperties->mode() )
77 {
83 {
84 temporalBands << temporalProperties->filteredBandsForTemporalRange( layer, temporalRange );
85 break;
86 }
87
89 {
90 temporalBands << temporalProperties->bandNumber();
91 break;
92 }
93 }
94
95 if ( temporalBands.empty() )
96 {
97 matched = false;
98 return -1;
99 }
100
101 switch ( elevationProperties->mode() )
102 {
105 return temporalBands.at( 0 );
106
108 {
109 // find the top-most band which matches the map range
110 int currentMatchingBand = -1;
111 matched = false;
112 QgsDoubleRange currentMatchingRange;
113 const QMap<int, QgsDoubleRange> rangePerBand = elevationProperties->fixedRangePerBand();
114 for ( int band : temporalBands )
115 {
116 const QgsDoubleRange rangeForBand = rangePerBand.value( band );
117 if ( rangeForBand.overlaps( elevationRange ) )
118 {
119 if ( currentMatchingRange.isInfinite()
120 || ( rangeForBand.includeUpper() && rangeForBand.upper() >= currentMatchingRange.upper() )
121 || ( !currentMatchingRange.includeUpper() && rangeForBand.upper() >= currentMatchingRange.upper() ) )
122 {
123 matched = true;
124 currentMatchingBand = band;
125 currentMatchingRange = rangeForBand;
126 }
127 }
128 }
129 return currentMatchingBand;
130 }
131
133 {
134 QgsExpressionContext context;
137 context.appendScope( bandScope );
138
141 lowerProperty.prepare( context );
142 upperProperty.prepare( context );
143
144 int currentMatchingBand = -1;
145 matched = false;
146 QgsDoubleRange currentMatchingRange;
147
148 for ( int band : temporalBands )
149 {
150 bandScope->setVariable( u"band"_s, band );
151 bandScope->setVariable( u"band_name"_s, layer->dataProvider()->displayBandName( band ) );
152 bandScope->setVariable( u"band_description"_s, layer->dataProvider()->bandDescription( band ) );
153
154 bool ok = false;
155 const double lower = lowerProperty.valueAsDouble( context, 0, &ok );
156 if ( !ok )
157 continue;
158 const double upper = upperProperty.valueAsDouble( context, 0, &ok );
159 if ( !ok )
160 continue;
161
162 const QgsDoubleRange bandRange = QgsDoubleRange( lower, upper );
163 if ( bandRange.overlaps( elevationRange ) )
164 {
165 if ( currentMatchingRange.isInfinite()
166 || ( bandRange.includeUpper() && bandRange.upper() >= currentMatchingRange.upper() )
167 || ( !currentMatchingRange.includeUpper() && bandRange.upper() >= currentMatchingRange.upper() ) )
168 {
169 currentMatchingBand = band;
170 currentMatchingRange = bandRange;
171 matched = true;
172 }
173 }
174 }
175 return currentMatchingBand;
176 }
177 }
179}
180
182 int band,
183 const QgsRasterMinMaxOrigin &mmo,
185 const QgsRectangle &extent,
186 int sampleSize,
187 double &min SIP_OUT,
188 double &max SIP_OUT )
189{
190 min = std::numeric_limits<double>::quiet_NaN();
191 max = std::numeric_limits<double>::quiet_NaN();
192
193 if ( !provider )
194 return;
195
197
199 {
200 QgsRasterBandStats myRasterBandStats = provider->bandStatistics( band, Qgis::RasterBandStatistic::Min | Qgis::RasterBandStatistic::Max, extent, sampleSize );
201 // Check if statistics were actually gathered, None means a failure
202 if ( myRasterBandStats.statsGathered == static_cast< int >( Qgis::RasterBandStatistic::NoStatistic ) )
203 {
204 // Best guess we can do
205 switch ( provider->dataType( band ) )
206 {
208 {
209 myRasterBandStats.minimumValue = 0;
210 myRasterBandStats.maximumValue = 255;
211 break;
212 }
214 {
215 myRasterBandStats.minimumValue = std::numeric_limits<int8_t>::lowest();
216 myRasterBandStats.maximumValue = std::numeric_limits<int8_t>::max();
217 break;
218 }
220 {
221 myRasterBandStats.minimumValue = 0;
222 myRasterBandStats.maximumValue = std::numeric_limits<uint16_t>::max();
223 break;
224 }
226 {
227 myRasterBandStats.minimumValue = 0;
228 myRasterBandStats.maximumValue = std::numeric_limits<uint32_t>::max();
229 break;
230 }
233 {
234 myRasterBandStats.minimumValue = std::numeric_limits<int16_t>::lowest();
235 myRasterBandStats.maximumValue = std::numeric_limits<int16_t>::max();
236 break;
237 }
240 {
241 myRasterBandStats.minimumValue = std::numeric_limits<int32_t>::lowest();
242 myRasterBandStats.maximumValue = std::numeric_limits<int32_t>::max();
243 break;
244 }
247 {
248 myRasterBandStats.minimumValue = std::numeric_limits<float_t>::lowest();
249 myRasterBandStats.maximumValue = std::numeric_limits<float_t>::max();
250 break;
251 }
254 {
255 myRasterBandStats.minimumValue = std::numeric_limits<double_t>::lowest();
256 myRasterBandStats.maximumValue = std::numeric_limits<double_t>::max();
257 break;
258 }
262 {
263 // Nothing to guess
264 break;
265 }
266 }
267 }
268 min = myRasterBandStats.minimumValue;
269 max = myRasterBandStats.maximumValue;
270 }
271 else if ( limits == Qgis::RasterRangeLimit::StdDev )
272 {
273 const QgsRasterBandStats myRasterBandStats = provider->bandStatistics( band, Qgis::RasterBandStatistic::Mean | Qgis::RasterBandStatistic::StdDev, extent, sampleSize );
274 min = myRasterBandStats.mean - ( mmo.stdDevFactor() * myRasterBandStats.stdDev );
275 max = myRasterBandStats.mean + ( mmo.stdDevFactor() * myRasterBandStats.stdDev );
276 }
277 else if ( limits == Qgis::RasterRangeLimit::CumulativeCut )
278 {
279 const double myLower = mmo.cumulativeCutLower();
280 const double myUpper = mmo.cumulativeCutUpper();
281 QgsDebugMsgLevel( u"myLower = %1 myUpper = %2"_s.arg( myLower ).arg( myUpper ), 4 );
282 provider->cumulativeCut( band, myLower, myUpper, min, max, extent, sampleSize );
283 }
284 QgsDebugMsgLevel( u"band = %1 min = %2 max = %3"_s.arg( band ).arg( min ).arg( max ), 4 );
285}
RasterRangeLimit
Describes the limits used to compute raster ranges (min/max values).
Definition qgis.h:1602
@ CumulativeCut
Range is [ min + cumulativeCutLower() * (max - min), min + cumulativeCutUpper() * (max - min) ].
Definition qgis.h:1606
@ StdDev
Range is [ mean - stdDevFactor() * stddev, mean + stdDevFactor() * stddev ].
Definition qgis.h:1605
@ MinimumMaximum
Real min-max values.
Definition qgis.h:1604
@ FixedRangePerBand
Layer has a fixed (manually specified) elevation range per band.
Definition qgis.h:4095
@ FixedElevationRange
Layer has a fixed elevation range.
Definition qgis.h:4093
@ RepresentsElevationSurface
Pixel values represent an elevation surface.
Definition qgis.h:4094
@ DynamicRangePerBand
Layer has a elevation range per band, calculated dynamically from an expression.
Definition qgis.h:4096
@ RepresentsTemporalValues
Pixel values represent an datetime.
Definition qgis.h:2684
@ RedrawLayerOnly
Redraw the layer when temporal range changes, but don't apply any filtering. Useful when raster symbo...
Definition qgis.h:2682
@ FixedRangePerBand
Layer has a fixed temporal range per band.
Definition qgis.h:2683
@ TemporalRangeFromDataProvider
Mode when raster layer delegates temporal range handling to the dataprovider.
Definition qgis.h:2681
@ FixedTemporalRange
Mode when temporal properties have fixed start and end datetimes.
Definition qgis.h:2680
@ FixedDateTime
Layer has a fixed date time instant.
Definition qgis.h:2685
@ StdDev
Standard deviation.
Definition qgis.h:6247
@ NoStatistic
No statistic.
Definition qgis.h:6241
@ CInt32
Complex Int32.
Definition qgis.h:390
@ Float32
Thirty two bit floating point (float).
Definition qgis.h:387
@ CFloat64
Complex Float64.
Definition qgis.h:392
@ Int16
Sixteen bit signed integer (qint16).
Definition qgis.h:384
@ ARGB32_Premultiplied
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32_Premultiplied.
Definition qgis.h:394
@ Int8
Eight bit signed integer (qint8) (added in QGIS 3.30).
Definition qgis.h:382
@ UInt16
Sixteen bit unsigned integer (quint16).
Definition qgis.h:383
@ Byte
Eight bit unsigned integer (quint8).
Definition qgis.h:381
@ UnknownDataType
Unknown or unspecified type.
Definition qgis.h:380
@ ARGB32
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32.
Definition qgis.h:393
@ Int32
Thirty two bit signed integer (qint32).
Definition qgis.h:386
@ Float64
Sixty four bit floating point (double).
Definition qgis.h:388
@ CFloat32
Complex Float32.
Definition qgis.h:391
@ CInt16
Complex Int16.
Definition qgis.h:389
@ UInt32
Thirty two bit unsigned integer (quint32).
Definition qgis.h:385
QgsRange which stores a range of double values.
Definition qgsrange.h:236
bool isInfinite() const
Returns true if the range consists of all possible values.
Definition qgsrange.h:290
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.
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:104
bool overlaps(const QgsRange< T > &other) const
Returns true if this range overlaps another range.
Definition qgsrange.h:179
T upper() const
Returns the upper bound of the range.
Definition qgsrange.h:88
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.
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.
Q_DECL_DEPRECATED QgsRasterBandStats bandStatistics(int bandNo, int stats, const QgsRectangle &extent=QgsRectangle(), int sampleSize=0, QgsRasterBlockFeedback *feedback=nullptr)
Returns the band statistics.
QString displayBandName(int bandNumber) const
Generates a friendly, descriptive name for the specified bandNumber.
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...
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).
A rectangle specified with double values.
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:485
#define BUILTIN_UNREACHABLE
Definition qgis.h:7524
#define SIP_OUT
Definition qgis_sip.h:58
#define QgsDebugMsgLevel(str, level)
Definition qgslogger.h:63
QgsTemporalRange< QDateTime > QgsDateTimeRange
QgsRange which stores a range of date times.
Definition qgsrange.h:764
#define QGIS_CHECK_OTHER_QOBJECT_THREAD_ACCESS(other)