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