Skip to content

Commit d57c182

Browse files
committedJan 21, 2019
Allow QgsRasterIterator to iterate over a raster layer, WITHOUT
actually fetching the raster block data This allows for efficient iteration over a "reference" layer, where you require the block extent/origin/pixel size/etc (but not the reference layer block data itself!), in order to fetch a block from a DIFFERENT set of rasters (but keeping these pixel-aligned to the reference raster).
1 parent b391c08 commit d57c182

File tree

4 files changed

+179
-2
lines changed

4 files changed

+179
-2
lines changed
 

‎python/core/auto_generated/raster/qgsrasteriterator.sip.in

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,28 @@ Start reading of raster band. Raster data can then be retrieved by calling readN
3333
:param nRows: number of rows
3434
:param extent: area to read
3535
:param feedback: optional raster feedback object for cancelation/preview. Added in QGIS 3.0.
36+
%End
37+
38+
bool next( int bandNumber, int &columns /Out/, int &rows /Out/, int &topLeftColumn /Out/, int &topLeftRow /Out/, QgsRectangle &blockExtent /Out/ );
39+
%Docstring
40+
Fetches details of the next part of the raster data. This method does NOT actually fetch the raster
41+
data itself, rather it calculates and iterates over the details of the raster alone.
42+
43+
It's useful for iterating over several layers using a target "reference" layer. E.g. summing
44+
the pixels in n rasters whilst aligning the result to a reference layer which is not being summed.
45+
46+
Note that calling this method also advances the iterator, just like calling readNextRasterPart().
47+
48+
:param bandNumber: band to read
49+
:param rows: number of rows on output device
50+
:param topLeftColumn: top left column
51+
:param topLeftRow: top left row
52+
:param blockExtent: exact extent of returned raster block
53+
54+
:return: - false if the last part was already returned
55+
- columns: number of columns on output device
56+
57+
.. versionadded:: 3.6
3658
%End
3759

