QGIS API Documentation 3.99.0-Master (26c88405ac0)
Loading...
Searching...
No Matches
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
20#include <algorithm>
21#include <cmath>
22#include <cstring>
23
24QgsRasterMatrix::QgsRasterMatrix( int nCols, int nRows, double *data, double nodataValue )
25 : mColumns( nCols )
26 , mRows( nRows )
27 , mData( data )
28 , mNodataValue( nodataValue )
29{
30}
31
36
38{
39 delete[] mData;
40}
41
43{
44 if ( this != &m )
45 {
46 delete[] mData;
47 mColumns = m.nColumns();
48 mRows = m.nRows();
49 const int nEntries = mColumns * mRows;
50 mData = new double[nEntries];
51 memcpy( mData, m.mData, sizeof( double ) * nEntries );
52 mNodataValue = m.nodataValue();
53 }
54 return *this;
55}
56
57void QgsRasterMatrix::setData( int cols, int rows, double *data, double nodataValue )
58{
59 delete[] mData;
60 mColumns = cols;
61 mRows = rows;
62 mData = data;
63 mNodataValue = nodataValue;
64}
65
67{
68 double *data = mData;
69 mData = nullptr;
70 mColumns = 0;
71 mRows = 0;
72 return data;
73}
74
76{
77 return twoArgumentOperation( opPLUS, other );
78}
79
81{
82 return twoArgumentOperation( opMINUS, other );
83}
84
86{
87 return twoArgumentOperation( opMUL, other );
88}
89
91{
92 return twoArgumentOperation( opDIV, other );
93}
94
96{
97 return twoArgumentOperation( opPOW, other );
98}
99
101{
102 return twoArgumentOperation( opEQ, other );
103}
104
106{
107 return twoArgumentOperation( opNE, other );
108}
109
111{
112 return twoArgumentOperation( opGT, other );
113}
114
116{
117 return twoArgumentOperation( opLT, other );
118}
119
121{
122 return twoArgumentOperation( opGE, other );
123}
124
126{
127 return twoArgumentOperation( opLE, other );
128}
129
131{
132 return twoArgumentOperation( opAND, other );
133}
134
136{
137 return twoArgumentOperation( opOR, other );
138}
139
141{
142 return twoArgumentOperation( opMAX, other );
143}
144
146{
147 return twoArgumentOperation( opMIN, other );
148}
149
151{
152 return oneArgumentOperation( opSQRT );
153}
154
156{
157 return oneArgumentOperation( opSIN );
158}
159
161{
162 return oneArgumentOperation( opASIN );
163}
164
166{
167 return oneArgumentOperation( opCOS );
168}
169
171{
172 return oneArgumentOperation( opACOS );
173}
174
176{
177 return oneArgumentOperation( opTAN );
178}
179
181{
182 return oneArgumentOperation( opATAN );
183}
184
186{
187 return oneArgumentOperation( opSIGN );
188}
189
191{
192 return oneArgumentOperation( opLOG );
193}
194
196{
197 return oneArgumentOperation( opLOG10 );
198}
199
201{
202 return oneArgumentOperation( opABS );
203}
204
205bool QgsRasterMatrix::oneArgumentOperation( OneArgOperator op )
206{
207 if ( !mData )
208 {
209 return false;
210 }
211
212 const int nEntries = mColumns * mRows;
213 double value;
214 for ( int i = 0; i < nEntries; ++i )
215 {
216 value = mData[i];
217 if ( value != mNodataValue )
218 {
219 switch ( op )
220 {
221 case opSQRT:
222 if ( value < 0 ) //no complex numbers
223 {
224 mData[i] = mNodataValue;
225 }
226 else
227 {
228 mData[i] = std::sqrt( value );
229 }
230 break;
231 case opSIN:
232 mData[i] = std::sin( value );
233 break;
234 case opCOS:
235 mData[i] = std::cos( value );
236 break;
237 case opTAN:
238 mData[i] = std::tan( value );
239 break;
240 case opASIN:
241 mData[i] = std::asin( value );
242 break;
243 case opACOS:
244 mData[i] = std::acos( value );
245 break;
246 case opATAN:
247 mData[i] = std::atan( value );
248 break;
249 case opSIGN:
250 mData[i] = -value;
251 break;
252 case opLOG:
253 if ( value <= 0 )
254 {
255 mData[i] = mNodataValue;
256 }
257 else
258 {
259 mData[i] = ::log( value );
260 }
261 break;
262 case opLOG10:
263 if ( value <= 0 )
264 {
265 mData[i] = mNodataValue;
266 }
267 else
268 {
269 mData[i] = ::log10( value );
270 }
271 break;
272 case opABS:
273 mData[i] = ::fabs( value );
274 break;
275 }
276 }
277 }
278 return true;
279}
280
281double QgsRasterMatrix::calculateTwoArgumentOp( TwoArgOperator op, double arg1, double arg2 ) const
282{
283 switch ( op )
284 {
285 case opPLUS:
286 return arg1 + arg2;
287 case opMINUS:
288 return arg1 - arg2;
289 case opMUL:
290 return arg1 * arg2;
291 case opDIV:
292 if ( arg2 == 0 )
293 {
294 return mNodataValue;
295 }
296 else
297 {
298 return arg1 / arg2;
299 }
300 case opPOW:
301 if ( !testPowerValidity( arg1, arg2 ) )
302 {
303 return mNodataValue;
304 }
305 else
306 {
307 return std::pow( arg1, arg2 );
308 }
309 case opEQ:
310 return ( arg1 == arg2 ? 1.0 : 0.0 );
311 case opNE:
312 return ( arg1 == arg2 ? 0.0 : 1.0 );
313 case opGT:
314 return ( arg1 > arg2 ? 1.0 : 0.0 );
315 case opLT:
316 return ( arg1 < arg2 ? 1.0 : 0.0 );
317 case opGE:
318 return ( arg1 >= arg2 ? 1.0 : 0.0 );
319 case opLE:
320 return ( arg1 <= arg2 ? 1.0 : 0.0 );
321 case opAND:
322 return ( arg1 && arg2 ? 1.0 : 0.0 );
323 case opOR:
324 return ( arg1 || arg2 ? 1.0 : 0.0 );
325 case opMAX:
326 return std::max( arg1, arg2 );
327 case opMIN:
328 return std::min( arg1, arg2 );
329 }
330 return mNodataValue;
331}
332
333bool QgsRasterMatrix::twoArgumentOperation( TwoArgOperator op, const QgsRasterMatrix &other )
334{
335 if ( isNumber() && other.isNumber() ) //operation on two 1x1 matrices
336 {
337 //operations with nodata values always generate nodata
338 if ( mData[0] == mNodataValue || other.number() == other.nodataValue() )
339 {
340 mData[0] = mNodataValue;
341 }
342 else
343 {
344 mData[0] = calculateTwoArgumentOp( op, mData[0], other.number() );
345 }
346 return true;
347 }
348
349 //two matrices
350 if ( !isNumber() && !other.isNumber() )
351 {
352 double *matrix = other.mData;
353 const int nEntries = mColumns * mRows;
354 double value1, value2;
355
356 for ( int i = 0; i < nEntries; ++i )
357 {
358 value1 = mData[i];
359 value2 = matrix[i];
360 if ( value1 == mNodataValue || value2 == other.mNodataValue )
361 {
362 mData[i] = mNodataValue;
363 }
364 else
365 {
366 mData[i] = calculateTwoArgumentOp( op, value1, value2 );
367 }
368 }
369 return true;
370 }
371
372 //this matrix is a single number and the other one a real matrix
373 if ( isNumber() )
374 {
375 double *matrix = other.mData;
376 const int nEntries = other.nColumns() * other.nRows();
377 const double value = mData[0];
378 delete[] mData;
379 mData = new double[nEntries];
380 mColumns = other.nColumns();
381 mRows = other.nRows();
382 mNodataValue = other.nodataValue();
383
384 if ( value == mNodataValue )
385 {
386 for ( int i = 0; i < nEntries; ++i )
387 {
388 mData[i] = mNodataValue;
389 }
390 return true;
391 }
392
393 for ( int i = 0; i < nEntries; ++i )
394 {
395 if ( matrix[i] == other.mNodataValue )
396 {
397 mData[i] = mNodataValue;
398 continue;
399 }
400
401 mData[i] = calculateTwoArgumentOp( op, value, matrix[i] );
402 }
403 return true;
404 }
405 else //this matrix is a real matrix and the other a number
406 {
407 const double value = other.number();
408 const int nEntries = mColumns * mRows;
409
410 if ( other.number() == other.mNodataValue )
411 {
412 for ( int i = 0; i < nEntries; ++i )
413 {
414 mData[i] = mNodataValue;
415 }
416 return true;
417 }
418
419 for ( int i = 0; i < nEntries; ++i )
420 {
421 if ( mData[i] == mNodataValue )
422 {
423 continue;
424 }
425
426 mData[i] = calculateTwoArgumentOp( op, mData[i], value );
427 }
428 return true;
429 }
430}
431
432bool QgsRasterMatrix::testPowerValidity( double base, double power ) const
433{
434 return !( ( base == 0 && power < 0 ) || ( base < 0 && ( power - std::floor( power ) ) > 0 ) );
435}
Represents a matrix in a raster calculator operation.
bool equal(const QgsRasterMatrix &other)
bool max(const QgsRasterMatrix &other)
Calculates the maximum value between two matrices.
bool greaterEqual(const QgsRasterMatrix &other)
double * takeData()
Returns data and ownership.
bool notEqual(const QgsRasterMatrix &other)
bool greaterThan(const QgsRasterMatrix &other)
QgsRasterMatrix()=default
bool logicalOr(const QgsRasterMatrix &other)
bool lesserEqual(const QgsRasterMatrix &other)
bool absoluteValue()
Calculates the absolute value.
bool logicalAnd(const QgsRasterMatrix &other)
bool isNumber() const
Returns true if matrix is 1x1 (=scalar number).
bool lesserThan(const QgsRasterMatrix &other)
bool add(const QgsRasterMatrix &other)
Adds another matrix to this one.
bool multiply(const QgsRasterMatrix &other)
QgsRasterMatrix & operator=(const QgsRasterMatrix &m)
int nRows() const
double * data()
Returns data array (but not ownership).
bool power(const QgsRasterMatrix &other)
double nodataValue() const
bool min(const QgsRasterMatrix &other)
Calculates the minimum value between two matrices.
double number() const
bool divide(const QgsRasterMatrix &other)
int nColumns() const
void setData(int cols, int rows, double *data, double nodataValue)
bool subtract(const QgsRasterMatrix &other)
Subtracts another matrix from this one.