QGIS API Documentation  3.4.15-Madeira (e83d02e274)
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, int nCols, int 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 
61  int &nCols, int &nRows,
62  QgsRasterBlock **block,
63  int &topLeftCol, int &topLeftRow )
64 {
65  *block = nullptr;
66  std::unique_ptr< QgsRasterBlock > nextBlock;
67  bool result = readNextRasterPart( bandNumber, nCols, nRows, nextBlock, topLeftCol, topLeftRow );
68  if ( result )
69  *block = nextBlock.release();
70  return result;
71 }
72 
73 bool QgsRasterIterator::readNextRasterPart( int bandNumber, int &nCols, int &nRows, std::unique_ptr<QgsRasterBlock> &block, int &topLeftCol, int &topLeftRow, QgsRectangle *blockExtent )
74 {
75  QgsDebugMsgLevel( QStringLiteral( "Entered" ), 4 );
76  block.reset();
77  //get partinfo
78  QMap<int, RasterPartInfo>::iterator partIt = mRasterPartInfos.find( bandNumber );
79  if ( partIt == mRasterPartInfos.end() )
80  {
81  return false;
82  }
83 
84  RasterPartInfo &pInfo = partIt.value();
85 
86  // If we started with zero cols or zero rows, just return (avoids divide by zero below)
87  if ( 0 == pInfo.nCols || 0 == pInfo.nRows )
88  {
89  return false;
90  }
91 
92  //remove last data block
93 
94  //already at end
95  if ( pInfo.currentCol == pInfo.nCols && pInfo.currentRow == pInfo.nRows )
96  {
97  return false;
98  }
99 
100  //read data block
101  nCols = std::min( mMaximumTileWidth, pInfo.nCols - pInfo.currentCol );
102  nRows = std::min( mMaximumTileHeight, pInfo.nRows - pInfo.currentRow );
103  QgsDebugMsgLevel( QStringLiteral( "nCols = %1 nRows = %2" ).arg( nCols ).arg( nRows ), 4 );
104 
105  //get subrectangle
106  QgsRectangle viewPortExtent = mExtent;
107  double xmin = viewPortExtent.xMinimum() + pInfo.currentCol / static_cast< double >( pInfo.nCols ) * viewPortExtent.width();
108  double xmax = pInfo.currentCol + nCols == pInfo.nCols ? viewPortExtent.xMaximum() : // avoid extra FP math if not necessary
109  viewPortExtent.xMinimum() + ( pInfo.currentCol + nCols ) / static_cast< double >( pInfo.nCols ) * viewPortExtent.width();
110  double ymin = pInfo.currentRow + nRows == pInfo.nRows ? viewPortExtent.yMinimum() : // avoid extra FP math if not necessary
111  viewPortExtent.yMaximum() - ( pInfo.currentRow + nRows ) / static_cast< double >( pInfo.nRows ) * viewPortExtent.height();
112  double ymax = viewPortExtent.yMaximum() - pInfo.currentRow / static_cast< double >( pInfo.nRows ) * viewPortExtent.height();
113  QgsRectangle blockRect( xmin, ymin, xmax, ymax );
114 
115  if ( blockExtent )
116  *blockExtent = blockRect;
117 
118  block.reset( mInput->block( bandNumber, blockRect, nCols, nRows, mFeedback ) );
119  topLeftCol = pInfo.currentCol;
120  topLeftRow = pInfo.currentRow;
121 
122  pInfo.currentCol += nCols;
123  if ( pInfo.currentCol == pInfo.nCols && pInfo.currentRow + nRows == pInfo.nRows ) //end of raster
124  {
125  pInfo.currentRow = pInfo.nRows;
126  }
127  else if ( pInfo.currentCol == pInfo.nCols ) //start new row
128  {
129  pInfo.currentCol = 0;
130  pInfo.currentRow += nRows;
131  }
132 
133  return true;
134 }
135 
136 void QgsRasterIterator::stopRasterRead( int bandNumber )
137 {
138  removePartInfo( bandNumber );
139 }
140 
141 void QgsRasterIterator::removePartInfo( int bandNumber )
142 {
143  auto partIt = mRasterPartInfos.constFind( bandNumber );
144  if ( partIt != mRasterPartInfos.constEnd() )
145  {
146  mRasterPartInfos.remove( bandNumber );
147  }
148 }
A rectangle specified with double values.
Definition: qgsrectangle.h:40
double yMaximum() const
Returns the y maximum value (top side of rectangle).
Definition: qgsrectangle.h:171
QgsRasterIterator(QgsRasterInterface *input)
Constructor for QgsRasterIterator, iterating over the specified input raster source.
virtual QgsRasterInterface * input() const
Current input.
virtual int stepWidth() const
Step width for raster iterations.
Raster data container.
double yMinimum() const
Returns the y minimum value (bottom side of rectangle).
Definition: qgsrectangle.h:176
double xMaximum() const
Returns the x maximum value (right side of rectangle).
Definition: qgsrectangle.h:161
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
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.
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...
Base class for processing filters like renderers, reprojector, resampler etc.
void stopRasterRead(int bandNumber)
Cancels the raster iteration and resets the iterator.
virtual int stepHeight() const
Step height for raster iterations.
double width() const
Returns the width of the rectangle.
Definition: qgsrectangle.h:201
Feedback object tailored for raster block reading.
double xMinimum() const
Returns the x minimum value (left side of rectangle).
Definition: qgsrectangle.h:166
void startRasterRead(int bandNumber, int nCols, int nRows, const QgsRectangle &extent, QgsRasterBlockFeedback *feedback=nullptr)
Start reading of raster band.
double height() const
Returns the height of the rectangle.
Definition: qgsrectangle.h:208
Base class for raster data providers.