Branch data Line data Source code
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 : : ***************************************************************************/
17 : : ///@cond PRIVATE
18 : :
19 : : #include <cfloat>
20 : :
21 : : #include "qgsmeshcalcnode.h"
22 : : #include "qgsmeshmemorydataprovider.h"
23 : :
24 : 0 : QgsMeshCalcNode::QgsMeshCalcNode()
25 : 0 : : mType( tNoData )
26 : : {
27 : 0 : }
28 : :
29 : 0 : QgsMeshCalcNode::QgsMeshCalcNode( double number )
30 : 0 : : mType( tNumber )
31 : 0 : , mNumber( number )
32 : : {
33 : 0 : }
34 : :
35 : :
36 : 0 : QgsMeshCalcNode::QgsMeshCalcNode( Operator op, QgsMeshCalcNode *left, QgsMeshCalcNode *right )
37 : 0 : : mType( tOperator )
38 : 0 : , mLeft( left )
39 : 0 : , mRight( right )
40 : 0 : , mOperator( op )
41 : : {
42 : 0 : }
43 : :
44 : 0 : QgsMeshCalcNode::QgsMeshCalcNode( QgsMeshCalcNode *condition /* bool condition */,
45 : : QgsMeshCalcNode *left /*if true */,
46 : : QgsMeshCalcNode *right /* if false */ )
47 : 0 : : mType( tOperator )
48 : 0 : , mLeft( left )
49 : 0 : , mRight( right )
50 : 0 : , mCondition( condition )
51 : 0 : , mOperator( opIF )
52 : : {
53 : 0 : }
54 : :
55 : 0 : QgsMeshCalcNode::QgsMeshCalcNode( const QString &datasetGroupName )
56 : 0 : : mType( tDatasetGroupRef )
57 : 0 : , mDatasetGroupName( datasetGroupName )
58 : : {
59 : 0 : if ( mDatasetGroupName.startsWith( '"' ) && mDatasetGroupName.endsWith( '"' ) )
60 : 0 : mDatasetGroupName = mDatasetGroupName.mid( 1, mDatasetGroupName.size() - 2 );
61 : 0 : }
62 : :
63 : 0 : QgsMeshCalcNode::~QgsMeshCalcNode() = default;
64 : :
65 : 0 : QgsMeshCalcNode::Type QgsMeshCalcNode::type() const
66 : : {
67 : 0 : return mType;
68 : : }
69 : :
70 : 0 : void QgsMeshCalcNode::setLeft( QgsMeshCalcNode *left )
71 : : {
72 : 0 : mLeft.reset( left );
73 : 0 : }
74 : :
75 : 0 : void QgsMeshCalcNode::setRight( QgsMeshCalcNode *right )
76 : : {
77 : 0 : mRight.reset( right );
78 : 0 : }
79 : :
80 : 0 : QStringList QgsMeshCalcNode::usedDatasetGroupNames() const
81 : : {
82 : 0 : QStringList res;
83 : :
84 : 0 : if ( mType == tDatasetGroupRef )
85 : : {
86 : 0 : res.append( mDatasetGroupName );
87 : 0 : }
88 : :
89 : 0 : if ( mLeft )
90 : : {
91 : 0 : res += mLeft->usedDatasetGroupNames();
92 : 0 : }
93 : :
94 : 0 : if ( mRight )
95 : : {
96 : 0 : res += mRight->usedDatasetGroupNames();
97 : 0 : }
98 : :
99 : 0 : if ( mCondition )
100 : : {
101 : 0 : res += mCondition->usedDatasetGroupNames();
102 : 0 : }
103 : :
104 : 0 : return res;
105 : 0 : }
106 : :
107 : 0 : bool QgsMeshCalcNode::calculate( const QgsMeshCalcUtils &dsu, QgsMeshMemoryDatasetGroup &result ) const
108 : : {
109 : 0 : if ( mType == tDatasetGroupRef )
110 : : {
111 : 0 : dsu.copy( result, mDatasetGroupName );
112 : 0 : return true;
113 : : }
114 : 0 : else if ( mType == tOperator )
115 : : {
116 : 0 : QgsMeshMemoryDatasetGroup leftDatasetGroup( "left", dsu.outputType() );
117 : 0 : QgsMeshMemoryDatasetGroup rightDatasetGroup( "right", dsu.outputType() );
118 : :
119 : 0 : if ( !mLeft || !mLeft->calculate( dsu, leftDatasetGroup ) )
120 : : {
121 : 0 : return false;
122 : : }
123 : 0 : if ( mRight && !mRight->calculate( dsu, rightDatasetGroup ) )
124 : : {
125 : 0 : return false;
126 : : }
127 : :
128 : 0 : QgsMeshMemoryDatasetGroup condition( "condition", dsu.outputType() );
129 : 0 : switch ( mOperator )
130 : : {
131 : : case opIF:
132 : : // Evaluate boolean condition
133 : 0 : if ( !mCondition->calculate( dsu, condition ) )
134 : : {
135 : : // invalid boolean condition
136 : 0 : return false;
137 : : }
138 : 0 : dsu.addIf( leftDatasetGroup, rightDatasetGroup, condition );
139 : 0 : break;
140 : :
141 : : case opPLUS:
142 : 0 : dsu.add( leftDatasetGroup, rightDatasetGroup );
143 : 0 : break;
144 : : case opMINUS:
145 : 0 : dsu.subtract( leftDatasetGroup, rightDatasetGroup );
146 : 0 : break;
147 : : case opMUL:
148 : 0 : dsu.multiply( leftDatasetGroup, rightDatasetGroup );
149 : 0 : break;
150 : : case opDIV:
151 : 0 : dsu.divide( leftDatasetGroup, rightDatasetGroup );
152 : 0 : break;
153 : : case opPOW:
154 : 0 : dsu.power( leftDatasetGroup, rightDatasetGroup );
155 : 0 : break;
156 : : case opEQ:
157 : 0 : dsu.equal( leftDatasetGroup, rightDatasetGroup );
158 : 0 : break;
159 : : case opNE:
160 : 0 : dsu.notEqual( leftDatasetGroup, rightDatasetGroup );
161 : 0 : break;
162 : : case opGT:
163 : 0 : dsu.greaterThan( leftDatasetGroup, rightDatasetGroup );
164 : 0 : break;
165 : : case opLT:
166 : 0 : dsu.lesserThan( leftDatasetGroup, rightDatasetGroup );
167 : 0 : break;
168 : : case opGE:
169 : 0 : dsu.greaterEqual( leftDatasetGroup, rightDatasetGroup );
170 : 0 : break;
171 : : case opLE:
172 : 0 : dsu.lesserEqual( leftDatasetGroup, rightDatasetGroup );
173 : 0 : break;
174 : : case opAND:
175 : 0 : dsu.logicalAnd( leftDatasetGroup, rightDatasetGroup );
176 : 0 : break;
177 : : case opOR:
178 : 0 : dsu.logicalOr( leftDatasetGroup, rightDatasetGroup );
179 : 0 : break;
180 : : case opNOT:
181 : 0 : dsu.logicalNot( leftDatasetGroup );
182 : 0 : break;
183 : : case opMIN:
184 : 0 : dsu.minimum( leftDatasetGroup, rightDatasetGroup );
185 : 0 : break;
186 : : case opMAX:
187 : 0 : dsu.maximum( leftDatasetGroup, rightDatasetGroup );
188 : 0 : break;
189 : : case opABS:
190 : 0 : dsu.abs( leftDatasetGroup );
191 : 0 : break;
192 : : case opSUM_AGGR:
193 : 0 : dsu.sumAggregated( leftDatasetGroup );
194 : 0 : break;
195 : : case opMIN_AGGR:
196 : 0 : dsu.minimumAggregated( leftDatasetGroup );
197 : 0 : break;
198 : : case opMAX_AGGR:
199 : 0 : dsu.maximumAggregated( leftDatasetGroup );
200 : 0 : break;
201 : : case opAVG_AGGR:
202 : 0 : dsu.averageAggregated( leftDatasetGroup );
203 : 0 : break;
204 : : case opSIGN:
205 : 0 : dsu.changeSign( leftDatasetGroup );
206 : 0 : break;
207 : : default:
208 : 0 : return false;
209 : : }
210 : 0 : dsu.transferDatasets( result, leftDatasetGroup );
211 : 0 : return true;
212 : 0 : }
213 : 0 : else if ( mType == tNumber )
214 : : {
215 : 0 : dsu.number( result, mNumber );
216 : 0 : return true;
217 : : }
218 : 0 : else if ( mType == tNoData )
219 : : {
220 : 0 : dsu.nodata( result );
221 : 0 : return true;
222 : : }
223 : :
224 : : // invalid type
225 : 0 : return false;
226 : 0 : }
227 : :
228 : 0 : QgsMeshCalcNode *QgsMeshCalcNode::parseMeshCalcString( const QString &str, QString &parserErrorMsg )
229 : : {
230 : : extern QgsMeshCalcNode *localParseMeshCalcString( const QString & str, QString & parserErrorMsg );
231 : 0 : return localParseMeshCalcString( str, parserErrorMsg );
232 : : }
233 : :
234 : 0 : bool QgsMeshCalcNode::isNonTemporal() const
235 : : {
236 : 0 : if ( mType == tNoData || mType == tNumber )
237 : 0 : return true;
238 : :
239 : 0 : if ( mType == tDatasetGroupRef )
240 : 0 : return false;
241 : :
242 : 0 : switch ( mOperator )
243 : : {
244 : : case QgsMeshCalcNode::opPLUS:
245 : : case QgsMeshCalcNode::opMINUS:
246 : : case QgsMeshCalcNode::opMUL:
247 : : case QgsMeshCalcNode::opDIV:
248 : : case QgsMeshCalcNode::opPOW:
249 : : case QgsMeshCalcNode::opEQ:
250 : : case QgsMeshCalcNode::opNE:
251 : : case QgsMeshCalcNode::opGT:
252 : : case QgsMeshCalcNode::opLT:
253 : : case QgsMeshCalcNode::opGE:
254 : : case QgsMeshCalcNode::opLE:
255 : : case QgsMeshCalcNode::opAND:
256 : : case QgsMeshCalcNode::opOR:
257 : : case QgsMeshCalcNode::opNOT:
258 : : case QgsMeshCalcNode::opIF:
259 : : case QgsMeshCalcNode::opSIGN:
260 : : case QgsMeshCalcNode::opMIN:
261 : : case QgsMeshCalcNode::opMAX:
262 : : case QgsMeshCalcNode::opABS:
263 : 0 : return ( mLeft && mLeft->isNonTemporal() ) &&
264 : 0 : ( mRight && mRight->isNonTemporal() );
265 : : break;
266 : : case QgsMeshCalcNode::opSUM_AGGR:
267 : : case QgsMeshCalcNode::opMAX_AGGR:
268 : : case QgsMeshCalcNode::opMIN_AGGR:
269 : : case QgsMeshCalcNode::opAVG_AGGR:
270 : : case QgsMeshCalcNode::opNONE:
271 : 0 : return true;
272 : : break;
273 : : }
274 : :
275 : 0 : return true;
276 : 0 : }
277 : :
278 : : ///@endcond
|