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