26 static const double eps = 1e-6;
35 std::unique_ptr<QgsMesh3dAveragingMethod> ret;
38 elem.attribute( QStringLiteral(
"method" ) ).toInt() );
63 if ( !hasValidInputs() )
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() );
72 const QVector<double> volumeValues = block3d.
values();
74 int startVolumeIndex = 0;
75 for (
int faceIndex = 0; faceIndex < count; ++faceIndex )
82 const int volumesBelowFaceCount = verticalLevelsCount[faceIndex];
83 if ( volumesBelowFaceCount <= 0 )
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];
93 if ( faceLevelTop < faceLevelBottom )
95 std::swap( faceLevelTop, faceLevelBottom );
98 double methodLevelTop = std::numeric_limits<double>::quiet_NaN();
99 double methodLevelBottom = std::numeric_limits<double>::quiet_NaN();
101 volumeRangeForFace( methodLevelTop,
103 verticalLevelsForFace );
105 if ( !std::isnan( methodLevelTop ) && !std::isnan( methodLevelBottom ) )
108 if ( methodLevelTop < methodLevelBottom )
110 std::swap( methodLevelTop, methodLevelBottom );
114 if ( ( methodLevelTop >= faceLevelBottom ) && ( methodLevelBottom <= faceLevelTop ) )
116 averageVolumeValuesForFace(
118 volumesBelowFaceCount,
123 verticalLevelsForFace,
131 startVolumeIndex += volumesBelowFaceCount;
142 void QgsMesh3dAveragingMethod::averageVolumeValuesForFace(
144 int volumesBelowFaceCount,
145 int startVolumeIndex,
146 double methodLevelTop,
147 double methodLevelBottom,
149 const QVector<double> &verticalLevelsForFace,
150 const QVector<double> &volumeValues,
151 QVector<double> &valuesFaces
154 double totalAveragedHeight = 0;
159 for (
int relativeVolumeIndex = 0; relativeVolumeIndex < volumesBelowFaceCount; ++relativeVolumeIndex )
161 const int volumeIndex = startVolumeIndex + relativeVolumeIndex;
162 double volumeLevelTop = verticalLevelsForFace[relativeVolumeIndex];
163 double volumeLevelBottom = verticalLevelsForFace[relativeVolumeIndex + 1];
164 if ( volumeLevelTop < volumeLevelBottom )
166 std::swap( volumeLevelTop, volumeLevelBottom );
169 const double intersectionLevelTop = std::min( methodLevelTop, volumeLevelTop );
170 const double intersectionLevelBottom = std::max( methodLevelBottom, volumeLevelBottom );
171 const double effectiveInterval = intersectionLevelTop - intersectionLevelBottom;
173 if ( effectiveInterval > eps )
177 const double x = volumeValues[2 * volumeIndex ];
178 const double y = volumeValues[ 2 * volumeIndex + 1 ];
179 if ( ! std::isnan( x ) &&
183 nSumX += x * effectiveInterval;
184 nSumY += y * effectiveInterval;
185 totalAveragedHeight += effectiveInterval;
190 const double x = volumeValues[ volumeIndex ];
191 if ( ! std::isnan( x ) )
193 nSumX += x * effectiveInterval;
194 totalAveragedHeight += effectiveInterval;
201 if ( totalAveragedHeight > eps )
205 valuesFaces[2 * faceIndex] = nSumX / totalAveragedHeight;
206 valuesFaces[2 * faceIndex + 1 ] = nSumY / totalAveragedHeight;
210 valuesFaces[faceIndex] = nSumX / totalAveragedHeight;
225 , mStartVerticalLevel( startLevel )
226 , mEndVerticalLevel( endLevel )
227 , mCountedFromTop( countedFromTop )
229 if ( mStartVerticalLevel > mEndVerticalLevel )
231 std::swap( mStartVerticalLevel, mEndVerticalLevel );
242 , mStartVerticalLevel( verticalLevel )
243 , mEndVerticalLevel( verticalLevel )
244 , mCountedFromTop( countedFromTop )
252 QDomElement elem = doc.createElement( QStringLiteral(
"multi-vertical-layers-settings" ) );
254 elem.setAttribute( QStringLiteral(
"end-layer-index" ),
endVerticalLevel() );
260 const QDomElement settings = elem.firstChildElement( QStringLiteral(
"multi-vertical-layers-settings" ) );
261 if ( !settings.isNull() )
263 mStartVerticalLevel = settings.attribute( QStringLiteral(
"start-layer-index" ) ).toInt();
264 mEndVerticalLevel = settings.attribute( QStringLiteral(
"end-layer-index" ) ).toInt();
265 if ( mStartVerticalLevel > mEndVerticalLevel )
267 std::swap( mStartVerticalLevel, mEndVerticalLevel );
292 return mStartVerticalLevel;
297 return mEndVerticalLevel;
300 bool QgsMeshMultiLevelsAveragingMethod::hasValidInputs()
const
302 return mStartVerticalLevel >= 1 && mEndVerticalLevel >= mStartVerticalLevel;
305 void QgsMeshMultiLevelsAveragingMethod::volumeRangeForFace(
306 double &startVerticalLevel,
307 double &endVerticalLevel,
308 const QVector<double> &verticalLevels
311 Q_ASSERT( mStartVerticalLevel <= mEndVerticalLevel );
315 const int startIndex = mStartVerticalLevel - 1;
316 if ( startIndex >= 0 && startIndex < verticalLevels.size() )
321 if ( mEndVerticalLevel >= 0 && mEndVerticalLevel < verticalLevels.size() )
332 const int volumesBelowFaceCount = verticalLevels.size() - 1;
333 const int startIndex = volumesBelowFaceCount - mEndVerticalLevel;
334 if ( startIndex >= 0 && startIndex < verticalLevels.size() )
343 const int endIndex = volumesBelowFaceCount - mStartVerticalLevel + 1;
344 if ( endIndex >= 0 && endIndex < verticalLevels.size() )
358 , mStartFraction( startFraction )
359 , mEndFraction( endFraction )
361 if ( mStartFraction > mEndFraction )
363 std::swap( mStartFraction, mEndFraction );
371 QDomElement elem = doc.createElement( QStringLiteral(
"sigma-settings" ) );
372 elem.setAttribute( QStringLiteral(
"start-fraction" ),
startFraction() );
373 elem.setAttribute( QStringLiteral(
"end-fraction" ),
endFraction() );
379 const QDomElement settings = elem.firstChildElement( QStringLiteral(
"sigma-settings" ) );
380 if ( !settings.isNull() )
382 mStartFraction = settings.attribute( QStringLiteral(
"start-fraction" ) ).toDouble();
383 mEndFraction = settings.attribute( QStringLiteral(
"end-fraction" ) ).toDouble();
384 if ( mStartFraction > mEndFraction )
386 std::swap( mStartFraction, mEndFraction );
408 return mStartFraction;
416 bool QgsMeshSigmaAveragingMethod::hasValidInputs()
const
418 return mStartFraction >= 0 && mEndFraction >= mStartFraction && mEndFraction <= 1;
421 void QgsMeshSigmaAveragingMethod::volumeRangeForFace(
422 double &startVerticalLevel,
423 double &endVerticalLevel,
424 const QVector<double> &verticalLevels
427 const double top = verticalLevels[ 0 ];
428 const double bot = verticalLevels[ verticalLevels.size() - 1 ];
429 const double diff = top - bot;
431 if ( mStartFraction < 0 )
432 startVerticalLevel = bot;
434 startVerticalLevel = bot + diff * mStartFraction;
436 if ( mEndFraction > 1 )
437 endVerticalLevel = top;
439 endVerticalLevel = bot + diff * mEndFraction;
444 return mCountedFromTop;
449 return mStartVerticalLevel == mEndVerticalLevel;
460 , mStartHeight( startDepth )
461 , mEndHeight( endDepth )
462 , mCountedFromTop( countedFromTop )
464 if ( mStartHeight > mEndHeight )
466 std::swap( mStartHeight, mEndHeight );
474 QDomElement elem = doc.createElement( QStringLiteral(
"relative-height-settings" ) );
475 elem.setAttribute( QStringLiteral(
"start-height" ),
startHeight() );
476 elem.setAttribute( QStringLiteral(
"end-height" ),
endHeight() );
482 const QDomElement settings = elem.firstChildElement( QStringLiteral(
"relative-height-settings" ) );
483 if ( !settings.isNull() )
485 mStartHeight = settings.attribute( QStringLiteral(
"start-height" ) ).toDouble();
486 mEndHeight = settings.attribute( QStringLiteral(
"end-height" ) ).toDouble();
487 if ( mStartHeight > mEndHeight )
489 std::swap( mStartHeight, mEndHeight );
521 bool QgsMeshRelativeHeightAveragingMethod::hasValidInputs()
const
523 return mStartHeight >= 0 && mEndHeight >= mStartHeight;
526 void QgsMeshRelativeHeightAveragingMethod::volumeRangeForFace(
527 double &startVerticalLevel,
528 double &endVerticalLevel,
529 const QVector<double> &verticalLevels )
const
533 const double top = verticalLevels[ 0 ];
534 startVerticalLevel = top - mStartHeight;
535 endVerticalLevel = top - mEndHeight;
539 const double bot = verticalLevels[verticalLevels.size() - 1];
540 startVerticalLevel = bot + mStartHeight;
541 endVerticalLevel = bot + mEndHeight;
547 return mCountedFromTop;
557 , mStartElevation( startElevation )
558 , mEndElevation( endElevation )
560 if ( mEndElevation > mStartElevation )
562 std::swap( mEndElevation, mStartElevation );
570 QDomElement elem = doc.createElement( QStringLiteral(
"elevation-settings" ) );
571 elem.setAttribute( QStringLiteral(
"start-elevation" ),
startElevation() );
572 elem.setAttribute( QStringLiteral(
"end-elevation" ),
endElevation() );
578 const QDomElement settings = elem.firstChildElement( QStringLiteral(
"elevation-settings" ) );
579 if ( !settings.isNull() )
581 mStartElevation = settings.attribute( QStringLiteral(
"start-elevation" ) ).toDouble();
582 mEndElevation = settings.attribute( QStringLiteral(
"end-elevation" ) ).toDouble();
583 if ( mEndElevation > mStartElevation )
585 std::swap( mEndElevation, mStartElevation );
607 return mStartElevation;
612 return mEndElevation;
615 bool QgsMeshElevationAveragingMethod::hasValidInputs()
const
617 return mStartElevation <= 0.0 && mEndElevation <= mStartElevation;
620 void QgsMeshElevationAveragingMethod::volumeRangeForFace(
621 double &startVerticalLevel,
622 double &endVerticalLevel,
623 const QVector<double> &verticalLevels )
const
625 Q_UNUSED( verticalLevels )
626 startVerticalLevel = mStartElevation;
627 endVerticalLevel = mEndElevation;