QGIS API Documentation  2.18.21-Las Palmas (9fba24a)
qgsrastermatrix.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsrastermatrix.cpp
3  -------------------
4  begin : 2010-10-23
5  copyright : (C) 20010 by Marco Hugentobler
6  email : marco dot hugentobler at sourcepole dot ch
7 ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #include "qgsrastermatrix.h"
19 #include <string.h>
20 #include <qmath.h>
21 
23  : mColumns( 0 )
24  , mRows( 0 )
25  , mData( nullptr )
26  , mNodataValue( -1 )
27 {
28 }
29 
30 QgsRasterMatrix::QgsRasterMatrix( int nCols, int nRows, double* data, double nodataValue )
31  : mColumns( nCols )
32  , mRows( nRows )
33  , mData( data )
34  , mNodataValue( nodataValue )
35 {
36 }
37 
39  : mColumns( 0 )
40  , mRows( 0 )
41  , mData( nullptr )
42 {
43  operator=( m );
44 }
45 
47 {
48  delete[] mData;
49 }
50 
52 {
53  delete[] mData;
54  mColumns = m.nColumns();
55  mRows = m.nRows();
56  int nEntries = mColumns * mRows;
57  mData = new double[nEntries];
58  memcpy( mData, m.mData, sizeof( double ) * nEntries );
59  mNodataValue = m.nodataValue();
60  return *this;
61 }
62 
63 void QgsRasterMatrix::setData( int cols, int rows, double* data, double nodataValue )
64 {
65  delete[] mData;
66  mColumns = cols;
67  mRows = rows;
68  mData = data;
69  mNodataValue = nodataValue;
70 }
71 
73 {
74  double* data = mData;
75  mData = nullptr;
76  mColumns = 0;
77  mRows = 0;
78  return data;
79 }
80 
82 {
83  return twoArgumentOperation( opPLUS, other );
84 }
85 
87 {
88  return twoArgumentOperation( opMINUS, other );
89 }
90 
92 {
93  return twoArgumentOperation( opMUL, other );
94 }
95 
97 {
98  return twoArgumentOperation( opDIV, other );
99 }
100 
102 {
103  return twoArgumentOperation( opPOW, other );
104 }
105 
107 {
108  return twoArgumentOperation( opEQ, other );
109 }
110 
112 {
113  return twoArgumentOperation( opNE, other );
114 }
115 
117 {
118  return twoArgumentOperation( opGT, other );
119 }
120 
122 {
123  return twoArgumentOperation( opLT, other );
124 }
125 
127 {
128  return twoArgumentOperation( opGE, other );
129 }
130 
132 {
133  return twoArgumentOperation( opLE, other );
134 }
135 
137 {
138  return twoArgumentOperation( opAND, other );
139 }
140 
142 {
143  return twoArgumentOperation( opOR, other );
144 }
145 
147 {
148  return oneArgumentOperation( opSQRT );
149 }
150 
152 {
153  return oneArgumentOperation( opSIN );
154 }
155 
157 {
158  return oneArgumentOperation( opASIN );
159 }
160 
162 {
163  return oneArgumentOperation( opCOS );
164 }
165 
167 {
168  return oneArgumentOperation( opACOS );
169 }
170 
172 {
173  return oneArgumentOperation( opTAN );
174 }
175 
177 {
178  return oneArgumentOperation( opATAN );
179 }
180 
182 {
183  return oneArgumentOperation( opSIGN );
184 }
185 
187 {
188  return oneArgumentOperation( opLOG );
189 }
190 
192 {
193  return oneArgumentOperation( opLOG10 );
194 }
195 
196 bool QgsRasterMatrix::oneArgumentOperation( OneArgOperator op )
197 {
198  if ( !mData )
199  {
200  return false;
201  }
202 
203  int nEntries = mColumns * mRows;
204  double value;
205  for ( int i = 0; i < nEntries; ++i )
206  {
207  value = mData[i];
208  if ( value != mNodataValue )
209  {
210  switch ( op )
211  {
212  case opSQRT:
213  if ( value < 0 ) //no complex numbers
214  {
215  mData[i] = mNodataValue;
216  }
217  else
218  {
219  mData[i] = sqrt( value );
220  }
221  break;
222  case opSIN:
223  mData[i] = sin( value );
224  break;
225  case opCOS:
226  mData[i] = cos( value );
227  break;
228  case opTAN:
229  mData[i] = tan( value );
230  break;
231  case opASIN:
232  mData[i] = asin( value );
233  break;
234  case opACOS:
235  mData[i] = acos( value );
236  break;
237  case opATAN:
238  mData[i] = atan( value );
239  break;
240  case opSIGN:
241  mData[i] = -value;
242  break;
243  case opLOG:
244  if ( value <= 0 )
245  {
246  mData[i] = mNodataValue;
247  }
248  else
249  {
250  mData[i] = ::log( value );
251  }
252  break;
253  case opLOG10:
254  if ( value <= 0 )
255  {
256  mData[i] = mNodataValue;
257  }
258  else
259  {
260  mData[i] = ::log10( value );
261  }
262  break;
263  }
264  }
265  }
266  return true;
267 }
268 
269 double QgsRasterMatrix::calculateTwoArgumentOp( TwoArgOperator op, double arg1, double arg2 ) const
270 {
271  switch ( op )
272  {
273  case opPLUS:
274  return arg1 + arg2;
275  case opMINUS:
276  return arg1 - arg2;
277  case opMUL:
278  return arg1 * arg2;
279  case opDIV:
280  if ( arg2 == 0 )
281  {
282  return mNodataValue;
283  }
284  else
285  {
286  return arg1 / arg2;
287  }
288  case opPOW:
289  if ( !testPowerValidity( arg1, arg2 ) )
290  {
291  return mNodataValue;
292  }
293  else
294  {
295  return qPow( arg1, arg2 );
296  }
297  case opEQ:
298  return ( arg1 == arg2 ? 1.0 : 0.0 );
299  case opNE:
300  return ( arg1 == arg2 ? 0.0 : 1.0 );
301  case opGT:
302  return ( arg1 > arg2 ? 1.0 : 0.0 );
303  case opLT:
304  return ( arg1 < arg2 ? 1.0 : 0.0 );
305  case opGE:
306  return ( arg1 >= arg2 ? 1.0 : 0.0 );
307  case opLE:
308  return ( arg1 <= arg2 ? 1.0 : 0.0 );
309  case opAND:
310  return ( arg1 && arg2 ? 1.0 : 0.0 );
311  case opOR:
312  return ( arg1 || arg2 ? 1.0 : 0.0 );
313  }
314  return mNodataValue;
315 }
316 
317 bool QgsRasterMatrix::twoArgumentOperation( TwoArgOperator op, const QgsRasterMatrix& other )
318 {
319  if ( isNumber() && other.isNumber() ) //operation on two 1x1 matrices
320  {
321  //operations with nodata values always generate nodata
322  if ( mData[0] == mNodataValue || other.number() == other.nodataValue() )
323  {
324  mData[0] = mNodataValue;
325  }
326  else
327  {
328  mData[0] = calculateTwoArgumentOp( op, mData[0], other.number() );
329  }
330  return true;
331  }
332 
333  //two matrices
334  if ( !isNumber() && !other.isNumber() )
335  {
336  double* matrix = other.mData;
337  int nEntries = mColumns * mRows;
338  double value1, value2;
339 
340  for ( int i = 0; i < nEntries; ++i )
341  {
342  value1 = mData[i];
343  value2 = matrix[i];
344  if ( value1 == mNodataValue || value2 == other.mNodataValue )
345  {
346  mData[i] = mNodataValue;
347  }
348  else
349  {
350  mData[i] = calculateTwoArgumentOp( op, value1, value2 );
351  }
352  }
353  return true;
354  }
355 
356  //this matrix is a single number and the other one a real matrix
357  if ( isNumber() )
358  {
359  double* matrix = other.mData;
360  int nEntries = other.nColumns() * other.nRows();
361  double value = mData[0];
362  delete[] mData;
363  mData = new double[nEntries];
364  mColumns = other.nColumns();
365  mRows = other.nRows();
366  mNodataValue = other.nodataValue();
367 
368  if ( value == mNodataValue )
369  {
370  for ( int i = 0; i < nEntries; ++i )
371  {
372  mData[i] = mNodataValue;
373  }
374  return true;
375  }
376 
377  for ( int i = 0; i < nEntries; ++i )
378  {
379  if ( matrix[i] == other.mNodataValue )
380  {
381  mData[i] = mNodataValue;
382  continue;
383  }
384 
385  mData[i] = calculateTwoArgumentOp( op, value, matrix[i] );
386  }
387  return true;
388  }
389  else //this matrix is a real matrix and the other a number
390  {
391  double value = other.number();
392  int nEntries = mColumns * mRows;
393 
394  if ( other.number() == other.mNodataValue )
395  {
396  for ( int i = 0; i < nEntries; ++i )
397  {
398  mData[i] = mNodataValue;
399  }
400  return true;
401  }
402 
403  for ( int i = 0; i < nEntries; ++i )
404  {
405  if ( mData[i] == mNodataValue )
406  {
407  continue;
408  }
409 
410  mData[i] = calculateTwoArgumentOp( op, mData[i], value );
411  }
412  return true;
413  }
414 }
415 
416 bool QgsRasterMatrix::testPowerValidity( double base, double power ) const
417 {
418  if (( base == 0 && power < 0 ) || ( base < 0 && ( power - floor( power ) ) > 0 ) )
419  {
420  return false;
421  }
422  return true;
423 }
double * takeData()
Returns data and ownership.
bool isNumber() const
Returns true if matrix is 1x1 (=scalar number)
QgsRasterMatrix & operator=(const QgsRasterMatrix &m)
bool add(const QgsRasterMatrix &other)
Adds another matrix to this one.
double nodataValue() const
bool power(const QgsRasterMatrix &other)
QgsRasterMatrix()
Takes ownership of data array.
bool greaterThan(const QgsRasterMatrix &other)
bool notEqual(const QgsRasterMatrix &other)
bool equal(const QgsRasterMatrix &other)
int nRows() const
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.
bool multiply(const QgsRasterMatrix &other)
int nColumns() const
bool lesserEqual(const QgsRasterMatrix &other)
bool divide(const QgsRasterMatrix &other)
bool greaterEqual(const QgsRasterMatrix &other)
double number() const
double * data()
Returns data array (but not ownership)
bool lesserThan(const QgsRasterMatrix &other)
bool logicalAnd(const QgsRasterMatrix &other)