22using namespace Qt::StringLiterals;
26 , mTileOverlapPixels( tileOverlapPixels )
35 mMaximumTileWidth = rdp->
stepWidth() - 2 * mTileOverlapPixels;
36 mMaximumTileHeight = rdp->
stepHeight() - 2 * mTileOverlapPixels;
44 const double xRes = rasterExtent.
width() / rasterWidth;
45 const double yRes = rasterExtent.
height() / rasterHeight;
48 int bottom = rasterHeight - 1;
50 int right = rasterWidth - 1;
54 top =
static_cast< int >( std::floor( ( rasterExtent.
yMaximum() -
subRegion.yMaximum() ) / yRes ) );
58 bottom =
static_cast< int >( std::ceil( ( rasterExtent.
yMaximum() -
subRegion.yMinimum() ) / yRes ) - 1 );
63 left =
static_cast< int >( std::floor( (
subRegion.xMinimum() - rasterExtent.
xMinimum() ) / xRes ) );
67 right =
static_cast< int >( std::ceil( (
subRegion.xMaximum() - rasterExtent.
xMinimum() ) / xRes ) - 1 );
70 if ( resamplingFactor > 1 )
73 left = ( ( left + resamplingFactor - 1 ) / resamplingFactor ) * resamplingFactor;
74 top = ( ( top + resamplingFactor - 1 ) / resamplingFactor ) * resamplingFactor;
77 right = ( right / resamplingFactor ) * resamplingFactor - 1;
78 bottom = ( bottom / resamplingFactor ) * resamplingFactor - 1;
81 subRegionWidth = right - left + 1;
82 subRegionHeight = bottom - top + 1;
88 rasterExtent.
yMaximum() - ( ( top + subRegionHeight ) * yRes ),
89 rasterExtent.
xMinimum() + ( ( left + subRegionWidth ) * xRes ),
90 rasterExtent.
yMaximum() - ( top * yRes ) );
101 mFeedback = feedback;
104 removePartInfo( bandNumber );
107 RasterPartInfo pInfo;
110 pInfo.currentCol = 0;
111 pInfo.currentRow = 0;
112 mRasterPartInfos.insert( bandNumber, pInfo );
114 mNumberBlocksWidth =
static_cast< int >( std::ceil(
static_cast< double >( nCols ) / mMaximumTileWidth ) );
115 mNumberBlocksHeight =
static_cast< int >( std::ceil(
static_cast< double >( nRows ) / mMaximumTileHeight ) );
120 int outTileColumns = 0;
122 int outTileTopLeftColumn = 0;
123 int outTileTopLeftRow = 0;
124 return readNextRasterPartInternal( bandNumber, columns, rows,
nullptr, topLeftColumn, topLeftRow, &blockExtent, outTileColumns, outTileRows, outTileTopLeftColumn, outTileTopLeftRow );
128 int &nCols,
int &nRows,
130 int &topLeftCol,
int &topLeftRow )
133 std::unique_ptr< QgsRasterBlock > nextBlock;
134 const bool result =
readNextRasterPart( bandNumber, nCols, nRows, nextBlock, topLeftCol, topLeftRow );
136 *block = nextBlock.release();
140bool QgsRasterIterator::readNextRasterPart(
int bandNumber,
int &nCols,
int &nRows, std::unique_ptr<QgsRasterBlock> &block,
int &topLeftCol,
int &topLeftRow,
QgsRectangle *blockExtent,
int *tileColumns,
int *tileRows,
int *tileTopLeftColumn,
int *tileTopLeftRow )
142 int outTileColumns = 0;
144 int outTileTopLeftColumn = 0;
145 int outTileTopLeftRow = 0;
146 const bool res = readNextRasterPartInternal( bandNumber, nCols, nRows, &block, topLeftCol, topLeftRow, blockExtent, outTileColumns, outTileRows, outTileTopLeftColumn, outTileTopLeftRow );
149 *tileColumns = outTileColumns;
151 *tileRows = outTileRows;
152 if ( tileTopLeftColumn )
153 *tileTopLeftColumn = outTileTopLeftColumn;
154 if ( tileTopLeftRow )
155 *tileTopLeftRow = outTileTopLeftRow;
160bool QgsRasterIterator::readNextRasterPartInternal(
int bandNumber,
int &nCols,
int &nRows, std::unique_ptr<QgsRasterBlock> *block,
int &topLeftCol,
int &topLeftRow,
QgsRectangle *blockExtent,
int &tileColumns,
int &tileRows,
int &tileTopLeftColumn,
int &tileTopLeftRow )
166 const QMap<int, RasterPartInfo>::iterator partIt = mRasterPartInfos.find( bandNumber );
167 if ( partIt == mRasterPartInfos.end() )
172 RasterPartInfo &pInfo = partIt.value();
175 if ( 0 == pInfo.nCols || 0 == pInfo.nRows )
183 if ( pInfo.currentCol == pInfo.nCols && pInfo.currentRow == pInfo.nRows )
189 tileTopLeftColumn = pInfo.currentCol;
190 tileTopLeftRow = pInfo.currentRow;
192 tileColumns =
static_cast< int >( std::min(
static_cast< qgssize >( mMaximumTileWidth ), pInfo.nCols - tileTopLeftColumn ) );
193 tileRows =
static_cast< int >( std::min(
static_cast< qgssize >( mMaximumTileHeight ), pInfo.nRows - tileTopLeftRow ) );
195 if ( mSnapToPixelFactor > 1 )
198 tileColumns = ( tileColumns / mSnapToPixelFactor ) * mSnapToPixelFactor;
199 tileRows = ( tileRows / mSnapToPixelFactor ) * mSnapToPixelFactor;
202 pInfo.previousIteratedPixels = pInfo.iteratedPixels;
203 pInfo.currentBlockSize =
static_cast< std::size_t
>( tileColumns ) *
static_cast< std::size_t
>( tileRows );
204 pInfo.iteratedPixels += pInfo.currentBlockSize;
206 const qgssize tileRight = tileTopLeftColumn + tileColumns;
207 const qgssize tileBottom = tileTopLeftRow + tileRows;
209 const qgssize blockLeft = tileTopLeftColumn >= mTileOverlapPixels ? ( tileTopLeftColumn - mTileOverlapPixels ) : 0;
210 const qgssize blockTop = tileTopLeftRow >= mTileOverlapPixels ? ( tileTopLeftRow - mTileOverlapPixels ) : 0;
211 const qgssize blockRight = std::min< qgssize >( tileRight + mTileOverlapPixels, pInfo.nCols );
212 const qgssize blockBottom = std::min< qgssize >( tileBottom + mTileOverlapPixels, pInfo.nRows );
214 nCols = blockRight - blockLeft;
215 nRows = blockBottom - blockTop;
217 if ( mSnapToPixelFactor > 1 )
220 nCols = ( nCols / mSnapToPixelFactor ) * mSnapToPixelFactor;
221 nRows = ( nRows / mSnapToPixelFactor ) * mSnapToPixelFactor;
222 if ( nCols == 0 || nRows == 0 )
226 QgsDebugMsgLevel( u
"nCols = %1 nRows = %2"_s.arg( nCols ).arg( nRows ), 4 );
229 const QgsRectangle viewPortExtent = mExtent;
230 const double xmin = viewPortExtent.
xMinimum() + blockLeft /
static_cast< double >( pInfo.nCols ) * viewPortExtent.
width();
231 const double xmax = blockLeft + nCols == pInfo.nCols ? viewPortExtent.
xMaximum() :
232 viewPortExtent.
xMinimum() + ( blockLeft + nCols ) /
static_cast< double >( pInfo.nCols ) * viewPortExtent.
width();
233 const double ymin = blockTop + nRows == pInfo.nRows ? viewPortExtent.
yMinimum() :
234 viewPortExtent.
yMaximum() - ( blockTop + nRows ) /
static_cast< double >( pInfo.nRows ) * viewPortExtent.
height();
235 const double ymax = viewPortExtent.
yMaximum() - blockTop /
static_cast< double >( pInfo.nRows ) * viewPortExtent.
height();
236 const QgsRectangle blockRect( xmin, ymin, xmax, ymax );
239 *blockExtent = blockRect;
242 block->reset( mInput->block( bandNumber, blockRect, nCols, nRows, mFeedback ) );
243 topLeftCol = blockLeft;
244 topLeftRow = blockTop;
246 pInfo.currentCol = tileRight;
247 if ( pInfo.currentCol == pInfo.nCols && tileBottom == pInfo.nRows )
249 pInfo.currentRow = pInfo.nRows;
251 else if ( pInfo.currentCol == pInfo.nCols )
253 pInfo.currentCol = 0;
254 pInfo.currentRow = tileBottom;
262 removePartInfo( bandNumber );
267 if ( currentBlockProgress < 0 )
269 const auto partIt = mRasterPartInfos.find( bandNumber );
270 if ( partIt == mRasterPartInfos.constEnd() )
274 const std::size_t totalSize =
static_cast< std::size_t
>( partIt->nCols ) *
static_cast< std::size_t
>( partIt->nRows );
275 return static_cast< double >( partIt->iteratedPixels ) /
static_cast< double >( totalSize );
279 const auto partIt = mRasterPartInfos.find( bandNumber );
280 if ( partIt == mRasterPartInfos.constEnd() )
285 const std::size_t totalSize =
static_cast< std::size_t
>( partIt->nCols ) *
static_cast< std::size_t
>( partIt->nRows );
286 const double startOfBlockProgress =
static_cast< double >( partIt->previousIteratedPixels ) /
static_cast< double >( totalSize );
287 const double currentBlockProgressFraction = currentBlockProgress *
static_cast< double >( partIt->currentBlockSize ) /
static_cast< double >( totalSize );
289 return startOfBlockProgress + currentBlockProgressFraction;
293void QgsRasterIterator::removePartInfo(
int bandNumber )
295 const auto partIt = mRasterPartInfos.constFind( bandNumber );
296 if ( partIt != mRasterPartInfos.constEnd() )
298 mRasterPartInfos.remove( bandNumber );
Feedback object tailored for raster block reading.
Base class for raster data providers.
virtual int stepHeight() const
Step height for raster iterations.
virtual int stepWidth() const
Step width for raster iterations.
Base class for processing filters like renderers, reprojector, resampler etc.
static QgsRectangle subRegion(const QgsRectangle &rasterExtent, int rasterWidth, int rasterHeight, const QgsRectangle &subRegion, int &subRegionWidth, int &subRegionHeight, int &subRegionLeft, int &subRegionTop, int resamplingFactor=1)
Given an overall raster extent and width and height in pixels, calculates the sub region of the raste...
bool next(int bandNumber, int &columns, int &rows, int &topLeftColumn, int &topLeftRow, QgsRectangle &blockExtent)
Fetches details of the next part of the raster data.
QgsRasterIterator(QgsRasterInterface *input, int tileOverlapPixels=0)
Constructor for QgsRasterIterator, iterating over the specified input raster source.
const QgsRasterInterface * input() const
Returns the input raster interface which is being iterated over.
void stopRasterRead(int bandNumber)
Cancels the raster iteration and resets the iterator.
static const int DEFAULT_MAXIMUM_TILE_WIDTH
Default maximum tile width.
bool readNextRasterPart(int bandNumber, int &nCols, int &nRows, QgsRasterBlock **block, int &topLeftCol, int &topLeftRow)
Fetches next part of raster data, caller takes ownership of the block and caller should delete the bl...
static const int DEFAULT_MAXIMUM_TILE_HEIGHT
Default maximum tile height.
double progress(int bandNumber, double currentBlockProgress=-1) const
Returns the raster iteration progress as a fraction from 0 to 1.0, for the specified bandNumber.
void startRasterRead(int bandNumber, qgssize nCols, qgssize nRows, const QgsRectangle &extent, QgsRasterBlockFeedback *feedback=nullptr)
Start reading of raster band.
A rectangle specified with double values.
unsigned long long qgssize
Qgssize is used instead of size_t, because size_t is stdlib type, unknown by SIP, and it would be har...
#define QgsDebugMsgLevel(str, level)