Branch data Line data Source code
1 : : /***************************************************************************
2 : : qgsmesh3daveraging.h
3 : : ---------------------
4 : : begin : November 2019
5 : : copyright : (C) 2019 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 QGSMESH3DAVERAGING_H
19 : : #define QGSMESH3DAVERAGING_H
20 : :
21 : : #include "qgis_core.h"
22 : : #include "qgis_sip.h"
23 : :
24 : : #include <QDomElement>
25 : :
26 : : class QgsMeshLayer;
27 : : class QgsMesh3dDataBlock;
28 : : class QgsMeshDataBlock;
29 : : class QgsMeshDatasetIndex;
30 : : class QgsFeedback;
31 : : class QgsMeshRenderer3dAveragingSettings;
32 : :
33 : : /**
34 : : * \ingroup core
35 : : * \brief Abstract class to interpolate 3d stacked mesh data to 2d data
36 : : *
37 : : * \since QGIS 3.12
38 : : */
39 : : class CORE_EXPORT QgsMesh3dAveragingMethod SIP_ABSTRACT
40 : : {
41 : :
42 : : #ifdef SIP_RUN
43 : : SIP_CONVERT_TO_SUBCLASS_CODE
44 : : QgsMesh3dAveragingMethod *averagingMethod = dynamic_cast<QgsMesh3dAveragingMethod *>( sipCpp );
45 : :
46 : : sipType = 0;
47 : :
48 : : if ( averagingMethod )
49 : : {
50 : : switch ( averagingMethod->method() )
51 : : {
52 : : case QgsMesh3dAveragingMethod::MultiLevelsAveragingMethod:
53 : : sipType = sipType_QgsMeshMultiLevelsAveragingMethod;
54 : : break;
55 : : case QgsMesh3dAveragingMethod::SigmaAveragingMethod:
56 : : sipType = sipType_QgsMeshSigmaAveragingMethod;
57 : : break;
58 : : case QgsMesh3dAveragingMethod::RelativeHeightAveragingMethod:
59 : : sipType = sipType_QgsMeshRelativeHeightAveragingMethod;
60 : : break;
61 : : case QgsMesh3dAveragingMethod::ElevationAveragingMethod:
62 : : sipType = sipType_QgsMeshElevationAveragingMethod;
63 : : break;
64 : : default:
65 : : sipType = nullptr;
66 : : break;
67 : : }
68 : : }
69 : : SIP_END
70 : : #endif
71 : :
72 : : public:
73 : : //! Type of averaging method
74 : : enum Method
75 : : {
76 : : //! Method to average values from selected vertical layers
77 : : MultiLevelsAveragingMethod = 0,
78 : : //! Method to average values between 0 (bed level) and 1 (surface)
79 : : SigmaAveragingMethod,
80 : : //! Method to average values defined by range of relative length units to the surface or bed level
81 : : RelativeHeightAveragingMethod,
82 : : //! Method to average values defined by range of absolute length units to the model's datum
83 : : ElevationAveragingMethod
84 : : };
85 : :
86 : : //! Ctor
87 : : QgsMesh3dAveragingMethod( Method method );
88 : :
89 : : //! Dtor
90 : 0 : virtual ~QgsMesh3dAveragingMethod() = default;
91 : :
92 : : //! Calculated 2d block values from 3d stacked mesh values
93 : : QgsMeshDataBlock calculate( const QgsMesh3dDataBlock &block3d, QgsFeedback *feedback = nullptr ) const;
94 : :
95 : : /**
96 : : * Writes configuration to a new DOM element
97 : : */
98 : : virtual QDomElement writeXml( QDomDocument &doc ) const = 0;
99 : :
100 : : //! Creates the instance from XML by calling readXml of derived classes
101 : : static QgsMesh3dAveragingMethod *createFromXml( const QDomElement &elem ) SIP_FACTORY;
102 : :
103 : : //! Reads configuration from the given DOM element
104 : : virtual void readXml( const QDomElement &elem ) = 0;
105 : :
106 : : //! Returns whether two methods equal
107 : : static bool equals( const QgsMesh3dAveragingMethod *a, const QgsMesh3dAveragingMethod *b );
108 : :
109 : : //! Returns whether method equals to other
110 : : virtual bool equals( const QgsMesh3dAveragingMethod *other ) const = 0;
111 : :
112 : : //! Clone the instance
113 : : virtual QgsMesh3dAveragingMethod *clone() const = 0 SIP_FACTORY;
114 : :
115 : : //! Returns type of averaging method
116 : : Method method() const;
117 : :
118 : : private:
119 : : //! Returns whether the method is correctly initialized
120 : : virtual bool hasValidInputs() const = 0;
121 : :
122 : : /**
123 : : * For one face, Calculates average of volume values
124 : : */
125 : : void averageVolumeValuesForFace(
126 : : int faceIndex,
127 : : int volumesBelowFaceCount,
128 : : int startVolumeIndex,
129 : : double methodLevelTop,
130 : : double methodLevelBottom,
131 : : bool isVector,
132 : : const QVector<double> &verticalLevelsForFace,
133 : : const QVector<double> &volumeValues,
134 : : QVector<double> &valuesFaces
135 : : ) const;
136 : :
137 : : /**
138 : : * For one face, calculates absolute vertical levels between which we need to average
139 : : */
140 : : virtual void volumeRangeForFace(
141 : : double &startVerticalLevel,
142 : : double &endVerticalLevel,
143 : : const QVector<double> &verticalLevels ) const = 0;
144 : :
145 : : Method mMethod;
146 : : };
147 : :
148 : : /**
149 : : * \ingroup core
150 : : *
151 : : * \brief Multi level averaging method specifies limits of vertical layers from the top layer down or reversed.
152 : : *
153 : : * The limits will be truncated to the maximum number of vertical layers.
154 : : * To pick value from a single layer, specify the upper and lower limit to be the same
155 : : *
156 : : * \since QGIS 3.12
157 : : */
158 : : class CORE_EXPORT QgsMeshMultiLevelsAveragingMethod: public QgsMesh3dAveragingMethod
159 : : {
160 : : public:
161 : : //! Constructs single level averaging method for 1st (top) vertical level
162 : : QgsMeshMultiLevelsAveragingMethod();
163 : :
164 : : /**
165 : : * Constructs multi level averaging method
166 : : * \param startLevel starting vertical level index numbered from 1
167 : : * \param endLevel ending vertical level index numbered from 1 (higher or equal than startLevel)
168 : : * \param countedFromTop if TRUE, the startLevel index is counted from surface (index 1 is the top layer).
169 : : * if FALSE, the startLevel index is counted from the bed level (index 1 is the bottom layer)
170 : : */
171 : : QgsMeshMultiLevelsAveragingMethod( int startLevel, int endLevel, bool countedFromTop );
172 : :
173 : : /**
174 : : * Constructs single level averaging method
175 : : * \param verticalLevel vertical level index numbered from 1
176 : : * \param countedFromTop if TRUE, the startLevel index is counted from surface (index 1 is the top layer).
177 : : * if FALSE, the startLevel index is counted from the bed level (index 1 is the bottom layer)
178 : : */
179 : : QgsMeshMultiLevelsAveragingMethod( int verticalLevel, bool countedFromTop );
180 : :
181 : : ~QgsMeshMultiLevelsAveragingMethod() override;
182 : : QDomElement writeXml( QDomDocument &doc ) const override;
183 : : void readXml( const QDomElement &elem ) override;
184 : : bool equals( const QgsMesh3dAveragingMethod *other ) const override;
185 : : QgsMesh3dAveragingMethod *clone() const override SIP_FACTORY;
186 : :
187 : : /**
188 : : * Returns starting vertical level.
189 : : *
190 : : * Numbered from 1. If countedFromTop(), 1 represents the top (surface) level,
191 : : * otherwise 1 represents the bottom (bed) level
192 : : *
193 : : * Always lower or equal than endVerticalLevel()
194 : : */
195 : : int startVerticalLevel() const;
196 : :
197 : : /**
198 : : * Returns ending vertical level.
199 : : *
200 : : * Numbered from 1. If countedFromTop(), 1 represents the top (surface) level,
201 : : * otherwise 1 represents the bottom (bed) level
202 : : *
203 : : * Always lower or equal than endVerticalLevel()
204 : : */
205 : : int endVerticalLevel() const;
206 : :
207 : : /**
208 : : * Returns whether the start and end vertical levels are indexed from top (surface) or bottom (bed) level
209 : : */
210 : : bool countedFromTop() const;
211 : :
212 : : /**
213 : : * Returns whether the averaging method selects only a single vertical level
214 : : */
215 : : bool isSingleLevel() const;
216 : :
217 : : private:
218 : : bool hasValidInputs() const override;
219 : : void volumeRangeForFace( double &startVerticalLevel,
220 : : double &endVerticalLevel,
221 : : const QVector<double> &verticalLevels ) const override;
222 : : void setLevels( int startVerticalLevel, int endVerticalLevel );
223 : : int mStartVerticalLevel = 1;
224 : : int mEndVerticalLevel = 1;
225 : : bool mCountedFromTop = true;
226 : : };
227 : :
228 : : /**
229 : : * \ingroup core
230 : : *
231 : : * \brief Sigma averages over the values between 0 (bed level) and 1 (surface).
232 : : *
233 : : * The fractions will be truncated to 0-1.
234 : : * For example: the average of between a quarter and 3 quarters of the water column - Sigma from 0.25 to 0.75
235 : : *
236 : : * \since QGIS 3.12
237 : : */
238 : : class CORE_EXPORT QgsMeshSigmaAveragingMethod: public QgsMesh3dAveragingMethod
239 : : {
240 : : public:
241 : : //! Constructs the sigma method for whole value range 0-1
242 : : QgsMeshSigmaAveragingMethod();
243 : :
244 : : /**
245 : : * Constructs the sigma method
246 : : * \param startFraction starting fraction (0-1)
247 : : * \param endFraction ending fraction, must be higher or equal than startFraction (0-1)
248 : : */
249 : : QgsMeshSigmaAveragingMethod( double startFraction, double endFraction );
250 : :
251 : : ~QgsMeshSigmaAveragingMethod() override;
252 : : QDomElement writeXml( QDomDocument &doc ) const override;
253 : : void readXml( const QDomElement &elem ) override;
254 : : bool equals( const QgsMesh3dAveragingMethod *other ) const override;
255 : : QgsMesh3dAveragingMethod *clone() const override SIP_FACTORY;
256 : :
257 : : /**
258 : : * Returns starting fraction.
259 : : *
260 : : * In range 0-1, where 1 means the surface level and 0 bed level.
261 : : * Always lower or equal than endFraction()
262 : : */
263 : : double startFraction() const;
264 : :
265 : : /**
266 : : * Returns ending fraction.
267 : : *
268 : : * In range 0-1, where 1 means the surface level and 0 bed level.
269 : : * Always higher or equal than startFraction()
270 : : */
271 : : double endFraction() const;
272 : :
273 : : private:
274 : : bool hasValidInputs() const override;
275 : : void volumeRangeForFace( double &startVerticalLevel,
276 : : double &endVerticalLevel,
277 : : const QVector<double> &verticalLevels ) const override;
278 : :
279 : : double mStartFraction = 0;
280 : : double mEndFraction = 1;
281 : : };
282 : :
283 : : /**
284 : : * \ingroup core
285 : : *
286 : : * \brief Relative height averaging method averages the values based on range defined relative to bed elevation or surface (when countedFromTop())
287 : : * The range is defined in the same length units as defined by model (e.g. meters)
288 : : *
289 : : * if countedFromTop(), the method represents averaging based on depth below surface.
290 : : * For example one can pull out results for between 6 to 12 meters below the water surface - depth from 6m to 12m.
291 : : * The depth will be truncated at the bed level.
292 : : *
293 : : * if not countedFromTop(), the method represents averaging based on height above bed level.
294 : : * For example one can pull out results for between 6 to 12 meters above the bed - height from 6m to 12m.
295 : : * The height will be truncated at the bed level.
296 : : *
297 : : * \since QGIS 3.12
298 : : */
299 : : class CORE_EXPORT QgsMeshRelativeHeightAveragingMethod: public QgsMesh3dAveragingMethod
300 : : {
301 : : public:
302 : :
303 : : //! Constructs default depth averaging method
304 : : QgsMeshRelativeHeightAveragingMethod();
305 : :
306 : : /**
307 : : * Constructs the depth/height averaging method
308 : : * \param startHeight starting depth/height, higher or equal than 0
309 : : * \param endHeight ending depth/height, higher or equal than startDepth
310 : : * \param countedFromTop if TRUE, the startLength and endLength is relative to surface (0 is surface level).
311 : : * if FALSE, the startLength and endLength is relative to bed (0 is bed level).
312 : : */
313 : : QgsMeshRelativeHeightAveragingMethod( double startHeight, double endHeight, bool countedFromTop );
314 : :
315 : : ~QgsMeshRelativeHeightAveragingMethod() override;
316 : : QDomElement writeXml( QDomDocument &doc ) const override;
317 : : void readXml( const QDomElement &elem ) override;
318 : : bool equals( const QgsMesh3dAveragingMethod *other ) const override;
319 : : QgsMesh3dAveragingMethod *clone() const override SIP_FACTORY;
320 : :
321 : : /**
322 : : * Returns starting depth/height.
323 : : *
324 : : * Always lower or equal than endLength()
325 : : */
326 : : double startHeight() const;
327 : :
328 : : /**
329 : : * Returns ending depth/height.
330 : : *
331 : : * Always higher or equal than startLength()
332 : : */
333 : : double endHeight() const;
334 : :
335 : : /**
336 : : * Returns whether the start and end vertical levels are relative to top (surface) or bottom (bed) level
337 : : */
338 : : bool countedFromTop() const;
339 : :
340 : : private:
341 : : bool hasValidInputs() const override;
342 : : void volumeRangeForFace( double &startVerticalLevel,
343 : : double &endVerticalLevel,
344 : : const QVector<double> &verticalLevels ) const override;
345 : : double mStartHeight = 0;
346 : : double mEndHeight = 0;
347 : : bool mCountedFromTop = true;
348 : : };
349 : :
350 : : /**
351 : : * \ingroup core
352 : : *
353 : : * \brief Elevation averaging method averages the values based on range defined absolute value to the model's datum
354 : : * The range is defined in the same length units as defined by model (e.g. meters)
355 : : *
356 : : * For example one can pull out results irrespective of water level change such as between -16m and -10m.
357 : : * The elevation will be truncated at the surface and bed levels.
358 : : *
359 : : * \since QGIS 3.12
360 : : */
361 : : class CORE_EXPORT QgsMeshElevationAveragingMethod: public QgsMesh3dAveragingMethod
362 : : {
363 : : public:
364 : :
365 : : //! Ctor
366 : : QgsMeshElevationAveragingMethod();
367 : :
368 : : /**
369 : : * Constructs elevation averaging method
370 : : * \param startElevation start elevation (absolute to model's datum)
371 : : * \param endElevation end elevation (absolute to model's datum)
372 : : */
373 : : QgsMeshElevationAveragingMethod( double startElevation, double endElevation );
374 : : ~QgsMeshElevationAveragingMethod() override;
375 : :
376 : : QDomElement writeXml( QDomDocument &doc ) const override;
377 : : void readXml( const QDomElement &elem ) override;
378 : : bool equals( const QgsMesh3dAveragingMethod *other ) const override;
379 : : QgsMesh3dAveragingMethod *clone() const override SIP_FACTORY;
380 : :
381 : : /**
382 : : * Returns start elevation
383 : : */
384 : : double startElevation() const;
385 : :
386 : : /**
387 : : * Returns end elevation
388 : : */
389 : : double endElevation() const;
390 : :
391 : : private:
392 : : bool hasValidInputs() const override;
393 : : void volumeRangeForFace( double &startVerticalLevel,
394 : : double &endVerticalLevel,
395 : : const QVector<double> &verticalLevels ) const override;
396 : : double mStartElevation = 0;
397 : : double mEndElevation = 0;
398 : : };
399 : :
400 : : #endif // QGSMESH3DAVERAGING_H
|