Skip to content

Commit a0017f9

Browse files
committed
Fix calculation of zonal stats when source contains nodata or nan
pixels (fix #11135)
1 parent c424307 commit a0017f9

File tree

2 files changed

+24
-11
lines changed

2 files changed

+24
-11
lines changed

src/analysis/vector/qgszonalstatistics.cpp

+20-11
Original file line numberDiff line numberDiff line change
@@ -302,27 +302,24 @@ void QgsZonalStatistics::statisticsFromMiddlePointTest( void* band, QgsGeometry*
302302
cellCenterX = rasterBBox.xMinimum() + pixelOffsetX * cellSizeX + cellSizeX / 2;
303303
for ( int j = 0; j < nCellsX; ++j )
304304
{
305-
GEOSGeom_destroy_r( geosctxt, currentCellCenter );
306-
cellCenterCoords = GEOSCoordSeq_create_r( geosctxt, 1, 2 );
307-
GEOSCoordSeq_setX_r( geosctxt, cellCenterCoords, 0, cellCenterX );
308-
GEOSCoordSeq_setY_r( geosctxt, cellCenterCoords, 0, cellCenterY );
309-
currentCellCenter = GEOSGeom_createPoint_r( geosctxt, cellCenterCoords );
310-
311-
if ( scanLine[j] != mInputNodataValue ) //don't consider nodata values
305+
if ( validPixel( scanLine[j] ) )
312306
{
307+
GEOSGeom_destroy_r( geosctxt, currentCellCenter );
308+
cellCenterCoords = GEOSCoordSeq_create_r( geosctxt, 1, 2 );
309+
GEOSCoordSeq_setX_r( geosctxt, cellCenterCoords, 0, cellCenterX );
310+
GEOSCoordSeq_setY_r( geosctxt, cellCenterCoords, 0, cellCenterY );
311+
currentCellCenter = GEOSGeom_createPoint_r( geosctxt, cellCenterCoords );
313312
if ( GEOSPreparedContains_r( geosctxt, polyGeosPrepared, currentCellCenter ) )
314313
{
315-
if ( !qIsNaN( scanLine[j] ) )
316-
{
317-
sum += scanLine[j];
318-
}
314+
sum += scanLine[j];
319315
++count;
320316
}
321317
}
322318
cellCenterX += cellSizeX;
323319
}
324320
cellCenterY -= cellSizeY;
325321
}
322+
GEOSGeom_destroy_r( geosctxt, currentCellCenter );
326323
CPLFree( scanLine );
327324
GEOSPreparedGeom_destroy_r( geosctxt, polyGeosPrepared );
328325
}
@@ -347,6 +344,9 @@ void QgsZonalStatistics::statisticsFromPreciseIntersection( void* band, QgsGeome
347344
for ( int col = 0; col < nCellsX; ++col )
348345
{
349346
GDALRasterIO( band, GF_Read, pixelOffsetX + col, pixelOffsetY + row, nCellsX, 1, pixelData, 1, 1, GDT_Float32, 0, 0 );
347+
if ( !validPixel( *pixelData ) )
348+
continue;
349+
350350
pixelRectGeometry = QgsGeometry::fromRect( QgsRectangle( currentX - hCellSizeX, currentY - hCellSizeY, currentX + hCellSizeX, currentY + hCellSizeY ) );
351351
if ( pixelRectGeometry )
352352
{
@@ -373,6 +373,15 @@ void QgsZonalStatistics::statisticsFromPreciseIntersection( void* band, QgsGeome
373373
CPLFree( pixelData );
374374
}
375375

376+
bool QgsZonalStatistics::validPixel( float value ) const
377+
{
378+
if ( value == mInputNodataValue || qIsNaN( value ) )
379+
{
380+
return false;
381+
}
382+
return true;
383+
}
384+
376385
QString QgsZonalStatistics::getUniqueFieldName( QString fieldName )
377386
{
378387
QgsVectorDataProvider* dp = mPolygonLayer->dataProvider();

src/analysis/vector/qgszonalstatistics.h

+4
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ class ANALYSIS_EXPORT QgsZonalStatistics
5454
void statisticsFromPreciseIntersection( void* band, QgsGeometry* poly, int pixelOffsetX, int pixelOffsetY, int nCellsX, int nCellsY,
5555
double cellSizeX, double cellSizeY, const QgsRectangle& rasterBBox, double& sum, double& count );
5656

57+
/**Tests whether a pixel's value should be included in the result*/
58+
bool validPixel( float value ) const;
59+
5760
QString getUniqueFieldName( QString fieldName );
5861

5962
QString mRasterFilePath;
@@ -63,6 +66,7 @@ class ANALYSIS_EXPORT QgsZonalStatistics
6366
QString mAttributePrefix;
6467
/**The nodata value of the input layer*/
6568
float mInputNodataValue;
69+
6670
};
6771

6872
#endif // QGSZONALSTATISTICS_H

0 commit comments

Comments
 (0)