Branch data Line data Source code
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 : :
21 : 0 : QgsRasterIterator::QgsRasterIterator( QgsRasterInterface *input )
22 : 0 : : mInput( input )
23 : 0 : , mMaximumTileWidth( DEFAULT_MAXIMUM_TILE_WIDTH )
24 : 0 : , mMaximumTileHeight( DEFAULT_MAXIMUM_TILE_HEIGHT )
25 : : {
26 : 0 : for ( QgsRasterInterface *ri = input; ri; ri = ri->input() )
27 : : {
28 : 0 : QgsRasterDataProvider *rdp = dynamic_cast<QgsRasterDataProvider *>( ri );
29 : 0 : if ( rdp )
30 : : {
31 : 0 : mMaximumTileWidth = rdp->stepWidth();
32 : 0 : mMaximumTileHeight = rdp->stepHeight();
33 : 0 : break;
34 : : }
35 : 0 : }
36 : 0 : }
37 : :
38 : 0 : void QgsRasterIterator::startRasterRead( int bandNumber, qgssize nCols, qgssize nRows, const QgsRectangle &extent, QgsRasterBlockFeedback *feedback )
39 : : {
40 : 0 : if ( !mInput )
41 : : {
42 : 0 : return;
43 : : }
44 : :
45 : 0 : mExtent = extent;
46 : 0 : mFeedback = feedback;
47 : :
48 : : //remove any previous part on that band
49 : 0 : removePartInfo( bandNumber );
50 : :
51 : : //split raster into small portions if necessary
52 : : RasterPartInfo pInfo;
53 : 0 : pInfo.nCols = nCols;
54 : 0 : pInfo.nRows = nRows;
55 : 0 : pInfo.currentCol = 0;
56 : 0 : pInfo.currentRow = 0;
57 : 0 : mRasterPartInfos.insert( bandNumber, pInfo );
58 : 0 : }
59 : :
60 : 0 : bool QgsRasterIterator::next( int bandNumber, int &columns, int &rows, int &topLeftColumn, int &topLeftRow, QgsRectangle &blockExtent )
61 : : {
62 : 0 : return readNextRasterPartInternal( bandNumber, columns, rows, nullptr, topLeftColumn, topLeftRow, &blockExtent );
63 : : }
64 : :
65 : 0 : bool QgsRasterIterator::readNextRasterPart( int bandNumber,
66 : : int &nCols, int &nRows,
67 : : QgsRasterBlock **block,
68 : : int &topLeftCol, int &topLeftRow )
69 : : {
70 : 0 : *block = nullptr;
71 : 0 : std::unique_ptr< QgsRasterBlock > nextBlock;
72 : 0 : bool result = readNextRasterPart( bandNumber, nCols, nRows, nextBlock, topLeftCol, topLeftRow );
73 : 0 : if ( result )
74 : 0 : *block = nextBlock.release();
75 : 0 : return result;
76 : 0 : }
77 : :
78 : 0 : bool QgsRasterIterator::readNextRasterPart( int bandNumber, int &nCols, int &nRows, std::unique_ptr<QgsRasterBlock> &block, int &topLeftCol, int &topLeftRow, QgsRectangle *blockExtent )
79 : : {
80 : 0 : return readNextRasterPartInternal( bandNumber, nCols, nRows, &block, topLeftCol, topLeftRow, blockExtent );
81 : : }
82 : :
83 : 0 : bool QgsRasterIterator::readNextRasterPartInternal( int bandNumber, int &nCols, int &nRows, std::unique_ptr<QgsRasterBlock> *block, int &topLeftCol, int &topLeftRow, QgsRectangle *blockExtent )
84 : : {
85 : 0 : QgsDebugMsgLevel( QStringLiteral( "Entered" ), 4 );
86 : 0 : if ( block )
87 : 0 : block->reset();
88 : : //get partinfo
89 : 0 : QMap<int, RasterPartInfo>::iterator partIt = mRasterPartInfos.find( bandNumber );
90 : 0 : if ( partIt == mRasterPartInfos.end() )
91 : : {
92 : 0 : return false;
93 : : }
94 : :
95 : 0 : RasterPartInfo &pInfo = partIt.value();
96 : :
97 : : // If we started with zero cols or zero rows, just return (avoids divide by zero below)
98 : 0 : if ( 0 == pInfo.nCols || 0 == pInfo.nRows )
99 : : {
100 : 0 : return false;
101 : : }
102 : :
103 : : //remove last data block
104 : :
105 : : //already at end
106 : 0 : if ( pInfo.currentCol == pInfo.nCols && pInfo.currentRow == pInfo.nRows )
107 : : {
108 : 0 : return false;
109 : : }
110 : :
111 : : //read data block
112 : 0 : nCols = static_cast< int >( std::min( static_cast< qgssize >( mMaximumTileWidth ), pInfo.nCols - pInfo.currentCol ) );
113 : 0 : nRows = static_cast< int >( std::min( static_cast< qgssize >( mMaximumTileHeight ), pInfo.nRows - pInfo.currentRow ) );
114 : 0 : QgsDebugMsgLevel( QStringLiteral( "nCols = %1 nRows = %2" ).arg( nCols ).arg( nRows ), 4 );
115 : :
116 : : //get subrectangle
117 : 0 : QgsRectangle viewPortExtent = mExtent;
118 : 0 : double xmin = viewPortExtent.xMinimum() + pInfo.currentCol / static_cast< double >( pInfo.nCols ) * viewPortExtent.width();
119 : 0 : double xmax = pInfo.currentCol + nCols == pInfo.nCols ? viewPortExtent.xMaximum() : // avoid extra FP math if not necessary
120 : 0 : viewPortExtent.xMinimum() + ( pInfo.currentCol + nCols ) / static_cast< double >( pInfo.nCols ) * viewPortExtent.width();
121 : 0 : double ymin = pInfo.currentRow + nRows == pInfo.nRows ? viewPortExtent.yMinimum() : // avoid extra FP math if not necessary
122 : 0 : viewPortExtent.yMaximum() - ( pInfo.currentRow + nRows ) / static_cast< double >( pInfo.nRows ) * viewPortExtent.height();
123 : 0 : double ymax = viewPortExtent.yMaximum() - pInfo.currentRow / static_cast< double >( pInfo.nRows ) * viewPortExtent.height();
124 : 0 : QgsRectangle blockRect( xmin, ymin, xmax, ymax );
125 : :
126 : 0 : if ( blockExtent )
127 : 0 : *blockExtent = blockRect;
128 : :
129 : 0 : if ( block )
130 : 0 : block->reset( mInput->block( bandNumber, blockRect, nCols, nRows, mFeedback ) );
131 : 0 : topLeftCol = pInfo.currentCol;
132 : 0 : topLeftRow = pInfo.currentRow;
133 : :
134 : 0 : pInfo.currentCol += nCols;
135 : 0 : if ( pInfo.currentCol == pInfo.nCols && pInfo.currentRow + nRows == pInfo.nRows ) //end of raster
136 : : {
137 : 0 : pInfo.currentRow = pInfo.nRows;
138 : 0 : }
139 : 0 : else if ( pInfo.currentCol == pInfo.nCols ) //start new row
140 : : {
141 : 0 : pInfo.currentCol = 0;
142 : 0 : pInfo.currentRow += nRows;
143 : 0 : }
144 : :
145 : 0 : return true;
146 : 0 : }
147 : :
148 : 0 : void QgsRasterIterator::stopRasterRead( int bandNumber )
149 : : {
150 : 0 : removePartInfo( bandNumber );
151 : 0 : }
152 : :
153 : 0 : void QgsRasterIterator::removePartInfo( int bandNumber )
154 : : {
155 : 0 : auto partIt = mRasterPartInfos.constFind( bandNumber );
156 : 0 : if ( partIt != mRasterPartInfos.constEnd() )
157 : : {
158 : 0 : mRasterPartInfos.remove( bandNumber );
159 : 0 : }
160 : 0 : }
|