35 rasterLayer ? rasterLayer->dataProvider() : nullptr,
37 rasterLayer ? rasterLayer->rasterUnitsPerPixelX() : 0,
38 rasterLayer ? rasterLayer->rasterUnitsPerPixelY() : 0,
46 const QgsCoordinateReferenceSystem &rasterCrs,
double rasterUnitsPerPixelX,
double rasterUnitsPerPixelY,
const QString &attributePrefix,
int rasterBand, QgsZonalStatistics::Statistics stats )
47 : mRasterInterface( rasterInterface )
48 , mRasterCrs( rasterCrs )
49 , mCellSizeX( std::fabs( rasterUnitsPerPixelX ) )
50 , mCellSizeY( std::fabs( rasterUnitsPerPixelY ) )
51 , mRasterBand( rasterBand )
52 , mPolygonLayer( polygonLayer )
53 , mAttributePrefix( attributePrefix )
54 , mStatistics( stats )
66 if ( !vectorProvider )
71 if ( !mRasterInterface )
76 if ( mRasterInterface->
bandCount() < mRasterBand )
82 int nCellsXProvider = mRasterInterface->
xSize();
83 int nCellsYProvider = mRasterInterface->
ySize();
88 QList<QgsField> newFieldList;
89 QString countFieldName;
92 countFieldName = getUniqueFieldName( mAttributePrefix +
"count", newFieldList );
93 QgsField countField( countFieldName, QVariant::Double, QStringLiteral(
"double precision" ) );
94 newFieldList.push_back( countField );
99 sumFieldName = getUniqueFieldName( mAttributePrefix +
"sum", newFieldList );
100 QgsField sumField( sumFieldName, QVariant::Double, QStringLiteral(
"double precision" ) );
101 newFieldList.push_back( sumField );
103 QString meanFieldName;
106 meanFieldName = getUniqueFieldName( mAttributePrefix +
"mean", newFieldList );
107 QgsField meanField( meanFieldName, QVariant::Double, QStringLiteral(
"double precision" ) );
108 newFieldList.push_back( meanField );
110 QString medianFieldName;
113 medianFieldName = getUniqueFieldName( mAttributePrefix +
"median", newFieldList );
114 QgsField medianField( medianFieldName, QVariant::Double, QStringLiteral(
"double precision" ) );
115 newFieldList.push_back( medianField );
117 QString stdevFieldName;
120 stdevFieldName = getUniqueFieldName( mAttributePrefix +
"stdev", newFieldList );
121 QgsField stdField( stdevFieldName, QVariant::Double, QStringLiteral(
"double precision" ) );
122 newFieldList.push_back( stdField );
124 QString minFieldName;
127 minFieldName = getUniqueFieldName( mAttributePrefix +
"min", newFieldList );
128 QgsField minField( minFieldName, QVariant::Double, QStringLiteral(
"double precision" ) );
129 newFieldList.push_back( minField );
131 QString maxFieldName;
134 maxFieldName = getUniqueFieldName( mAttributePrefix +
"max", newFieldList );
135 QgsField maxField( maxFieldName, QVariant::Double, QStringLiteral(
"double precision" ) );
136 newFieldList.push_back( maxField );
138 QString rangeFieldName;
141 rangeFieldName = getUniqueFieldName( mAttributePrefix +
"range", newFieldList );
142 QgsField rangeField( rangeFieldName, QVariant::Double, QStringLiteral(
"double precision" ) );
143 newFieldList.push_back( rangeField );
145 QString minorityFieldName;
148 minorityFieldName = getUniqueFieldName( mAttributePrefix +
"minority", newFieldList );
149 QgsField minorityField( minorityFieldName, QVariant::Double, QStringLiteral(
"double precision" ) );
150 newFieldList.push_back( minorityField );
152 QString majorityFieldName;
155 majorityFieldName = getUniqueFieldName( mAttributePrefix +
"majority", newFieldList );
156 QgsField majField( majorityFieldName, QVariant::Double, QStringLiteral(
"double precision" ) );
157 newFieldList.push_back( majField );
159 QString varietyFieldName;
162 varietyFieldName = getUniqueFieldName( mAttributePrefix +
"variety", newFieldList );
163 QgsField varietyField( varietyFieldName, QVariant::Int, QStringLiteral(
"int" ) );
164 newFieldList.push_back( varietyField );
166 QString varianceFieldName;
169 varianceFieldName = getUniqueFieldName( mAttributePrefix +
"variance", newFieldList );
170 QgsField varianceField( varianceFieldName, QVariant::Double, QStringLiteral(
"double precision" ) );
171 newFieldList.push_back( varianceField );
176 int countIndex = mStatistics & QgsZonalStatistics::Count ? vectorProvider->
fieldNameIndex( countFieldName ) : -1;
177 int sumIndex = mStatistics & QgsZonalStatistics::Sum ? vectorProvider->
fieldNameIndex( sumFieldName ) : -1;
178 int meanIndex = mStatistics & QgsZonalStatistics::Mean ? vectorProvider->
fieldNameIndex( meanFieldName ) : -1;
179 int medianIndex = mStatistics & QgsZonalStatistics::Median ? vectorProvider->
fieldNameIndex( medianFieldName ) : -1;
180 int stdevIndex = mStatistics & QgsZonalStatistics::StDev ? vectorProvider->
fieldNameIndex( stdevFieldName ) : -1;
181 int minIndex = mStatistics & QgsZonalStatistics::Min ? vectorProvider->
fieldNameIndex( minFieldName ) : -1;
182 int maxIndex = mStatistics & QgsZonalStatistics::Max ? vectorProvider->
fieldNameIndex( maxFieldName ) : -1;
183 int rangeIndex = mStatistics & QgsZonalStatistics::Range ? vectorProvider->
fieldNameIndex( rangeFieldName ) : -1;
184 int minorityIndex = mStatistics & QgsZonalStatistics::Minority ? vectorProvider->
fieldNameIndex( minorityFieldName ) : -1;
185 int majorityIndex = mStatistics & QgsZonalStatistics::Majority ? vectorProvider->
fieldNameIndex( majorityFieldName ) : -1;
186 int varietyIndex = mStatistics & QgsZonalStatistics::Variety ? vectorProvider->
fieldNameIndex( varietyFieldName ) : -1;
187 int varianceIndex = mStatistics & QgsZonalStatistics::Variance ? vectorProvider->
fieldNameIndex( varianceFieldName ) : -1;
189 if ( ( mStatistics & QgsZonalStatistics::Count && countIndex == -1 )
190 || ( mStatistics & QgsZonalStatistics::Sum && sumIndex == -1 )
191 || ( mStatistics & QgsZonalStatistics::Mean && meanIndex == -1 )
192 || ( mStatistics & QgsZonalStatistics::Median && medianIndex == -1 )
193 || ( mStatistics & QgsZonalStatistics::StDev && stdevIndex == -1 )
194 || ( mStatistics & QgsZonalStatistics::Min && minIndex == -1 )
195 || ( mStatistics & QgsZonalStatistics::Max && maxIndex == -1 )
196 || ( mStatistics & QgsZonalStatistics::Range && rangeIndex == -1 )
197 || ( mStatistics & QgsZonalStatistics::Minority && minorityIndex == -1 )
198 || ( mStatistics & QgsZonalStatistics::Majority && majorityIndex == -1 )
199 || ( mStatistics & QgsZonalStatistics::Variety && varietyIndex == -1 )
200 || ( mStatistics & QgsZonalStatistics::Variance && varianceIndex == -1 )
218 ( mStatistics & QgsZonalStatistics::StDev ) ||
221 ( mStatistics & QgsZonalStatistics::Majority );
223 FeatureStats featureStats( statsStoreValues, statsStoreValueCount );
224 int featureCounter = 0;
236 feedback->
setProgress( 100.0 * static_cast< double >( featureCounter ) / featureCount );
253 int nCellsX, nCellsY;
255 QgsRasterAnalysisUtils::cellInfoForBBox( rasterBBox, featureRect, mCellSizeX, mCellSizeY, nCellsX, nCellsY, nCellsXProvider, nCellsYProvider, rasterBlockExtent );
257 featureStats.reset();
258 QgsRasterAnalysisUtils::statisticsFromMiddlePointTest( mRasterInterface, mRasterBand, featureGeometry, nCellsX, nCellsY, mCellSizeX, mCellSizeY,
259 rasterBlockExtent, [ &featureStats ](
double value ) { featureStats.addValue( value ); } );
261 if ( featureStats.count <= 1 )
264 featureStats.reset();
265 QgsRasterAnalysisUtils::statisticsFromPreciseIntersection( mRasterInterface, mRasterBand, featureGeometry, nCellsX, nCellsY, mCellSizeX, mCellSizeY,
266 rasterBlockExtent, [ &featureStats ](
double value,
double weight ) { featureStats.addValue( value, weight ); } );
271 if ( mStatistics & QgsZonalStatistics::Count )
272 changeAttributeMap.insert( countIndex, QVariant( featureStats.count ) );
273 if ( mStatistics & QgsZonalStatistics::Sum )
274 changeAttributeMap.insert( sumIndex, QVariant( featureStats.sum ) );
275 if ( featureStats.count > 0 )
277 double mean = featureStats.sum / featureStats.count;
278 if ( mStatistics & QgsZonalStatistics::Mean )
279 changeAttributeMap.insert( meanIndex, QVariant( mean ) );
280 if ( mStatistics & QgsZonalStatistics::Median )
282 std::sort( featureStats.values.begin(), featureStats.values.end() );
283 int size = featureStats.values.count();
284 bool even = ( size % 2 ) < 1;
288 medianValue = ( featureStats.values.at( size / 2 - 1 ) + featureStats.values.at( size / 2 ) ) / 2;
292 medianValue = featureStats.values.at( ( size + 1 ) / 2 - 1 );
294 changeAttributeMap.insert( medianIndex, QVariant( medianValue ) );
296 if ( mStatistics & QgsZonalStatistics::StDev || mStatistics & QgsZonalStatistics::Variance )
298 double sumSquared = 0;
299 for (
int i = 0; i < featureStats.values.count(); ++i )
301 double diff = featureStats.values.at( i ) - mean;
302 sumSquared += diff * diff;
304 double variance = sumSquared / featureStats.values.count();
305 if ( mStatistics & QgsZonalStatistics::StDev )
307 double stdev = std::pow( variance, 0.5 );
308 changeAttributeMap.insert( stdevIndex, QVariant( stdev ) );
310 if ( mStatistics & QgsZonalStatistics::Variance )
311 changeAttributeMap.insert( varianceIndex, QVariant( variance ) );
313 if ( mStatistics & QgsZonalStatistics::Min )
314 changeAttributeMap.insert( minIndex, QVariant( featureStats.min ) );
315 if ( mStatistics & QgsZonalStatistics::Max )
316 changeAttributeMap.insert( maxIndex, QVariant( featureStats.max ) );
317 if ( mStatistics & QgsZonalStatistics::Range )
318 changeAttributeMap.insert( rangeIndex, QVariant( featureStats.max - featureStats.min ) );
319 if ( mStatistics & QgsZonalStatistics::Minority || mStatistics & QgsZonalStatistics::Majority )
321 QList<int> vals = featureStats.valueCount.values();
322 std::sort( vals.begin(), vals.end() );
323 if ( mStatistics & QgsZonalStatistics::Minority )
325 double minorityKey = featureStats.valueCount.key( vals.first() );
326 changeAttributeMap.insert( minorityIndex, QVariant( minorityKey ) );
328 if ( mStatistics & QgsZonalStatistics::Majority )
330 double majKey = featureStats.valueCount.key( vals.last() );
331 changeAttributeMap.insert( majorityIndex, QVariant( majKey ) );
334 if ( mStatistics & QgsZonalStatistics::Variety )
335 changeAttributeMap.insert( varietyIndex, QVariant( featureStats.valueCount.count() ) );
338 changeMap.insert( f.
id(), changeAttributeMap );
359 QString QgsZonalStatistics::getUniqueFieldName(
const QString &fieldName,
const QList<QgsField> &newFields )
363 if ( !dp->
storageType().contains( QLatin1String(
"ESRI Shapefile" ) ) )
369 allFields.append( newFields );
370 QString shortName = fieldName.mid( 0, 10 );
373 for (
int idx = 0; idx < allFields.count(); ++idx )
375 if ( shortName == allFields.at( idx ).name() )
388 shortName = QStringLiteral(
"%1_%2" ).arg( fieldName.mid( 0, 8 ) ).arg( n );
393 for (
int idx = 0; idx < allFields.count(); ++idx )
395 if ( shortName == allFields.at( idx ).name() )
400 shortName = QStringLiteral(
"%1_%2" ).arg( fieldName.mid( 0, 8 ) ).arg( n );
404 shortName = QStringLiteral(
"%1_%2" ).arg( fieldName.mid( 0, 7 ) ).arg( n );
void updateFields()
Will regenerate the fields property of this layer by obtaining all fields from the dataProvider...
QgsFeatureRequest & setDestinationCrs(const QgsCoordinateReferenceSystem &crs, const QgsCoordinateTransformContext &context)
Sets the destination crs for feature's geometries.
virtual int bandCount() const =0
Gets number of bands.
Wrapper for iterator of features from vector data provider or vector layer.
A rectangle specified with double values.
virtual bool addAttributes(const QList< QgsField > &attributes)
Adds new attributes to the provider.
virtual QgsRectangle extent() const
Gets the extent of the interface.
This class provides qgis with the ability to render raster datasets onto the mapcanvas.
void setProgress(double progress)
Sets the current progress for the feedback object.
virtual int ySize() const
QgsWkbTypes::GeometryType geometryType() const
Returns point, line or polygon.
A geometry is the spatial representation of a feature.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
const QgsCoordinateReferenceSystem & crs
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Minority of pixel values.
Variety (count of distinct) pixel values.
Base class for feedback objects to be used for cancellation of something running in a worker thread...
Variance of pixel values.
bool isEmpty() const
Returns true if the rectangle is empty.
QgsFeatureRequest & setNoAttributes()
Set that no attributes will be fetched.
QgsFields fields() const override=0
Returns the fields associated with this data provider.
virtual bool changeAttributeValues(const QgsChangedAttributesMap &attr_map)
Changes attribute values of existing features.
QgsRectangle intersect(const QgsRectangle &rect) const
Returns the intersection with the given rectangle.
QMap< int, QVariant > QgsAttributeMap
Majority of pixel values.
This class wraps a request for features to a vector layer (or directly its vector data provider)...
int fieldNameIndex(const QString &fieldName) const
Returns the index of a field name or -1 if the field does not exist.
Encapsulate a field in an attribute table or data source.
int calculateStatistics(QgsFeedback *feedback)
Starts the calculation.
Base class for processing filters like renderers, reprojector, resampler etc.
Range of pixel values (max - min)
bool isCanceled() const
Tells whether the operation has been canceled already.
QMap< QgsFeatureId, QgsAttributeMap > QgsChangedAttributesMap
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const override=0
Query the provider for features specified in request.
long featureCount() const override=0
Number of features in the layer.
QgsZonalStatistics(QgsVectorLayer *polygonLayer, QgsRasterLayer *rasterLayer, const QString &attributePrefix=QString(), int rasterBand=1, QgsZonalStatistics::Statistics stats=QgsZonalStatistics::Statistics(QgsZonalStatistics::Count|QgsZonalStatistics::Sum|QgsZonalStatistics::Mean))
Convenience constructor for QgsZonalStatistics, using an input raster layer.
static QgsProject * instance()
Returns the QgsProject singleton instance.
QgsRectangle boundingBox() const
Returns the bounding box of the geometry.
This class represents a coordinate reference system (CRS).
QList< QgsField > toList() const
Utility function to return a list of QgsField instances.
A class that calculates raster statistics (count, sum, mean) for a polygon or multipolygon layer and ...
virtual QString storageType() const
Returns the permanent storage type for this layer as a friendly name.
QgsVectorDataProvider * dataProvider() FINAL
Returns the layer's data provider, it may be nullptr.
bool nextFeature(QgsFeature &f)
This is the base class for vector data providers.
Represents a vector layer which manages a vector based data sets.
virtual int xSize() const
Gets raster size.
Standard deviation of pixel values.