33 : mRasterLayer( rasterLayer )
34 , mRasterBand( rasterBand )
35 , mPolygonLayer( polygonLayer )
36 , mAttributePrefix( attributePrefix )
37 , mStatistics( stats )
48 if ( !vectorProvider )
58 if ( mRasterLayer->
bandCount() < mRasterBand )
67 int nCellsXProvider = mRasterProvider->
xSize();
68 int nCellsYProvider = mRasterProvider->
ySize();
72 cellsizeX = -cellsizeX;
77 cellsizeY = -cellsizeY;
82 QList<QgsField> newFieldList;
83 QString countFieldName;
86 countFieldName = getUniqueFieldName( mAttributePrefix +
"count", newFieldList );
87 QgsField countField( countFieldName, QVariant::Double, QStringLiteral(
"double precision" ) );
88 newFieldList.push_back( countField );
93 sumFieldName = getUniqueFieldName( mAttributePrefix +
"sum", newFieldList );
94 QgsField sumField( sumFieldName, QVariant::Double, QStringLiteral(
"double precision" ) );
95 newFieldList.push_back( sumField );
97 QString meanFieldName;
100 meanFieldName = getUniqueFieldName( mAttributePrefix +
"mean", newFieldList );
101 QgsField meanField( meanFieldName, QVariant::Double, QStringLiteral(
"double precision" ) );
102 newFieldList.push_back( meanField );
104 QString medianFieldName;
107 medianFieldName = getUniqueFieldName( mAttributePrefix +
"median", newFieldList );
108 QgsField medianField( medianFieldName, QVariant::Double, QStringLiteral(
"double precision" ) );
109 newFieldList.push_back( medianField );
111 QString stdevFieldName;
114 stdevFieldName = getUniqueFieldName( mAttributePrefix +
"stdev", newFieldList );
115 QgsField stdField( stdevFieldName, QVariant::Double, QStringLiteral(
"double precision" ) );
116 newFieldList.push_back( stdField );
118 QString minFieldName;
121 minFieldName = getUniqueFieldName( mAttributePrefix +
"min", newFieldList );
122 QgsField minField( minFieldName, QVariant::Double, QStringLiteral(
"double precision" ) );
123 newFieldList.push_back( minField );
125 QString maxFieldName;
128 maxFieldName = getUniqueFieldName( mAttributePrefix +
"max", newFieldList );
129 QgsField maxField( maxFieldName, QVariant::Double, QStringLiteral(
"double precision" ) );
130 newFieldList.push_back( maxField );
132 QString rangeFieldName;
135 rangeFieldName = getUniqueFieldName( mAttributePrefix +
"range", newFieldList );
136 QgsField rangeField( rangeFieldName, QVariant::Double, QStringLiteral(
"double precision" ) );
137 newFieldList.push_back( rangeField );
139 QString minorityFieldName;
142 minorityFieldName = getUniqueFieldName( mAttributePrefix +
"minority", newFieldList );
143 QgsField minorityField( minorityFieldName, QVariant::Double, QStringLiteral(
"double precision" ) );
144 newFieldList.push_back( minorityField );
146 QString majorityFieldName;
149 majorityFieldName = getUniqueFieldName( mAttributePrefix +
"majority", newFieldList );
150 QgsField majField( majorityFieldName, QVariant::Double, QStringLiteral(
"double precision" ) );
151 newFieldList.push_back( majField );
153 QString varietyFieldName;
156 varietyFieldName = getUniqueFieldName( mAttributePrefix +
"variety", newFieldList );
157 QgsField varietyField( varietyFieldName, QVariant::Int, QStringLiteral(
"int" ) );
158 newFieldList.push_back( varietyField );
160 QString varianceFieldName;
163 varianceFieldName = getUniqueFieldName( mAttributePrefix +
"variance", newFieldList );
164 QgsField varianceField( varianceFieldName, QVariant::Double, QStringLiteral(
"double precision" ) );
165 newFieldList.push_back( varianceField );
170 int countIndex = mStatistics & QgsZonalStatistics::Count ? vectorProvider->
fieldNameIndex( countFieldName ) : -1;
171 int sumIndex = mStatistics & QgsZonalStatistics::Sum ? vectorProvider->
fieldNameIndex( sumFieldName ) : -1;
172 int meanIndex = mStatistics & QgsZonalStatistics::Mean ? vectorProvider->
fieldNameIndex( meanFieldName ) : -1;
173 int medianIndex = mStatistics & QgsZonalStatistics::Median ? vectorProvider->
fieldNameIndex( medianFieldName ) : -1;
174 int stdevIndex = mStatistics & QgsZonalStatistics::StDev ? vectorProvider->
fieldNameIndex( stdevFieldName ) : -1;
175 int minIndex = mStatistics & QgsZonalStatistics::Min ? vectorProvider->
fieldNameIndex( minFieldName ) : -1;
176 int maxIndex = mStatistics & QgsZonalStatistics::Max ? vectorProvider->
fieldNameIndex( maxFieldName ) : -1;
177 int rangeIndex = mStatistics & QgsZonalStatistics::Range ? vectorProvider->
fieldNameIndex( rangeFieldName ) : -1;
178 int minorityIndex = mStatistics & QgsZonalStatistics::Minority ? vectorProvider->
fieldNameIndex( minorityFieldName ) : -1;
179 int majorityIndex = mStatistics & QgsZonalStatistics::Majority ? vectorProvider->
fieldNameIndex( majorityFieldName ) : -1;
180 int varietyIndex = mStatistics & QgsZonalStatistics::Variety ? vectorProvider->
fieldNameIndex( varietyFieldName ) : -1;
181 int varianceIndex = mStatistics & QgsZonalStatistics::Variance ? vectorProvider->
fieldNameIndex( varianceFieldName ) : -1;
183 if ( ( mStatistics & QgsZonalStatistics::Count && countIndex == -1 )
184 || ( mStatistics & QgsZonalStatistics::Sum && sumIndex == -1 )
185 || ( mStatistics & QgsZonalStatistics::Mean && meanIndex == -1 )
186 || ( mStatistics & QgsZonalStatistics::Median && medianIndex == -1 )
187 || ( mStatistics & QgsZonalStatistics::StDev && stdevIndex == -1 )
188 || ( mStatistics & QgsZonalStatistics::Min && minIndex == -1 )
189 || ( mStatistics & QgsZonalStatistics::Max && maxIndex == -1 )
190 || ( mStatistics & QgsZonalStatistics::Range && rangeIndex == -1 )
191 || ( mStatistics & QgsZonalStatistics::Minority && minorityIndex == -1 )
192 || ( mStatistics & QgsZonalStatistics::Majority && majorityIndex == -1 )
193 || ( mStatistics & QgsZonalStatistics::Variety && varietyIndex == -1 )
194 || ( mStatistics & QgsZonalStatistics::Variance && varianceIndex == -1 )
211 ( mStatistics & QgsZonalStatistics::StDev ) ||
214 ( mStatistics & QgsZonalStatistics::Majority );
216 FeatureStats featureStats( statsStoreValues, statsStoreValueCount );
217 int featureCounter = 0;
229 feedback->
setProgress( 100.0 * static_cast< double >( featureCounter ) / featureCount );
246 int offsetX, offsetY, nCellsX, nCellsY;
247 if ( cellInfoForBBox( rasterBBox, featureRect, cellsizeX, cellsizeY, offsetX, offsetY, nCellsX, nCellsY ) != 0 )
254 if ( ( offsetX + nCellsX ) > nCellsXProvider )
256 nCellsX = nCellsXProvider - offsetX;
258 if ( ( offsetY + nCellsY ) > nCellsYProvider )
260 nCellsY = nCellsYProvider - offsetY;
263 statisticsFromMiddlePointTest( featureGeometry, offsetX, offsetY, nCellsX, nCellsY, cellsizeX, cellsizeY,
264 rasterBBox, featureStats );
266 if ( featureStats.count <= 1 )
269 statisticsFromPreciseIntersection( featureGeometry, offsetX, offsetY, nCellsX, nCellsY, cellsizeX, cellsizeY,
270 rasterBBox, featureStats );
275 if ( mStatistics & QgsZonalStatistics::Count )
276 changeAttributeMap.insert( countIndex, QVariant( featureStats.count ) );
277 if ( mStatistics & QgsZonalStatistics::Sum )
278 changeAttributeMap.insert( sumIndex, QVariant( featureStats.sum ) );
279 if ( featureStats.count > 0 )
281 double mean = featureStats.sum / featureStats.count;
282 if ( mStatistics & QgsZonalStatistics::Mean )
283 changeAttributeMap.insert( meanIndex, QVariant( mean ) );
284 if ( mStatistics & QgsZonalStatistics::Median )
286 std::sort( featureStats.values.begin(), featureStats.values.end() );
287 int size = featureStats.values.count();
288 bool even = ( size % 2 ) < 1;
292 medianValue = ( featureStats.values.at( size / 2 - 1 ) + featureStats.values.at( size / 2 ) ) / 2;
296 medianValue = featureStats.values.at( ( size + 1 ) / 2 - 1 );
298 changeAttributeMap.insert( medianIndex, QVariant( medianValue ) );
300 if ( mStatistics & QgsZonalStatistics::StDev || mStatistics & QgsZonalStatistics::Variance )
302 double sumSquared = 0;
303 for (
int i = 0; i < featureStats.values.count(); ++i )
305 double diff = featureStats.values.at( i ) - mean;
306 sumSquared += diff * diff;
308 double variance = sumSquared / featureStats.values.count();
309 if ( mStatistics & QgsZonalStatistics::StDev )
311 double stdev = std::pow( variance, 0.5 );
312 changeAttributeMap.insert( stdevIndex, QVariant( stdev ) );
314 if ( mStatistics & QgsZonalStatistics::Variance )
315 changeAttributeMap.insert( varianceIndex, QVariant( variance ) );
317 if ( mStatistics & QgsZonalStatistics::Min )
318 changeAttributeMap.insert( minIndex, QVariant( featureStats.min ) );
319 if ( mStatistics & QgsZonalStatistics::Max )
320 changeAttributeMap.insert( maxIndex, QVariant( featureStats.max ) );
321 if ( mStatistics & QgsZonalStatistics::Range )
322 changeAttributeMap.insert( rangeIndex, QVariant( featureStats.max - featureStats.min ) );
323 if ( mStatistics & QgsZonalStatistics::Minority || mStatistics & QgsZonalStatistics::Majority )
325 QList<int> vals = featureStats.valueCount.values();
326 std::sort( vals.begin(), vals.end() );
327 if ( mStatistics & QgsZonalStatistics::Minority )
329 float minorityKey = featureStats.valueCount.key( vals.first() );
330 changeAttributeMap.insert( minorityIndex, QVariant( minorityKey ) );
332 if ( mStatistics & QgsZonalStatistics::Majority )
334 float majKey = featureStats.valueCount.key( vals.last() );
335 changeAttributeMap.insert( majorityIndex, QVariant( majKey ) );
338 if ( mStatistics & QgsZonalStatistics::Variety )
339 changeAttributeMap.insert( varietyIndex, QVariant( featureStats.valueCount.count() ) );
342 changeMap.insert( f.
id(), changeAttributeMap );
363 int QgsZonalStatistics::cellInfoForBBox(
const QgsRectangle &rasterBBox,
const QgsRectangle &featureBBox,
double cellSizeX,
double cellSizeY,
364 int &offsetX,
int &offsetY,
int &nCellsX,
int &nCellsY )
const 378 offsetX = ( int )( ( intersectBox.
xMinimum() - rasterBBox.
xMinimum() ) / cellSizeX );
379 offsetY = ( int )( ( rasterBBox.
yMaximum() - intersectBox.
yMaximum() ) / cellSizeY );
381 int maxColumn = ( int )( ( intersectBox.
xMaximum() - rasterBBox.
xMinimum() ) / cellSizeX ) + 1;
382 int maxRow = ( int )( ( rasterBBox.
yMaximum() - intersectBox.
yMinimum() ) / cellSizeY ) + 1;
384 nCellsX = maxColumn - offsetX;
385 nCellsY = maxRow - offsetY;
390 void QgsZonalStatistics::statisticsFromMiddlePointTest(
const QgsGeometry &poly,
int pixelOffsetX,
391 int pixelOffsetY,
int nCellsX,
int nCellsY,
double cellSizeX,
double cellSizeY,
const QgsRectangle &rasterBBox, FeatureStats &stats )
393 double cellCenterX, cellCenterY;
395 cellCenterY = rasterBBox.
yMaximum() - pixelOffsetY * cellSizeY - cellSizeY / 2;
406 if ( !polyGeosPrepared )
411 GEOSCoordSequence *cellCenterCoords =
nullptr;
417 std::unique_ptr< QgsRasterBlock > block( mRasterProvider->
block( mRasterBand, intersectBBox, nCellsX, nCellsY ) );
418 for (
int i = 0; i < nCellsY; ++i )
420 cellCenterX = rasterBBox.
xMinimum() + pixelOffsetX * cellSizeX + cellSizeX / 2;
421 for (
int j = 0; j < nCellsX; ++j )
423 if ( validPixel( block->value( i, j ) ) )
425 cellCenterCoords = GEOSCoordSeq_create_r( geosctxt, 1, 2 );
426 GEOSCoordSeq_setX_r( geosctxt, cellCenterCoords, 0, cellCenterX );
427 GEOSCoordSeq_setY_r( geosctxt, cellCenterCoords, 0, cellCenterY );
428 currentCellCenter.reset( GEOSGeom_createPoint_r( geosctxt, cellCenterCoords ) );
429 if ( GEOSPreparedContains_r( geosctxt, polyGeosPrepared.get(), currentCellCenter.get() ) )
431 stats.addValue( block->value( i, j ) );
434 cellCenterX += cellSizeX;
436 cellCenterY -= cellSizeY;
440 void QgsZonalStatistics::statisticsFromPreciseIntersection(
const QgsGeometry &poly,
int pixelOffsetX,
441 int pixelOffsetY,
int nCellsX,
int nCellsY,
double cellSizeX,
double cellSizeY,
const QgsRectangle &rasterBBox, FeatureStats &stats )
445 double currentY = rasterBBox.
yMaximum() - pixelOffsetY * cellSizeY - cellSizeY / 2;
448 double hCellSizeX = cellSizeX / 2.0;
449 double hCellSizeY = cellSizeY / 2.0;
450 double pixelArea = cellSizeX * cellSizeY;
456 QgsRasterBlock *block = mRasterProvider->
block( mRasterBand, intersectBBox, nCellsX, nCellsY );
457 for (
int i = 0; i < nCellsY; ++i )
459 double currentX = rasterBBox.
xMinimum() + cellSizeX / 2.0 + pixelOffsetX * cellSizeX;
460 for (
int j = 0; j < nCellsX; ++j )
462 if ( !validPixel( block->
value( i, j ) ) )
468 if ( !pixelRectGeometry.
isNull() )
472 if ( !intersectGeometry.
isNull() )
474 double intersectionArea = intersectGeometry.
area();
475 if ( intersectionArea >= 0.0 )
477 weight = intersectionArea / pixelArea;
478 stats.addValue( block->
value( i, j ), weight );
483 currentX += cellSizeX;
485 currentY -= cellSizeY;
490 bool QgsZonalStatistics::validPixel(
float value )
const 492 return !( value == mInputNodataValue || std::isnan( value ) );
495 QString QgsZonalStatistics::getUniqueFieldName(
const QString &fieldName,
const QList<QgsField> &newFields )
499 if ( !dp->
storageType().contains( QLatin1String(
"ESRI Shapefile" ) ) )
505 allFields.append( newFields );
506 QString shortName = fieldName.mid( 0, 10 );
509 for (
int idx = 0; idx < allFields.count(); ++idx )
511 if ( shortName == allFields.at( idx ).name() )
524 shortName = QStringLiteral(
"%1_%2" ).arg( fieldName.mid( 0, 8 ) ).arg( n );
529 for (
int idx = 0; idx < allFields.count(); ++idx )
531 if ( shortName == allFields.at( idx ).name() )
536 shortName = QStringLiteral(
"%1_%2" ).arg( fieldName.mid( 0, 8 ) ).arg( n );
540 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...
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.
int bandCount() const
Get the number of bands in this layer.
bool isNull() const
Returns true if the geometry is null (ie, contains no underlying geometry accessible via geometry() )...
std::unique_ptr< const GEOSPreparedGeometry, GeosDeleter > prepared_unique_ptr
Scoped GEOS prepared geometry pointer.
This class provides qgis with the ability to render raster datasets onto the mapcanvas.
double rasterUnitsPerPixelX() const
Returns the number of raster units per each raster pixel in X axis. In a world file, this is normally the first row (without the sign)
void setProgress(double progress)
Sets the current progress for the feedback object.
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
virtual int ySize() const
QgsWkbTypes::GeometryType geometryType() const
Returns point, line or polygon.
double rasterUnitsPerPixelY() const
Returns the number of raster units per each raster pixel in Y axis. In a world file, this is normally the first row (without the sign)
A geometry is the spatial representation of a feature.
QgsRectangle intersect(const QgsRectangle *rect) const
Return the intersection with the given rectangle.
QgsGeometry intersection(const QgsGeometry &geometry) const
Returns a geometry representing the points shared by this geometry and other.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
bool hasGeometry() const
Returns true if the feature has an associated geometry.
virtual double sourceNoDataValue(int bandNo) const
Value representing no data value.
Minority of pixel values.
Variety (count of distinct) pixel values.
Base class for feedback objects to be used for cancelation of something running in a worker thread...
static QgsGeometry fromRect(const QgsRectangle &rect)
Creates a new geometry from a QgsRectangle.
Variance of pixel values.
QgsRasterDataProvider * dataProvider() override
bool isEmpty() const
Returns true if the rectangle is empty.
QgsRectangle extent() const override=0
Returns the extent of the layer.
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.
std::unique_ptr< GEOSGeometry, GeosDeleter > unique_ptr
Scoped GEOS pointer.
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.
QgsGeometry geometry() const
Returns the geometry associated with this feature.
int calculateStatistics(QgsFeedback *feedback)
Starts the calculation.
double yMinimum() const
Returns the y minimum value (bottom side of rectangle).
double xMaximum() const
Returns the x maximum value (right side of rectangle).
Range of pixel values (max - min)
QgsRasterBlock * block(int bandNo, const QgsRectangle &boundingBox, int width, int height, QgsRasterBlockFeedback *feedback=nullptr) override
Read block of data using given extent and size.
bool isCanceled() const
Tells whether the operation has been canceled already.
QMap< QgsFeatureId, QgsAttributeMap > QgsChangedAttributesMap
static GEOSContextHandle_t getGEOSHandler()
Return GEOS context handle.
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.
GEOSGeometry * exportToGeos(double precision=0) const
Returns a geos geometry - caller takes ownership of the object (should be deleted with GEOSGeom_destr...
QgsZonalStatistics(QgsVectorLayer *polygonLayer, QgsRasterLayer *rasterLayer, const QString &attributePrefix=QString(), int rasterBand=1, QgsZonalStatistics::Statistics stats=QgsZonalStatistics::Statistics(QgsZonalStatistics::Count|QgsZonalStatistics::Sum|QgsZonalStatistics::Mean))
Constructor for QgsZonalStatistics.
QgsRectangle boundingBox() const
Returns the bounding box of the geometry.
QList< QgsField > toList() const
Utility function to return a list of QgsField instances.
QgsVectorDataProvider * dataProvider() override
Returns the layer's data provider.
double value(int row, int column) const
Read a single value if type of block is numeric.
double xMinimum() const
Returns the x minimum value (left side of rectangle).
double yMaximum() const
Returns the y maximum value (top side of rectangle).
virtual QString storageType() const
Returns the permanent storage type for this layer as a friendly name.
QList< int > QgsAttributeList
double area() const
Returns the area of the geometry using GEOS.
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
Get raster size.
Standard deviation of pixel values.