QGIS API Documentation  2.99.0-Master (0a63d1f)
qgszonalstatistics.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgszonalstatistics.cpp - description
3  ----------------------------
4  begin : August 29th, 2009
5  copyright : (C) 2009 by Marco Hugentobler
6  email : marco at hugis dot net
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 "qgszonalstatistics.h"
19 #include "qgsfeatureiterator.h"
20 #include "qgsgeometry.h"
21 #include "qgsvectordataprovider.h"
22 #include "qgsvectorlayer.h"
23 #include "qmath.h"
24 #include "gdal.h"
25 #include "cpl_string.h"
26 #include "qgslogger.h"
27 
28 #include <QProgressDialog>
29 #include <QFile>
30 
31 QgsZonalStatistics::QgsZonalStatistics( QgsVectorLayer* polygonLayer, const QString& rasterFile, const QString& attributePrefix, int rasterBand, Statistics stats )
32  : mRasterFilePath( rasterFile )
33  , mRasterBand( rasterBand )
34  , mPolygonLayer( polygonLayer )
35  , mAttributePrefix( attributePrefix )
36  , mInputNodataValue( -1 )
37  , mStatistics( stats )
38 {
39 
40 }
41 
43  : mRasterBand( 0 )
44  , mPolygonLayer( nullptr )
45  , mInputNodataValue( -1 )
46  , mStatistics( QgsZonalStatistics::All )
47 {
48 
49 }
50 
51 int QgsZonalStatistics::calculateStatistics( QProgressDialog* p )
52 {
53  if ( !mPolygonLayer || mPolygonLayer->geometryType() != QgsWkbTypes::PolygonGeometry )
54  {
55  return 1;
56  }
57 
58  QgsVectorDataProvider* vectorProvider = mPolygonLayer->dataProvider();
59  if ( !vectorProvider )
60  {
61  return 2;
62  }
63 
64  //open the raster layer and the raster band
65  GDALAllRegister();
66  GDALDatasetH inputDataset = GDALOpen( mRasterFilePath.toUtf8().constData(), GA_ReadOnly );
67  if ( !inputDataset )
68  {
69  return 3;
70  }
71 
72  if ( GDALGetRasterCount( inputDataset ) < ( mRasterBand - 1 ) )
73  {
74  GDALClose( inputDataset );
75  return 4;
76  }
77 
78  GDALRasterBandH rasterBand = GDALGetRasterBand( inputDataset, mRasterBand );
79  if ( !rasterBand )
80  {
81  GDALClose( inputDataset );
82  return 5;
83  }
84  mInputNodataValue = GDALGetRasterNoDataValue( rasterBand, nullptr );
85 
86  //get geometry info about raster layer
87  int nCellsXGDAL = GDALGetRasterXSize( inputDataset );
88  int nCellsYGDAL = GDALGetRasterYSize( inputDataset );
89  double geoTransform[6];
90  if ( GDALGetGeoTransform( inputDataset, geoTransform ) != CE_None )
91  {
92  GDALClose( inputDataset );
93  return 6;
94  }
95  double cellsizeX = geoTransform[1];
96  if ( cellsizeX < 0 )
97  {
98  cellsizeX = -cellsizeX;
99  }
100  double cellsizeY = geoTransform[5];
101  if ( cellsizeY < 0 )
102  {
103  cellsizeY = -cellsizeY;
104  }
105  QgsRectangle rasterBBox( geoTransform[0], geoTransform[3] - ( nCellsYGDAL * cellsizeY ),
106  geoTransform[0] + ( nCellsXGDAL * cellsizeX ), geoTransform[3] );
107 
108  //add the new fields to the provider
109  QList<QgsField> newFieldList;
110  QString countFieldName;
111  if ( mStatistics & QgsZonalStatistics::Count )
112  {
113  countFieldName = getUniqueFieldName( mAttributePrefix + "count" );
114  QgsField countField( countFieldName, QVariant::Double, QStringLiteral( "double precision" ) );
115  newFieldList.push_back( countField );
116  }
117  QString sumFieldName;
118  if ( mStatistics & QgsZonalStatistics::Sum )
119  {
120  sumFieldName = getUniqueFieldName( mAttributePrefix + "sum" );
121  QgsField sumField( sumFieldName, QVariant::Double, QStringLiteral( "double precision" ) );
122  newFieldList.push_back( sumField );
123  }
124  QString meanFieldName;
125  if ( mStatistics & QgsZonalStatistics::Mean )
126  {
127  meanFieldName = getUniqueFieldName( mAttributePrefix + "mean" );
128  QgsField meanField( meanFieldName, QVariant::Double, QStringLiteral( "double precision" ) );
129  newFieldList.push_back( meanField );
130  }
131  QString medianFieldName;
132  if ( mStatistics & QgsZonalStatistics::Median )
133  {
134  medianFieldName = getUniqueFieldName( mAttributePrefix + "median" );
135  QgsField medianField( medianFieldName, QVariant::Double, QStringLiteral( "double precision" ) );
136  newFieldList.push_back( medianField );
137  }
138  QString stdevFieldName;
139  if ( mStatistics & QgsZonalStatistics::StDev )
140  {
141  stdevFieldName = getUniqueFieldName( mAttributePrefix + "stdev" );
142  QgsField stdField( stdevFieldName, QVariant::Double, QStringLiteral( "double precision" ) );
143  newFieldList.push_back( stdField );
144  }
145  QString minFieldName;
146  if ( mStatistics & QgsZonalStatistics::Min )
147  {
148  minFieldName = getUniqueFieldName( mAttributePrefix + "min" );
149  QgsField minField( minFieldName, QVariant::Double, QStringLiteral( "double precision" ) );
150  newFieldList.push_back( minField );
151  }
152  QString maxFieldName;
153  if ( mStatistics & QgsZonalStatistics::Max )
154  {
155  maxFieldName = getUniqueFieldName( mAttributePrefix + "max" );
156  QgsField maxField( maxFieldName, QVariant::Double, QStringLiteral( "double precision" ) );
157  newFieldList.push_back( maxField );
158  }
159  QString rangeFieldName;
160  if ( mStatistics & QgsZonalStatistics::Range )
161  {
162  rangeFieldName = getUniqueFieldName( mAttributePrefix + "range" );
163  QgsField rangeField( rangeFieldName, QVariant::Double, QStringLiteral( "double precision" ) );
164  newFieldList.push_back( rangeField );
165  }
166  QString minorityFieldName;
167  if ( mStatistics & QgsZonalStatistics::Minority )
168  {
169  minorityFieldName = getUniqueFieldName( mAttributePrefix + "minority" );
170  QgsField minorityField( minorityFieldName, QVariant::Double, QStringLiteral( "double precision" ) );
171  newFieldList.push_back( minorityField );
172  }
173  QString majorityFieldName;
174  if ( mStatistics & QgsZonalStatistics::Majority )
175  {
176  majorityFieldName = getUniqueFieldName( mAttributePrefix + "majority" );
177  QgsField majField( majorityFieldName, QVariant::Double, QStringLiteral( "double precision" ) );
178  newFieldList.push_back( majField );
179  }
180  QString varietyFieldName;
181  if ( mStatistics & QgsZonalStatistics::Variety )
182  {
183  varietyFieldName = getUniqueFieldName( mAttributePrefix + "variety" );
184  QgsField varietyField( varietyFieldName, QVariant::Int, QStringLiteral( "int" ) );
185  newFieldList.push_back( varietyField );
186  }
187  vectorProvider->addAttributes( newFieldList );
188 
189  //index of the new fields
190  int countIndex = mStatistics & QgsZonalStatistics::Count ? vectorProvider->fieldNameIndex( countFieldName ) : -1;
191  int sumIndex = mStatistics & QgsZonalStatistics::Sum ? vectorProvider->fieldNameIndex( sumFieldName ) : -1;
192  int meanIndex = mStatistics & QgsZonalStatistics::Mean ? vectorProvider->fieldNameIndex( meanFieldName ) : -1;
193  int medianIndex = mStatistics & QgsZonalStatistics::Median ? vectorProvider->fieldNameIndex( medianFieldName ) : -1;
194  int stdevIndex = mStatistics & QgsZonalStatistics::StDev ? vectorProvider->fieldNameIndex( stdevFieldName ) : -1;
195  int minIndex = mStatistics & QgsZonalStatistics::Min ? vectorProvider->fieldNameIndex( minFieldName ) : -1;
196  int maxIndex = mStatistics & QgsZonalStatistics::Max ? vectorProvider->fieldNameIndex( maxFieldName ) : -1;
197  int rangeIndex = mStatistics & QgsZonalStatistics::Range ? vectorProvider->fieldNameIndex( rangeFieldName ) : -1;
198  int minorityIndex = mStatistics & QgsZonalStatistics::Minority ? vectorProvider->fieldNameIndex( minorityFieldName ) : -1;
199  int majorityIndex = mStatistics & QgsZonalStatistics::Majority ? vectorProvider->fieldNameIndex( majorityFieldName ) : -1;
200  int varietyIndex = mStatistics & QgsZonalStatistics::Variety ? vectorProvider->fieldNameIndex( varietyFieldName ) : -1;
201 
202  if (( mStatistics & QgsZonalStatistics::Count && countIndex == -1 )
203  || ( mStatistics & QgsZonalStatistics::Sum && sumIndex == -1 )
204  || ( mStatistics & QgsZonalStatistics::Mean && meanIndex == -1 )
205  || ( mStatistics & QgsZonalStatistics::Median && medianIndex == -1 )
206  || ( mStatistics & QgsZonalStatistics::StDev && stdevIndex == -1 )
207  || ( mStatistics & QgsZonalStatistics::Min && minIndex == -1 )
208  || ( mStatistics & QgsZonalStatistics::Max && maxIndex == -1 )
209  || ( mStatistics & QgsZonalStatistics::Range && rangeIndex == -1 )
210  || ( mStatistics & QgsZonalStatistics::Minority && minorityIndex == -1 )
211  || ( mStatistics & QgsZonalStatistics::Majority && majorityIndex == -1 )
212  || ( mStatistics & QgsZonalStatistics::Variety && varietyIndex == -1 )
213  )
214  {
215  //failed to create a required field
216  return 8;
217  }
218 
219  //progress dialog
220  long featureCount = vectorProvider->featureCount();
221  if ( p )
222  {
223  p->setMaximum( featureCount );
224  }
225 
226 
227  //iterate over each polygon
228  QgsFeatureRequest request;
230  QgsFeatureIterator fi = vectorProvider->getFeatures( request );
231  QgsFeature f;
232 
233  bool statsStoreValues = ( mStatistics & QgsZonalStatistics::Median ) ||
234  ( mStatistics & QgsZonalStatistics::StDev );
235  bool statsStoreValueCount = ( mStatistics & QgsZonalStatistics::Minority ) ||
236  ( mStatistics & QgsZonalStatistics::Majority );
237 
238  FeatureStats featureStats( statsStoreValues, statsStoreValueCount );
239  int featureCounter = 0;
240 
241  QgsChangedAttributesMap changeMap;
242  while ( fi.nextFeature( f ) )
243  {
244  if ( p )
245  {
246  p->setValue( featureCounter );
247  }
248 
249  if ( p && p->wasCanceled() )
250  {
251  break;
252  }
253 
254  if ( !f.hasGeometry() )
255  {
256  ++featureCounter;
257  continue;
258  }
259  QgsGeometry featureGeometry = f.geometry();
260 
261  QgsRectangle featureRect = featureGeometry.boundingBox().intersect( &rasterBBox );
262  if ( featureRect.isEmpty() )
263  {
264  ++featureCounter;
265  continue;
266  }
267 
268  int offsetX, offsetY, nCellsX, nCellsY;
269  if ( cellInfoForBBox( rasterBBox, featureRect, cellsizeX, cellsizeY, offsetX, offsetY, nCellsX, nCellsY ) != 0 )
270  {
271  ++featureCounter;
272  continue;
273  }
274 
275  //avoid access to cells outside of the raster (may occur because of rounding)
276  if (( offsetX + nCellsX ) > nCellsXGDAL )
277  {
278  nCellsX = nCellsXGDAL - offsetX;
279  }
280  if (( offsetY + nCellsY ) > nCellsYGDAL )
281  {
282  nCellsY = nCellsYGDAL - offsetY;
283  }
284 
285  statisticsFromMiddlePointTest( rasterBand, featureGeometry, offsetX, offsetY, nCellsX, nCellsY, cellsizeX, cellsizeY,
286  rasterBBox, featureStats );
287 
288  if ( featureStats.count <= 1 )
289  {
290  //the cell resolution is probably larger than the polygon area. We switch to precise pixel - polygon intersection in this case
291  statisticsFromPreciseIntersection( rasterBand, featureGeometry, offsetX, offsetY, nCellsX, nCellsY, cellsizeX, cellsizeY,
292  rasterBBox, featureStats );
293  }
294 
295  //write the statistics value to the vector data provider
296  QgsAttributeMap changeAttributeMap;
297  if ( mStatistics & QgsZonalStatistics::Count )
298  changeAttributeMap.insert( countIndex, QVariant( featureStats.count ) );
299  if ( mStatistics & QgsZonalStatistics::Sum )
300  changeAttributeMap.insert( sumIndex, QVariant( featureStats.sum ) );
301  if ( featureStats.count > 0 )
302  {
303  double mean = featureStats.sum / featureStats.count;
304  if ( mStatistics & QgsZonalStatistics::Mean )
305  changeAttributeMap.insert( meanIndex, QVariant( mean ) );
306  if ( mStatistics & QgsZonalStatistics::Median )
307  {
308  qSort( featureStats.values.begin(), featureStats.values.end() );
309  int size = featureStats.values.count();
310  bool even = ( size % 2 ) < 1;
311  double medianValue;
312  if ( even )
313  {
314  medianValue = ( featureStats.values.at( size / 2 - 1 ) + featureStats.values.at( size / 2 ) ) / 2;
315  }
316  else //odd
317  {
318  medianValue = featureStats.values.at(( size + 1 ) / 2 - 1 );
319  }
320  changeAttributeMap.insert( medianIndex, QVariant( medianValue ) );
321  }
322  if ( mStatistics & QgsZonalStatistics::StDev )
323  {
324  double sumSquared = 0;
325  for ( int i = 0; i < featureStats.values.count(); ++i )
326  {
327  double diff = featureStats.values.at( i ) - mean;
328  sumSquared += diff * diff;
329  }
330  double stdev = qPow( sumSquared / featureStats.values.count(), 0.5 );
331  changeAttributeMap.insert( stdevIndex, QVariant( stdev ) );
332  }
333  if ( mStatistics & QgsZonalStatistics::Min )
334  changeAttributeMap.insert( minIndex, QVariant( featureStats.min ) );
335  if ( mStatistics & QgsZonalStatistics::Max )
336  changeAttributeMap.insert( maxIndex, QVariant( featureStats.max ) );
337  if ( mStatistics & QgsZonalStatistics::Range )
338  changeAttributeMap.insert( rangeIndex, QVariant( featureStats.max - featureStats.min ) );
339  if ( mStatistics & QgsZonalStatistics::Minority || mStatistics & QgsZonalStatistics::Majority )
340  {
341  QList<int> vals = featureStats.valueCount.values();
342  qSort( vals.begin(), vals.end() );
343  if ( mStatistics & QgsZonalStatistics::Minority )
344  {
345  float minorityKey = featureStats.valueCount.key( vals.first() );
346  changeAttributeMap.insert( minorityIndex, QVariant( minorityKey ) );
347  }
348  if ( mStatistics & QgsZonalStatistics::Majority )
349  {
350  float majKey = featureStats.valueCount.key( vals.last() );
351  changeAttributeMap.insert( majorityIndex, QVariant( majKey ) );
352  }
353  }
354  if ( mStatistics & QgsZonalStatistics::Variety )
355  changeAttributeMap.insert( varietyIndex, QVariant( featureStats.valueCount.count() ) );
356  }
357 
358  changeMap.insert( f.id(), changeAttributeMap );
359  ++featureCounter;
360  }
361 
362  vectorProvider->changeAttributeValues( changeMap );
363 
364  if ( p )
365  {
366  p->setValue( featureCount );
367  }
368 
369  GDALClose( inputDataset );
370  mPolygonLayer->updateFields();
371 
372  if ( p && p->wasCanceled() )
373  {
374  return 9;
375  }
376 
377  return 0;
378 }
379 
380 int QgsZonalStatistics::cellInfoForBBox( const QgsRectangle& rasterBBox, const QgsRectangle& featureBBox, double cellSizeX, double cellSizeY,
381  int& offsetX, int& offsetY, int& nCellsX, int& nCellsY ) const
382 {
383  //get intersecting bbox
384  QgsRectangle intersectBox = rasterBBox.intersect( &featureBBox );
385  if ( intersectBox.isEmpty() )
386  {
387  nCellsX = 0;
388  nCellsY = 0;
389  offsetX = 0;
390  offsetY = 0;
391  return 0;
392  }
393 
394  //get offset in pixels in x- and y- direction
395  offsetX = ( int )(( intersectBox.xMinimum() - rasterBBox.xMinimum() ) / cellSizeX );
396  offsetY = ( int )(( rasterBBox.yMaximum() - intersectBox.yMaximum() ) / cellSizeY );
397 
398  int maxColumn = ( int )(( intersectBox.xMaximum() - rasterBBox.xMinimum() ) / cellSizeX ) + 1;
399  int maxRow = ( int )(( rasterBBox.yMaximum() - intersectBox.yMinimum() ) / cellSizeY ) + 1;
400 
401  nCellsX = maxColumn - offsetX;
402  nCellsY = maxRow - offsetY;
403 
404  return 0;
405 }
406 
407 void QgsZonalStatistics::statisticsFromMiddlePointTest( void* band, const QgsGeometry& poly, int pixelOffsetX,
408  int pixelOffsetY, int nCellsX, int nCellsY, double cellSizeX, double cellSizeY, const QgsRectangle& rasterBBox, FeatureStats &stats )
409 {
410  double cellCenterX, cellCenterY;
411 
412  float* scanLine = ( float * ) CPLMalloc( sizeof( float ) * nCellsX );
413  cellCenterY = rasterBBox.yMaximum() - pixelOffsetY * cellSizeY - cellSizeY / 2;
414  stats.reset();
415 
416  GEOSGeometry* polyGeos = poly.exportToGeos();
417  if ( !polyGeos )
418  {
419  return;
420  }
421 
422  GEOSContextHandle_t geosctxt = QgsGeometry::getGEOSHandler();
423  const GEOSPreparedGeometry* polyGeosPrepared = GEOSPrepare_r( geosctxt, polyGeos );
424  if ( !polyGeosPrepared )
425  {
426  GEOSGeom_destroy_r( geosctxt, polyGeos );
427  return;
428  }
429 
430  GEOSCoordSequence* cellCenterCoords = nullptr;
431  GEOSGeometry* currentCellCenter = nullptr;
432 
433  for ( int i = 0; i < nCellsY; ++i )
434  {
435  if ( GDALRasterIO( band, GF_Read, pixelOffsetX, pixelOffsetY + i, nCellsX, 1, scanLine, nCellsX, 1, GDT_Float32, 0, 0 )
436  != CPLE_None )
437  {
438  continue;
439  }
440  cellCenterX = rasterBBox.xMinimum() + pixelOffsetX * cellSizeX + cellSizeX / 2;
441  for ( int j = 0; j < nCellsX; ++j )
442  {
443  if ( validPixel( scanLine[j] ) )
444  {
445  GEOSGeom_destroy_r( geosctxt, currentCellCenter );
446  cellCenterCoords = GEOSCoordSeq_create_r( geosctxt, 1, 2 );
447  GEOSCoordSeq_setX_r( geosctxt, cellCenterCoords, 0, cellCenterX );
448  GEOSCoordSeq_setY_r( geosctxt, cellCenterCoords, 0, cellCenterY );
449  currentCellCenter = GEOSGeom_createPoint_r( geosctxt, cellCenterCoords );
450  if ( GEOSPreparedContains_r( geosctxt, polyGeosPrepared, currentCellCenter ) )
451  {
452  stats.addValue( scanLine[j] );
453  }
454  }
455  cellCenterX += cellSizeX;
456  }
457  cellCenterY -= cellSizeY;
458  }
459  GEOSGeom_destroy_r( geosctxt, currentCellCenter );
460  CPLFree( scanLine );
461  GEOSPreparedGeom_destroy_r( geosctxt, polyGeosPrepared );
462  GEOSGeom_destroy_r( geosctxt, polyGeos );
463 }
464 
465 void QgsZonalStatistics::statisticsFromPreciseIntersection( void* band, const QgsGeometry& poly, int pixelOffsetX,
466  int pixelOffsetY, int nCellsX, int nCellsY, double cellSizeX, double cellSizeY, const QgsRectangle& rasterBBox, FeatureStats &stats )
467 {
468  stats.reset();
469 
470  double currentY = rasterBBox.yMaximum() - pixelOffsetY * cellSizeY - cellSizeY / 2;
471  float* pixelData = ( float * ) CPLMalloc( sizeof( float ) );
472  QgsGeometry pixelRectGeometry;
473 
474  double hCellSizeX = cellSizeX / 2.0;
475  double hCellSizeY = cellSizeY / 2.0;
476  double pixelArea = cellSizeX * cellSizeY;
477  double weight = 0;
478 
479  for ( int row = 0; row < nCellsY; ++row )
480  {
481  double currentX = rasterBBox.xMinimum() + cellSizeX / 2.0 + pixelOffsetX * cellSizeX;
482  for ( int col = 0; col < nCellsX; ++col )
483  {
484  if ( GDALRasterIO( band, GF_Read, pixelOffsetX + col, pixelOffsetY + row, nCellsX, 1, pixelData, 1, 1, GDT_Float32, 0, 0 ) != CE_None )
485  {
486  QgsDebugMsg( "Raster IO Error" );
487  }
488 
489  if ( !validPixel( *pixelData ) )
490  continue;
491 
492  pixelRectGeometry = QgsGeometry::fromRect( QgsRectangle( currentX - hCellSizeX, currentY - hCellSizeY, currentX + hCellSizeX, currentY + hCellSizeY ) );
493  if ( !pixelRectGeometry.isEmpty() )
494  {
495  //intersection
496  QgsGeometry intersectGeometry = pixelRectGeometry.intersection( poly );
497  if ( !intersectGeometry.isEmpty() )
498  {
499  double intersectionArea = intersectGeometry.area();
500  if ( intersectionArea >= 0.0 )
501  {
502  weight = intersectionArea / pixelArea;
503  stats.addValue( *pixelData, weight );
504  }
505  }
506  pixelRectGeometry = QgsGeometry();
507  }
508  currentX += cellSizeX;
509  }
510  currentY -= cellSizeY;
511  }
512  CPLFree( pixelData );
513 }
514 
515 bool QgsZonalStatistics::validPixel( float value ) const
516 {
517  if ( value == mInputNodataValue || qIsNaN( value ) )
518  {
519  return false;
520  }
521  return true;
522 }
523 
524 QString QgsZonalStatistics::getUniqueFieldName( const QString& fieldName )
525 {
526  QgsVectorDataProvider* dp = mPolygonLayer->dataProvider();
527 
528  if ( !dp->storageType().contains( QLatin1String( "ESRI Shapefile" ) ) )
529  {
530  return fieldName;
531  }
532 
533  QgsFields providerFields = dp->fields();
534  QString shortName = fieldName.mid( 0, 10 );
535 
536  bool found = false;
537  for ( int idx = 0; idx < providerFields.count(); ++idx )
538  {
539  if ( shortName == providerFields.at( idx ).name() )
540  {
541  found = true;
542  break;
543  }
544  }
545 
546  if ( !found )
547  {
548  return shortName;
549  }
550 
551  int n = 1;
552  shortName = QStringLiteral( "%1_%2" ).arg( fieldName.mid( 0, 8 ) ).arg( n );
553  found = true;
554  while ( found )
555  {
556  found = false;
557  for ( int idx = 0; idx < providerFields.count(); ++idx )
558  {
559  if ( shortName == providerFields.at( idx ).name() )
560  {
561  n += 1;
562  if ( n < 9 )
563  {
564  shortName = QStringLiteral( "%1_%2" ).arg( fieldName.mid( 0, 8 ) ).arg( n );
565  }
566  else
567  {
568  shortName = QStringLiteral( "%1_%2" ).arg( fieldName.mid( 0, 7 ) ).arg( n );
569  }
570  found = true;
571  }
572  }
573  }
574  return shortName;
575 }
void updateFields()
Assembles mUpdatedFields considering provider fields, joined fields and added fields.
QgsFeatureId id
Definition: qgsfeature.h:140
Wrapper for iterator of features from vector data provider or vector layer.
A rectangle specified with double values.
Definition: qgsrectangle.h:36
QString name
Definition: qgsfield.h:53
QMap< int, QVariant > QgsAttributeMap
Definition: qgsfeature.h:45
virtual bool addAttributes(const QList< QgsField > &attributes)
Adds new attributes.
#define QgsDebugMsg(str)
Definition: qgslogger.h:36
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
QgsWkbTypes::GeometryType geometryType() const
Returns point, line or polygon.
Container of fields for a vector layer.
Definition: qgsfields.h:39
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:79
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...
Definition: qgsfeature.h:136
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Definition: qgsfeature.cpp:199
int count() const
Return number of items.
Definition: qgsfields.cpp:115
Median of pixel values.
Minority of pixel values.
Variety (count of distinct) pixel values.
QgsField at(int i) const
Get field at particular index (must be in range 0..N-1)
Definition: qgsfields.cpp:135
static QgsGeometry fromRect(const QgsRectangle &rect)
Creates a new geometry from a QgsRectangle.
bool isEmpty() const
test if rectangle is empty.
virtual QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const =0
Query the provider for features specified in request.
virtual bool changeAttributeValues(const QgsChangedAttributesMap &attr_map)
Changes attribute values of existing features.
virtual QgsFields fields() const =0
Returns the fields associated with this data provider.
Sum of pixel values.
virtual long featureCount() const =0
Number of features in the layer.
Majority of pixel values.
This class wraps a request for features to a vector layer (or directly its vector data provider)...
QList< int > QgsAttributeList
int fieldNameIndex(const QString &fieldName) const
Returns the index of a field name or -1 if the field does not exist.
bool isEmpty() const
Returns true if the geometry is empty (ie, contains no underlying geometry accessible via geometry)...
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:45
QgsZonalStatistics(QgsVectorLayer *polygonLayer, const QString &rasterFile, const QString &attributePrefix="", int rasterBand=1, Statistics stats=Statistics(Count|Sum|Mean))
Constructor for QgsZonalStatistics.
QgsGeometry geometry() const
Returns the geometry associated with this feature.
Definition: qgsfeature.cpp:113
void * GDALDatasetH
Max of pixel values.
double yMinimum() const
Get the y minimum value (bottom side of rectangle)
Definition: qgsrectangle.h:207
double xMaximum() const
Get the x maximum value (right side of rectangle)
Definition: qgsrectangle.h:192
Mean of pixel values.
Range of pixel values (max - min)
int calculateStatistics(QProgressDialog *p)
Starts the calculation.
QMap< QgsFeatureId, QgsAttributeMap > QgsChangedAttributesMap
Definition: qgsfeature.h:343
static GEOSContextHandle_t getGEOSHandler()
Return GEOS context handle.
GEOSGeometry * exportToGeos(double precision=0) const
Returns a geos geometry - caller takes ownership of the object (should be deleted with GEOSGeom_destr...
QgsRectangle boundingBox() const
Returns the bounding box of the geometry.
double xMinimum() const
Get the x minimum value (left side of rectangle)
Definition: qgsrectangle.h:197
double yMaximum() const
Get the y maximum value (top side of rectangle)
Definition: qgsrectangle.h:202
Min of pixel values.
virtual QString storageType() const
Returns the permanent storage type for this layer as a friendly name.
double area() const
Returns the area of the geometry using GEOS.
QgsVectorDataProvider * dataProvider()
Returns the data provider.
bool nextFeature(QgsFeature &f)
This is the base class for vector data providers.
Represents a vector layer which manages a vector based data sets.
Standard deviation of pixel values.