Skip to content

Commit 0bc3870

Browse files
author
mhugent
committed
Added a slightly faster zonal statistics method (but still not as fast as it could be)
git-svn-id: http://svn.osgeo.org/qgis/trunk@13012 c8812cc2-4d05-0410-92ff-de0c093fc19c
1 parent f921dc4 commit 0bc3870

File tree

2 files changed

+124
-2
lines changed

2 files changed

+124
-2
lines changed

src/analysis/vector/qgszonalstatistics.cpp

+121-2
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ int QgsZonalStatistics::calculateStatistics( QProgressDialog* p )
137137

138138
while ( vectorProvider->nextFeature( f ) )
139139
{
140+
qWarning( QString::number( featureCounter ).toLocal8Bit().data() );
140141
if ( p )
141142
{
142143
p->setValue( featureCounter );
@@ -161,8 +162,8 @@ int QgsZonalStatistics::calculateStatistics( QProgressDialog* p )
161162
continue;
162163
}
163164

164-
statisticsFromMiddlePointTest( rasterBand, featureGeometry, offsetX, offsetY, nCellsX, nCellsY, cellsizeX, cellsizeY, \
165-
rasterBBox, sum, count );
165+
statisticsFromMiddlePointTest_improved( rasterBand, featureGeometry, offsetX, offsetY, nCellsX, nCellsY, cellsizeX, cellsizeY, \
166+
rasterBBox, sum, count );
166167

167168
if ( count <= 1 )
168169
{
@@ -304,6 +305,124 @@ void QgsZonalStatistics::statisticsFromPreciseIntersection( void* band, QgsGeome
304305
CPLFree( pixelData );
305306
}
306307

308+
void QgsZonalStatistics::statisticsFromMiddlePointTest_improved( void* band, QgsGeometry* poly, int pixelOffsetX, int pixelOffsetY, int nCellsX, int nCellsY, \
309+
double cellSizeX, double cellSizeY, const QgsRectangle& rasterBBox, double& sum, double& count )
310+
{
311+
double cellCenterX, cellCenterY;
312+
QgsPoint currentCellCenter;
313+
314+
float* scanLine = ( float * ) CPLMalloc( sizeof( float ) * nCellsX );
315+
cellCenterY = rasterBBox.yMaximum() - pixelOffsetY * cellSizeY - cellSizeY / 2;
316+
count = 0;
317+
sum = 0;
318+
319+
for ( int i = 0; i < nCellsY; ++i )
320+
{
321+
GDALRasterIO( band, GF_Read, pixelOffsetX, pixelOffsetY + i, nCellsX, 1, scanLine, nCellsX, 1, GDT_Float32, 0, 0 );
322+
cellCenterX = rasterBBox.xMinimum() + pixelOffsetX * cellSizeX + cellSizeX / 2;
323+
324+
//do intersection of scanline with geometry
325+
GEOSCoordSequence* scanLineSequence = GEOSCoordSeq_create( 2, 2 );
326+
GEOSCoordSeq_setX( scanLineSequence, 0, cellCenterX );
327+
GEOSCoordSeq_setY( scanLineSequence, 0, cellCenterY );
328+
GEOSCoordSeq_setX( scanLineSequence, 1, cellCenterX + nCellsX * cellSizeX );
329+
GEOSCoordSeq_setY( scanLineSequence, 1, cellCenterY );
330+
GEOSGeometry* scanLineGeos = GEOSGeom_createLineString( scanLineSequence ); //todo: delete
331+
GEOSGeometry* polyGeos = poly->asGeos();
332+
GEOSGeometry* scanLineIntersection = GEOSIntersection( scanLineGeos, polyGeos );
333+
GEOSGeom_destroy( scanLineGeos );
334+
if ( !scanLineIntersection )
335+
{
336+
cellCenterY -= cellSizeY;
337+
continue;
338+
}
339+
340+
//debug
341+
char* scanLineIntersectionType = GEOSGeomType( scanLineIntersection );
342+
343+
int numGeoms = GEOSGetNumGeometries( scanLineIntersection );
344+
if ( numGeoms < 1 )
345+
{
346+
GEOSGeom_destroy( scanLineIntersection );
347+
cellCenterY -= cellSizeY;
348+
continue;
349+
}
350+
351+
QList<double> scanLineList;
352+
double currentValue;
353+
GEOSGeometry* currentGeom = 0;
354+
for ( int z = 0; z < numGeoms; ++z )
355+
{
356+
if ( numGeoms == 1 )
357+
{
358+
currentGeom = scanLineIntersection;
359+
}
360+
else
361+
{
362+
currentGeom = GEOSGeom_clone( GEOSGetGeometryN( scanLineIntersection, z ) );
363+
}
364+
const GEOSCoordSequence* scanLineCoordSequence = GEOSGeom_getCoordSeq( currentGeom );
365+
if ( !scanLineCoordSequence )
366+
{
367+
//error
368+
}
369+
unsigned int scanLineIntersectionSize;
370+
GEOSCoordSeq_getSize( scanLineCoordSequence, &scanLineIntersectionSize );
371+
if ( !scanLineCoordSequence || scanLineIntersectionSize < 2 || ( scanLineIntersectionSize & 1 ) )
372+
{
373+
//error
374+
}
375+
for ( int k = 0; k < scanLineIntersectionSize; ++k )
376+
{
377+
GEOSCoordSeq_getX( scanLineCoordSequence, k, &currentValue );
378+
scanLineList.push_back( currentValue );
379+
}
380+
381+
if ( numGeoms != 1 )
382+
{
383+
GEOSGeom_destroy( currentGeom );
384+
}
385+
}
386+
GEOSGeom_destroy( scanLineIntersection );
387+
qSort( scanLineList );
388+
389+
if ( scanLineList.size() < 1 )
390+
{
391+
cellCenterY -= cellSizeY;
392+
continue;
393+
}
394+
395+
int listPlace = -1;
396+
for ( int j = 0; j < nCellsX; ++j )
397+
{
398+
//currentCellCenter = QgsPoint( cellCenterX, cellCenterY );
307399

400+
//instead of doing a contained test every time, find the place of scanLineList and check if even / odd
401+
if ( listPlace >= scanLineList.size() - 1 )
402+
{
403+
break;
404+
}
405+
if ( cellCenterX >= scanLineList.at( listPlace + 1 ) )
406+
{
407+
++listPlace;
408+
if ( listPlace >= scanLineList.size() )
409+
{
410+
break;
411+
}
412+
}
413+
if ( listPlace >= 0 && listPlace < ( scanLineList.size() - 1 ) && !( listPlace & 1 ) )
414+
{
415+
if ( scanLine[j] != mInputNodataValue ) //don't consider nodata values
416+
{
417+
sum += scanLine[j];
418+
++count;
419+
}
420+
}
421+
cellCenterX += cellSizeX;
422+
}
423+
cellCenterY -= cellSizeY;
424+
}
425+
CPLFree( scanLine );
426+
}
308427

309428

src/analysis/vector/qgszonalstatistics.h

+3
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ class ANALYSIS_EXPORT QgsZonalStatistics
4747
void statisticsFromMiddlePointTest( void* band, QgsGeometry* poly, int pixelOffsetX, int pixelOffsetY, int nCellsX, int nCellsY, \
4848
double cellSizeX, double cellSizeY, const QgsRectangle& rasterBBox, double& sum, double& count );
4949

50+
void statisticsFromMiddlePointTest_improved( void* band, QgsGeometry* poly, int pixelOffsetX, int pixelOffsetY, int nCellsX, int nCellsY, \
51+
double cellSizeX, double cellSizeY, const QgsRectangle& rasterBBox, double& sum, double& count );
52+
5053
/**Returns statistics with precise pixel - polygon intersection test (slow) */
5154
void statisticsFromPreciseIntersection( void* band, QgsGeometry* poly, int pixelOffsetX, int pixelOffsetY, int nCellsX, int nCellsY, \
5255
double cellSizeX, double cellSizeY, const QgsRectangle& rasterBBox, double& sum, double& count );

0 commit comments

Comments
 (0)