Branch data Line data Source code
1 : : /***************************************************************************
2 : : qgsrastercalcnode.cpp
3 : : ---------------------
4 : : begin : October 2010
5 : : copyright : (C) 2010 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 "qgsrastercalcnode.h"
16 : : #include "qgsrasterblock.h"
17 : : #include "qgsrastermatrix.h"
18 : :
19 : 0 : QgsRasterCalcNode::QgsRasterCalcNode( double number )
20 : 0 : : mNumber( number )
21 : : {
22 : 0 : }
23 : :
24 : 0 : QgsRasterCalcNode::QgsRasterCalcNode( QgsRasterMatrix *matrix )
25 : 0 : : mType( tMatrix )
26 : 0 : , mMatrix( matrix )
27 : : {
28 : :
29 : 0 : }
30 : :
31 : 0 : QgsRasterCalcNode::QgsRasterCalcNode( Operator op, QgsRasterCalcNode *left, QgsRasterCalcNode *right )
32 : 0 : : mType( tOperator )
33 : 0 : , mLeft( left )
34 : 0 : , mRight( right )
35 : 0 : , mOperator( op )
36 : : {
37 : 0 : }
38 : :
39 : 0 : QgsRasterCalcNode::QgsRasterCalcNode( const QString &rasterName )
40 : 0 : : mType( tRasterRef )
41 : 0 : , mRasterName( rasterName )
42 : : {
43 : 0 : if ( mRasterName.startsWith( '"' ) && mRasterName.endsWith( '"' ) )
44 : 0 : mRasterName = mRasterName.mid( 1, mRasterName.size() - 2 );
45 : 0 : }
46 : :
47 : 0 : QgsRasterCalcNode::~QgsRasterCalcNode()
48 : : {
49 : 0 : delete mLeft;
50 : 0 : delete mRight;
51 : 0 : }
52 : :
53 : 0 : bool QgsRasterCalcNode::calculate( QMap<QString, QgsRasterBlock * > &rasterData, QgsRasterMatrix &result, int row ) const
54 : : {
55 : : //if type is raster ref: return a copy of the corresponding matrix
56 : :
57 : : //if type is operator, call the proper matrix operations
58 : 0 : if ( mType == tRasterRef )
59 : : {
60 : 0 : QMap<QString, QgsRasterBlock *>::iterator it = rasterData.find( mRasterName );
61 : 0 : if ( it == rasterData.end() )
62 : : {
63 : 0 : QgsDebugMsg( QStringLiteral( "Error: could not find raster data for \"%1\"" ).arg( mRasterName ) );
64 : 0 : return false;
65 : : }
66 : :
67 : 0 : int nRows = ( row >= 0 ? 1 : ( *it )->height() );
68 : 0 : int startRow = ( row >= 0 ? row : 0 );
69 : 0 : int endRow = startRow + nRows;
70 : 0 : int nCols = ( *it )->width();
71 : 0 : int nEntries = nCols * nRows;
72 : 0 : double *data = new double[nEntries];
73 : :
74 : : //convert input raster values to double, also convert input no data to result no data
75 : :
76 : 0 : int outRow = 0;
77 : 0 : bool isNoData = false;
78 : 0 : for ( int dataRow = startRow; dataRow < endRow ; ++dataRow, ++outRow )
79 : : {
80 : 0 : for ( int dataCol = 0; dataCol < nCols; ++dataCol )
81 : : {
82 : 0 : const double value = ( *it )->valueAndNoData( dataRow, dataCol, isNoData );
83 : 0 : data[ dataCol + nCols * outRow] = isNoData ? result.nodataValue() : value;
84 : 0 : }
85 : 0 : }
86 : 0 : result.setData( nCols, nRows, data, result.nodataValue() );
87 : 0 : return true;
88 : : }
89 : 0 : else if ( mType == tOperator )
90 : : {
91 : 0 : QgsRasterMatrix leftMatrix( result.nColumns(), result.nRows(), nullptr, result.nodataValue() );
92 : 0 : QgsRasterMatrix rightMatrix( result.nColumns(), result.nRows(), nullptr, result.nodataValue() );
93 : :
94 : 0 : if ( !mLeft || !mLeft->calculate( rasterData, leftMatrix, row ) )
95 : : {
96 : 0 : return false;
97 : : }
98 : 0 : if ( mRight && !mRight->calculate( rasterData, rightMatrix, row ) )
99 : : {
100 : 0 : return false;
101 : : }
102 : :
103 : 0 : switch ( mOperator )
104 : : {
105 : : case opPLUS:
106 : 0 : leftMatrix.add( rightMatrix );
107 : 0 : break;
108 : : case opMINUS:
109 : 0 : leftMatrix.subtract( rightMatrix );
110 : 0 : break;
111 : : case opMUL:
112 : 0 : leftMatrix.multiply( rightMatrix );
113 : 0 : break;
114 : : case opDIV:
115 : 0 : leftMatrix.divide( rightMatrix );
116 : 0 : break;
117 : : case opPOW:
118 : 0 : leftMatrix.power( rightMatrix );
119 : 0 : break;
120 : : case opEQ:
121 : 0 : leftMatrix.equal( rightMatrix );
122 : 0 : break;
123 : : case opNE:
124 : 0 : leftMatrix.notEqual( rightMatrix );
125 : 0 : break;
126 : : case opGT:
127 : 0 : leftMatrix.greaterThan( rightMatrix );
128 : 0 : break;
129 : : case opLT:
130 : 0 : leftMatrix.lesserThan( rightMatrix );
131 : 0 : break;
132 : : case opGE:
133 : 0 : leftMatrix.greaterEqual( rightMatrix );
134 : 0 : break;
135 : 0 : case opLE:
136 : 0 : leftMatrix.lesserEqual( rightMatrix );
137 : 0 : break;
138 : 0 : case opAND:
139 : 0 : leftMatrix.logicalAnd( rightMatrix );
140 : 0 : break;
141 : : case opOR:
142 : 0 : leftMatrix.logicalOr( rightMatrix );
143 : 0 : break;
144 : : case opMIN:
145 : 0 : leftMatrix.min( rightMatrix );
146 : 0 : break;
147 : : case opMAX:
148 : 0 : leftMatrix.max( rightMatrix );
149 : 0 : break;
150 : : case opSQRT:
151 : 0 : leftMatrix.squareRoot();
152 : 0 : break;
153 : : case opSIN:
154 : 0 : leftMatrix.sinus();
155 : 0 : break;
156 : : case opCOS:
157 : 0 : leftMatrix.cosinus();
158 : 0 : break;
159 : : case opTAN:
160 : 0 : leftMatrix.tangens();
161 : 0 : break;
162 : : case opASIN:
163 : 0 : leftMatrix.asinus();
164 : 0 : break;
165 : : case opACOS:
166 : 0 : leftMatrix.acosinus();
167 : 0 : break;
168 : : case opATAN:
169 : 0 : leftMatrix.atangens();
170 : 0 : break;
171 : : case opSIGN:
172 : 0 : leftMatrix.changeSign();
173 : 0 : break;
174 : : case opLOG:
175 : 0 : leftMatrix.log();
176 : 0 : break;
177 : : case opLOG10:
178 : 0 : leftMatrix.log10();
179 : 0 : break;
180 : : case opABS:
181 : 0 : leftMatrix.absoluteValue();
182 : 0 : break;
183 : : default:
184 : 0 : return false;
185 : : }
186 : 0 : int newNColumns = leftMatrix.nColumns();
187 : 0 : int newNRows = leftMatrix.nRows();
188 : 0 : result.setData( newNColumns, newNRows, leftMatrix.takeData(), leftMatrix.nodataValue() );
189 : 0 : return true;
190 : 0 : }
191 : 0 : else if ( mType == tNumber )
192 : : {
193 : 0 : size_t nEntries = static_cast<size_t>( result.nColumns() * result.nRows() );
194 : 0 : double *data = new double[ nEntries ];
195 : 0 : std::fill( data, data + nEntries, mNumber );
196 : 0 : result.setData( result.nColumns(), 1, data, result.nodataValue() );
197 : :
198 : 0 : return true;
199 : : }
200 : 0 : else if ( mType == tMatrix )
201 : : {
202 : 0 : int nEntries = mMatrix->nColumns() * mMatrix->nRows();
203 : 0 : double *data = new double[nEntries];
204 : 0 : for ( int i = 0; i < nEntries; ++i )
205 : : {
206 : 0 : data[i] = mMatrix->data()[i] == mMatrix->nodataValue() ? result.nodataValue() : mMatrix->data()[i];
207 : 0 : }
208 : 0 : result.setData( mMatrix->nColumns(), mMatrix->nRows(), data, result.nodataValue() );
209 : 0 : return true;
210 : : }
211 : 0 : return false;
212 : 0 : }
213 : :
214 : 0 : QString QgsRasterCalcNode::toString( bool cStyle ) const
215 : : {
216 : 0 : QString result;
217 : 0 : QString left;
218 : 0 : QString right;
219 : 0 : if ( mLeft )
220 : 0 : left = mLeft->toString( cStyle );
221 : 0 : if ( mRight )
222 : 0 : right = mRight->toString( cStyle );
223 : :
224 : 0 : switch ( mType )
225 : : {
226 : : case tOperator:
227 : 0 : switch ( mOperator )
228 : : {
229 : : case opPLUS:
230 : 0 : result = QStringLiteral( "( %1 + %2 )" ).arg( left ).arg( right );
231 : 0 : break;
232 : : case opMINUS:
233 : 0 : result = QStringLiteral( "( %1 - %2 )" ).arg( left ).arg( right );
234 : 0 : break;
235 : : case opSIGN:
236 : 0 : result = QStringLiteral( "-%1" ).arg( left );
237 : 0 : break;
238 : : case opMUL:
239 : 0 : result = QStringLiteral( "%1 * %2" ).arg( left ).arg( right );
240 : 0 : break;
241 : : case opDIV:
242 : 0 : result = QStringLiteral( "%1 / %2" ).arg( left ).arg( right );
243 : 0 : break;
244 : : case opPOW:
245 : 0 : if ( cStyle )
246 : 0 : result = QStringLiteral( "pow( %1, %2 )" ).arg( left ).arg( right );
247 : : else
248 : 0 : result = QStringLiteral( "%1^%2" ).arg( left ).arg( right );
249 : 0 : break;
250 : : case opEQ:
251 : 0 : if ( cStyle )
252 : 0 : result = QStringLiteral( "( float ) ( %1 == %2 )" ).arg( left ).arg( right );
253 : : else
254 : 0 : result = QStringLiteral( "%1 = %2" ).arg( left ).arg( right );
255 : 0 : break;
256 : : case opNE:
257 : 0 : if ( cStyle )
258 : 0 : result = QStringLiteral( "( float ) ( %1 != %2 )" ).arg( left ).arg( right );
259 : : else
260 : 0 : result = QStringLiteral( "%1 != %2" ).arg( left ).arg( right );
261 : 0 : break;
262 : : case opGT:
263 : 0 : if ( cStyle )
264 : 0 : result = QStringLiteral( "( float ) ( %1 > %2 )" ).arg( left ).arg( right );
265 : : else
266 : 0 : result = QStringLiteral( "%1 > %2" ).arg( left ).arg( right );
267 : 0 : break;
268 : : case opLT:
269 : 0 : if ( cStyle )
270 : 0 : result = QStringLiteral( "( float ) ( %1 < %2 )" ).arg( left ).arg( right );
271 : : else
272 : 0 : result = QStringLiteral( "%1 < %2" ).arg( left ).arg( right );
273 : 0 : break;
274 : : case opGE:
275 : 0 : if ( cStyle )
276 : 0 : result = QStringLiteral( "( float ) ( %1 >= %2 )" ).arg( left ).arg( right );
277 : : else
278 : 0 : result = QStringLiteral( "%1 >= %2" ).arg( left ).arg( right );
279 : 0 : break;
280 : : case opLE:
281 : 0 : if ( cStyle )
282 : 0 : result = QStringLiteral( "( float ) ( %1 <= %2 )" ).arg( left ).arg( right );
283 : : else
284 : 0 : result = QStringLiteral( "%1 <= %2" ).arg( left ).arg( right );
285 : 0 : break;
286 : : case opAND:
287 : 0 : if ( cStyle )
288 : 0 : result = QStringLiteral( "( float ) ( %1 && %2 )" ).arg( left ).arg( right );
289 : : else
290 : 0 : result = QStringLiteral( "%1 AND %2" ).arg( left ).arg( right );
291 : 0 : break;
292 : : case opOR:
293 : 0 : if ( cStyle )
294 : 0 : result = QStringLiteral( "( float ) ( %1 || %2 )" ).arg( left ).arg( right );
295 : : else
296 : 0 : result = QStringLiteral( "%1 OR %2" ).arg( left ).arg( right );
297 : 0 : break;
298 : : case opSQRT:
299 : 0 : result = QStringLiteral( "sqrt( %1 )" ).arg( left );
300 : 0 : break;
301 : : case opSIN:
302 : 0 : result = QStringLiteral( "sin( %1 )" ).arg( left );
303 : 0 : break;
304 : : case opCOS:
305 : 0 : result = QStringLiteral( "cos( %1 )" ).arg( left );
306 : 0 : break;
307 : : case opTAN:
308 : 0 : result = QStringLiteral( "tan( %1 )" ).arg( left );
309 : 0 : break;
310 : : case opASIN:
311 : 0 : result = QStringLiteral( "asin( %1 )" ).arg( left );
312 : 0 : break;
313 : : case opACOS:
314 : 0 : result = QStringLiteral( "acos( %1 )" ).arg( left );
315 : 0 : break;
316 : : case opATAN:
317 : 0 : result = QStringLiteral( "atan( %1 )" ).arg( left );
318 : 0 : break;
319 : : case opLOG:
320 : 0 : result = QStringLiteral( "log( %1 )" ).arg( left );
321 : 0 : break;
322 : : case opLOG10:
323 : 0 : result = QStringLiteral( "log10( %1 )" ).arg( left );
324 : 0 : break;
325 : : case opABS:
326 : 0 : if ( cStyle )
327 : 0 : result = QStringLiteral( "fabs( %1 )" ).arg( left );
328 : : else
329 : : // Call the floating point version
330 : 0 : result = QStringLiteral( "abs( %1 )" ).arg( left );
331 : 0 : break;
332 : : case opMIN:
333 : 0 : if ( cStyle )
334 : 0 : result = QStringLiteral( "min( ( float ) ( %1 ), ( float ) ( %2 ) )" ).arg( left ).arg( right );
335 : : else
336 : 0 : result = QStringLiteral( "min( %1, %2 )" ).arg( left ).arg( right );
337 : 0 : break;
338 : : case opMAX:
339 : 0 : if ( cStyle )
340 : 0 : result = QStringLiteral( "max( ( float ) ( %1 ), ( float ) ( %2 ) )" ).arg( left ).arg( right );
341 : : else
342 : 0 : result = QStringLiteral( "max( %1, %2 )" ).arg( left ).arg( right );
343 : 0 : break;
344 : : case opNONE:
345 : 0 : break;
346 : : }
347 : 0 : break;
348 : : case tRasterRef:
349 : 0 : if ( cStyle )
350 : 0 : result = QStringLiteral( "( float ) \"%1\"" ).arg( mRasterName );
351 : : else
352 : 0 : result = QStringLiteral( "\"%1\"" ).arg( mRasterName );
353 : 0 : break;
354 : : case tNumber:
355 : 0 : result = QString::number( mNumber );
356 : 0 : if ( cStyle )
357 : : {
358 : 0 : result = QStringLiteral( "( float ) %1" ).arg( result );
359 : 0 : }
360 : 0 : break;
361 : : case tMatrix:
362 : 0 : break;
363 : : }
364 : 0 : return result;
365 : 0 : }
366 : :
367 : 0 : QList<const QgsRasterCalcNode *> QgsRasterCalcNode::findNodes( const QgsRasterCalcNode::Type type ) const
368 : : {
369 : 0 : QList<const QgsRasterCalcNode *> nodeList;
370 : 0 : if ( mType == type )
371 : 0 : nodeList.push_back( this );
372 : 0 : if ( mLeft )
373 : 0 : nodeList.append( mLeft->findNodes( type ) );
374 : 0 : if ( mRight )
375 : 0 : nodeList.append( mRight->findNodes( type ) );
376 : 0 : return nodeList;
377 : 0 : }
378 : :
379 : 0 : QgsRasterCalcNode *QgsRasterCalcNode::parseRasterCalcString( const QString &str, QString &parserErrorMsg )
380 : : {
381 : : extern QgsRasterCalcNode *localParseRasterCalcString( const QString & str, QString & parserErrorMsg );
382 : 0 : return localParseRasterCalcString( str, parserErrorMsg );
383 : : }
384 : :
|