mirror of
https://github.com/qgis/QGIS.git
synced 2025-10-08 00:05:09 -04:00
Fix zonal statistics calculations when pixel size is greater than
polygon size Fixes #17159
This commit is contained in:
parent
985aee6920
commit
83d44b9fe9
@ -456,25 +456,23 @@ void QgsZonalStatistics::statisticsFromPreciseIntersection( const QgsGeometry &p
|
||||
for ( int j = 0; j < nCellsX; ++j )
|
||||
{
|
||||
double pixelValue = block->value( i, j );
|
||||
if ( !validPixel( pixelValue ) || block->isNoData( i, j ) )
|
||||
if ( validPixel( pixelValue ) && !block->isNoData( i, j ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
pixelRectGeometry = QgsGeometry::fromRect( QgsRectangle( currentX - hCellSizeX, currentY - hCellSizeY, currentX + hCellSizeX, currentY + hCellSizeY ) );
|
||||
// GEOS intersects tests on prepared geometry is MAGNITUDES faster than calculating the intersection itself,
|
||||
// so we first test to see if there IS an intersection before doing the actual calculation
|
||||
if ( !pixelRectGeometry.isNull() && polyEngine->intersects( pixelRectGeometry.constGet() ) )
|
||||
{
|
||||
//intersection
|
||||
QgsGeometry intersectGeometry = pixelRectGeometry.intersection( poly );
|
||||
if ( !intersectGeometry.isEmpty() )
|
||||
pixelRectGeometry = QgsGeometry::fromRect( QgsRectangle( currentX - hCellSizeX, currentY - hCellSizeY, currentX + hCellSizeX, currentY + hCellSizeY ) );
|
||||
// GEOS intersects tests on prepared geometry is MAGNITUDES faster than calculating the intersection itself,
|
||||
// so we first test to see if there IS an intersection before doing the actual calculation
|
||||
if ( !pixelRectGeometry.isNull() && polyEngine->intersects( pixelRectGeometry.constGet() ) )
|
||||
{
|
||||
double intersectionArea = intersectGeometry.area();
|
||||
if ( intersectionArea >= 0.0 )
|
||||
//intersection
|
||||
QgsGeometry intersectGeometry = pixelRectGeometry.intersection( poly );
|
||||
if ( !intersectGeometry.isEmpty() )
|
||||
{
|
||||
weight = intersectionArea / pixelArea;
|
||||
stats.addValue( pixelValue, weight );
|
||||
double intersectionArea = intersectGeometry.area();
|
||||
if ( intersectionArea >= 0.0 )
|
||||
{
|
||||
weight = intersectionArea / pixelArea;
|
||||
stats.addValue( pixelValue, weight );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -41,6 +41,7 @@ class TestQgsZonalStatistics : public QObject
|
||||
void testStatistics();
|
||||
void testReprojection();
|
||||
void testNoData();
|
||||
void testSmallPolygons();
|
||||
|
||||
private:
|
||||
QgsVectorLayer *mVectorLayer = nullptr;
|
||||
@ -302,5 +303,45 @@ void TestQgsZonalStatistics::testNoData()
|
||||
QCOMPARE( f.attribute( "unsum" ).toDouble(), 0.0 );
|
||||
}
|
||||
|
||||
void TestQgsZonalStatistics::testSmallPolygons()
|
||||
{
|
||||
QString myDataPath( TEST_DATA_DIR ); //defined in CmakeLists.txt
|
||||
QString myTestDataPath = myDataPath + "/zonalstatistics/";
|
||||
|
||||
// test that zonal stats works ok with polygons much smaller than pixel size
|
||||
std::unique_ptr< QgsRasterLayer > rasterLayer = qgis::make_unique< QgsRasterLayer >( myTestDataPath + "raster.tif", QStringLiteral( "raster" ), QStringLiteral( "gdal" ) );
|
||||
std::unique_ptr< QgsVectorLayer > vectorLayer = qgis::make_unique< QgsVectorLayer >( mTempPath + "small_polys.shp", QStringLiteral( "poly" ), QStringLiteral( "ogr" ) );
|
||||
|
||||
QgsZonalStatistics zs( vectorLayer.get(), rasterLayer.get(), QStringLiteral( "n" ), 1, QgsZonalStatistics::All );
|
||||
zs.calculateStatistics( nullptr );
|
||||
|
||||
QgsFeature f;
|
||||
QgsFeatureRequest request;
|
||||
QgsFeatureIterator it = vectorLayer->getFeatures( request );
|
||||
bool fetched = it.nextFeature( f );
|
||||
QVERIFY( fetched );
|
||||
QGSCOMPARENEAR( f.attribute( "ncount" ).toDouble(), 0.698248, 0.001 );
|
||||
QGSCOMPARENEAR( f.attribute( "nsum" ).toDouble(), 588.711, 0.001 );
|
||||
QCOMPARE( f.attribute( "nmin" ).toDouble(), 826.0 );
|
||||
QCOMPARE( f.attribute( "nmax" ).toDouble(), 851.0 );
|
||||
QGSCOMPARENEAR( f.attribute( "nmean" ).toDouble(), 843.125292, 0.001 );
|
||||
|
||||
fetched = it.nextFeature( f );
|
||||
QVERIFY( fetched );
|
||||
QGSCOMPARENEAR( f.attribute( "ncount" ).toDouble(), 0.240808, 0.001 );
|
||||
QGSCOMPARENEAR( f.attribute( "nsum" ).toDouble(), 208.030921, 0.001 );
|
||||
QCOMPARE( f.attribute( "nmin" ).toDouble(), 859.0 );
|
||||
QCOMPARE( f.attribute( "nmax" ).toDouble(), 868.0 );
|
||||
QGSCOMPARENEAR( f.attribute( "nmean" ).toDouble(), 863.887500, 0.001 );
|
||||
|
||||
fetched = it.nextFeature( f );
|
||||
QVERIFY( fetched );
|
||||
QGSCOMPARENEAR( f.attribute( "ncount" ).toDouble(), 0.259522, 0.001 );
|
||||
QGSCOMPARENEAR( f.attribute( "nsum" ).toDouble(), 224.300747, 0.001 );
|
||||
QCOMPARE( f.attribute( "nmin" ).toDouble(), 851.0 );
|
||||
QCOMPARE( f.attribute( "nmax" ).toDouble(), 872.0 );
|
||||
QGSCOMPARENEAR( f.attribute( "nmean" ).toDouble(), 864.285638, 0.001 );
|
||||
}
|
||||
|
||||
QGSTEST_MAIN( TestQgsZonalStatistics )
|
||||
#include "testqgszonalstatistics.moc"
|
||||
|
1
tests/testdata/zonalstatistics/small_polys.cpg
vendored
Normal file
1
tests/testdata/zonalstatistics/small_polys.cpg
vendored
Normal file
@ -0,0 +1 @@
|
||||
UTF-8
|
BIN
tests/testdata/zonalstatistics/small_polys.dbf
vendored
Normal file
BIN
tests/testdata/zonalstatistics/small_polys.dbf
vendored
Normal file
Binary file not shown.
1
tests/testdata/zonalstatistics/small_polys.prj
vendored
Normal file
1
tests/testdata/zonalstatistics/small_polys.prj
vendored
Normal file
@ -0,0 +1 @@
|
||||
PROJCS["ED50_UTM_zone_30N",GEOGCS["GCS_European_1950",DATUM["D_European_1950",SPHEROID["International_1924",6378388,297]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]],PROJECTION["Transverse_Mercator"],PARAMETER["latitude_of_origin",0],PARAMETER["central_meridian",-3],PARAMETER["scale_factor",0.9996],PARAMETER["false_easting",500000],PARAMETER["false_northing",0],UNIT["Meter",1]]
|
1
tests/testdata/zonalstatistics/small_polys.qpj
vendored
Normal file
1
tests/testdata/zonalstatistics/small_polys.qpj
vendored
Normal file
@ -0,0 +1 @@
|
||||
PROJCS["ED50 / UTM zone 30N",GEOGCS["ED50",DATUM["European_Datum_1950",SPHEROID["International 1924",6378388,297,AUTHORITY["EPSG","7022"]],TOWGS84[-87,-98,-121,0,0,0,0],AUTHORITY["EPSG","6230"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4230"]],PROJECTION["Transverse_Mercator"],PARAMETER["latitude_of_origin",0],PARAMETER["central_meridian",-3],PARAMETER["scale_factor",0.9996],PARAMETER["false_easting",500000],PARAMETER["false_northing",0],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AXIS["Easting",EAST],AXIS["Northing",NORTH],AUTHORITY["EPSG","23030"]]
|
BIN
tests/testdata/zonalstatistics/small_polys.shp
vendored
Normal file
BIN
tests/testdata/zonalstatistics/small_polys.shp
vendored
Normal file
Binary file not shown.
BIN
tests/testdata/zonalstatistics/small_polys.shx
vendored
Normal file
BIN
tests/testdata/zonalstatistics/small_polys.shx
vendored
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user