QGIS API Documentation  2.12.0-Lyon
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( 0 )
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( 0 )
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 = 0; mColumns = 0; mRows = 0;
76  return data;
77 }
78 
80 {
81  return twoArgumentOperation( opPLUS, other );
82 }
83 
85 {
86  return twoArgumentOperation( opMINUS, other );
87 }
88 
90 {
91  return twoArgumentOperation( opMUL, other );
92 }
93 
95 {
96  return twoArgumentOperation( opDIV, other );
97 }
98 
100 {
101  return twoArgumentOperation( opPOW, other );
102 }
103 
105 {
106  return twoArgumentOperation( opEQ, other );
107 }
108 
110 {
111  return twoArgumentOperation( opNE, other );
112 }
113 
115 {
116  return twoArgumentOperation( opGT, other );
117 }
118 
120 {
121  return twoArgumentOperation( opLT, other );
122 }
123 
125 {
126  return twoArgumentOperation( opGE, other );
127 }
128 
130 {
131  return twoArgumentOperation( opLE, other );
132 }
133 
135 {
136  return twoArgumentOperation( opAND, other );
137 }
138 
140 {
141  return twoArgumentOperation( opOR, other );
142 }
143 
145 {
146  return oneArgumentOperation( opSQRT );
147 }
148 
150 {
151  return oneArgumentOperation( opSIN );
152 }
153 
155 {
156  return oneArgumentOperation( opASIN );
157 }
158 
160 {
161  return oneArgumentOperation( opCOS );
162 }
163 
165 {
166  return oneArgumentOperation( opACOS );
167 }
168 
170 {
171  return oneArgumentOperation( opTAN );
172 }
173 
175 {
176  return oneArgumentOperation( opATAN );
177 }
178 
180 {
181  return oneArgumentOperation( opSIGN );
182 }
183 
185 {
186  return oneArgumentOperation( opLOG );
187 }
188 
190 {
191  return oneArgumentOperation( opLOG10 );
192 }
193 
194 bool QgsRasterMatrix::oneArgumentOperation( OneArgOperator op )
195 {
196  if ( !mData )
197  {
198  return false;
199  }
200 
201  int nEntries = mColumns * mRows;
202  double value;
203  for ( int i = 0; i < nEntries; ++i )
204  {
205  value = mData[i];
206  if ( value != mNodataValue )
207  {
208  switch ( op )
209  {
210  case opSQRT:
211  if ( value < 0 ) //no complex numbers
212  {
213  mData[i] = mNodataValue;
214  }
215  else
216  {
217  mData[i] = sqrt( value );
218  }
219  break;
220  case opSIN:
221  mData[i] = sin( value );
222  break;
223  case opCOS:
224  mData[i] = cos( value );
225  break;
226  case opTAN:
227  mData[i] = tan( value );
228  break;
229  case opASIN:
230  mData[i] = asin( value );
231  break;
232  case opACOS:
233  mData[i] = acos( value );
234  break;
235  case opATAN:
236  mData[i] = atan( value );
237  break;
238  case opSIGN:
239  mData[i] = -value;
240  break;
241  case opLOG:
242  if ( value <= 0 )
243  {
244  mData[i] = mNodataValue;
245  }
246  else
247  {
248  mData[i] = ::log( value );
249  }
250  break;
251  case opLOG10:
252  if ( value <= 0 )
253  {
254  mData[i] = mNodataValue;
255  }
256  else
257  {
258  mData[i] = ::log10( value );
259  }
260  break;
261  }
262  }
263  }
264  return true;
265 }
266 
267 double QgsRasterMatrix::calculateTwoArgumentOp( TwoArgOperator op, double arg1, double arg2 ) const
268 {
269  switch ( op )
270  {
271  case opPLUS:
272  return arg1 + arg2;
273  case opMINUS:
274  return arg1 - arg2;
275  case opMUL:
276  return arg1 * arg2;
277  case opDIV:
278  if ( arg2 == 0 )
279  {
280  return mNodataValue;
281  }
282  else
283  {
284  return arg1 / arg2;
285  }
286  case opPOW:
287  if ( !testPowerValidity( arg1, arg2 ) )
288  {
289  return mNodataValue;
290  }
291  else
292  {
293  return qPow( arg1, arg2 );
294  }
295  case opEQ:
296  return ( arg1 == arg2 ? 1.0 : 0.0 );
297  case opNE:
298  return ( arg1 == arg2 ? 0.0 : 1.0 );
299  case opGT:
300  return ( arg1 > arg2 ? 1.0 : 0.0 );
301  case opLT:
302  return ( arg1 < arg2 ? 1.0 : 0.0 );
303  case opGE:
304  return ( arg1 >= arg2 ? 1.0 : 0.0 );
305  case opLE:
306  return ( arg1 <= arg2 ? 1.0 : 0.0 );
307  case opAND:
308  return ( arg1 && arg2 ? 1.0 : 0.0 );
309  case opOR:
310  return ( arg1 || arg2 ? 1.0 : 0.0 );
311  }
312  return mNodataValue;
313 }
314 
315 bool QgsRasterMatrix::twoArgumentOperation( TwoArgOperator op, const QgsRasterMatrix& other )
316 {
317  if ( isNumber() && other.isNumber() ) //operation on two 1x1 matrices
318  {
319  //operations with nodata values always generate nodata
320  if ( mData[0] == mNodataValue || other.number() == other.nodataValue() )
321  {
322  mData[0] = mNodataValue;
323  }
324  else
325  {
326  mData[0] = calculateTwoArgumentOp( op, mData[0], other.number() );
327  }
328  return true;
329  }
330 
331  //two matrices
332  if ( !isNumber() && !other.isNumber() )
333  {
334  double* matrix = other.mData;
335  int nEntries = mColumns * mRows;
336  double value1, value2;
337 
338  for ( int i = 0; i < nEntries; ++i )
339  {
340  value1 = mData[i]; value2 = matrix[i];
341  if ( value1 == mNodataValue || value2 == other.mNodataValue )
342  {
343  mData[i] = mNodataValue;
344  }
345  else
346  {
347  mData[i] = calculateTwoArgumentOp( op, value1, value2 );
348  }
349  }
350  return true;
351  }
352 
353  //this matrix is a single number and the other one a real matrix
354  if ( isNumber() )
355  {
356  double* matrix = other.mData;
357  int nEntries = other.nColumns() * other.nRows();
358  double value = mData[0];
359  delete[] mData;
360  mData = new double[nEntries]; mColumns = other.nColumns(); mRows = other.nRows();
361  mNodataValue = other.nodataValue();
362 
363  if ( value == mNodataValue )
364  {
365  for ( int i = 0; i < nEntries; ++i )
366  {
367  mData[i] = mNodataValue;
368  }
369  return true;
370  }
371 
372  for ( int i = 0; i < nEntries; ++i )
373  {
374  if ( matrix[i] == other.mNodataValue )
375  {
376  mData[i] = mNodataValue;
377  continue;
378  }
379 
380  mData[i] = calculateTwoArgumentOp( op, value, matrix[i] );
381  }
382  return true;
383  }
384  else //this matrix is a real matrix and the other a number
385  {
386  double value = other.number();
387  int nEntries = mColumns * mRows;
388 
389  if ( other.number() == other.mNodataValue )
390  {
391  for ( int i = 0; i < nEntries; ++i )
392  {
393  mData[i] = mNodataValue;
394  }
395  return true;
396  }
397 
398  for ( int i = 0; i < nEntries; ++i )
399  {
400  if ( mData[i] == mNodataValue )
401  {
402  continue;
403  }
404 
405  mData[i] = calculateTwoArgumentOp( op, mData[i], value );
406  }
407  return true;
408  }
409 }
410 
411 bool QgsRasterMatrix::testPowerValidity( double base, double power ) const
412 {
413  if (( base == 0 && power < 0 ) || ( base < 0 && ( power - floor( power ) ) > 0 ) )
414  {
415  return false;
416  }
417  return true;
418 }
double * takeData()
Returns data and ownership.
QgsRasterMatrix & operator=(const QgsRasterMatrix &m)
bool add(const QgsRasterMatrix &other)
Adds another matrix to this one.
bool power(const QgsRasterMatrix &other)
QgsRasterMatrix()
Takes ownership of data array.
bool greaterThan(const QgsRasterMatrix &other)
int nColumns() const
bool notEqual(const QgsRasterMatrix &other)
bool equal(const QgsRasterMatrix &other)
double number() 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.
int nRows() const
bool multiply(const QgsRasterMatrix &other)
bool isNumber() const
Returns true if matrix is 1x1 (=scalar number)
bool lesserEqual(const QgsRasterMatrix &other)
bool divide(const QgsRasterMatrix &other)
double ANALYSIS_EXPORT power(double a, int b)
Power function for integer coefficients.
double nodataValue() const
bool greaterEqual(const QgsRasterMatrix &other)
double * data()
Returns data array (but not ownership)
bool lesserThan(const QgsRasterMatrix &other)
bool logicalAnd(const QgsRasterMatrix &other)