Skip to content
Permalink
Browse files

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)
  • Loading branch information
nyalldawson committed Jun 8, 2018
1 parent 43d8567 commit ff9e7ba3289d288bd8e8da9b83926a4d98f105cd
Showing with 11 additions and 3 deletions.
  1. +11 −3 src/analysis/vector/qgszonalstatistics.cpp
@@ -444,6 +444,13 @@ void QgsZonalStatistics::statisticsFromPreciseIntersection( const QgsGeometry &p
QgsRectangle featureBBox = poly.boundingBox().intersect( &rasterBBox );
QgsRectangle intersectBBox = rasterBBox.intersect( &featureBBox );

std::unique_ptr< QgsGeometryEngine > polyEngine( QgsGeometry::createGeometryEngine( poly.constGet( ) ) );
if ( !polyEngine )
{
return;
}
polyEngine->prepareGeometry();

std::unique_ptr< QgsRasterBlock > block( mRasterProvider->block( mRasterBand, intersectBBox, nCellsX, nCellsY ) );
for ( int i = 0; i < nCellsY; ++i )
{
@@ -457,11 +464,13 @@ void QgsZonalStatistics::statisticsFromPreciseIntersection( const QgsGeometry &p
}

pixelRectGeometry = QgsGeometry::fromRect( QgsRectangle( currentX - hCellSizeX, currentY - hCellSizeY, currentX + hCellSizeX, currentY + hCellSizeY ) );
if ( !pixelRectGeometry.isNull() )
// 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.isNull() )
if ( !intersectGeometry.isEmpty() )
{
double intersectionArea = intersectGeometry.area();
if ( intersectionArea >= 0.0 )
@@ -470,7 +479,6 @@ void QgsZonalStatistics::statisticsFromPreciseIntersection( const QgsGeometry &p
stats.addValue( pixelValue, weight );
}
}
pixelRectGeometry = QgsGeometry();
}
currentX += cellSizeX;
}

0 comments on commit ff9e7ba

Please sign in to comment.
You can’t perform that action at this time.