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