25 static const double eps = 1e-6;
34 std::unique_ptr<QgsMesh3dAveragingMethod> ret;
37 elem.attribute( QStringLiteral(
"method" ) ).toInt() );
62 if ( !hasValidInputs() )
66 int count = block3d.
count();
68 QVector<double> valuesFaces( isVector ? 2 * count : count, std::numeric_limits<double>::quiet_NaN() );
71 const QVector<double> volumeValues = block3d.
values();
73 int startVolumeIndex = 0;
74 for (
int faceIndex = 0; faceIndex < count; ++faceIndex )
81 int volumesBelowFaceCount = verticalLevelsCount[faceIndex];
82 if ( volumesBelowFaceCount <= 0 )
85 int startVerticalLevelIndex = startVolumeIndex + faceIndex;
86 Q_ASSERT( verticalLevels.size() >= startVerticalLevelIndex + volumesBelowFaceCount + 1 );
87 QVector<double> verticalLevelsForFace = verticalLevels.mid( startVerticalLevelIndex, volumesBelowFaceCount + 1 );
88 double faceLevelTop = verticalLevelsForFace[0];
89 double faceLevelBottom = verticalLevelsForFace[verticalLevelsForFace.size() - 1];
92 if ( faceLevelTop < faceLevelBottom )
94 std::swap( faceLevelTop, faceLevelBottom );
97 double methodLevelTop = std::numeric_limits<double>::quiet_NaN();
98 double methodLevelBottom = std::numeric_limits<double>::quiet_NaN();
100 volumeRangeForFace( methodLevelTop,
102 verticalLevelsForFace );
104 if ( !std::isnan( methodLevelTop ) && !std::isnan( methodLevelBottom ) )
107 if ( methodLevelTop < methodLevelBottom )
109 std::swap( methodLevelTop, methodLevelBottom );
113 if ( ( methodLevelTop >= faceLevelBottom ) && ( methodLevelBottom <= faceLevelTop ) )
115 averageVolumeValuesForFace(
117 volumesBelowFaceCount,
122 verticalLevelsForFace,
130 startVolumeIndex += volumesBelowFaceCount;
141 void QgsMesh3dAveragingMethod::averageVolumeValuesForFace(
143 int volumesBelowFaceCount,
144 int startVolumeIndex,
145 double methodLevelTop,
146 double methodLevelBottom,
148 const QVector<double> &verticalLevelsForFace,
149 const QVector<double> &volumeValues,
150 QVector<double> &valuesFaces
153 double totalAveragedHeight = 0;
158 for (
int relativeVolumeIndex = 0; relativeVolumeIndex < volumesBelowFaceCount; ++relativeVolumeIndex )
160 const int volumeIndex = startVolumeIndex + relativeVolumeIndex;
161 double volumeLevelTop = verticalLevelsForFace[relativeVolumeIndex];
162 double volumeLevelBottom = verticalLevelsForFace[relativeVolumeIndex + 1];
163 if ( volumeLevelTop < volumeLevelBottom )
165 std::swap( volumeLevelTop, volumeLevelBottom );
168 const double intersectionLevelTop = std::min( methodLevelTop, volumeLevelTop );
169 const double intersectionLevelBottom = std::max( methodLevelBottom, volumeLevelBottom );
170 const double effectiveInterval = intersectionLevelTop - intersectionLevelBottom;
172 if ( effectiveInterval > eps )
176 const double x = volumeValues[2 * volumeIndex ];
177 const double y = volumeValues[ 2 * volumeIndex + 1 ];
178 if ( ! std::isnan( x ) &&
182 nSumX += x * effectiveInterval;
183 nSumY += y * effectiveInterval;
184 totalAveragedHeight += effectiveInterval;
189 const double x = volumeValues[ volumeIndex ];
190 if ( ! std::isnan( x ) )
192 nSumX += x * effectiveInterval;
193 totalAveragedHeight += effectiveInterval;
200 if ( totalAveragedHeight > eps )
204 valuesFaces[2 * faceIndex] = nSumX / totalAveragedHeight;
205 valuesFaces[2 * faceIndex + 1 ] = nSumY / totalAveragedHeight;
209 valuesFaces[faceIndex] = nSumX / totalAveragedHeight;
224 , mStartVerticalLevel( startLevel )
225 , mEndVerticalLevel( endLevel )
226 , mCountedFromTop( countedFromTop )
228 if ( mStartVerticalLevel > mEndVerticalLevel )
230 std::swap( mStartVerticalLevel, mEndVerticalLevel );
241 , mStartVerticalLevel( verticalLevel )
242 , mEndVerticalLevel( verticalLevel )
243 , mCountedFromTop( countedFromTop )
251 QDomElement elem = doc.createElement( QStringLiteral(
"multi-vertical-layers-settings" ) );
253 elem.setAttribute( QStringLiteral(
"end-layer-index" ),
endVerticalLevel() );
259 QDomElement settings = elem.firstChildElement( QStringLiteral(
"multi-vertical-layers-settings" ) );
260 if ( !settings.isNull() )
262 mStartVerticalLevel = settings.attribute( QStringLiteral(
"start-layer-index" ) ).toInt();
263 mEndVerticalLevel = settings.attribute( QStringLiteral(
"end-layer-index" ) ).toInt();
264 if ( mStartVerticalLevel > mEndVerticalLevel )
266 std::swap( mStartVerticalLevel, mEndVerticalLevel );
291 return mStartVerticalLevel;
296 return mEndVerticalLevel;
299 bool QgsMeshMultiLevelsAveragingMethod::hasValidInputs()
const
301 return mStartVerticalLevel >= 1 && mEndVerticalLevel >= mStartVerticalLevel;
304 void QgsMeshMultiLevelsAveragingMethod::volumeRangeForFace(
305 double &startVerticalLevel,
306 double &endVerticalLevel,
307 const QVector<double> &verticalLevels
310 Q_ASSERT( mStartVerticalLevel <= mEndVerticalLevel );
314 int startIndex = mStartVerticalLevel - 1;
315 if ( startIndex >= 0 && startIndex < verticalLevels.size() )
320 if ( mEndVerticalLevel >= 0 && mEndVerticalLevel < verticalLevels.size() )
331 int volumesBelowFaceCount = verticalLevels.size() - 1;
332 int startIndex = volumesBelowFaceCount - mEndVerticalLevel;
333 if ( startIndex >= 0 && startIndex < verticalLevels.size() )
342 int endIndex = volumesBelowFaceCount - mStartVerticalLevel + 1;
343 if ( endIndex >= 0 && endIndex < verticalLevels.size() )
357 , mStartFraction( startFraction )
358 , mEndFraction( endFraction )
360 if ( mStartFraction > mEndFraction )
362 std::swap( mStartFraction, mEndFraction );
370 QDomElement elem = doc.createElement( QStringLiteral(
"sigma-settings" ) );
371 elem.setAttribute( QStringLiteral(
"start-fraction" ),
startFraction() );
372 elem.setAttribute( QStringLiteral(
"end-fraction" ),
endFraction() );
378 QDomElement settings = elem.firstChildElement( QStringLiteral(
"sigma-settings" ) );
379 if ( !settings.isNull() )
381 mStartFraction = settings.attribute( QStringLiteral(
"start-fraction" ) ).toDouble();
382 mEndFraction = settings.attribute( QStringLiteral(
"end-fraction" ) ).toDouble();
383 if ( mStartFraction > mEndFraction )
385 std::swap( mStartFraction, mEndFraction );
407 return mStartFraction;
415 bool QgsMeshSigmaAveragingMethod::hasValidInputs()
const
417 return mStartFraction >= 0 && mEndFraction >= mStartFraction && mEndFraction <= 1;
420 void QgsMeshSigmaAveragingMethod::volumeRangeForFace(
421 double &startVerticalLevel,
422 double &endVerticalLevel,
423 const QVector<double> &verticalLevels
426 const double top = verticalLevels[ 0 ];
427 const double bot = verticalLevels[ verticalLevels.size() - 1 ];
428 const double diff = top - bot;
430 if ( mStartFraction < 0 )
431 startVerticalLevel = bot;
433 startVerticalLevel = bot + diff * mStartFraction;
435 if ( mEndFraction > 1 )
436 endVerticalLevel = top;
438 endVerticalLevel = bot + diff * mEndFraction;
443 return mCountedFromTop;
448 return mStartVerticalLevel == mEndVerticalLevel;
459 , mStartHeight( startDepth )
460 , mEndHeight( endDepth )
461 , mCountedFromTop( countedFromTop )
463 if ( mStartHeight > mEndHeight )
465 std::swap( mStartHeight, mEndHeight );
473 QDomElement elem = doc.createElement( QStringLiteral(
"relative-height-settings" ) );
474 elem.setAttribute( QStringLiteral(
"start-height" ),
startHeight() );
475 elem.setAttribute( QStringLiteral(
"end-height" ),
endHeight() );
481 QDomElement settings = elem.firstChildElement( QStringLiteral(
"relative-height-settings" ) );
482 if ( !settings.isNull() )
484 mStartHeight = settings.attribute( QStringLiteral(
"start-height" ) ).toDouble();
485 mEndHeight = settings.attribute( QStringLiteral(
"end-height" ) ).toDouble();
486 if ( mStartHeight > mEndHeight )
488 std::swap( mStartHeight, mEndHeight );
520 bool QgsMeshRelativeHeightAveragingMethod::hasValidInputs()
const
522 return mStartHeight >= 0 && mEndHeight >= mStartHeight;
525 void QgsMeshRelativeHeightAveragingMethod::volumeRangeForFace(
526 double &startVerticalLevel,
527 double &endVerticalLevel,
528 const QVector<double> &verticalLevels )
const
532 const double top = verticalLevels[ 0 ];
533 startVerticalLevel = top - mStartHeight;
534 endVerticalLevel = top - mEndHeight;
538 const double bot = verticalLevels[verticalLevels.size() - 1];
539 startVerticalLevel = bot + mStartHeight;
540 endVerticalLevel = bot + mEndHeight;
546 return mCountedFromTop;
556 , mStartElevation( startElevation )
557 , mEndElevation( endElevation )
559 if ( mEndElevation > mStartElevation )
561 std::swap( mEndElevation, mStartElevation );
569 QDomElement elem = doc.createElement( QStringLiteral(
"elevation-settings" ) );
570 elem.setAttribute( QStringLiteral(
"start-elevation" ),
startElevation() );
571 elem.setAttribute( QStringLiteral(
"end-elevation" ),
endElevation() );
577 QDomElement settings = elem.firstChildElement( QStringLiteral(
"elevation-settings" ) );
578 if ( !settings.isNull() )
580 mStartElevation = settings.attribute( QStringLiteral(
"start-elevation" ) ).toDouble();
581 mEndElevation = settings.attribute( QStringLiteral(
"end-elevation" ) ).toDouble();
582 if ( mEndElevation > mStartElevation )
584 std::swap( mEndElevation, mStartElevation );
606 return mStartElevation;
611 return mEndElevation;
614 bool QgsMeshElevationAveragingMethod::hasValidInputs()
const
616 return mStartElevation <= 0.0 && mEndElevation <= mStartElevation;
619 void QgsMeshElevationAveragingMethod::volumeRangeForFace(
620 double &startVerticalLevel,
621 double &endVerticalLevel,
622 const QVector<double> &verticalLevels )
const
624 Q_UNUSED( verticalLevels )
625 startVerticalLevel = mStartElevation;
626 endVerticalLevel = mEndElevation;