QGIS API Documentation  3.10.0-A Coruña (6c816b4204)
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 bool QgsMeshCalcNode::calculate( const QgsMeshCalcUtils &dsu, QgsMeshMemoryDatasetGroup &result ) const
108 {
109  if ( mType == tDatasetGroupRef )
110  {
111  dsu.copy( result, mDatasetGroupName );
112  return true;
113  }
114  else if ( mType == tOperator )
115  {
116  QgsMeshMemoryDatasetGroup leftDatasetGroup( "left" );
117  QgsMeshMemoryDatasetGroup rightDatasetGroup( "right" );
118 
119  if ( !mLeft || !mLeft->calculate( dsu, leftDatasetGroup ) )
120  {
121  return false;
122  }
123  if ( mRight && !mRight->calculate( dsu, rightDatasetGroup ) )
124  {
125  return false;
126  }
127 
128  QgsMeshMemoryDatasetGroup condition( "condition" );
129  switch ( mOperator )
130  {
131  case opIF:
132  // Evaluate boolean condition
133  if ( !mCondition->calculate( dsu, condition ) )
134  {
135  // invalid boolean condition
136  return false;
137  }
138  dsu.addIf( leftDatasetGroup, rightDatasetGroup, condition );
139  break;
140 
141  case opPLUS:
142  dsu.add( leftDatasetGroup, rightDatasetGroup );
143  break;
144  case opMINUS:
145  dsu.subtract( leftDatasetGroup, rightDatasetGroup );
146  break;
147  case opMUL:
148  dsu.multiply( leftDatasetGroup, rightDatasetGroup );
149  break;
150  case opDIV:
151  dsu.divide( leftDatasetGroup, rightDatasetGroup );
152  break;
153  case opPOW:
154  dsu.power( leftDatasetGroup, rightDatasetGroup );
155  break;
156  case opEQ:
157  dsu.equal( leftDatasetGroup, rightDatasetGroup );
158  break;
159  case opNE:
160  dsu.notEqual( leftDatasetGroup, rightDatasetGroup );
161  break;
162  case opGT:
163  dsu.greaterThan( leftDatasetGroup, rightDatasetGroup );
164  break;
165  case opLT:
166  dsu.lesserThan( leftDatasetGroup, rightDatasetGroup );
167  break;
168  case opGE:
169  dsu.greaterEqual( leftDatasetGroup, rightDatasetGroup );
170  break;
171  case opLE:
172  dsu.lesserEqual( leftDatasetGroup, rightDatasetGroup );
173  break;
174  case opAND:
175  dsu.logicalAnd( leftDatasetGroup, rightDatasetGroup );
176  break;
177  case opOR:
178  dsu.logicalOr( leftDatasetGroup, rightDatasetGroup );
179  break;
180  case opNOT:
181  dsu.logicalNot( leftDatasetGroup );
182  break;
183  case opMIN:
184  dsu.minimum( leftDatasetGroup, rightDatasetGroup );
185  break;
186  case opMAX:
187  dsu.maximum( leftDatasetGroup, rightDatasetGroup );
188  break;
189  case opABS:
190  dsu.abs( leftDatasetGroup );
191  break;
192  case opSUM_AGGR:
193  dsu.sumAggregated( leftDatasetGroup );
194  break;
195  case opMIN_AGGR:
196  dsu.minimumAggregated( leftDatasetGroup );
197  break;
198  case opMAX_AGGR:
199  dsu.maximumAggregated( leftDatasetGroup );
200  break;
201  case opAVG_AGGR:
202  dsu.averageAggregated( leftDatasetGroup );
203  break;
204  case opSIGN:
205  dsu.changeSign( leftDatasetGroup );
206  break;
207  default:
208  return false;
209  }
210  dsu.transferDatasets( result, leftDatasetGroup );
211  return true;
212  }
213  else if ( mType == tNumber )
214  {
215  dsu.number( result, mNumber );
216  return true;
217  }
218  else if ( mType == tNoData )
219  {
220  dsu.nodata( result );
221  return true;
222  }
223 
224  // invalid type
225  return false;
226 }
227 
228 QgsMeshCalcNode *QgsMeshCalcNode::parseMeshCalcString( const QString &str, QString &parserErrorMsg )
229 {
230  extern QgsMeshCalcNode *localParseMeshCalcString( const QString & str, QString & parserErrorMsg );
231  return localParseMeshCalcString( str, parserErrorMsg );
232 }
233