mirror of
https://github.com/qgis/QGIS.git
synced 2025-02-25 00:58:06 -05:00
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).
This commit is contained in:
parent
b391c0876f
commit
d57c182d8b
@ -33,6 +33,28 @@ Start reading of raster band. Raster data can then be retrieved by calling readN
|
||||
:param nRows: number of rows
|
||||
:param extent: area to read
|
||||
:param feedback: optional raster feedback object for cancelation/preview. Added in QGIS 3.0.
|
||||
%End
|
||||
|
||||
bool next( int bandNumber, int &columns /Out/, int &rows /Out/, int &topLeftColumn /Out/, int &topLeftRow /Out/, QgsRectangle &blockExtent /Out/ );
|
||||
%Docstring
|
||||
Fetches details of the next part of the raster data. This method does NOT actually fetch the raster
|
||||
data itself, rather it calculates and iterates over the details of the raster alone.
|
||||
|
||||
It's useful for iterating over several layers using a target "reference" layer. E.g. summing
|
||||
the pixels in n rasters whilst aligning the result to a reference layer which is not being summed.
|
||||
|
||||
Note that calling this method also advances the iterator, just like calling readNextRasterPart().
|
||||
|
||||
:param bandNumber: band to read
|
||||
:param rows: number of rows on output device
|
||||
:param topLeftColumn: top left column
|
||||
:param topLeftRow: top left row
|
||||
:param blockExtent: exact extent of returned raster block
|
||||
|
||||
:return: - false if the last part was already returned
|
||||
- columns: number of columns on output device
|
||||
|
||||
.. versionadded:: 3.6
|
||||
%End
|
||||
|
||||
bool readNextRasterPart( int bandNumber,
|
||||
|
@ -57,6 +57,11 @@ void QgsRasterIterator::startRasterRead( int bandNumber, int nCols, int nRows, c
|
||||
mRasterPartInfos.insert( bandNumber, pInfo );
|
||||
}
|
||||
|
||||
bool QgsRasterIterator::next( int bandNumber, int &columns, int &rows, int &topLeftColumn, int &topLeftRow, QgsRectangle &blockExtent )
|
||||
{
|
||||
return readNextRasterPartInternal( bandNumber, columns, rows, nullptr, topLeftColumn, topLeftRow, &blockExtent );
|
||||
}
|
||||
|
||||
bool QgsRasterIterator::readNextRasterPart( int bandNumber,
|
||||
int &nCols, int &nRows,
|
||||
QgsRasterBlock **block,
|
||||
@ -71,9 +76,15 @@ bool QgsRasterIterator::readNextRasterPart( int bandNumber,
|
||||
}
|
||||
|
||||
bool QgsRasterIterator::readNextRasterPart( int bandNumber, int &nCols, int &nRows, std::unique_ptr<QgsRasterBlock> &block, int &topLeftCol, int &topLeftRow, QgsRectangle *blockExtent )
|
||||
{
|
||||
return readNextRasterPartInternal( bandNumber, nCols, nRows, &block, topLeftCol, topLeftRow, blockExtent );
|
||||
}
|
||||
|
||||
bool QgsRasterIterator::readNextRasterPartInternal( int bandNumber, int &nCols, int &nRows, std::unique_ptr<QgsRasterBlock> *block, int &topLeftCol, int &topLeftRow, QgsRectangle *blockExtent )
|
||||
{
|
||||
QgsDebugMsgLevel( QStringLiteral( "Entered" ), 4 );
|
||||
block.reset();
|
||||
if ( block )
|
||||
block->reset();
|
||||
//get partinfo
|
||||
QMap<int, RasterPartInfo>::iterator partIt = mRasterPartInfos.find( bandNumber );
|
||||
if ( partIt == mRasterPartInfos.end() )
|
||||
@ -115,7 +126,8 @@ bool QgsRasterIterator::readNextRasterPart( int bandNumber, int &nCols, int &nRo
|
||||
if ( blockExtent )
|
||||
*blockExtent = blockRect;
|
||||
|
||||
block.reset( mInput->block( bandNumber, blockRect, nCols, nRows, mFeedback ) );
|
||||
if ( block )
|
||||
block->reset( mInput->block( bandNumber, blockRect, nCols, nRows, mFeedback ) );
|
||||
topLeftCol = pInfo.currentCol;
|
||||
topLeftRow = pInfo.currentRow;
|
||||
|
||||
|
@ -49,6 +49,27 @@ class CORE_EXPORT QgsRasterIterator
|
||||
*/
|
||||
void startRasterRead( int bandNumber, int nCols, int nRows, const QgsRectangle &extent, QgsRasterBlockFeedback *feedback = nullptr );
|
||||
|
||||
/**
|
||||
* Fetches details of the next part of the raster data. This method does NOT actually fetch the raster
|
||||
* data itself, rather it calculates and iterates over the details of the raster alone.
|
||||
*
|
||||
* It's useful for iterating over several layers using a target "reference" layer. E.g. summing
|
||||
* the pixels in n rasters whilst aligning the result to a reference layer which is not being summed.
|
||||
*
|
||||
* Note that calling this method also advances the iterator, just like calling readNextRasterPart().
|
||||
*
|
||||
* \param bandNumber band to read
|
||||
* \param columns number of columns on output device
|
||||
* \param rows number of rows on output device
|
||||
* \param topLeftColumn top left column
|
||||
* \param topLeftRow top left row
|
||||
* \param blockExtent exact extent of returned raster block
|
||||
* \returns false if the last part was already returned
|
||||
*
|
||||
* \since QGIS 3.6
|
||||
*/
|
||||
bool next( int bandNumber, int &columns SIP_OUT, int &rows SIP_OUT, int &topLeftColumn SIP_OUT, int &topLeftRow SIP_OUT, QgsRectangle &blockExtent SIP_OUT );
|
||||
|
||||
/**
|
||||
* Fetches next part of raster data, caller takes ownership of the block and
|
||||
* caller should delete the block.
|
||||
@ -148,6 +169,7 @@ class CORE_EXPORT QgsRasterIterator
|
||||
|
||||
//! Remove part into and release memory
|
||||
void removePartInfo( int bandNumber );
|
||||
bool readNextRasterPartInternal( int bandNumber, int &nCols, int &nRows, std::unique_ptr<QgsRasterBlock> *block, int &topLeftCol, int &topLeftRow, QgsRectangle *blockExtent );
|
||||
};
|
||||
|
||||
#endif // QGSRASTERITERATOR_H
|
||||
|
@ -39,6 +39,7 @@ class TestQgsRasterIterator : public QObject
|
||||
void cleanup() {} // will be called after every testfunction.
|
||||
|
||||
void testBasic();
|
||||
void testNoBlock();
|
||||
|
||||
private:
|
||||
|
||||
@ -232,6 +233,126 @@ void TestQgsRasterIterator::testBasic()
|
||||
QVERIFY( !block.get() );
|
||||
}
|
||||
|
||||
void TestQgsRasterIterator::testNoBlock()
|
||||
{
|
||||
// test iterating with no block
|
||||
QgsRasterDataProvider *provider = mpRasterLayer->dataProvider();
|
||||
QVERIFY( provider );
|
||||
QgsRasterIterator it( provider );
|
||||
|
||||
QCOMPARE( it.input(), provider );
|
||||
|
||||
it.setMaximumTileHeight( 2500 );
|
||||
QCOMPARE( it.maximumTileHeight(), 2500 );
|
||||
|
||||
it.setMaximumTileWidth( 3000 );
|
||||
QCOMPARE( it.maximumTileWidth(), 3000 );
|
||||
|
||||
it.startRasterRead( 1, mpRasterLayer->width(), mpRasterLayer->height(), mpRasterLayer->extent() );
|
||||
|
||||
int nCols;
|
||||
int nRows;
|
||||
int topLeftCol;
|
||||
int topLeftRow;
|
||||
QgsRectangle blockExtent;
|
||||
|
||||
QVERIFY( it.next( 1, nCols, nRows, topLeftCol, topLeftRow, blockExtent ) );
|
||||
QCOMPARE( nCols, 3000 );
|
||||
QCOMPARE( nRows, 2500 );
|
||||
QCOMPARE( topLeftCol, 0 );
|
||||
QCOMPARE( topLeftRow, 0 );
|
||||
QCOMPARE( blockExtent.xMinimum(), 497470.0 );
|
||||
QCOMPARE( blockExtent.xMaximum(), 497770.0 );
|
||||
QCOMPARE( blockExtent.yMinimum(), 7050880.0 );
|
||||
QCOMPARE( blockExtent.yMaximum(), 7051130.0 );
|
||||
QCOMPARE( blockExtent.xMinimum(), mpRasterLayer->extent().xMinimum() + topLeftCol * mpRasterLayer->rasterUnitsPerPixelX() );
|
||||
QCOMPARE( blockExtent.yMinimum(), mpRasterLayer->extent().yMaximum() - nRows * mpRasterLayer->rasterUnitsPerPixelY() );
|
||||
QCOMPARE( blockExtent.width(), nCols * mpRasterLayer->rasterUnitsPerPixelX() );
|
||||
QCOMPARE( blockExtent.height(), nRows * mpRasterLayer->rasterUnitsPerPixelY() );
|
||||
|
||||
QVERIFY( it.next( 1, nCols, nRows, topLeftCol, topLeftRow, blockExtent ) );
|
||||
QCOMPARE( nCols, 3000 );
|
||||
QCOMPARE( nRows, 2500 );
|
||||
QCOMPARE( topLeftCol, 3000 );
|
||||
QCOMPARE( topLeftRow, 0 );
|
||||
QCOMPARE( blockExtent.xMinimum(), mpRasterLayer->extent().xMinimum() + topLeftCol * mpRasterLayer->rasterUnitsPerPixelX() );
|
||||
QCOMPARE( blockExtent.yMinimum(), mpRasterLayer->extent().yMaximum() - nRows * mpRasterLayer->rasterUnitsPerPixelY() );
|
||||
QCOMPARE( blockExtent.width(), nCols * mpRasterLayer->rasterUnitsPerPixelX() );
|
||||
QCOMPARE( blockExtent.height(), nRows * mpRasterLayer->rasterUnitsPerPixelY() );
|
||||
|
||||
QVERIFY( it.next( 1, nCols, nRows, topLeftCol, topLeftRow, blockExtent ) );
|
||||
QCOMPARE( nCols, 1200 );
|
||||
QCOMPARE( nRows, 2500 );
|
||||
QCOMPARE( topLeftCol, 6000 );
|
||||
QCOMPARE( topLeftRow, 0 );
|
||||
QCOMPARE( blockExtent.xMinimum(), mpRasterLayer->extent().xMinimum() + topLeftCol * mpRasterLayer->rasterUnitsPerPixelX() );
|
||||
QCOMPARE( blockExtent.yMinimum(), mpRasterLayer->extent().yMaximum() - nRows * mpRasterLayer->rasterUnitsPerPixelY() );
|
||||
QCOMPARE( blockExtent.width(), nCols * mpRasterLayer->rasterUnitsPerPixelX() );
|
||||
QCOMPARE( blockExtent.height(), nRows * mpRasterLayer->rasterUnitsPerPixelY() );
|
||||
|
||||
QVERIFY( it.next( 1, nCols, nRows, topLeftCol, topLeftRow, blockExtent ) );
|
||||
QCOMPARE( nCols, 3000 );
|
||||
QCOMPARE( nRows, 2500 );
|
||||
QCOMPARE( topLeftCol, 0 );
|
||||
QCOMPARE( topLeftRow, 2500 );
|
||||
QCOMPARE( blockExtent.xMinimum(), mpRasterLayer->extent().xMinimum() + topLeftCol * mpRasterLayer->rasterUnitsPerPixelX() );
|
||||
QCOMPARE( blockExtent.yMinimum(), mpRasterLayer->extent().yMaximum() - ( nRows + topLeftRow )* mpRasterLayer->rasterUnitsPerPixelY() );
|
||||
QCOMPARE( blockExtent.width(), nCols * mpRasterLayer->rasterUnitsPerPixelX() );
|
||||
QCOMPARE( blockExtent.height(), nRows * mpRasterLayer->rasterUnitsPerPixelY() );
|
||||
|
||||
QVERIFY( it.next( 1, nCols, nRows, topLeftCol, topLeftRow, blockExtent ) );
|
||||
QCOMPARE( nCols, 3000 );
|
||||
QCOMPARE( nRows, 2500 );
|
||||
QCOMPARE( topLeftCol, 3000 );
|
||||
QCOMPARE( topLeftRow, 2500 );
|
||||
QCOMPARE( blockExtent.xMinimum(), mpRasterLayer->extent().xMinimum() + topLeftCol * mpRasterLayer->rasterUnitsPerPixelX() );
|
||||
QCOMPARE( blockExtent.yMinimum(), mpRasterLayer->extent().yMaximum() - ( nRows + topLeftRow )* mpRasterLayer->rasterUnitsPerPixelY() );
|
||||
QCOMPARE( blockExtent.width(), nCols * mpRasterLayer->rasterUnitsPerPixelX() );
|
||||
QCOMPARE( blockExtent.height(), nRows * mpRasterLayer->rasterUnitsPerPixelY() );
|
||||
|
||||
QVERIFY( it.next( 1, nCols, nRows, topLeftCol, topLeftRow, blockExtent ) );
|
||||
QCOMPARE( nCols, 1200 );
|
||||
QCOMPARE( nRows, 2500 );
|
||||
QCOMPARE( topLeftCol, 6000 );
|
||||
QCOMPARE( topLeftRow, 2500 );
|
||||
QCOMPARE( blockExtent.xMinimum(), mpRasterLayer->extent().xMinimum() + topLeftCol * mpRasterLayer->rasterUnitsPerPixelX() );
|
||||
QCOMPARE( blockExtent.yMinimum(), mpRasterLayer->extent().yMaximum() - ( nRows + topLeftRow )* mpRasterLayer->rasterUnitsPerPixelY() );
|
||||
QCOMPARE( blockExtent.width(), nCols * mpRasterLayer->rasterUnitsPerPixelX() );
|
||||
QCOMPARE( blockExtent.height(), nRows * mpRasterLayer->rasterUnitsPerPixelY() );
|
||||
|
||||
QVERIFY( it.next( 1, nCols, nRows, topLeftCol, topLeftRow, blockExtent ) );
|
||||
QCOMPARE( nCols, 3000 );
|
||||
QCOMPARE( nRows, 450 );
|
||||
QCOMPARE( topLeftCol, 0 );
|
||||
QCOMPARE( topLeftRow, 5000 );
|
||||
QCOMPARE( blockExtent.xMinimum(), mpRasterLayer->extent().xMinimum() + topLeftCol * mpRasterLayer->rasterUnitsPerPixelX() );
|
||||
QCOMPARE( blockExtent.yMinimum(), mpRasterLayer->extent().yMaximum() - ( nRows + topLeftRow )* mpRasterLayer->rasterUnitsPerPixelY() );
|
||||
QCOMPARE( blockExtent.width(), nCols * mpRasterLayer->rasterUnitsPerPixelX() );
|
||||
QCOMPARE( blockExtent.height(), nRows * mpRasterLayer->rasterUnitsPerPixelY() );
|
||||
|
||||
QVERIFY( it.next( 1, nCols, nRows, topLeftCol, topLeftRow, blockExtent ) );
|
||||
QCOMPARE( nCols, 3000 );
|
||||
QCOMPARE( nRows, 450 );
|
||||
QCOMPARE( topLeftCol, 3000 );
|
||||
QCOMPARE( topLeftRow, 5000 );
|
||||
QCOMPARE( blockExtent.xMinimum(), mpRasterLayer->extent().xMinimum() + topLeftCol * mpRasterLayer->rasterUnitsPerPixelX() );
|
||||
QCOMPARE( blockExtent.yMinimum(), mpRasterLayer->extent().yMaximum() - ( nRows + topLeftRow )* mpRasterLayer->rasterUnitsPerPixelY() );
|
||||
QCOMPARE( blockExtent.width(), nCols * mpRasterLayer->rasterUnitsPerPixelX() );
|
||||
QCOMPARE( blockExtent.height(), nRows * mpRasterLayer->rasterUnitsPerPixelY() );
|
||||
|
||||
QVERIFY( it.next( 1, nCols, nRows, topLeftCol, topLeftRow, blockExtent ) );
|
||||
QCOMPARE( nCols, 1200 );
|
||||
QCOMPARE( nRows, 450 );
|
||||
QCOMPARE( topLeftCol, 6000 );
|
||||
QCOMPARE( topLeftRow, 5000 );
|
||||
QCOMPARE( blockExtent.xMinimum(), mpRasterLayer->extent().xMinimum() + topLeftCol * mpRasterLayer->rasterUnitsPerPixelX() );
|
||||
QCOMPARE( blockExtent.yMinimum(), mpRasterLayer->extent().yMaximum() - ( nRows + topLeftRow )* mpRasterLayer->rasterUnitsPerPixelY() );
|
||||
QCOMPARE( blockExtent.width(), nCols * mpRasterLayer->rasterUnitsPerPixelX() );
|
||||
QCOMPARE( blockExtent.height(), nRows * mpRasterLayer->rasterUnitsPerPixelY() );
|
||||
|
||||
QVERIFY( !it.next( 1, nCols, nRows, topLeftCol, topLeftRow, blockExtent ) );
|
||||
}
|
||||
|
||||
|
||||
QGSTEST_MAIN( TestQgsRasterIterator )
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user