QGIS API Documentation  2.99.0-Master (53aba61)
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 
21  : mType( tNumber )
22  , mNumber( 0 )
23  , mOperator( opNONE )
24 {
25 }
26 
28  : mType( tNumber )
29  , mNumber( number )
30  , mOperator( opNONE )
31 {
32 }
33 
35  : mType( tMatrix )
36  , mNumber( 0 )
37  , mMatrix( matrix )
38  , mOperator( opNONE )
39 {
40 
41 }
42 
44  : mType( tOperator )
45  , mLeft( left )
46  , mRight( right )
47  , mNumber( 0 )
48  , mOperator( op )
49 {
50 }
51 
52 QgsRasterCalcNode::QgsRasterCalcNode( const QString &rasterName )
53  : mType( tRasterRef )
54  , mNumber( 0 )
55  , mRasterName( rasterName )
56  , mOperator( opNONE )
57 {
58  if ( mRasterName.startsWith( '"' ) && mRasterName.endsWith( '"' ) )
59  mRasterName = mRasterName.mid( 1, mRasterName.size() - 2 );
60 }
61 
63 {
64  if ( mLeft )
65  {
66  delete mLeft;
67  }
68  if ( mRight )
69  {
70  delete mRight;
71  }
72 }
73 
74 bool QgsRasterCalcNode::calculate( QMap<QString, QgsRasterBlock * > &rasterData, QgsRasterMatrix &result, int row ) const
75 {
76  //if type is raster ref: return a copy of the corresponding matrix
77 
78  //if type is operator, call the proper matrix operations
79  if ( mType == tRasterRef )
80  {
81  QMap<QString, QgsRasterBlock *>::iterator it = rasterData.find( mRasterName );
82  if ( it == rasterData.end() )
83  {
84  return false;
85  }
86 
87  int nRows = ( row >= 0 ? 1 : ( *it )->height() );
88  int startRow = ( row >= 0 ? row : 0 );
89  int endRow = startRow + nRows;
90  int nCols = ( *it )->width();
91  int nEntries = nCols * nRows;
92  double *data = new double[nEntries];
93 
94  //convert input raster values to double, also convert input no data to result no data
95 
96  int outRow = 0;
97  for ( int dataRow = startRow; dataRow < endRow ; ++dataRow, ++outRow )
98  {
99  for ( int dataCol = 0; dataCol < nCols; ++dataCol )
100  {
101  data[ dataCol + nCols * outRow] = ( *it )->isNoData( dataRow, dataCol ) ? result.nodataValue() : ( *it )->value( dataRow, dataCol );
102  }
103  }
104  result.setData( nCols, nRows, data, result.nodataValue() );
105  return true;
106  }
107  else if ( mType == tOperator )
108  {
109  QgsRasterMatrix leftMatrix, rightMatrix;
110  leftMatrix.setNodataValue( result.nodataValue() );
111  rightMatrix.setNodataValue( result.nodataValue() );
112 
113  if ( !mLeft || !mLeft->calculate( rasterData, leftMatrix, row ) )
114  {
115  return false;
116  }
117  if ( mRight && !mRight->calculate( rasterData, rightMatrix, row ) )
118  {
119  return false;
120  }
121 
122  switch ( mOperator )
123  {
124  case opPLUS:
125  leftMatrix.add( rightMatrix );
126  break;
127  case opMINUS:
128  leftMatrix.subtract( rightMatrix );
129  break;
130  case opMUL:
131  leftMatrix.multiply( rightMatrix );
132  break;
133  case opDIV:
134  leftMatrix.divide( rightMatrix );
135  break;
136  case opPOW:
137  leftMatrix.power( rightMatrix );
138  break;
139  case opEQ:
140  leftMatrix.equal( rightMatrix );
141  break;
142  case opNE:
143  leftMatrix.notEqual( rightMatrix );
144  break;
145  case opGT:
146  leftMatrix.greaterThan( rightMatrix );
147  break;
148  case opLT:
149  leftMatrix.lesserThan( rightMatrix );
150  break;
151  case opGE:
152  leftMatrix.greaterEqual( rightMatrix );
153  break;
154  case opLE:
155  leftMatrix.lesserEqual( rightMatrix );
156  break;
157  case opAND:
158  leftMatrix.logicalAnd( rightMatrix );
159  break;
160  case opOR:
161  leftMatrix.logicalOr( rightMatrix );
162  break;
163  case opSQRT:
164  leftMatrix.squareRoot();
165  break;
166  case opSIN:
167  leftMatrix.sinus();
168  break;
169  case opCOS:
170  leftMatrix.cosinus();
171  break;
172  case opTAN:
173  leftMatrix.tangens();
174  break;
175  case opASIN:
176  leftMatrix.asinus();
177  break;
178  case opACOS:
179  leftMatrix.acosinus();
180  break;
181  case opATAN:
182  leftMatrix.atangens();
183  break;
184  case opSIGN:
185  leftMatrix.changeSign();
186  break;
187  case opLOG:
188  leftMatrix.log();
189  break;
190  case opLOG10:
191  leftMatrix.log10();
192  break;
193  default:
194  return false;
195  }
196  int newNColumns = leftMatrix.nColumns();
197  int newNRows = leftMatrix.nRows();
198  result.setData( newNColumns, newNRows, leftMatrix.takeData(), leftMatrix.nodataValue() );
199  return true;
200  }
201  else if ( mType == tNumber )
202  {
203  double *data = new double[1];
204  data[0] = mNumber;
205  result.setData( 1, 1, data, result.nodataValue() );
206  return true;
207  }
208  else if ( mType == tMatrix )
209  {
210  int nEntries = mMatrix->nColumns() * mMatrix->nRows();
211  double *data = new double[nEntries];
212  for ( int i = 0; i < nEntries; ++i )
213  {
214  data[i] = mMatrix->data()[i] == mMatrix->nodataValue() ? result.nodataValue() : mMatrix->data()[i];
215  }
216  result.setData( mMatrix->nColumns(), mMatrix->nRows(), data, result.nodataValue() );
217  return true;
218  }
219  return false;
220 }
221 
222 QgsRasterCalcNode *QgsRasterCalcNode::parseRasterCalcString( const QString &str, QString &parserErrorMsg )
223 {
224  extern QgsRasterCalcNode *localParseRasterCalcString( const QString & str, QString & parserErrorMsg );
225  return localParseRasterCalcString( str, parserErrorMsg );
226 }
227 
double * takeData()
Returns data and ownership.
bool add(const QgsRasterMatrix &other)
Adds another matrix to this one.
void setNodataValue(double d)
double nodataValue() const
bool power(const QgsRasterMatrix &other)
bool greaterThan(const QgsRasterMatrix &other)
bool notEqual(const QgsRasterMatrix &other)
bool equal(const QgsRasterMatrix &other)
int nRows() const
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 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.
Operator
possible operators
bool multiply(const QgsRasterMatrix &other)
int nColumns() const
bool lesserEqual(const QgsRasterMatrix &other)
bool divide(const QgsRasterMatrix &other)
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)
bool logicalAnd(const QgsRasterMatrix &other)