QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
qgsrasteriterator.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsrasteriterator.cpp
3  ---------------------
4  begin : July 2012
5  copyright : (C) 2012 by Marco Hugentobler
6  email : marco dot hugentobler at sourcepole dot ch
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 #include "qgsrasteriterator.h"
16 #include "qgsrasterinterface.h"
17 #include "qgsrasterprojector.h"
18 #include "qgsrasterviewport.h"
19 #include "qgsrasterdataprovider.h"
20 
22  : mInput( input )
23  , mMaximumTileWidth( DEFAULT_MAXIMUM_TILE_WIDTH )
24  , mMaximumTileHeight( DEFAULT_MAXIMUM_TILE_HEIGHT )
25 {
26  for ( QgsRasterInterface *ri = input; ri; ri = ri->input() )
27  {
28  QgsRasterDataProvider *rdp = dynamic_cast<QgsRasterDataProvider *>( ri );
29  if ( rdp )
30  {
31  mMaximumTileWidth = rdp->stepWidth();
32  mMaximumTileHeight = rdp->stepHeight();
33  break;
34  }
35  }
36 }
37 
38 QgsRectangle QgsRasterIterator::subRegion( const QgsRectangle &rasterExtent, int rasterWidth, int rasterHeight, const QgsRectangle &subRegion, int &subRegionWidth, int &subRegionHeight, int &subRegionLeft, int &subRegionTop )
39 {
40  const double xRes = rasterExtent.width() / rasterWidth;
41  const double yRes = rasterExtent.height() / rasterHeight;
42 
43  int top = 0;
44  int bottom = rasterHeight - 1;
45  int left = 0;
46  int right = rasterWidth - 1;
47 
48  if ( subRegion.yMaximum() < rasterExtent.yMaximum() )
49  {
50  top = static_cast< int >( std::floor( ( rasterExtent.yMaximum() - subRegion.yMaximum() ) / yRes ) );
51  }
52  if ( subRegion.yMinimum() > rasterExtent.yMinimum() )
53  {
54  bottom = static_cast< int >( std::ceil( ( rasterExtent.yMaximum() - subRegion.yMinimum() ) / yRes ) - 1 );
55  }
56 
57  if ( subRegion.xMinimum() > rasterExtent.xMinimum() )
58  {
59  left = static_cast< int >( std::floor( ( subRegion.xMinimum() - rasterExtent.xMinimum() ) / xRes ) );
60  }
61  if ( subRegion.xMaximum() < rasterExtent.xMaximum() )
62  {
63  right = static_cast< int >( std::ceil( ( subRegion.xMaximum() - rasterExtent.xMinimum() ) / xRes ) - 1 );
64  }
65 
66  subRegionWidth = right - left + 1;
67  subRegionHeight = bottom - top + 1;
68  subRegionLeft = left;
69  subRegionTop = top;
70 
71  return QgsRectangle( rasterExtent.xMinimum() + ( left * xRes ),
72  rasterExtent.yMaximum() - ( ( top + subRegionHeight ) * yRes ),
73  rasterExtent.xMinimum() + ( ( left + subRegionWidth ) * xRes ),
74  rasterExtent.yMaximum() - ( top * yRes ) );
75 }
76 
77 void QgsRasterIterator::startRasterRead( int bandNumber, qgssize nCols, qgssize nRows, const QgsRectangle &extent, QgsRasterBlockFeedback *feedback )
78 {
79  if ( !mInput )
80  {
81  return;
82  }
83 
84  mExtent = extent;
85  mFeedback = feedback;
86 
87  //remove any previous part on that band
88  removePartInfo( bandNumber );
89 
90  //split raster into small portions if necessary
91  RasterPartInfo pInfo;
92  pInfo.nCols = nCols;
93  pInfo.nRows = nRows;
94  pInfo.currentCol = 0;
95  pInfo.currentRow = 0;
96  mRasterPartInfos.insert( bandNumber, pInfo );
97 }
98 
99 bool QgsRasterIterator::next( int bandNumber, int &columns, int &rows, int &topLeftColumn, int &topLeftRow, QgsRectangle &blockExtent )
100 {
101  return readNextRasterPartInternal( bandNumber, columns, rows, nullptr, topLeftColumn, topLeftRow, &blockExtent );
102 }
103 
105  int &nCols, int &nRows,
106  QgsRasterBlock **block,
107  int &topLeftCol, int &topLeftRow )
108 {
109  *block = nullptr;
110  std::unique_ptr< QgsRasterBlock > nextBlock;
111  const bool result = readNextRasterPart( bandNumber, nCols, nRows, nextBlock, topLeftCol, topLeftRow );
112  if ( result )
113  *block = nextBlock.release();
114  return result;
115 }
116 
117 bool QgsRasterIterator::readNextRasterPart( int bandNumber, int &nCols, int &nRows, std::unique_ptr<QgsRasterBlock> &block, int &topLeftCol, int &topLeftRow, QgsRectangle *blockExtent )
118 {
119  return readNextRasterPartInternal( bandNumber, nCols, nRows, &block, topLeftCol, topLeftRow, blockExtent );
120 }
121 
122 bool QgsRasterIterator::readNextRasterPartInternal( int bandNumber, int &nCols, int &nRows, std::unique_ptr<QgsRasterBlock> *block, int &topLeftCol, int &topLeftRow, QgsRectangle *blockExtent )
123 {
124  QgsDebugMsgLevel( QStringLiteral( "Entered" ), 4 );
125  if ( block )
126  block->reset();
127  //get partinfo
128  const QMap<int, RasterPartInfo>::iterator partIt = mRasterPartInfos.find( bandNumber );
129  if ( partIt == mRasterPartInfos.end() )
130  {
131  return false;
132  }
133 
134  RasterPartInfo &pInfo = partIt.value();
135 
136  // If we started with zero cols or zero rows, just return (avoids divide by zero below)
137  if ( 0 == pInfo.nCols || 0 == pInfo.nRows )
138  {
139  return false;
140  }
141 
142  //remove last data block
143 
144  //already at end
145  if ( pInfo.currentCol == pInfo.nCols && pInfo.currentRow == pInfo.nRows )
146  {
147  return false;
148  }
149 
150  //read data block
151  nCols = static_cast< int >( std::min( static_cast< qgssize >( mMaximumTileWidth ), pInfo.nCols - pInfo.currentCol ) );
152  nRows = static_cast< int >( std::min( static_cast< qgssize >( mMaximumTileHeight ), pInfo.nRows - pInfo.currentRow ) );
153  QgsDebugMsgLevel( QStringLiteral( "nCols = %1 nRows = %2" ).arg( nCols ).arg( nRows ), 4 );
154 
155  //get subrectangle
156  const QgsRectangle viewPortExtent = mExtent;
157  const double xmin = viewPortExtent.xMinimum() + pInfo.currentCol / static_cast< double >( pInfo.nCols ) * viewPortExtent.width();
158  const double xmax = pInfo.currentCol + nCols == pInfo.nCols ? viewPortExtent.xMaximum() : // avoid extra FP math if not necessary
159  viewPortExtent.xMinimum() + ( pInfo.currentCol + nCols ) / static_cast< double >( pInfo.nCols ) * viewPortExtent.width();
160  const double ymin = pInfo.currentRow + nRows == pInfo.nRows ? viewPortExtent.yMinimum() : // avoid extra FP math if not necessary
161  viewPortExtent.yMaximum() - ( pInfo.currentRow + nRows ) / static_cast< double >( pInfo.nRows ) * viewPortExtent.height();
162  const double ymax = viewPortExtent.yMaximum() - pInfo.currentRow / static_cast< double >( pInfo.nRows ) * viewPortExtent.height();
163  const QgsRectangle blockRect( xmin, ymin, xmax, ymax );
164 
165  if ( blockExtent )
166  *blockExtent = blockRect;
167 
168  if ( block )
169  block->reset( mInput->block( bandNumber, blockRect, nCols, nRows, mFeedback ) );
170  topLeftCol = pInfo.currentCol;
171  topLeftRow = pInfo.currentRow;
172 
173  pInfo.currentCol += nCols;
174  if ( pInfo.currentCol == pInfo.nCols && pInfo.currentRow + nRows == pInfo.nRows ) //end of raster
175  {
176  pInfo.currentRow = pInfo.nRows;
177  }
178  else if ( pInfo.currentCol == pInfo.nCols ) //start new row
179  {
180  pInfo.currentCol = 0;
181  pInfo.currentRow += nRows;
182  }
183 
184  return true;
185 }
186 
187 void QgsRasterIterator::stopRasterRead( int bandNumber )
188 {
189  removePartInfo( bandNumber );
190 }
191 
192 void QgsRasterIterator::removePartInfo( int bandNumber )
193 {
194  const auto partIt = mRasterPartInfos.constFind( bandNumber );
195  if ( partIt != mRasterPartInfos.constEnd() )
196  {
197  mRasterPartInfos.remove( bandNumber );
198  }
199 }
qgsrasterprojector.h
QgsRectangle::height
double height() const SIP_HOLDGIL
Returns the height of the rectangle.
Definition: qgsrectangle.h:230
QgsDebugMsgLevel
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
qgsrasterviewport.h
QgsRectangle::yMinimum
double yMinimum() const SIP_HOLDGIL
Returns the y minimum value (bottom side of rectangle).
Definition: qgsrectangle.h:198
QgsRasterIterator::subRegion
static QgsRectangle subRegion(const QgsRectangle &rasterExtent, int rasterWidth, int rasterHeight, const QgsRectangle &subRegion, int &subRegionWidth, int &subRegionHeight, int &subRegionLeft, int &subRegionTop)
Given an overall raster extent and width and height in pixels, calculates the sub region of the raste...
Definition: qgsrasteriterator.cpp:38
QgsRectangle
A rectangle specified with double values.
Definition: qgsrectangle.h:41
QgsRasterIterator::QgsRasterIterator
QgsRasterIterator(QgsRasterInterface *input)
Constructor for QgsRasterIterator, iterating over the specified input raster source.
Definition: qgsrasteriterator.cpp:21
QgsRasterIterator::next
bool next(int bandNumber, int &columns, int &rows, int &topLeftColumn, int &topLeftRow, QgsRectangle &blockExtent)
Fetches details of the next part of the raster data.
Definition: qgsrasteriterator.cpp:99
qgsrasteriterator.h
QgsRectangle::xMaximum
double xMaximum() const SIP_HOLDGIL
Returns the x maximum value (right side of rectangle).
Definition: qgsrectangle.h:183
qgsrasterinterface.h
QgsRasterDataProvider::stepHeight
virtual int stepHeight() const
Step height for raster iterations.
Definition: qgsrasterdataprovider.h:613
QgsRasterIterator::startRasterRead
void startRasterRead(int bandNumber, qgssize nCols, qgssize nRows, const QgsRectangle &extent, QgsRasterBlockFeedback *feedback=nullptr)
Start reading of raster band.
Definition: qgsrasteriterator.cpp:77
QgsRasterDataProvider::stepWidth
virtual int stepWidth() const
Step width for raster iterations.
Definition: qgsrasterdataprovider.h:606
QgsRasterIterator::input
const QgsRasterInterface * input() const
Returns the input raster interface which is being iterated over.
Definition: qgsrasteriterator.h:136
QgsRasterIterator::stopRasterRead
void stopRasterRead(int bandNumber)
Cancels the raster iteration and resets the iterator.
Definition: qgsrasteriterator.cpp:187
QgsRectangle::xMinimum
double xMinimum() const SIP_HOLDGIL
Returns the x minimum value (left side of rectangle).
Definition: qgsrectangle.h:188
QgsRasterIterator::readNextRasterPart
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...
Definition: qgsrasteriterator.cpp:104
QgsRasterInterface
Base class for processing filters like renderers, reprojector, resampler etc.
Definition: qgsrasterinterface.h:135
QgsRectangle::yMaximum
double yMaximum() const SIP_HOLDGIL
Returns the y maximum value (top side of rectangle).
Definition: qgsrectangle.h:193
QgsRectangle::width
double width() const SIP_HOLDGIL
Returns the width of the rectangle.
Definition: qgsrectangle.h:223
QgsRasterInterface::input
virtual QgsRasterInterface * input() const
Current input.
Definition: qgsrasterinterface.h:302
QgsRasterBlockFeedback
Feedback object tailored for raster block reading.
Definition: qgsrasterinterface.h:41
QgsRasterInterface::block
virtual QgsRasterBlock * block(int bandNo, const QgsRectangle &extent, int width, int height, QgsRasterBlockFeedback *feedback=nullptr)=0
Read block of data using given extent and size.
QgsRasterDataProvider
Base class for raster data providers.
Definition: qgsrasterdataprovider.h:88
QgsRasterBlock
Raster data container.
Definition: qgsrasterblock.h:36
qgsrasterdataprovider.h
qgssize
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...
Definition: qgis.h:2791