QGIS API Documentation  3.4.15-Madeira (e83d02e274)
qgsrastercalcnode.cpp
Go to the documentation of this file.
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 #include <cfloat>
19 #include <QtDebug>
20 
22  : mNumber( number )
23 {
24 }
25 
27  : mType( tMatrix )
28  , mMatrix( matrix )
29 {
30 
31 }
32 
34  : mType( tOperator )
35  , mLeft( left )
36  , mRight( right )
37  , mOperator( op )
38 {
39 }
40 
41 QgsRasterCalcNode::QgsRasterCalcNode( const QString &rasterName )
42  : mType( tRasterRef )
43  , mRasterName( rasterName )
44 {
45  if ( mRasterName.startsWith( '"' ) && mRasterName.endsWith( '"' ) )
46  mRasterName = mRasterName.mid( 1, mRasterName.size() - 2 );
47 }
48 
50 {
51  delete mLeft;
52  delete mRight;
53 }
54 
55 bool QgsRasterCalcNode::calculate( QMap<QString, QgsRasterBlock * > &rasterData, QgsRasterMatrix &result, int row ) const
56 {
57  //if type is raster ref: return a copy of the corresponding matrix
58 
59  //if type is operator, call the proper matrix operations
60  if ( mType == tRasterRef )
61  {
62  QMap<QString, QgsRasterBlock *>::iterator it = rasterData.find( mRasterName );
63  if ( it == rasterData.end() )
64  {
65  return false;
66  }
67 
68  int nRows = ( row >= 0 ? 1 : ( *it )->height() );
69  int startRow = ( row >= 0 ? row : 0 );
70  int endRow = startRow + nRows;
71  int nCols = ( *it )->width();
72  int nEntries = nCols * nRows;
73  double *data = new double[nEntries];
74 
75  //convert input raster values to double, also convert input no data to result no data
76 
77  int outRow = 0;
78  for ( int dataRow = startRow; dataRow < endRow ; ++dataRow, ++outRow )
79  {
80  for ( int dataCol = 0; dataCol < nCols; ++dataCol )
81  {
82  data[ dataCol + nCols * outRow] = ( *it )->isNoData( dataRow, dataCol ) ? result.nodataValue() : ( *it )->value( dataRow, dataCol );
83  }
84  }
85  result.setData( nCols, nRows, data, result.nodataValue() );
86  return true;
87  }
88  else if ( mType == tOperator )
89  {
90  QgsRasterMatrix leftMatrix, rightMatrix;
91  leftMatrix.setNodataValue( result.nodataValue() );
92  rightMatrix.setNodataValue( result.nodataValue() );
93 
94  if ( !mLeft || !mLeft->calculate( rasterData, leftMatrix, row ) )
95  {
96  return false;
97  }
98  if ( mRight && !mRight->calculate( rasterData, rightMatrix, row ) )
99  {
100  return false;
101  }
102 
103  switch ( mOperator )
104  {
105  case opPLUS:
106  leftMatrix.add( rightMatrix );
107  break;
108  case opMINUS:
109  leftMatrix.subtract( rightMatrix );
110  break;
111  case opMUL:
112  leftMatrix.multiply( rightMatrix );
113  break;
114  case opDIV:
115  leftMatrix.divide( rightMatrix );
116  break;
117  case opPOW:
118  leftMatrix.power( rightMatrix );
119  break;
120  case opEQ:
121  leftMatrix.equal( rightMatrix );
122  break;
123  case opNE:
124  leftMatrix.notEqual( rightMatrix );
125  break;
126  case opGT:
127  leftMatrix.greaterThan( rightMatrix );
128  break;
129  case opLT:
130  leftMatrix.lesserThan( rightMatrix );
131  break;
132  case opGE:
133  leftMatrix.greaterEqual( rightMatrix );
134  break;
135  case opLE:
136  leftMatrix.lesserEqual( rightMatrix );
137  break;
138  case opAND:
139  leftMatrix.logicalAnd( rightMatrix );
140  break;
141  case opOR:
142  leftMatrix.logicalOr( rightMatrix );
143  break;
144  case opSQRT:
145  leftMatrix.squareRoot();
146  break;
147  case opSIN:
148  leftMatrix.sinus();
149  break;
150  case opCOS:
151  leftMatrix.cosinus();
152  break;
153  case opTAN:
154  leftMatrix.tangens();
155  break;
156  case opASIN:
157  leftMatrix.asinus();
158  break;
159  case opACOS:
160  leftMatrix.acosinus();
161  break;
162  case opATAN:
163  leftMatrix.atangens();
164  break;
165  case opSIGN:
166  leftMatrix.changeSign();
167  break;
168  case opLOG:
169  leftMatrix.log();
170  break;
171  case opLOG10:
172  leftMatrix.log10();
173  break;
174  default:
175  return false;
176  }
177  int newNColumns = leftMatrix.nColumns();
178  int newNRows = leftMatrix.nRows();
179  result.setData( newNColumns, newNRows, leftMatrix.takeData(), leftMatrix.nodataValue() );
180  return true;
181  }
182  else if ( mType == tNumber )
183  {
184  double *data = new double[1];
185  data[0] = mNumber;
186  result.setData( 1, 1, data, result.nodataValue() );
187  return true;
188  }
189  else if ( mType == tMatrix )
190  {
191  int nEntries = mMatrix->nColumns() * mMatrix->nRows();
192  double *data = new double[nEntries];
193  for ( int i = 0; i < nEntries; ++i )
194  {
195  data[i] = mMatrix->data()[i] == mMatrix->nodataValue() ? result.nodataValue() : mMatrix->data()[i];
196  }
197  result.setData( mMatrix->nColumns(), mMatrix->nRows(), data, result.nodataValue() );
198  return true;
199  }
200  return false;
201 }
202 
203 QString QgsRasterCalcNode::toString( bool cStyle ) const
204 {
205  QString result;
206  QString left;
207  QString right;
208  if ( mLeft )
209  left = mLeft->toString( cStyle );
210  if ( mRight )
211  right = mRight->toString( cStyle );
212  switch ( mType )
213  {
214  case tOperator:
215  switch ( mOperator )
216  {
217  case opPLUS:
218  result = QStringLiteral( "%1 + %2" ).arg( left ).arg( right );
219  break;
220  case opMINUS:
221  case opSIGN:
222  result = QStringLiteral( "%1 - %2" ).arg( left ).arg( right );
223  break;
224  case opMUL:
225  result = QStringLiteral( "%1 * %2" ).arg( left ).arg( right );
226  break;
227  case opDIV:
228  result = QStringLiteral( "%1 / %2" ).arg( left ).arg( right );
229  break;
230  case opPOW:
231  if ( cStyle )
232  result = QStringLiteral( "pow( %1, %2 )" ).arg( left ).arg( right );
233  else
234  result = QStringLiteral( "%1^%2" ).arg( left ).arg( right );
235  break;
236  case opEQ:
237  if ( cStyle )
238  result = QStringLiteral( "%1 == %2" ).arg( left ).arg( right );
239  else
240  result = QStringLiteral( "%1 = %2" ).arg( left ).arg( right );
241  break;
242  case opNE:
243  result = QStringLiteral( "%1 != %2" ).arg( left ).arg( right );
244  break;
245  case opGT:
246  result = QStringLiteral( "%1 > %2" ).arg( left ).arg( right );
247  break;
248  case opLT:
249  result = QStringLiteral( "%1 < %2" ).arg( left ).arg( right );
250  break;
251  case opGE:
252  result = QStringLiteral( "%1 >= %2" ).arg( left ).arg( right );
253  break;
254  case opLE:
255  result = QStringLiteral( "%1 <= %2" ).arg( left ).arg( right );
256  break;
257  case opAND:
258  if ( cStyle )
259  result = QStringLiteral( "%1 && %2" ).arg( left ).arg( right );
260  else
261  result = QStringLiteral( "%1 AND %2" ).arg( left ).arg( right );
262  break;
263  case opOR:
264  if ( cStyle )
265  result = QStringLiteral( "%1 || %2" ).arg( left ).arg( right );
266  else
267  result = QStringLiteral( "%1 OR %2" ).arg( left ).arg( right );
268  break;
269  case opSQRT:
270  result = QStringLiteral( "sqrt( %1 )" ).arg( left );
271  break;
272  case opSIN:
273  result = QStringLiteral( "sin( %1 )" ).arg( left );
274  break;
275  case opCOS:
276  result = QStringLiteral( "cos( %1 )" ).arg( left );
277  break;
278  case opTAN:
279  result = QStringLiteral( "tan( %1 )" ).arg( left );
280  break;
281  case opASIN:
282  result = QStringLiteral( "asin( %1 )" ).arg( left );
283  break;
284  case opACOS:
285  result = QStringLiteral( "acos( %1 )" ).arg( left );
286  break;
287  case opATAN:
288  result = QStringLiteral( "atan( %1 )" ).arg( left );
289  break;
290  case opLOG:
291  result = QStringLiteral( "log( %1 )" ).arg( left );
292  break;
293  case opLOG10:
294  result = QStringLiteral( "log10( %1 )" ).arg( left );
295  break;
296  case opNONE:
297  break;
298  }
299  break;
300  case tRasterRef:
301  result = QStringLiteral( "\"%1\"" ).arg( mRasterName );
302  break;
303  case tNumber:
304  result = QString::number( mNumber );
305  break;
306  case tMatrix:
307  break;
308  }
309  return result;
310 }
311 
312 QList<const QgsRasterCalcNode *> QgsRasterCalcNode::findNodes( const QgsRasterCalcNode::Type type ) const
313 {
314  QList<const QgsRasterCalcNode *> nodeList;
315  if ( mType == type )
316  nodeList.push_back( this );
317  if ( mLeft )
318  nodeList.append( mLeft->findNodes( type ) );
319  if ( mRight )
320  nodeList.append( mRight->findNodes( type ) );
321  return nodeList;
322 }
323 
324 QgsRasterCalcNode *QgsRasterCalcNode::parseRasterCalcString( const QString &str, QString &parserErrorMsg )
325 {
326  extern QgsRasterCalcNode *localParseRasterCalcString( const QString & str, QString & parserErrorMsg );
327  return localParseRasterCalcString( str, parserErrorMsg );
328 }
329 
double * takeData()
Returns data and ownership.
bool calculate(QMap< QString, QgsRasterBlock * > &rasterData, QgsRasterMatrix &result, int row=-1) const
Calculates result of raster calculation (might be real matrix or single number).
bool add(const QgsRasterMatrix &other)
Adds another matrix to this one.
void setNodataValue(double d)
bool power(const QgsRasterMatrix &other)
QList< const QgsRasterCalcNode * > findNodes(const QgsRasterCalcNode::Type type) const
Returns a list of nodes of a specific type.
bool greaterThan(const QgsRasterMatrix &other)
QString toString(bool cStyle=false) const
Returns a string representation of the expression.
int nColumns() const
bool notEqual(const QgsRasterMatrix &other)
bool equal(const QgsRasterMatrix &other)
bool logicalOr(const QgsRasterMatrix &other)
void setData(int cols, int rows, double *data, double nodataValue)
bool subtract(const QgsRasterMatrix &other)
Subtracts another matrix from this one.
int nRows() const
Type
defines possible types of node
Operator
possible operators
QgsRasterCalcNode()=default
Constructor for QgsRasterCalcNode.
bool multiply(const QgsRasterMatrix &other)
bool lesserEqual(const QgsRasterMatrix &other)
bool divide(const QgsRasterMatrix &other)
double nodataValue() const
bool greaterEqual(const QgsRasterMatrix &other)
double * data()
Returns data array (but not ownership)
static QgsRasterCalcNode * parseRasterCalcString(const QString &str, QString &parserErrorMsg)
bool lesserThan(const QgsRasterMatrix &other)
Type type() const
bool logicalAnd(const QgsRasterMatrix &other)