QGIS API Documentation  3.24.2-Tisler (13c1a02865)
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 void QgsRasterIterator::startRasterRead( int bandNumber, qgssize nCols, qgssize nRows, const QgsRectangle &extent, QgsRasterBlockFeedback *feedback )
39 {
40  if ( !mInput )
41  {
42  return;
43  }
44 
45  mExtent = extent;
46  mFeedback = feedback;
47 
48  //remove any previous part on that band
49  removePartInfo( bandNumber );
50 
51  //split raster into small portions if necessary
52  RasterPartInfo pInfo;
53  pInfo.nCols = nCols;
54  pInfo.nRows = nRows;
55  pInfo.currentCol = 0;
56  pInfo.currentRow = 0;
57  mRasterPartInfos.insert( bandNumber, pInfo );
58 }
59 
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 
66  int &nCols, int &nRows,
67  QgsRasterBlock **block,
68  int &topLeftCol, int &topLeftRow )
69 {
70  *block = nullptr;
71  std::unique_ptr< QgsRasterBlock > nextBlock;
72  const bool result = readNextRasterPart( bandNumber, nCols, nRows, nextBlock, topLeftCol, topLeftRow );
73  if ( result )
74  *block = nextBlock.release();
75  return result;
76 }
77 
78 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 )
84 {
85  QgsDebugMsgLevel( QStringLiteral( "Entered" ), 4 );
86  if ( block )
87  block->reset();
88  //get partinfo
89  const QMap<int, RasterPartInfo>::iterator partIt = mRasterPartInfos.find( bandNumber );
90  if ( partIt == mRasterPartInfos.end() )
91  {
92  return false;
93  }
94 
95  RasterPartInfo &pInfo = partIt.value();
96 
97  // If we started with zero cols or zero rows, just return (avoids divide by zero below)
98  if ( 0 == pInfo.nCols || 0 == pInfo.nRows )
99  {
100  return false;
101  }
102 
103  //remove last data block
104 
105  //already at end
106  if ( pInfo.currentCol == pInfo.nCols && pInfo.currentRow == pInfo.nRows )
107  {
108  return false;
109  }
110 
111  //read data block
112  nCols = static_cast< int >( std::min( static_cast< qgssize >( mMaximumTileWidth ), pInfo.nCols - pInfo.currentCol ) );
113  nRows = static_cast< int >( std::min( static_cast< qgssize >( mMaximumTileHeight ), pInfo.nRows - pInfo.currentRow ) );
114  QgsDebugMsgLevel( QStringLiteral( "nCols = %1 nRows = %2" ).arg( nCols ).arg( nRows ), 4 );
115 
116  //get subrectangle
117  const QgsRectangle viewPortExtent = mExtent;
118  const double xmin = viewPortExtent.xMinimum() + pInfo.currentCol / static_cast< double >( pInfo.nCols ) * viewPortExtent.width();
119  const double xmax = pInfo.currentCol + nCols == pInfo.nCols ? viewPortExtent.xMaximum() : // avoid extra FP math if not necessary
120  viewPortExtent.xMinimum() + ( pInfo.currentCol + nCols ) / static_cast< double >( pInfo.nCols ) * viewPortExtent.width();
121  const double ymin = pInfo.currentRow + nRows == pInfo.nRows ? viewPortExtent.yMinimum() : // avoid extra FP math if not necessary
122  viewPortExtent.yMaximum() - ( pInfo.currentRow + nRows ) / static_cast< double >( pInfo.nRows ) * viewPortExtent.height();
123  const double ymax = viewPortExtent.yMaximum() - pInfo.currentRow / static_cast< double >( pInfo.nRows ) * viewPortExtent.height();
124  const QgsRectangle blockRect( xmin, ymin, xmax, ymax );
125 
126  if ( blockExtent )
127  *blockExtent = blockRect;
128 
129  if ( block )
130  block->reset( mInput->block( bandNumber, blockRect, nCols, nRows, mFeedback ) );
131  topLeftCol = pInfo.currentCol;
132  topLeftRow = pInfo.currentRow;
133 
134  pInfo.currentCol += nCols;
135  if ( pInfo.currentCol == pInfo.nCols && pInfo.currentRow + nRows == pInfo.nRows ) //end of raster
136  {
137  pInfo.currentRow = pInfo.nRows;
138  }
139  else if ( pInfo.currentCol == pInfo.nCols ) //start new row
140  {
141  pInfo.currentCol = 0;
142  pInfo.currentRow += nRows;
143  }
144 
145  return true;
146 }
147 
148 void QgsRasterIterator::stopRasterRead( int bandNumber )
149 {
150  removePartInfo( bandNumber );
151 }
152 
153 void QgsRasterIterator::removePartInfo( int bandNumber )
154 {
155  const auto partIt = mRasterPartInfos.constFind( bandNumber );
156  if ( partIt != mRasterPartInfos.constEnd() )
157  {
158  mRasterPartInfos.remove( bandNumber );
159  }
160 }
Feedback object tailored for raster block reading.
Raster data container.
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.
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.
virtual QgsRasterInterface * input() const
Current input.
const QgsRasterInterface * input() const
Returns the input raster interface which is being iterated over.
bool next(int bandNumber, int &columns, int &rows, int &topLeftColumn, int &topLeftRow, QgsRectangle &blockExtent)
Fetches details of the next part of the raster data.
void stopRasterRead(int bandNumber)
Cancels the raster iteration and resets the iterator.
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...
void startRasterRead(int bandNumber, qgssize nCols, qgssize nRows, const QgsRectangle &extent, QgsRasterBlockFeedback *feedback=nullptr)
Start reading of raster band.
QgsRasterIterator(QgsRasterInterface *input)
Constructor for QgsRasterIterator, iterating over the specified input raster source.
A rectangle specified with double values.
Definition: qgsrectangle.h:42
double yMaximum() const SIP_HOLDGIL
Returns the y maximum value (top side of rectangle).
Definition: qgsrectangle.h:193
double xMaximum() const SIP_HOLDGIL
Returns the x maximum value (right side of rectangle).
Definition: qgsrectangle.h:183
double xMinimum() const SIP_HOLDGIL
Returns the x minimum value (left side of rectangle).
Definition: qgsrectangle.h:188
double yMinimum() const SIP_HOLDGIL
Returns the y minimum value (bottom side of rectangle).
Definition: qgsrectangle.h:198
double height() const SIP_HOLDGIL
Returns the height of the rectangle.
Definition: qgsrectangle.h:230
double width() const SIP_HOLDGIL
Returns the width of the rectangle.
Definition: qgsrectangle.h:223
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:2036
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39