3860
bool readNextRasterPart( int bandNumber,

‎src/core/raster/qgsrasteriterator.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,11 @@ void QgsRasterIterator::startRasterRead( int bandNumber, int nCols, int nRows, c
5757
mRasterPartInfos.insert( bandNumber, pInfo );
5858
}
5959

60+
bool QgsRasterIterator::next( int bandNumber, int &columns, int &rows, int &topLeftColumn, int &topLeftRow, QgsRectangle &blockExtent )
61+
{
62+
return readNextRasterPartInternal( bandNumber, columns, rows, nullptr, topLeftColumn, topLeftRow, &blockExtent );
63+
}
64+
6065
bool QgsRasterIterator::readNextRasterPart( int bandNumber,
6166
int &nCols, int &nRows,
6267
QgsRasterBlock **block,
@@ -71,9 +76,15 @@ bool QgsRasterIterator::readNextRasterPart( int bandNumber,
7176
}
7277

7378
bool QgsRasterIterator::readNextRasterPart( int bandNumber, int &nCols, int &nRows, std::unique_ptr<QgsRasterBlock> &block, int &topLeftCol, int &topLeftRow, QgsRectangle *blockExtent )
79+
{
80+
return readNextRasterPartInternal( bandNumber, nCols, nRows, &block, topLeftCol, topLeftRow, blockExtent );
81+
}
82+
83+
bool QgsRasterIterator::readNextRasterPartInternal( int bandNumber, int &nCols, int &nRows, std::unique_ptr<QgsRasterBlock> *block, int &topLeftCol, int &topLeftRow, QgsRectangle *blockExtent )
7484
{
7585
QgsDebugMsgLevel( QStringLiteral( "Entered" ), 4 );
76-
block.reset();
86+
if ( block )
87+
block->reset();
7788
//get partinfo
7889
QMap<int, RasterPartInfo>::iterator partIt = mRasterPartInfos.find( bandNumber );
7990
if ( partIt == mRasterPartInfos.end() )
@@ -115,7 +126,8 @@ bool QgsRasterIterator::readNextRasterPart( int bandNumber, int &nCols, int &nRo
115126
if ( blockExtent )
116127
*blockExtent = blockRect;
117128

118-
block.reset( mInput->block( bandNumber, blockRect, nCols, nRows, mFeedback ) );
129+
if ( block )
130+
block->reset( mInput->block( bandNumber, blockRect, nCols, nRows, mFeedback ) );
119131
topLeftCol = pInfo.currentCol;
120132
topLeftRow = pInfo.currentRow;
121133

‎src/core/raster/qgsrasteriterator.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,27 @@ class CORE_EXPORT QgsRasterIterator
4949
*/
5050
void startRasterRead( int bandNumber, int nCols, int nRows, const QgsRectangle &extent, QgsRasterBlockFeedback *feedback = nullptr );
5151

52+
/**
53+
* Fetches details of the next part of the raster data. This method does NOT actually fetch the raster
54+
* data itself, rather it calculates and iterates over the details of the raster alone.
55+
*
56+
* It's useful for iterating over several layers using a target "reference" layer. E.g. summing
57+
* the pixels in n rasters whilst aligning the result to a reference layer which is not being summed.
58+
*
59+
* Note that calling this method also advances the iterator, just like calling readNextRasterPart().
60+
*
61+
* \param bandNumber band to read
62+
* \param columns number of columns on output device
63+
* \param rows number of rows on output device
64+
* \param topLeftColumn top left column
65+
* \param topLeftRow top left row
66+
* \param blockExtent exact extent of returned raster block
67+
* \returns false if the last part was already returned
68+
*
69+
* \since QGIS 3.6
70+
*/
71+
bool next( int bandNumber, int &columns SIP_OUT, int &rows SIP_OUT, int &topLeftColumn SIP_OUT, int &topLeftRow SIP_OUT, QgsRectangle &blockExtent SIP_OUT );
72+
5273
/**
5374
* Fetches next part of raster data, caller takes ownership of the block and
5475
* caller should delete the block.
@@ -148,6 +169,7 @@ class CORE_EXPORT QgsRasterIterator
148169

149170
//! Remove part into and release memory
150171
void removePartInfo( int bandNumber );
172+
bool readNextRasterPartInternal( int bandNumber, int &nCols, int &nRows, std::unique_ptr<QgsRasterBlock> *block, int &topLeftCol, int &topLeftRow, QgsRectangle *blockExtent );
151173
};
152174

153175
#endif // QGSRASTERITERATOR_H

‎tests/src/core/testqgsrasteriterator.cpp

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ class TestQgsRasterIterator : public QObject
3939
void cleanup() {} // will be called after every testfunction.
4040

4141
void testBasic();
42+
void testNoBlock();
4243

4344
private:
4445

@@ -232,6 +233,126 @@ void TestQgsRasterIterator::testBasic()
232233
QVERIFY( !block.get() );
233234
}
234235

236+
void TestQgsRasterIterator::testNoBlock()
237+
{
238+
// test iterating with no block
239+
QgsRasterDataProvider *provider = mpRasterLayer->dataProvider();
240+
QVERIFY( provider );
241+
QgsRasterIterator it( provider );
242+
243+
QCOMPARE( it.input(), provider );
244+
245+
it.setMaximumTileHeight( 2500 );
246+
QCOMPARE( it.maximumTileHeight(), 2500 );
247+
248+
it.setMaximumTileWidth( 3000 );
249+
QCOMPARE( it.maximumTileWidth(), 3000 );
250+
251+
it.startRasterRead( 1, mpRasterLayer->width(), mpRasterLayer->height(), mpRasterLayer->extent() );
252+
253+
int nCols;
254+
int nRows;
255+
int topLeftCol;
256+
int topLeftRow;
257+
QgsRectangle blockExtent;
258+
259+
QVERIFY( it.next( 1, nCols, nRows, topLeftCol, topLeftRow, blockExtent ) );
260+
QCOMPARE( nCols, 3000 );
261+
QCOMPARE( nRows, 2500 );
262+
QCOMPARE( topLeftCol, 0 );
263+
QCOMPARE( topLeftRow, 0 );
264+
QCOMPARE( blockExtent.xMinimum(), 497470.0 );
265+
QCOMPARE( blockExtent.xMaximum(), 497770.0 );
266+
QCOMPARE( blockExtent.yMinimum(), 7050880.0 );
267+
QCOMPARE( blockExtent.yMaximum(), 7051130.0 );
268+
QCOMPARE( blockExtent.xMinimum(), mpRasterLayer->extent().xMinimum() + topLeftCol * mpRasterLayer->rasterUnitsPerPixelX() );
269+
QCOMPARE( blockExtent.yMinimum(), mpRasterLayer->extent().yMaximum() - nRows * mpRasterLayer->rasterUnitsPerPixelY() );
270+
QCOMPARE( blockExtent.width(), nCols * mpRasterLayer->rasterUnitsPerPixelX() );
271+
QCOMPARE( blockExtent.height(), nRows * mpRasterLayer->rasterUnitsPerPixelY() );
272+
273+
QVERIFY( it.next( 1, nCols, nRows, topLeftCol, topLeftRow, blockExtent ) );
274+
QCOMPARE( nCols, 3000 );
275+
QCOMPARE( nRows, 2500 );
276+
QCOMPARE( topLeftCol, 3000 );
277+
QCOMPARE( topLeftRow, 0 );
278+
QCOMPARE( blockExtent.xMinimum(), mpRasterLayer->extent().xMinimum() + topLeftCol * mpRasterLayer->rasterUnitsPerPixelX() );
279+
QCOMPARE( blockExtent.yMinimum(), mpRasterLayer->extent().yMaximum() - nRows * mpRasterLayer->rasterUnitsPerPixelY() );
280+
QCOMPARE( blockExtent.width(), nCols * mpRasterLayer->rasterUnitsPerPixelX() );
281+
QCOMPARE( blockExtent.height(), nRows * mpRasterLayer->rasterUnitsPerPixelY() );
282+
283+
QVERIFY( it.next( 1, nCols, nRows, topLeftCol, topLeftRow, blockExtent ) );
284+
QCOMPARE( nCols, 1200 );
285+
QCOMPARE( nRows, 2500 );
286+
QCOMPARE( topLeftCol, 6000 );
287+
QCOMPARE( topLeftRow, 0 );
288+
QCOMPARE( blockExtent.xMinimum(), mpRasterLayer->extent().xMinimum() + topLeftCol * mpRasterLayer->rasterUnitsPerPixelX() );
289+
QCOMPARE( blockExtent.yMinimum(), mpRasterLayer->extent().yMaximum() - nRows * mpRasterLayer->rasterUnitsPerPixelY() );
290+
QCOMPARE( blockExtent.width(), nCols * mpRasterLayer->rasterUnitsPerPixelX() );
291+
QCOMPARE( blockExtent.height(), nRows * mpRasterLayer->rasterUnitsPerPixelY() );
292+
293+
QVERIFY( it.next( 1, nCols, nRows, topLeftCol, topLeftRow, blockExtent ) );
294+
QCOMPARE( nCols, 3000 );
295+
QCOMPARE( nRows, 2500 );
296+
QCOMPARE( topLeftCol, 0 );
297+
QCOMPARE( topLeftRow, 2500 );
298+
QCOMPARE( blockExtent.xMinimum(), mpRasterLayer->extent().xMinimum() + topLeftCol * mpRasterLayer->rasterUnitsPerPixelX() );
299+
QCOMPARE( blockExtent.yMinimum(), mpRasterLayer->extent().yMaximum() - ( nRows + topLeftRow )* mpRasterLayer->rasterUnitsPerPixelY() );
300+
QCOMPARE( blockExtent.width(), nCols * mpRasterLayer->rasterUnitsPerPixelX() );
301+
QCOMPARE( blockExtent.height(), nRows * mpRasterLayer->rasterUnitsPerPixelY() );
302+
303+
QVERIFY( it.next( 1, nCols, nRows, topLeftCol, topLeftRow, blockExtent ) );
304+
QCOMPARE( nCols, 3000 );
305+
QCOMPARE( nRows, 2500 );
306+
QCOMPARE( topLeftCol, 3000 );
307+
QCOMPARE( topLeftRow, 2500 );
308+
QCOMPARE( blockExtent.xMinimum(), mpRasterLayer->extent().xMinimum() + topLeftCol * mpRasterLayer->rasterUnitsPerPixelX() );
309+
QCOMPARE( blockExtent.yMinimum(), mpRasterLayer->extent().yMaximum() - ( nRows + topLeftRow )* mpRasterLayer->rasterUnitsPerPixelY() );
310+
QCOMPARE( blockExtent.width(), nCols * mpRasterLayer->rasterUnitsPerPixelX() );
311+
QCOMPARE( blockExtent.height(), nRows * mpRasterLayer->rasterUnitsPerPixelY() );
312+
313+
QVERIFY( it.next( 1, nCols, nRows, topLeftCol, topLeftRow, blockExtent ) );
314+
QCOMPARE( nCols, 1200 );
315+
QCOMPARE( nRows, 2500 );
316+
QCOMPARE( topLeftCol, 6000 );
317+
QCOMPARE( topLeftRow, 2500 );
318+
QCOMPARE( blockExtent.xMinimum(), mpRasterLayer->extent().xMinimum() + topLeftCol * mpRasterLayer->rasterUnitsPerPixelX() );
319+
QCOMPARE( blockExtent.yMinimum(), mpRasterLayer->extent().yMaximum() - ( nRows + topLeftRow )* mpRasterLayer->rasterUnitsPerPixelY() );
320+
QCOMPARE( blockExtent.width(), nCols * mpRasterLayer->rasterUnitsPerPixelX() );
321+
QCOMPARE( blockExtent.height(), nRows * mpRasterLayer->rasterUnitsPerPixelY() );
322+
323+
QVERIFY( it.next( 1, nCols, nRows, topLeftCol, topLeftRow, blockExtent ) );
324+
QCOMPARE( nCols, 3000 );
325+
QCOMPARE( nRows, 450 );
326+
QCOMPARE( topLeftCol, 0 );
327+
QCOMPARE( topLeftRow, 5000 );
328+
QCOMPARE( blockExtent.xMinimum(), mpRasterLayer->extent().xMinimum() + topLeftCol * mpRasterLayer->rasterUnitsPerPixelX() );
329+
QCOMPARE( blockExtent.yMinimum(), mpRasterLayer->extent().yMaximum() - ( nRows + topLeftRow )* mpRasterLayer->rasterUnitsPerPixelY() );
330+
QCOMPARE( blockExtent.width(), nCols * mpRasterLayer->rasterUnitsPerPixelX() );
331+
QCOMPARE( blockExtent.height(), nRows * mpRasterLayer->rasterUnitsPerPixelY() );
332+
333+
QVERIFY( it.next( 1, nCols, nRows, topLeftCol, topLeftRow, blockExtent ) );
334+
QCOMPARE( nCols, 3000 );
335+
QCOMPARE( nRows, 450 );
336+
QCOMPARE( topLeftCol, 3000 );
337+
QCOMPARE( topLeftRow, 5000 );
338+
QCOMPARE( blockExtent.xMinimum(), mpRasterLayer->extent().xMinimum() + topLeftCol * mpRasterLayer->rasterUnitsPerPixelX() );
339+
QCOMPARE( blockExtent.yMinimum(), mpRasterLayer->extent().yMaximum() - ( nRows + topLeftRow )* mpRasterLayer->rasterUnitsPerPixelY() );
340+
QCOMPARE( blockExtent.width(), nCols * mpRasterLayer->rasterUnitsPerPixelX() );
341+
QCOMPARE( blockExtent.height(), nRows * mpRasterLayer->rasterUnitsPerPixelY() );
342+
343+
QVERIFY( it.next( 1, nCols, nRows, topLeftCol, topLeftRow, blockExtent ) );
344+
QCOMPARE( nCols, 1200 );
345+
QCOMPARE( nRows, 450 );
346+
QCOMPARE( topLeftCol, 6000 );
347+
QCOMPARE( topLeftRow, 5000 );
348+
QCOMPARE( blockExtent.xMinimum(), mpRasterLayer->extent().xMinimum() + topLeftCol * mpRasterLayer->rasterUnitsPerPixelX() );
349+
QCOMPARE( blockExtent.yMinimum(), mpRasterLayer->extent().yMaximum() - ( nRows + topLeftRow )* mpRasterLayer->rasterUnitsPerPixelY() );
350+
QCOMPARE( blockExtent.width(), nCols * mpRasterLayer->rasterUnitsPerPixelX() );
351+
QCOMPARE( blockExtent.height(), nRows * mpRasterLayer->rasterUnitsPerPixelY() );
352+
353+
QVERIFY( !it.next( 1, nCols, nRows, topLeftCol, topLeftRow, blockExtent ) );
354+
}
355+
235356

236357
QGSTEST_MAIN( TestQgsRasterIterator )
237358

0 commit comments

Comments
 (0)
Please sign in to comment.