@@ -137,6 +137,7 @@ int QgsZonalStatistics::calculateStatistics( QProgressDialog* p )
137
137
138
138
while ( vectorProvider->nextFeature ( f ) )
139
139
{
140
+ qWarning ( QString::number ( featureCounter ).toLocal8Bit ().data () );
140
141
if ( p )
141
142
{
142
143
p->setValue ( featureCounter );
@@ -161,8 +162,8 @@ int QgsZonalStatistics::calculateStatistics( QProgressDialog* p )
161
162
continue ;
162
163
}
163
164
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 );
166
167
167
168
if ( count <= 1 )
168
169
{
@@ -304,6 +305,124 @@ void QgsZonalStatistics::statisticsFromPreciseIntersection( void* band, QgsGeome
304
305
CPLFree ( pixelData );
305
306
}
306
307
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, ¤tValue );
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 );
307
399
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
+ }
308
427
309
428
0 commit comments