QGIS API Documentation 3.41.0-Master (cea29feecf2)
Loading...
Searching...
No Matches
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
24QgsMeshCalcNode::QgsMeshCalcNode()
25 : mType( tNoData )
26{
27}
28
29QgsMeshCalcNode::QgsMeshCalcNode( double number )
30 : mType( tNumber )
31 , mNumber( number )
32{
33}
34
35
36QgsMeshCalcNode::QgsMeshCalcNode( Operator op, QgsMeshCalcNode *left, QgsMeshCalcNode *right )
37 : mType( tOperator )
38 , mLeft( left )
39 , mRight( right )
40 , mOperator( op )
41{
42}
43
44QgsMeshCalcNode::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
55QgsMeshCalcNode::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
63QgsMeshCalcNode::~QgsMeshCalcNode() = default;
64
65QgsMeshCalcNode::Type QgsMeshCalcNode::type() const
66{
67 return mType;
68}
69
70void QgsMeshCalcNode::setLeft( QgsMeshCalcNode *left )
71{
72 mLeft.reset( left );
73}
74
75void QgsMeshCalcNode::setRight( QgsMeshCalcNode *right )
76{
77 mRight.reset( right );
78}
79
80QStringList 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
107QStringList 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
172QStringList 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
228bool 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
354QgsMeshCalcNode *QgsMeshCalcNode::parseMeshCalcString( const QString &str, QString &parserErrorMsg )
355{
356 extern QgsMeshCalcNode *localParseMeshCalcString( const QString & str, QString & parserErrorMsg );
357 return localParseMeshCalcString( str, parserErrorMsg );
358}
359
360bool 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.