QGIS API Documentation  3.27.0-Master (11ef3e5184)
qgsmesh3daveraging.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsmesh3daveraging.cpp
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 #include <memory>
19 
20 #include "qgsmesh3daveraging.h"
21 #include "qgsmeshdataprovider.h"
23 #include "qgsfeedback.h"
24 
25 // threshold for length intervals, to avoid division by 0
26 static const double eps = 1e-6;
27 
29  : mMethod( method )
30 {
31 }
32 
34 {
35  std::unique_ptr<QgsMesh3dAveragingMethod> ret;
36 
38  elem.attribute( QStringLiteral( "method" ) ).toInt() );
39  switch ( method )
40  {
42  ret.reset( new QgsMeshMultiLevelsAveragingMethod() );
43  break;
45  ret.reset( new QgsMeshSigmaAveragingMethod() );
46  break;
48  ret.reset( new QgsMeshRelativeHeightAveragingMethod() );
49  break;
51  ret.reset( new QgsMeshElevationAveragingMethod() );
52  break;
53  }
54  ret->readXml( elem );
55  return ret.release();
56 }
57 
59 {
60  if ( !block3d.isValid() )
61  return QgsMeshDataBlock();
62 
63  if ( !hasValidInputs() )
64  return QgsMeshDataBlock();
65 
66  const bool isVector = block3d.isVector();
67  const int count = block3d.count();
69  QVector<double> valuesFaces( isVector ? 2 * count : count, std::numeric_limits<double>::quiet_NaN() );
70  const QVector<int> verticalLevelsCount = block3d.verticalLevelsCount();
71  const QVector<double> verticalLevels = block3d.verticalLevels();
72  const QVector<double> volumeValues = block3d.values();
73 
74  int startVolumeIndex = 0;
75  for ( int faceIndex = 0; faceIndex < count; ++faceIndex )
76  {
77  if ( feedback && feedback->isCanceled() )
78  {
79  return QgsMeshDataBlock();
80  }
81 
82  const int volumesBelowFaceCount = verticalLevelsCount[faceIndex];
83  if ( volumesBelowFaceCount <= 0 )
84  continue;
85 
86  const int startVerticalLevelIndex = startVolumeIndex + faceIndex;
87  Q_ASSERT( verticalLevels.size() >= startVerticalLevelIndex + volumesBelowFaceCount + 1 );
88  QVector<double> verticalLevelsForFace = verticalLevels.mid( startVerticalLevelIndex, volumesBelowFaceCount + 1 );
89  double faceLevelTop = verticalLevelsForFace[0];
90  double faceLevelBottom = verticalLevelsForFace[verticalLevelsForFace.size() - 1];
91 
92  // the level is value below surface, so top level (-0.1m) is usually higher number than bottom level (e.g. -1.2m)
93  if ( faceLevelTop < faceLevelBottom )
94  {
95  std::swap( faceLevelTop, faceLevelBottom );
96  }
97 
98  double methodLevelTop = std::numeric_limits<double>::quiet_NaN();
99  double methodLevelBottom = std::numeric_limits<double>::quiet_NaN();
100 
101  int singleVerticalIndex = -1;
102  volumeRangeForFace( methodLevelTop,
103  methodLevelBottom,
104  singleVerticalIndex,
105  verticalLevelsForFace );
106 
107  if ( singleVerticalIndex != -1 )
108  {
109  int volumeIndex = singleVerticalIndex + startVolumeIndex;
110  if ( isVector )
111  {
112  valuesFaces[2 * faceIndex] = volumeValues.at( 2 * volumeIndex );
113  valuesFaces[2 * faceIndex + 1 ] = volumeValues.at( 2 * volumeIndex + 1 );
114  }
115  else
116  {
117  valuesFaces[faceIndex] = volumeValues.at( volumeIndex );
118  }
119  }
120  else if ( !std::isnan( methodLevelTop ) && !std::isnan( methodLevelBottom ) )
121  {
122  // the level is value below surface, so top level (-0.1m) is usually higher number than bottom level (e.g. -1.2m)
123  if ( methodLevelTop < methodLevelBottom )
124  {
125  std::swap( methodLevelTop, methodLevelBottom );
126  }
127 
128  // check if we are completely outside the limits
129  if ( ( methodLevelTop >= faceLevelBottom ) && ( methodLevelBottom <= faceLevelTop ) )
130  {
131  averageVolumeValuesForFace(
132  faceIndex,
133  volumesBelowFaceCount,
134  startVolumeIndex,
135  methodLevelTop,
136  methodLevelBottom,
137  isVector,
138  verticalLevelsForFace,
139  volumeValues,
140  valuesFaces
141  );
142  }
143  }
144 
145  // move to next face and associated volumes
146  startVolumeIndex += volumesBelowFaceCount;
147  }
148  result.setValues( valuesFaces );
149  return result;
150 }
151 
153 {
154  return mMethod;
155 }
156 
157 void QgsMesh3dAveragingMethod::averageVolumeValuesForFace(
158  int faceIndex,
159  int volumesBelowFaceCount,
160  int startVolumeIndex,
161  double methodLevelTop,
162  double methodLevelBottom,
163  bool isVector,
164  const QVector<double> &verticalLevelsForFace,
165  const QVector<double> &volumeValues,
166  QVector<double> &valuesFaces
167 ) const
168 {
169  double totalAveragedHeight = 0;
170  double nSumX = 0.0;
171  double nSumY = 0.0;
172 
173  // Now go through all volumes below face and check if we need to take that volume into consideration
174  for ( int relativeVolumeIndex = 0; relativeVolumeIndex < volumesBelowFaceCount; ++relativeVolumeIndex )
175  {
176  const int volumeIndex = startVolumeIndex + relativeVolumeIndex;
177  double volumeLevelTop = verticalLevelsForFace[relativeVolumeIndex];
178  double volumeLevelBottom = verticalLevelsForFace[relativeVolumeIndex + 1];
179  if ( volumeLevelTop < volumeLevelBottom )
180  {
181  std::swap( volumeLevelTop, volumeLevelBottom );
182  }
183 
184  const double intersectionLevelTop = std::min( methodLevelTop, volumeLevelTop );
185  const double intersectionLevelBottom = std::max( methodLevelBottom, volumeLevelBottom );
186  const double effectiveInterval = intersectionLevelTop - intersectionLevelBottom;
187 
188  if ( effectiveInterval > eps )
189  {
190  if ( isVector )
191  {
192  const double x = volumeValues[2 * volumeIndex ];
193  const double y = volumeValues[ 2 * volumeIndex + 1 ];
194  if ( ! std::isnan( x ) &&
195  ! std::isnan( y )
196  )
197  {
198  nSumX += x * effectiveInterval;
199  nSumY += y * effectiveInterval;
200  totalAveragedHeight += effectiveInterval;
201  }
202  }
203  else
204  {
205  const double x = volumeValues[ volumeIndex ];
206  if ( ! std::isnan( x ) )
207  {
208  nSumX += x * effectiveInterval;
209  totalAveragedHeight += effectiveInterval;
210  }
211  }
212  }
213  }
214 
215  // calculate average
216  if ( totalAveragedHeight > eps )
217  {
218  if ( isVector )
219  {
220  valuesFaces[2 * faceIndex] = nSumX / totalAveragedHeight;
221  valuesFaces[2 * faceIndex + 1 ] = nSumY / totalAveragedHeight;
222  }
223  else
224  {
225  valuesFaces[faceIndex] = nSumX / totalAveragedHeight;
226  }
227  }
228 }
229 
231 {
232  if ( a )
233  return a->equals( b );
234  else
235  return !b;
236 }
237 
238 QgsMeshMultiLevelsAveragingMethod::QgsMeshMultiLevelsAveragingMethod( int startLevel, int endLevel, bool countedFromTop )
239  : QgsMesh3dAveragingMethod( QgsMesh3dAveragingMethod::MultiLevelsAveragingMethod )
240  , mStartVerticalLevel( startLevel )
241  , mEndVerticalLevel( endLevel )
242  , mCountedFromTop( countedFromTop )
243 {
244  if ( mStartVerticalLevel > mEndVerticalLevel )
245  {
246  std::swap( mStartVerticalLevel, mEndVerticalLevel );
247  }
248 }
249 
251  : QgsMesh3dAveragingMethod( QgsMesh3dAveragingMethod::MultiLevelsAveragingMethod )
252 {
253 }
254 
256  : QgsMesh3dAveragingMethod( QgsMesh3dAveragingMethod::MultiLevelsAveragingMethod )
257  , mStartVerticalLevel( verticalLevel )
258  , mEndVerticalLevel( verticalLevel )
259  , mCountedFromTop( countedFromTop )
260 {
261 }
262 
264 
265 QDomElement QgsMeshMultiLevelsAveragingMethod::writeXml( QDomDocument &doc ) const
266 {
267  QDomElement elem = doc.createElement( QStringLiteral( "multi-vertical-layers-settings" ) );
268  elem.setAttribute( QStringLiteral( "start-layer-index" ), startVerticalLevel() );
269  elem.setAttribute( QStringLiteral( "end-layer-index" ), endVerticalLevel() );
270  return elem;
271 }
272 
273 void QgsMeshMultiLevelsAveragingMethod::readXml( const QDomElement &elem )
274 {
275  const QDomElement settings = elem.firstChildElement( QStringLiteral( "multi-vertical-layers-settings" ) );
276  if ( !settings.isNull() )
277  {
278  mStartVerticalLevel = settings.attribute( QStringLiteral( "start-layer-index" ) ).toInt();
279  mEndVerticalLevel = settings.attribute( QStringLiteral( "end-layer-index" ) ).toInt();
280  if ( mStartVerticalLevel > mEndVerticalLevel )
281  {
282  std::swap( mStartVerticalLevel, mEndVerticalLevel );
283  }
284  }
285 }
286 
288 {
289  if ( !other || other->method() != method() )
290  return false;
291 
292  const QgsMeshMultiLevelsAveragingMethod *otherMethod = static_cast<const QgsMeshMultiLevelsAveragingMethod *>( other );
293 
294  return ( otherMethod->startVerticalLevel() == startVerticalLevel() ) &&
295  ( otherMethod->endVerticalLevel() == endVerticalLevel() ) &&
296  ( otherMethod->countedFromTop() == countedFromTop() );
297 }
298 
300 {
302 }
303 
304 
306 {
307  return mStartVerticalLevel;
308 }
309 
311 {
312  return mEndVerticalLevel;
313 }
314 
315 bool QgsMeshMultiLevelsAveragingMethod::hasValidInputs() const
316 {
317  return mStartVerticalLevel >= 1 && mEndVerticalLevel >= mStartVerticalLevel;
318 }
319 
320 void QgsMeshMultiLevelsAveragingMethod::volumeRangeForFace( double &startVerticalLevel,
321  double &endVerticalLevel,
322  int &singleVerticalIndex,
323  const QVector<double> &verticalLevels ) const
324 {
325  Q_ASSERT( mStartVerticalLevel <= mEndVerticalLevel );
326 
327  if ( countedFromTop() )
328  {
329  const int startIndex = mStartVerticalLevel - 1;
330  if ( mStartVerticalLevel == mEndVerticalLevel )
331  {
332  if ( startIndex >= 0 && startIndex < verticalLevels.size() - 1 )
333  singleVerticalIndex = startIndex;
334  }
335  else
336  {
337  if ( startIndex >= 0 && startIndex < verticalLevels.size() )
338  {
339  startVerticalLevel = verticalLevels[ startIndex ];
340  }
341 
342  if ( mEndVerticalLevel >= 0 && mEndVerticalLevel < verticalLevels.size() )
343  {
344  endVerticalLevel = verticalLevels[ mEndVerticalLevel ];
345  }
346  else
347  {
348  endVerticalLevel = verticalLevels[ verticalLevels.size() - 1 ];
349  }
350  }
351  }
352  else
353  {
354  const int volumesBelowFaceCount = verticalLevels.size() - 1;
355  const int startIndex = volumesBelowFaceCount - mEndVerticalLevel;
356  if ( mStartVerticalLevel == mEndVerticalLevel )
357  {
358  if ( startIndex >= 0 && startIndex < verticalLevels.size() - 1 )
359  singleVerticalIndex = startIndex;
360  }
361  else
362  {
363  if ( startIndex >= 0 && startIndex < verticalLevels.size() )
364  {
365  startVerticalLevel = verticalLevels[ startIndex ];
366  }
367  else
368  {
369  startVerticalLevel = verticalLevels[ 0 ];
370  }
371 
372  const int endIndex = volumesBelowFaceCount - mStartVerticalLevel + 1;
373  if ( endIndex >= 0 && endIndex < verticalLevels.size() )
374  {
375  endVerticalLevel = verticalLevels[ endIndex ];
376  }
377  }
378  }
379 }
380 
382  : QgsMesh3dAveragingMethod( QgsMesh3dAveragingMethod::SigmaAveragingMethod )
383 {
384 }
385 
386 QgsMeshSigmaAveragingMethod::QgsMeshSigmaAveragingMethod( double startFraction, double endFraction )
387  : QgsMesh3dAveragingMethod( QgsMesh3dAveragingMethod::SigmaAveragingMethod )
388  , mStartFraction( startFraction )
389  , mEndFraction( endFraction )
390 {
391  if ( mStartFraction > mEndFraction )
392  {
393  std::swap( mStartFraction, mEndFraction );
394  }
395 }
396 
398 
399 QDomElement QgsMeshSigmaAveragingMethod::writeXml( QDomDocument &doc ) const
400 {
401  QDomElement elem = doc.createElement( QStringLiteral( "sigma-settings" ) );
402  elem.setAttribute( QStringLiteral( "start-fraction" ), startFraction() );
403  elem.setAttribute( QStringLiteral( "end-fraction" ), endFraction() );
404  return elem;
405 }
406 
407 void QgsMeshSigmaAveragingMethod::readXml( const QDomElement &elem )
408 {
409  const QDomElement settings = elem.firstChildElement( QStringLiteral( "sigma-settings" ) );
410  if ( !settings.isNull() )
411  {
412  mStartFraction = settings.attribute( QStringLiteral( "start-fraction" ) ).toDouble();
413  mEndFraction = settings.attribute( QStringLiteral( "end-fraction" ) ).toDouble();
414  if ( mStartFraction > mEndFraction )
415  {
416  std::swap( mStartFraction, mEndFraction );
417  }
418  }
419 }
420 
422 {
423  if ( !other || other->method() != method() )
424  return false;
425 
426  const QgsMeshSigmaAveragingMethod *otherMethod = static_cast<const QgsMeshSigmaAveragingMethod *>( other );
427 
428  return qgsDoubleNear( otherMethod->startFraction(), startFraction() ) && qgsDoubleNear( otherMethod->endFraction(), endFraction() ) ;
429 }
430 
432 {
434 }
435 
437 {
438  return mStartFraction;
439 }
440 
442 {
443  return mEndFraction;
444 }
445 
446 bool QgsMeshSigmaAveragingMethod::hasValidInputs() const
447 {
448  return mStartFraction >= 0 && mEndFraction >= mStartFraction && mEndFraction <= 1;
449 }
450 
451 void QgsMeshSigmaAveragingMethod::volumeRangeForFace( double &startVerticalLevel,
452  double &endVerticalLevel,
453  int &,
454  const QVector<double> &verticalLevels ) const
455 {
456  const double top = verticalLevels[ 0 ];
457  const double bot = verticalLevels[ verticalLevels.size() - 1 ];
458  const double diff = top - bot;
459 
460  if ( mStartFraction < 0 )
461  startVerticalLevel = bot;
462  else
463  startVerticalLevel = bot + diff * mStartFraction;
464 
465  if ( mEndFraction > 1 )
466  endVerticalLevel = top;
467  else
468  endVerticalLevel = bot + diff * mEndFraction;
469 }
470 
472 {
473  return mCountedFromTop;
474 }
475 
477 {
478  return mStartVerticalLevel == mEndVerticalLevel;
479 }
480 
481 
483  : QgsMesh3dAveragingMethod( QgsMesh3dAveragingMethod::RelativeHeightAveragingMethod )
484 {
485 }
486 
487 QgsMeshRelativeHeightAveragingMethod::QgsMeshRelativeHeightAveragingMethod( double startDepth, double endDepth, bool countedFromTop )
488  : QgsMesh3dAveragingMethod( QgsMesh3dAveragingMethod::RelativeHeightAveragingMethod )
489  , mStartHeight( startDepth )
490  , mEndHeight( endDepth )
491  , mCountedFromTop( countedFromTop )
492 {
493  if ( mStartHeight > mEndHeight )
494  {
495  std::swap( mStartHeight, mEndHeight );
496  }
497 }
498 
500 
501 QDomElement QgsMeshRelativeHeightAveragingMethod::writeXml( QDomDocument &doc ) const
502 {
503  QDomElement elem = doc.createElement( QStringLiteral( "relative-height-settings" ) );
504  elem.setAttribute( QStringLiteral( "start-height" ), startHeight() );
505  elem.setAttribute( QStringLiteral( "end-height" ), endHeight() );
506  return elem;
507 }
508 
509 void QgsMeshRelativeHeightAveragingMethod::readXml( const QDomElement &elem )
510 {
511  const QDomElement settings = elem.firstChildElement( QStringLiteral( "relative-height-settings" ) );
512  if ( !settings.isNull() )
513  {
514  mStartHeight = settings.attribute( QStringLiteral( "start-height" ) ).toDouble();
515  mEndHeight = settings.attribute( QStringLiteral( "end-height" ) ).toDouble();
516  if ( mStartHeight > mEndHeight )
517  {
518  std::swap( mStartHeight, mEndHeight );
519  }
520  }
521 }
522 
524 {
525  if ( !other || other->method() != method() )
526  return false;
527 
528  const QgsMeshRelativeHeightAveragingMethod *otherMethod = static_cast<const QgsMeshRelativeHeightAveragingMethod *>( other );
529 
530  return qgsDoubleNear( otherMethod->startHeight(), startHeight() ) &&
531  qgsDoubleNear( otherMethod->endHeight(), endHeight() ) &&
532  otherMethod->countedFromTop() == countedFromTop();
533 }
534 
536 {
538 }
539 
541 {
542  return mStartHeight;
543 }
544 
546 {
547  return mEndHeight;
548 }
549 
550 bool QgsMeshRelativeHeightAveragingMethod::hasValidInputs() const
551 {
552  return mStartHeight >= 0 && mEndHeight >= mStartHeight;
553 }
554 
555 void QgsMeshRelativeHeightAveragingMethod::volumeRangeForFace( double &startVerticalLevel,
556  double &endVerticalLevel,
557  int &,
558  const QVector<double> &verticalLevels ) const
559 {
560  if ( countedFromTop() )
561  {
562  const double top = verticalLevels[ 0 ];
563  startVerticalLevel = top - mStartHeight;
564  endVerticalLevel = top - mEndHeight;
565  }
566  else
567  {
568  const double bot = verticalLevels[verticalLevels.size() - 1];
569  startVerticalLevel = bot + mStartHeight;
570  endVerticalLevel = bot + mEndHeight;
571  }
572 }
573 
575 {
576  return mCountedFromTop;
577 }
578 
580  : QgsMesh3dAveragingMethod( QgsMesh3dAveragingMethod::ElevationAveragingMethod )
581 {
582 }
583 
584 QgsMeshElevationAveragingMethod::QgsMeshElevationAveragingMethod( double startElevation, double endElevation )
585  : QgsMesh3dAveragingMethod( QgsMesh3dAveragingMethod::ElevationAveragingMethod )
586  , mStartElevation( startElevation )
587  , mEndElevation( endElevation )
588 {
589  if ( mEndElevation > mStartElevation )
590  {
591  std::swap( mEndElevation, mStartElevation );
592  }
593 }
594 
596 
597 QDomElement QgsMeshElevationAveragingMethod::writeXml( QDomDocument &doc ) const
598 {
599  QDomElement elem = doc.createElement( QStringLiteral( "elevation-settings" ) );
600  elem.setAttribute( QStringLiteral( "start-elevation" ), startElevation() );
601  elem.setAttribute( QStringLiteral( "end-elevation" ), endElevation() );
602  return elem;
603 }
604 
605 void QgsMeshElevationAveragingMethod::readXml( const QDomElement &elem )
606 {
607  const QDomElement settings = elem.firstChildElement( QStringLiteral( "elevation-settings" ) );
608  if ( !settings.isNull() )
609  {
610  mStartElevation = settings.attribute( QStringLiteral( "start-elevation" ) ).toDouble();
611  mEndElevation = settings.attribute( QStringLiteral( "end-elevation" ) ).toDouble();
612  if ( mEndElevation > mStartElevation )
613  {
614  std::swap( mEndElevation, mStartElevation );
615  }
616  }
617 }
618 
620 {
621  if ( !other || other->method() != method() )
622  return false;
623 
624  const QgsMeshElevationAveragingMethod *otherMethod = static_cast<const QgsMeshElevationAveragingMethod *>( other );
625 
626  return qgsDoubleNear( otherMethod->startElevation(), startElevation() ) && qgsDoubleNear( otherMethod->endElevation(), endElevation() ) ;
627 }
628 
630 {
632 }
633 
635 {
636  return mStartElevation;
637 }
638 
640 {
641  return mEndElevation;
642 }
643 
644 bool QgsMeshElevationAveragingMethod::hasValidInputs() const
645 {
646  return mStartElevation <= 0.0 && mEndElevation <= mStartElevation;
647 }
648 
649 void QgsMeshElevationAveragingMethod::volumeRangeForFace( double &startVerticalLevel,
650  double &endVerticalLevel,
651  int &,
652  const QVector<double> &verticalLevels ) const
653 {
654  Q_UNUSED( verticalLevels )
655  startVerticalLevel = mStartElevation;
656  endVerticalLevel = mEndElevation;
657 }
Base class for feedback objects to be used for cancellation of something running in a worker thread.
Definition: qgsfeedback.h:45
bool isCanceled() const SIP_HOLDGIL
Tells whether the operation has been canceled already.
Definition: qgsfeedback.h:54
Abstract class to interpolate 3d stacked mesh data to 2d data.
Method method() const
Returns type of averaging method.
Method
Type of averaging method.
@ RelativeHeightAveragingMethod
Method to average values defined by range of relative length units to the surface or bed level.
@ MultiLevelsAveragingMethod
Method to average values from selected vertical layers.
@ ElevationAveragingMethod
Method to average values defined by range of absolute length units to the model's datum.
@ SigmaAveragingMethod
Method to average values between 0 (bed level) and 1 (surface)
QgsMesh3dAveragingMethod(Method method)
Ctor.
QgsMeshDataBlock calculate(const QgsMesh3dDataBlock &block3d, QgsFeedback *feedback=nullptr) const
Calculated 2d block values from 3d stacked mesh values.
static QgsMesh3dAveragingMethod * createFromXml(const QDomElement &elem)
Creates the instance from XML by calling readXml of derived classes.
static bool equals(const QgsMesh3dAveragingMethod *a, const QgsMesh3dAveragingMethod *b)
Returns whether two methods equal.
QgsMesh3dDataBlock is a block of 3d stacked mesh data related N faces defined on base mesh frame.
bool isValid() const
Whether the block is valid.
bool isVector() const
Whether we store vector values.
QVector< int > verticalLevelsCount() const
Returns number of vertical level above 2d faces.
int count() const
Number of 2d faces for which the volume data is stored in the block.
QVector< double > verticalLevels() const
Returns the vertical levels height.
QVector< double > values() const
Returns the values at volume centers.
QgsMeshDataBlock is a block of integers/doubles that can be used to retrieve: active flags (e....
@ ScalarDouble
Scalar double values.
@ Vector2DDouble
Vector double pairs (x1, y1, x2, y2, ... )
void setValues(const QVector< double > &vals)
Sets values.
Elevation averaging method averages the values based on range defined absolute value to the model's d...
double startElevation() const
Returns start elevation.
void readXml(const QDomElement &elem) override
Reads configuration from the given DOM element.
QgsMesh3dAveragingMethod * clone() const override
Clone the instance.
double endElevation() const
Returns end elevation.
bool equals(const QgsMesh3dAveragingMethod *other) const override
Returns whether method equals to other.
QDomElement writeXml(QDomDocument &doc) const override
Writes configuration to a new DOM element.
Multi level averaging method specifies limits of vertical layers from the top layer down or reversed.
QDomElement writeXml(QDomDocument &doc) const override
Writes configuration to a new DOM element.
QgsMeshMultiLevelsAveragingMethod()
Constructs single level averaging method for 1st (top) vertical level.
int endVerticalLevel() const
Returns ending vertical level.
bool equals(const QgsMesh3dAveragingMethod *other) const override
Returns whether method equals to other.
bool countedFromTop() const
Returns whether the start and end vertical levels are indexed from top (surface) or bottom (bed) leve...
bool isSingleLevel() const
Returns whether the averaging method selects only a single vertical level.
QgsMesh3dAveragingMethod * clone() const override
Clone the instance.
void readXml(const QDomElement &elem) override
Reads configuration from the given DOM element.
int startVerticalLevel() const
Returns starting vertical level.
Relative height averaging method averages the values based on range defined relative to bed elevation...
void readXml(const QDomElement &elem) override
Reads configuration from the given DOM element.
double startHeight() const
Returns starting depth/height.
QgsMesh3dAveragingMethod * clone() const override
Clone the instance.
QgsMeshRelativeHeightAveragingMethod()
Constructs default depth averaging method.
bool countedFromTop() const
Returns whether the start and end vertical levels are relative to top (surface) or bottom (bed) level...
bool equals(const QgsMesh3dAveragingMethod *other) const override
Returns whether method equals to other.
QDomElement writeXml(QDomDocument &doc) const override
Writes configuration to a new DOM element.
double endHeight() const
Returns ending depth/height.
Sigma averages over the values between 0 (bed level) and 1 (surface).
double endFraction() const
Returns ending fraction.
QgsMeshSigmaAveragingMethod()
Constructs the sigma method for whole value range 0-1.
void readXml(const QDomElement &elem) override
Reads configuration from the given DOM element.
QDomElement writeXml(QDomDocument &doc) const override
Writes configuration to a new DOM element.
bool equals(const QgsMesh3dAveragingMethod *other) const override
Returns whether method equals to other.
QgsMesh3dAveragingMethod * clone() const override
Clone the instance.
~QgsMeshSigmaAveragingMethod() override
double startFraction() const
Returns starting fraction.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:2527