QGIS API Documentation  3.23.0-Master (dd0cd13a00)
qgsmeshcalcnode.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsmeshcalcnode.cpp
3  -------------------
4  begin : December 18th, 2018
5  copyright : (C) 2018 by Peter Petrik
6  email : zilolv at gmail dot com
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  ***************************************************************************/
18 
19 #include <cfloat>
20 
21 #include "qgsmeshcalcnode.h"
22 #include "qgsmeshmemorydataprovider.h"
23 
24 QgsMeshCalcNode::QgsMeshCalcNode()
25  : mType( tNoData )
26 {
27 }
28 
29 QgsMeshCalcNode::QgsMeshCalcNode( double number )
30  : mType( tNumber )
31  , mNumber( number )
32 {
33 }
34 
35 
36 QgsMeshCalcNode::QgsMeshCalcNode( Operator op, QgsMeshCalcNode *left, QgsMeshCalcNode *right )
37  : mType( tOperator )
38  , mLeft( left )
39  , mRight( right )
40  , mOperator( op )
41 {
42 }
43 
44 QgsMeshCalcNode::QgsMeshCalcNode( QgsMeshCalcNode *condition /* bool condition */,
45  QgsMeshCalcNode *left /*if true */,
46  QgsMeshCalcNode *right /* if false */ )
47  : mType( tOperator )
48  , mLeft( left )
49  , mRight( right )
50  , mCondition( condition )
51  , mOperator( opIF )
52 {
53 }
54 
55 QgsMeshCalcNode::QgsMeshCalcNode( const QString &datasetGroupName )
56  : mType( tDatasetGroupRef )
57  , mDatasetGroupName( datasetGroupName )
58 {
59  if ( mDatasetGroupName.startsWith( '"' ) && mDatasetGroupName.endsWith( '"' ) )
60  mDatasetGroupName = mDatasetGroupName.mid( 1, mDatasetGroupName.size() - 2 );
61 }
62 
63 QgsMeshCalcNode::~QgsMeshCalcNode() = default;
64 
65 QgsMeshCalcNode::Type QgsMeshCalcNode::type() const
66 {
67  return mType;
68 }
69 
70 void QgsMeshCalcNode::setLeft( QgsMeshCalcNode *left )
71 {
72  mLeft.reset( left );
73 }
74 
75 void QgsMeshCalcNode::setRight( QgsMeshCalcNode *right )
76 {
77  mRight.reset( right );
78 }
79 
80 QStringList QgsMeshCalcNode::usedDatasetGroupNames() const
81 {
82  QStringList res;
83 
84  if ( mType == tDatasetGroupRef )
85  {
86  res.append( mDatasetGroupName );
87  }
88 
89  if ( mLeft )
90  {
91  res += mLeft->usedDatasetGroupNames();
92  }
93 
94  if ( mRight )
95  {
96  res += mRight->usedDatasetGroupNames();
97  }
98 
99  if ( mCondition )
100  {
101  res += mCondition->usedDatasetGroupNames();
102  }
103 
104  return res;
105 }
106 
107 QStringList QgsMeshCalcNode::aggregatedUsedDatasetGroupNames() const
108 {
109  QStringList res;
110 
111  switch ( mOperator )
112  {
113  case QgsMeshCalcNode::opPLUS:
114  case QgsMeshCalcNode::opMINUS:
115  case QgsMeshCalcNode::opMUL:
116  case QgsMeshCalcNode::opDIV:
117  case QgsMeshCalcNode::opPOW:
118  case QgsMeshCalcNode::opEQ:
119  case QgsMeshCalcNode::opNE:
120  case QgsMeshCalcNode::opGT:
121  case QgsMeshCalcNode::opLT:
122  case QgsMeshCalcNode::opGE:
123  case QgsMeshCalcNode::opLE:
124  case QgsMeshCalcNode::opAND:
125  case QgsMeshCalcNode::opOR:
126  case QgsMeshCalcNode::opNOT:
127  case QgsMeshCalcNode::opIF:
128  case QgsMeshCalcNode::opSIGN:
129  case QgsMeshCalcNode::opMIN:
130  case QgsMeshCalcNode::opMAX:
131  case QgsMeshCalcNode::opABS:
132  case QgsMeshCalcNode::opNONE:
133  if ( mLeft )
134  {
135  res += mLeft->aggregatedUsedDatasetGroupNames();
136  }
137 
138  if ( mRight )
139  {
140  res += mRight->aggregatedUsedDatasetGroupNames();
141  }
142 
143  if ( mCondition )
144  {
145  res += mCondition->aggregatedUsedDatasetGroupNames();
146  }
147  break;
148  case QgsMeshCalcNode::opSUM_AGGR:
149  case QgsMeshCalcNode::opMAX_AGGR:
150  case QgsMeshCalcNode::opMIN_AGGR:
151  case QgsMeshCalcNode::opAVG_AGGR:
152  if ( mLeft )
153  {
154  res += mLeft->usedDatasetGroupNames();
155  }
156 
157  if ( mRight )
158  {
159  res += mRight->usedDatasetGroupNames();
160  }
161 
162  if ( mCondition )
163  {
164  res += mCondition->usedDatasetGroupNames();
165  }
166  break;
167  }
168 
169  return res;
170 }
171 
172 QStringList QgsMeshCalcNode::notAggregatedUsedDatasetGroupNames() const
173 {
174  QStringList res;
175 
176  if ( mType == tDatasetGroupRef )
177  {
178  res.append( mDatasetGroupName );
179  }
180 
181  switch ( mOperator )
182  {
183  case QgsMeshCalcNode::opPLUS:
184  case QgsMeshCalcNode::opMINUS:
185  case QgsMeshCalcNode::opMUL:
186  case QgsMeshCalcNode::opDIV:
187  case QgsMeshCalcNode::opPOW:
188  case QgsMeshCalcNode::opEQ:
189  case QgsMeshCalcNode::opNE:
190  case QgsMeshCalcNode::opGT:
191  case QgsMeshCalcNode::opLT:
192  case QgsMeshCalcNode::opGE:
193  case QgsMeshCalcNode::opLE:
194  case QgsMeshCalcNode::opAND:
195  case QgsMeshCalcNode::opOR:
196  case QgsMeshCalcNode::opNOT:
197  case QgsMeshCalcNode::opIF:
198  case QgsMeshCalcNode::opSIGN:
199  case QgsMeshCalcNode::opMIN:
200  case QgsMeshCalcNode::opMAX:
201  case QgsMeshCalcNode::opABS:
202  if ( mLeft )
203  {
204  res += mLeft->notAggregatedUsedDatasetGroupNames();
205  }
206 
207  if ( mRight )
208  {
209  res += mRight->notAggregatedUsedDatasetGroupNames();
210  }
211 
212  if ( mCondition )
213  {
214  res += mCondition->notAggregatedUsedDatasetGroupNames();
215  }
216  break;
217  case QgsMeshCalcNode::opSUM_AGGR:
218  case QgsMeshCalcNode::opMAX_AGGR:
219  case QgsMeshCalcNode::opMIN_AGGR:
220  case QgsMeshCalcNode::opAVG_AGGR:
221  case QgsMeshCalcNode::opNONE:
222  break;
223  }
224 
225  return res;
226 }
227 
228 bool QgsMeshCalcNode::calculate( const QgsMeshCalcUtils &dsu, QgsMeshMemoryDatasetGroup &result, bool isAggregate ) const
229 {
230  if ( mType == tDatasetGroupRef )
231  {
232  dsu.copy( result, mDatasetGroupName, isAggregate );
233  return true;
234  }
235  else if ( mType == tOperator )
236  {
237  QgsMeshMemoryDatasetGroup leftDatasetGroup( "left", dsu.outputType() );
238  QgsMeshMemoryDatasetGroup rightDatasetGroup( "right", dsu.outputType() );
239 
240  bool currentOperatorIsAggregate = mOperator == opSUM_AGGR ||
241  mOperator == opMAX_AGGR ||
242  mOperator == opMIN_AGGR ||
243  mOperator == opAVG_AGGR;
244 
245  if ( !mLeft || !mLeft->calculate( dsu, leftDatasetGroup, isAggregate || currentOperatorIsAggregate ) )
246  {
247  return false;
248  }
249  if ( mRight && !mRight->calculate( dsu, rightDatasetGroup, isAggregate || currentOperatorIsAggregate ) )
250  {
251  return false;
252  }
253 
254  QgsMeshMemoryDatasetGroup condition( "condition", dsu.outputType() );
255  switch ( mOperator )
256  {
257  case opIF:
258  // Evaluate boolean condition
259  if ( !mCondition->calculate( dsu, condition ) )
260  {
261  // invalid boolean condition
262  return false;
263  }
264  dsu.addIf( leftDatasetGroup, rightDatasetGroup, condition );
265  break;
266 
267  case opPLUS:
268  dsu.add( leftDatasetGroup, rightDatasetGroup );
269  break;
270  case opMINUS:
271  dsu.subtract( leftDatasetGroup, rightDatasetGroup );
272  break;
273  case opMUL:
274  dsu.multiply( leftDatasetGroup, rightDatasetGroup );
275  break;
276  case opDIV:
277  dsu.divide( leftDatasetGroup, rightDatasetGroup );
278  break;
279  case opPOW:
280  dsu.power( leftDatasetGroup, rightDatasetGroup );
281  break;
282  case opEQ:
283  dsu.equal( leftDatasetGroup, rightDatasetGroup );
284  break;
285  case opNE:
286  dsu.notEqual( leftDatasetGroup, rightDatasetGroup );
287  break;
288  case opGT:
289  dsu.greaterThan( leftDatasetGroup, rightDatasetGroup );
290  break;
291  case opLT:
292  dsu.lesserThan( leftDatasetGroup, rightDatasetGroup );
293  break;
294  case opGE:
295  dsu.greaterEqual( leftDatasetGroup, rightDatasetGroup );
296  break;
297  case opLE:
298  dsu.lesserEqual( leftDatasetGroup, rightDatasetGroup );
299  break;
300  case opAND:
301  dsu.logicalAnd( leftDatasetGroup, rightDatasetGroup );
302  break;
303  case opOR:
304  dsu.logicalOr( leftDatasetGroup, rightDatasetGroup );
305  break;
306  case opNOT:
307  dsu.logicalNot( leftDatasetGroup );
308  break;
309  case opMIN:
310  dsu.minimum( leftDatasetGroup, rightDatasetGroup );
311  break;
312  case opMAX:
313  dsu.maximum( leftDatasetGroup, rightDatasetGroup );
314  break;
315  case opABS:
316  dsu.abs( leftDatasetGroup );
317  break;
318  case opSUM_AGGR:
319  dsu.sumAggregated( leftDatasetGroup );
320  break;
321  case opMIN_AGGR:
322  dsu.minimumAggregated( leftDatasetGroup );
323  break;
324  case opMAX_AGGR:
325  dsu.maximumAggregated( leftDatasetGroup );
326  break;
327  case opAVG_AGGR:
328  dsu.averageAggregated( leftDatasetGroup );
329  break;
330  case opSIGN:
331  dsu.changeSign( leftDatasetGroup );
332  break;
333  default:
334  return false;
335  }
336  dsu.transferDatasets( result, leftDatasetGroup );
337  return true;
338  }
339  else if ( mType == tNumber )
340  {
341  dsu.number( result, mNumber );
342  return true;
343  }
344  else if ( mType == tNoData )
345  {
346  dsu.nodata( result );
347  return true;
348  }
349 
350  // invalid type
351  return false;
352 }
353 
354 QgsMeshCalcNode *QgsMeshCalcNode::parseMeshCalcString( const QString &str, QString &parserErrorMsg )
355 {
356  extern QgsMeshCalcNode *localParseMeshCalcString( const QString & str, QString & parserErrorMsg );
357  return localParseMeshCalcString( str, parserErrorMsg );
358 }
359 
360 bool QgsMeshCalcNode::isNonTemporal() const
361 {
362  if ( mType == tNoData || mType == tNumber )
363  return true;
364 
365  if ( mType == tDatasetGroupRef )
366  return false;
367 
368  switch ( mOperator )
369  {
370  case QgsMeshCalcNode::opIF:
371  return ( mLeft && mLeft->isNonTemporal() ) &&
372  ( mRight && mRight->isNonTemporal() &&
373  mCondition->isNonTemporal() );
374  break;
375  case QgsMeshCalcNode::opPLUS:
376  case QgsMeshCalcNode::opMINUS:
377  case QgsMeshCalcNode::opMUL:
378  case QgsMeshCalcNode::opDIV:
379  case QgsMeshCalcNode::opPOW:
380  case QgsMeshCalcNode::opEQ:
381  case QgsMeshCalcNode::opNE:
382  case QgsMeshCalcNode::opGT:
383  case QgsMeshCalcNode::opLT:
384  case QgsMeshCalcNode::opGE:
385  case QgsMeshCalcNode::opLE:
386  case QgsMeshCalcNode::opAND:
387  case QgsMeshCalcNode::opOR:
388  case QgsMeshCalcNode::opNOT:
389  case QgsMeshCalcNode::opSIGN:
390  case QgsMeshCalcNode::opMIN:
391  case QgsMeshCalcNode::opMAX:
392  case QgsMeshCalcNode::opABS:
393  return ( mLeft && mLeft->isNonTemporal() ) &&
394  ( mRight && mRight->isNonTemporal() );
395  break;
396  case QgsMeshCalcNode::opSUM_AGGR:
397  case QgsMeshCalcNode::opMAX_AGGR:
398  case QgsMeshCalcNode::opMIN_AGGR:
399  case QgsMeshCalcNode::opAVG_AGGR:
400  case QgsMeshCalcNode::opNONE:
401  return true;
402  break;
403  }
404 
405  return true;
406 }
407 
Class that represents a dataset group stored in memory.
#define str(x)
Definition: qgis.cpp:37