Skip to content

Commit ff9e7ba

Browse files
committed
Use prepared geometries to check for intersection between
pixel rectangles and polygons when doing exact statistics calculations in zonal stats Sppeds up zonal stats calculation by ~10x when pixel size is large (compared to polygon sizes)
1 parent 43d8567 commit ff9e7ba

File tree

1 file changed

+11
-3
lines changed

1 file changed

+11
-3
lines changed

src/analysis/vector/qgszonalstatistics.cpp

+11-3
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,13 @@ void QgsZonalStatistics::statisticsFromPreciseIntersection( const QgsGeometry &p
444444
QgsRectangle featureBBox = poly.boundingBox().intersect( &rasterBBox );
445445
QgsRectangle intersectBBox = rasterBBox.intersect( &featureBBox );
446446

447+
std::unique_ptr< QgsGeometryEngine > polyEngine( QgsGeometry::createGeometryEngine( poly.constGet( ) ) );
448+
if ( !polyEngine )
449+
{
450+
return;
451+
}
452+
polyEngine->prepareGeometry();
453+
447454
std::unique_ptr< QgsRasterBlock > block( mRasterProvider->block( mRasterBand, intersectBBox, nCellsX, nCellsY ) );
448455
for ( int i = 0; i < nCellsY; ++i )
449456
{
@@ -457,11 +464,13 @@ void QgsZonalStatistics::statisticsFromPreciseIntersection( const QgsGeometry &p
457464
}
458465

459466
pixelRectGeometry = QgsGeometry::fromRect( QgsRectangle( currentX - hCellSizeX, currentY - hCellSizeY, currentX + hCellSizeX, currentY + hCellSizeY ) );
460-
if ( !pixelRectGeometry.isNull() )
467+
// GEOS intersects tests on prepared geometry is MAGNITUDES faster than calculating the intersection itself,
468+
// so we first test to see if there IS an intersection before doing the actual calculation
469+
if ( !pixelRectGeometry.isNull() && polyEngine->intersects( pixelRectGeometry.constGet() ) )
461470
{
462471
//intersection
463472
QgsGeometry intersectGeometry = pixelRectGeometry.intersection( poly );
464-
if ( !intersectGeometry.isNull() )
473+
if ( !intersectGeometry.isEmpty() )
465474
{
466475
double intersectionArea = intersectGeometry.area();
467476
if ( intersectionArea >= 0.0 )
@@ -470,7 +479,6 @@ void QgsZonalStatistics::statisticsFromPreciseIntersection( const QgsGeometry &p
470479
stats.addValue( pixelValue, weight );
471480
}
472481
}
473-
pixelRectGeometry = QgsGeometry();
474482
}
475483
currentX += cellSizeX;
476484
}

0 commit comments

Comments
 (0)