Branch data Line data Source code
1 : : /***************************************************************************
2 : : qgsmeshcalcutils.h
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 : :
18 : : #ifndef QGSMESHCALCUTILS_H
19 : : #define QGSMESHCALCUTILS_H
20 : :
21 : : #define SIP_NO_FILE
22 : :
23 : : ///@cond PRIVATE
24 : :
25 : : #include <QStringList>
26 : : #include <QMap>
27 : : #include <QVector>
28 : :
29 : : #include <algorithm>
30 : : #include <functional>
31 : : #include <math.h>
32 : : #include <numeric>
33 : :
34 : : #include "qgsrectangle.h"
35 : : #include "qgsmeshlayer.h"
36 : : #include "qgsmeshdataprovider.h"
37 : : #include "qgis_core.h"
38 : :
39 : : /**
40 : : * \ingroup core
41 : : * \class QgsMeshCalcUtils
42 : : * \brief Mathematical operations on QgsMeshMemoryDatasetGroup
43 : : *
44 : : * QgsMeshMemoryDatasetGroups must be compatible (same mesh structure, same number of datasets, ...)
45 : : * Any operation with NODATA is NODATA (e.g. NODATA + 1 = NODATA)
46 : : *
47 : : * \since QGIS 3.6
48 : : */
49 : 0 : class CORE_EXPORT QgsMeshCalcUtils
50 : : {
51 : : public:
52 : :
53 : : /**
54 : : * Creates the utils and validates the input
55 : : *
56 : : * The constructor fetches all dataset values and creates memory datasets from them.
57 : : *
58 : : * \param layer mesh layer
59 : : * \param usedGroupNames dataset group's names that are used in the expression
60 : : * \param startTime start time
61 : : * \param endTime end time
62 : : */
63 : : QgsMeshCalcUtils( QgsMeshLayer *layer,
64 : : const QStringList &usedGroupNames,
65 : : double startTime,
66 : : double endTime );
67 : :
68 : : /**
69 : : * Creates the utils and validates the input
70 : : *
71 : : * The constructor fetches dataset values from selected dataset corresponding to the relative time \a relativeTime
72 : : * (see QgsMeshLayer::datasetIndexAtRelativeTime() and creates memory datasets from them.
73 : : * There are only one dataset per group, selected with the matching method defined for the layer.
74 : : *
75 : : * \param layer mesh layer
76 : : * \param usedGroupNames dataset group's names that are used in the expression
77 : : * \param timeRange time range
78 : : */
79 : : QgsMeshCalcUtils( QgsMeshLayer *layer,
80 : : const QStringList &usedGroupNames,
81 : : const QgsInterval &relativeTime );
82 : :
83 : : //! Returns whether the input parameters are consistent and valid for given mesh layer
84 : : bool isValid() const;
85 : :
86 : : //! Returns associated mesh layer
87 : : const QgsMeshLayer *layer() const;
88 : :
89 : : //! Returns dataset group based on name
90 : : std::shared_ptr<const QgsMeshMemoryDatasetGroup> group( const QString &groupName ) const;
91 : :
92 : : //! Creates a single dataset with all values set to 1
93 : : void ones( QgsMeshMemoryDatasetGroup &group1 ) const;
94 : :
95 : : //! Creates a single dataset with all values set to NODATA
96 : : void nodata( QgsMeshMemoryDatasetGroup &group1 ) const;
97 : :
98 : : //! Returns a single dataset with all values set to val
99 : : std::shared_ptr<QgsMeshMemoryDataset> number( double val, double time ) const;
100 : :
101 : : //! Creates a deepcopy of group with groupName to group1. Does not copy datasets for filtered out times.
102 : : void copy( QgsMeshMemoryDatasetGroup &group1, const QString &groupName ) const;
103 : :
104 : : //! Creates a deepcopy of dataset0
105 : : std::shared_ptr<QgsMeshMemoryDataset> copy( std::shared_ptr<const QgsMeshMemoryDataset> dataset0 ) const;
106 : :
107 : : //! Changes ownership of all datasets from group2 to group1
108 : : void transferDatasets( QgsMeshMemoryDatasetGroup &group1, QgsMeshMemoryDatasetGroup &group2 ) const;
109 : :
110 : : //! If group2 has more datasets than group1, duplicates datasets in group1 so it has the same number of datasets as group2
111 : : void expand( QgsMeshMemoryDatasetGroup &group1,
112 : : const QgsMeshMemoryDatasetGroup &group2 ) const;
113 : :
114 : : //! Creates a single dataset with custom number
115 : : void number( QgsMeshMemoryDatasetGroup &group1, double val ) const;
116 : :
117 : : //! If condition is TRUE (for given time&point), takes val from trueGroup else from falseGroup
118 : : void addIf( QgsMeshMemoryDatasetGroup &trueGroup,
119 : : const QgsMeshMemoryDatasetGroup &falseGroup,
120 : : const QgsMeshMemoryDatasetGroup &condition ) const;
121 : :
122 : : //! Creates a spatial filter from extent
123 : : void filter( QgsMeshMemoryDatasetGroup &group1, const QgsRectangle &extent ) const;
124 : :
125 : : //! Creates a spatial filter from geometry
126 : : void filter( QgsMeshMemoryDatasetGroup &group1, const QgsGeometry &mask ) const;
127 : :
128 : : //! Operator NOT
129 : : void logicalNot( QgsMeshMemoryDatasetGroup &group1 ) const;
130 : :
131 : : //! Operator SIGN
132 : : void changeSign( QgsMeshMemoryDatasetGroup &group1 ) const;
133 : :
134 : : //! Operator ABS
135 : : void abs( QgsMeshMemoryDatasetGroup &group1 ) const;
136 : :
137 : : //! Operator aggregated sum (over all datasets)
138 : : void sumAggregated( QgsMeshMemoryDatasetGroup &group1 ) const;
139 : :
140 : : //! Operator aggregated min (over all datasets)
141 : : void minimumAggregated( QgsMeshMemoryDatasetGroup &group1 ) const;
142 : :
143 : : //! Operator aggregated max (over all datasets)
144 : : void maximumAggregated( QgsMeshMemoryDatasetGroup &group1 ) const;
145 : :
146 : : //! Operator aggregated average (over all datasets)
147 : : void averageAggregated( QgsMeshMemoryDatasetGroup &group1 ) const;
148 : :
149 : : //! Operator +
150 : : void add( QgsMeshMemoryDatasetGroup &group1, const QgsMeshMemoryDatasetGroup &group2 ) const;
151 : :
152 : : //! Operator -
153 : : void subtract( QgsMeshMemoryDatasetGroup &group1, const QgsMeshMemoryDatasetGroup &group2 ) const;
154 : :
155 : : //! Operator *
156 : : void multiply( QgsMeshMemoryDatasetGroup &group1, const QgsMeshMemoryDatasetGroup &group2 ) const;
157 : :
158 : : //! Operator /
159 : : void divide( QgsMeshMemoryDatasetGroup &group1, const QgsMeshMemoryDatasetGroup &group2 ) const;
160 : :
161 : : //! Operator ^
162 : : void power( QgsMeshMemoryDatasetGroup &group1, const QgsMeshMemoryDatasetGroup &group2 ) const;
163 : :
164 : : //! Operator ==
165 : : void equal( QgsMeshMemoryDatasetGroup &group1, const QgsMeshMemoryDatasetGroup &group2 ) const;
166 : :
167 : : //! Operator !=
168 : : void notEqual( QgsMeshMemoryDatasetGroup &group1, const QgsMeshMemoryDatasetGroup &group2 ) const;
169 : :
170 : : //! Operator >
171 : : void greaterThan( QgsMeshMemoryDatasetGroup &group1, const QgsMeshMemoryDatasetGroup &group2 ) const;
172 : :
173 : : //! Operator <
174 : : void lesserThan( QgsMeshMemoryDatasetGroup &group1, const QgsMeshMemoryDatasetGroup &group2 ) const;
175 : :
176 : : //! Operator <=
177 : : void lesserEqual( QgsMeshMemoryDatasetGroup &group1, const QgsMeshMemoryDatasetGroup &group2 ) const;
178 : :
179 : : //! Operator >=
180 : : void greaterEqual( QgsMeshMemoryDatasetGroup &group1, const QgsMeshMemoryDatasetGroup &group2 ) const;
181 : :
182 : : //! Operator AND
183 : : void logicalAnd( QgsMeshMemoryDatasetGroup &group1, const QgsMeshMemoryDatasetGroup &group2 ) const;
184 : :
185 : : //! Operator OR
186 : : void logicalOr( QgsMeshMemoryDatasetGroup &group1, const QgsMeshMemoryDatasetGroup &group2 ) const;
187 : :
188 : : //! Operator minimum
189 : : void minimum( QgsMeshMemoryDatasetGroup &group1, const QgsMeshMemoryDatasetGroup &group2 ) const;
190 : :
191 : : //! Operator maximum
192 : : void maximum( QgsMeshMemoryDatasetGroup &group1, const QgsMeshMemoryDatasetGroup &group2 ) const;
193 : :
194 : : //! Calculates the data type of result dataset group
195 : : static QgsMeshDatasetGroupMetadata::DataType determineResultDataType( QgsMeshLayer *layer, const QStringList &usedGroupNames );
196 : :
197 : : //! Returns the data type of result dataset group
198 : : QgsMeshDatasetGroupMetadata::DataType outputType() const;
199 : :
200 : : private:
201 : : double ffilter( double val1, double filter ) const;
202 : : double fadd( double val1, double val2 ) const;
203 : : double fsubtract( double val1, double val2 ) const;
204 : : double fmultiply( double val1, double val2 ) const;
205 : : double fdivide( double val1, double val2 ) const;
206 : : double fpower( double val1, double val2 ) const;
207 : : double fequal( double val1, double val2 ) const;
208 : : double fnotEqual( double val1, double val2 ) const;
209 : : double fgreaterThan( double val1, double val2 ) const;
210 : : double flesserThan( double val1, double val2 ) const;
211 : : double flesserEqual( double val1, double val2 ) const;
212 : : double fgreaterEqual( double val1, double val2 ) const;
213 : : double flogicalAnd( double val1, double val2 ) const;
214 : : double flogicalOr( double val1, double val2 ) const;
215 : : double flogicalNot( double val1 ) const;
216 : : double fchangeSign( double val1 ) const;
217 : : double fmin( double val1, double val2 ) const;
218 : : double fmax( double val1, double val2 ) const;
219 : : double fabs( double val1 ) const;
220 : : double fsumAggregated( QVector<double> &vals ) const;
221 : : double fminimumAggregated( QVector<double> &vals ) const;
222 : : double fmaximumAggregated( QVector<double> &vals ) const;
223 : : double faverageAggregated( QVector<double> &vals ) const;
224 : :
225 : : /**
226 : : * Clones the dataset data to memory
227 : : *
228 : : * Finds dataset group in provider with the name and copies all values to
229 : : * memory dataset group. Returns NULLPTR if no such dataset group
230 : : * exists. Resulting datasets are guaranteed to have the same mOutputType type
231 : : */
232 : : std::shared_ptr<QgsMeshMemoryDatasetGroup> createMemoryDatasetGroup( const QString &datasetGroupName, const QgsInterval &relativeTime = QgsInterval() ) const;
233 : :
234 : : /**
235 : : * Creates dataset based on group. Initializes values and active based on group type.
236 : : */
237 : : std::shared_ptr<QgsMeshMemoryDataset> createMemoryDataset( const QgsMeshMemoryDatasetGroup &grp ) const;
238 : :
239 : : /**
240 : : * Creates dataset based on group. Fill with values of corresponding dataset
241 : : */
242 : : std::shared_ptr<QgsMeshMemoryDataset> createMemoryDataset( const QgsMeshDatasetIndex &datasetIndex ) const;
243 : :
244 : : /**
245 : : * Creates dataset with given type. Initializes values and active based on type.
246 : : */
247 : : std::shared_ptr<QgsMeshMemoryDataset> createMemoryDataset( const QgsMeshDatasetGroupMetadata::DataType type ) const;
248 : :
249 : : /**
250 : : * Returns dataset based on (time) index. If group has only 1 dataset, returns first one
251 : : */
252 : : std::shared_ptr<QgsMeshMemoryDataset> canditateDataset( QgsMeshMemoryDatasetGroup &group,
253 : : int datasetIndex ) const;
254 : :
255 : : /**
256 : : * Returns dataset based on on (time) index. If group has only 1 dataset, returns first one
257 : : */
258 : : std::shared_ptr<const QgsMeshMemoryDataset> constCandidateDataset( const QgsMeshMemoryDatasetGroup &group,
259 : : int datasetIndex ) const;
260 : :
261 : : /**
262 : : * Returns maximum number of datasets in the groups
263 : : */
264 : : int datasetCount( const QgsMeshMemoryDatasetGroup &group1, const QgsMeshMemoryDatasetGroup &group2 ) const;
265 : :
266 : : /**
267 : : * Set active property for vertices in dataset based on:
268 : : * if given vertex is active in dataset and refDataset
269 : : * if all values in vertices that are referenced by the dataset are not NODATA
270 : : */
271 : : void activate( std::shared_ptr<QgsMeshMemoryDataset> dataset,
272 : : std::shared_ptr<const QgsMeshMemoryDataset> refDataset = nullptr ) const;
273 : :
274 : : //! Activates all datasets in group
275 : : void activate( QgsMeshMemoryDatasetGroup &group ) const;
276 : :
277 : : //! Creates spatial filter group from rectagle
278 : : void populateSpatialFilter( QgsMeshMemoryDatasetGroup &filter, const QgsRectangle &extent ) const; // create a filter from extent
279 : :
280 : : //! Creates mask filter group from geometry
281 : : void populateMaskFilter( QgsMeshMemoryDatasetGroup &filter, const QgsGeometry &mask ) const; // create a filter from mask
282 : :
283 : : //! Calculates unary operators
284 : : void func1( QgsMeshMemoryDatasetGroup &group,
285 : : std::function<double( double )> func ) const;
286 : :
287 : : //! Calculates binary operators
288 : : void func2( QgsMeshMemoryDatasetGroup &group1,
289 : : const QgsMeshMemoryDatasetGroup &group2,
290 : : std::function<double( double, double )> func ) const;
291 : :
292 : : //! Calculates unary aggregate operator (e.g. sum of values of one vertex for all times)
293 : : void funcAggr( QgsMeshMemoryDatasetGroup &group1,
294 : : std::function<double( QVector<double>& )> func ) const;
295 : :
296 : : const QgsTriangularMesh *triangularMesh() const;
297 : : const QgsMesh *nativeMesh() const;
298 : : void updateMesh() const;
299 : :
300 : : QgsMeshLayer *mMeshLayer; //!< Reference mesh
301 : : bool mIsValid; //!< All used datasets (in datasetMap) do have outputs for same times & all used dataset names are present in mesh
302 : : QgsMeshDatasetGroupMetadata::DataType mOutputType; //!< Mesh can work only with one output types, so you cannot mix
303 : : //!< E.g. one dataset with element outputs and one with node outputs
304 : : QVector<double> mTimes;
305 : : QMap < QString, std::shared_ptr<QgsMeshMemoryDatasetGroup> > mDatasetGroupMap; //!< Groups that are referenced in the expression
306 : : };
307 : :
308 : : ///@endcond
309 : :
310 : : #endif // QGSMESHCALCUTILS_H
|