LCOV - code coverage report
Current view: top level - core/mesh - qgsmesh3daveraging.cpp (source / functions) Hit Total Coverage
Test: coverage.info.cleaned Lines: 0 364 0.0 %
Date: 2021-03-26 12:19:53 Functions: 0 0 -
Branches: 0 0 -

           Branch data     Line data    Source code
       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"
      22                 :            : #include "qgsmeshrenderersettings.h"
      23                 :            : #include "qgsfeedback.h"
      24                 :            : 
      25                 :            : // threshold for length intervals, to avoid division by 0
      26                 :            : static const double eps = 1e-6;
      27                 :            : 
      28                 :          0 : QgsMesh3dAveragingMethod::QgsMesh3dAveragingMethod( Method method )
      29                 :          0 :   : mMethod( method )
      30                 :          0 : {
      31                 :          0 : }
      32                 :            : 
      33                 :          0 : QgsMesh3dAveragingMethod *QgsMesh3dAveragingMethod::createFromXml( const QDomElement &elem )
      34                 :            : {
      35                 :          0 :   std::unique_ptr<QgsMesh3dAveragingMethod> ret;
      36                 :            : 
      37                 :          0 :   QgsMesh3dAveragingMethod::Method method = static_cast<QgsMesh3dAveragingMethod::Method>(
      38                 :          0 :         elem.attribute( QStringLiteral( "method" ) ).toInt() );
      39                 :          0 :   switch ( method )
      40                 :            :   {
      41                 :            :     case QgsMesh3dAveragingMethod::MultiLevelsAveragingMethod:
      42                 :          0 :       ret.reset( new QgsMeshMultiLevelsAveragingMethod() );
      43                 :          0 :       break;
      44                 :            :     case QgsMesh3dAveragingMethod::SigmaAveragingMethod:
      45                 :          0 :       ret.reset( new QgsMeshSigmaAveragingMethod() );
      46                 :          0 :       break;
      47                 :            :     case QgsMesh3dAveragingMethod::RelativeHeightAveragingMethod:
      48                 :          0 :       ret.reset( new QgsMeshRelativeHeightAveragingMethod() );
      49                 :          0 :       break;
      50                 :            :     case QgsMesh3dAveragingMethod::ElevationAveragingMethod:
      51                 :          0 :       ret.reset( new QgsMeshElevationAveragingMethod() );
      52                 :          0 :       break;
      53                 :            :   }
      54                 :          0 :   ret->readXml( elem );
      55                 :          0 :   return ret.release();
      56                 :          0 : }
      57                 :            : 
      58                 :          0 : QgsMeshDataBlock QgsMesh3dAveragingMethod::calculate( const QgsMesh3dDataBlock &block3d, QgsFeedback *feedback ) const
      59                 :            : {
      60                 :          0 :   if ( !block3d.isValid() )
      61                 :          0 :     return QgsMeshDataBlock();
      62                 :            : 
      63                 :          0 :   if ( !hasValidInputs() )
      64                 :          0 :     return QgsMeshDataBlock();
      65                 :            : 
      66                 :          0 :   bool isVector = block3d.isVector();
      67                 :          0 :   int count = block3d.count();
      68                 :          0 :   QgsMeshDataBlock result( isVector ? QgsMeshDataBlock::Vector2DDouble : QgsMeshDataBlock::ScalarDouble, count );
      69                 :          0 :   QVector<double> valuesFaces( isVector ? 2 * count : count, std::numeric_limits<double>::quiet_NaN() );
      70                 :          0 :   const QVector<int> verticalLevelsCount = block3d.verticalLevelsCount();
      71                 :          0 :   const QVector<double> verticalLevels = block3d.verticalLevels();
      72                 :          0 :   const QVector<double> volumeValues = block3d.values();
      73                 :            : 
      74                 :          0 :   int startVolumeIndex = 0;
      75                 :          0 :   for ( int faceIndex = 0; faceIndex < count; ++faceIndex )
      76                 :            :   {
      77                 :          0 :     if ( feedback && feedback->isCanceled() )
      78                 :            :     {
      79                 :          0 :       return QgsMeshDataBlock();
      80                 :            :     }
      81                 :            : 
      82                 :          0 :     int volumesBelowFaceCount = verticalLevelsCount[faceIndex];
      83                 :          0 :     if ( volumesBelowFaceCount <= 0 )
      84                 :          0 :       continue;
      85                 :            : 
      86                 :          0 :     int startVerticalLevelIndex = startVolumeIndex + faceIndex;
      87                 :            :     Q_ASSERT( verticalLevels.size() >= startVerticalLevelIndex + volumesBelowFaceCount + 1 );
      88                 :          0 :     QVector<double> verticalLevelsForFace = verticalLevels.mid( startVerticalLevelIndex, volumesBelowFaceCount + 1 );
      89                 :          0 :     double faceLevelTop = verticalLevelsForFace[0];
      90                 :          0 :     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                 :          0 :     if ( faceLevelTop < faceLevelBottom )
      94                 :            :     {
      95                 :          0 :       std::swap( faceLevelTop, faceLevelBottom );
      96                 :          0 :     }
      97                 :            : 
      98                 :          0 :     double methodLevelTop = std::numeric_limits<double>::quiet_NaN();
      99                 :          0 :     double methodLevelBottom = std::numeric_limits<double>::quiet_NaN();
     100                 :            : 
     101                 :          0 :     volumeRangeForFace( methodLevelTop,
     102                 :            :                         methodLevelBottom,
     103                 :            :                         verticalLevelsForFace );
     104                 :            : 
     105                 :          0 :     if ( !std::isnan( methodLevelTop ) && !std::isnan( methodLevelBottom ) )
     106                 :            :     {
     107                 :            :       // the level is value below surface, so top level (-0.1m) is usually higher number than bottom level (e.g. -1.2m)
     108                 :          0 :       if ( methodLevelTop < methodLevelBottom )
     109                 :            :       {
     110                 :          0 :         std::swap( methodLevelTop, methodLevelBottom );
     111                 :          0 :       }
     112                 :            : 
     113                 :            :       // check if we are completely outside the limits
     114                 :          0 :       if ( ( methodLevelTop >= faceLevelBottom ) && ( methodLevelBottom <= faceLevelTop ) )
     115                 :            :       {
     116                 :          0 :         averageVolumeValuesForFace(
     117                 :          0 :           faceIndex,
     118                 :          0 :           volumesBelowFaceCount,
     119                 :          0 :           startVolumeIndex,
     120                 :          0 :           methodLevelTop,
     121                 :          0 :           methodLevelBottom,
     122                 :          0 :           isVector,
     123                 :            :           verticalLevelsForFace,
     124                 :            :           volumeValues,
     125                 :            :           valuesFaces
     126                 :            :         );
     127                 :          0 :       }
     128                 :          0 :     }
     129                 :            : 
     130                 :            :     // move to next face and associated volumes
     131                 :          0 :     startVolumeIndex += volumesBelowFaceCount;
     132                 :          0 :   }
     133                 :          0 :   result.setValues( valuesFaces );
     134                 :          0 :   return result;
     135                 :          0 : }
     136                 :            : 
     137                 :          0 : QgsMesh3dAveragingMethod::Method QgsMesh3dAveragingMethod::method() const
     138                 :            : {
     139                 :          0 :   return mMethod;
     140                 :            : }
     141                 :            : 
     142                 :          0 : void QgsMesh3dAveragingMethod::averageVolumeValuesForFace(
     143                 :            :   int faceIndex,
     144                 :            :   int volumesBelowFaceCount,
     145                 :            :   int startVolumeIndex,
     146                 :            :   double methodLevelTop,
     147                 :            :   double methodLevelBottom,
     148                 :            :   bool isVector,
     149                 :            :   const QVector<double> &verticalLevelsForFace,
     150                 :            :   const QVector<double> &volumeValues,
     151                 :            :   QVector<double> &valuesFaces
     152                 :            : ) const
     153                 :            : {
     154                 :          0 :   double totalAveragedHeight = 0;
     155                 :          0 :   double nSumX = 0.0;
     156                 :          0 :   double nSumY = 0.0;
     157                 :            : 
     158                 :            :   // Now go through all volumes below face and check if we need to take that volume into consideration
     159                 :          0 :   for ( int relativeVolumeIndex = 0; relativeVolumeIndex < volumesBelowFaceCount; ++relativeVolumeIndex )
     160                 :            :   {
     161                 :          0 :     const int volumeIndex = startVolumeIndex + relativeVolumeIndex;
     162                 :          0 :     double volumeLevelTop = verticalLevelsForFace[relativeVolumeIndex];
     163                 :          0 :     double volumeLevelBottom = verticalLevelsForFace[relativeVolumeIndex + 1];
     164                 :          0 :     if ( volumeLevelTop < volumeLevelBottom )
     165                 :            :     {
     166                 :          0 :       std::swap( volumeLevelTop, volumeLevelBottom );
     167                 :          0 :     }
     168                 :            : 
     169                 :          0 :     const double intersectionLevelTop = std::min( methodLevelTop, volumeLevelTop );
     170                 :          0 :     const double intersectionLevelBottom = std::max( methodLevelBottom, volumeLevelBottom );
     171                 :          0 :     const double effectiveInterval = intersectionLevelTop - intersectionLevelBottom;
     172                 :            : 
     173                 :          0 :     if ( effectiveInterval > eps )
     174                 :            :     {
     175                 :          0 :       if ( isVector )
     176                 :            :       {
     177                 :          0 :         const double x = volumeValues[2 * volumeIndex ];
     178                 :          0 :         const double y = volumeValues[ 2 * volumeIndex + 1 ];
     179                 :          0 :         if ( ! std::isnan( x ) &&
     180                 :          0 :              ! std::isnan( y )
     181                 :            :            )
     182                 :            :         {
     183                 :          0 :           nSumX += x * effectiveInterval;
     184                 :          0 :           nSumY += y * effectiveInterval;
     185                 :          0 :           totalAveragedHeight += effectiveInterval;
     186                 :          0 :         }
     187                 :          0 :       }
     188                 :            :       else
     189                 :            :       {
     190                 :          0 :         const double x = volumeValues[ volumeIndex ];
     191                 :          0 :         if ( ! std::isnan( x ) )
     192                 :            :         {
     193                 :          0 :           nSumX += x * effectiveInterval;
     194                 :          0 :           totalAveragedHeight += effectiveInterval;
     195                 :          0 :         }
     196                 :            :       }
     197                 :          0 :     }
     198                 :          0 :   }
     199                 :            : 
     200                 :            :   // calculate average
     201                 :          0 :   if ( totalAveragedHeight > eps )
     202                 :            :   {
     203                 :          0 :     if ( isVector )
     204                 :            :     {
     205                 :          0 :       valuesFaces[2 * faceIndex] = nSumX / totalAveragedHeight;
     206                 :          0 :       valuesFaces[2 * faceIndex + 1 ] = nSumY / totalAveragedHeight;
     207                 :          0 :     }
     208                 :            :     else
     209                 :            :     {
     210                 :          0 :       valuesFaces[faceIndex] = nSumX / totalAveragedHeight;
     211                 :            :     }
     212                 :          0 :   }
     213                 :          0 : }
     214                 :            : 
     215                 :          0 : bool QgsMesh3dAveragingMethod::equals( const QgsMesh3dAveragingMethod *a, const QgsMesh3dAveragingMethod *b )
     216                 :            : {
     217                 :          0 :   if ( a )
     218                 :          0 :     return a->equals( b );
     219                 :            :   else
     220                 :          0 :     return !b;
     221                 :          0 : }
     222                 :            : 
     223                 :          0 : QgsMeshMultiLevelsAveragingMethod::QgsMeshMultiLevelsAveragingMethod( int startLevel, int endLevel, bool countedFromTop )
     224                 :          0 :   : QgsMesh3dAveragingMethod( QgsMesh3dAveragingMethod::MultiLevelsAveragingMethod )
     225                 :          0 :   , mStartVerticalLevel( startLevel )
     226                 :          0 :   , mEndVerticalLevel( endLevel )
     227                 :          0 :   , mCountedFromTop( countedFromTop )
     228                 :          0 : {
     229                 :          0 :   if ( mStartVerticalLevel > mEndVerticalLevel )
     230                 :            :   {
     231                 :          0 :     std::swap( mStartVerticalLevel, mEndVerticalLevel );
     232                 :          0 :   }
     233                 :          0 : }
     234                 :            : 
     235                 :          0 : QgsMeshMultiLevelsAveragingMethod::QgsMeshMultiLevelsAveragingMethod()
     236                 :          0 :   : QgsMesh3dAveragingMethod( QgsMesh3dAveragingMethod::MultiLevelsAveragingMethod )
     237                 :          0 : {
     238                 :          0 : }
     239                 :            : 
     240                 :          0 : QgsMeshMultiLevelsAveragingMethod::QgsMeshMultiLevelsAveragingMethod( int verticalLevel, bool countedFromTop )
     241                 :          0 :   : QgsMesh3dAveragingMethod( QgsMesh3dAveragingMethod::MultiLevelsAveragingMethod )
     242                 :          0 :   , mStartVerticalLevel( verticalLevel )
     243                 :          0 :   , mEndVerticalLevel( verticalLevel )
     244                 :          0 :   , mCountedFromTop( countedFromTop )
     245                 :          0 : {
     246                 :          0 : }
     247                 :            : 
     248                 :          0 : QgsMeshMultiLevelsAveragingMethod::~QgsMeshMultiLevelsAveragingMethod() = default;
     249                 :            : 
     250                 :          0 : QDomElement QgsMeshMultiLevelsAveragingMethod::writeXml( QDomDocument &doc ) const
     251                 :            : {
     252                 :          0 :   QDomElement elem = doc.createElement( QStringLiteral( "multi-vertical-layers-settings" ) );
     253                 :          0 :   elem.setAttribute( QStringLiteral( "start-layer-index" ), startVerticalLevel() );
     254                 :          0 :   elem.setAttribute( QStringLiteral( "end-layer-index" ), endVerticalLevel() );
     255                 :          0 :   return elem;
     256                 :          0 : }
     257                 :            : 
     258                 :          0 : void QgsMeshMultiLevelsAveragingMethod::readXml( const QDomElement &elem )
     259                 :            : {
     260                 :          0 :   QDomElement settings = elem.firstChildElement( QStringLiteral( "multi-vertical-layers-settings" ) );
     261                 :          0 :   if ( !settings.isNull() )
     262                 :            :   {
     263                 :          0 :     mStartVerticalLevel = settings.attribute( QStringLiteral( "start-layer-index" ) ).toInt();
     264                 :          0 :     mEndVerticalLevel = settings.attribute( QStringLiteral( "end-layer-index" ) ).toInt();
     265                 :          0 :     if ( mStartVerticalLevel > mEndVerticalLevel )
     266                 :            :     {
     267                 :          0 :       std::swap( mStartVerticalLevel, mEndVerticalLevel );
     268                 :          0 :     }
     269                 :          0 :   }
     270                 :          0 : }
     271                 :            : 
     272                 :          0 : bool QgsMeshMultiLevelsAveragingMethod::equals( const QgsMesh3dAveragingMethod *other ) const
     273                 :            : {
     274                 :          0 :   if ( !other || other->method() != method() )
     275                 :          0 :     return false;
     276                 :            : 
     277                 :          0 :   const QgsMeshMultiLevelsAveragingMethod *otherMethod = static_cast<const QgsMeshMultiLevelsAveragingMethod *>( other );
     278                 :            : 
     279                 :          0 :   return ( otherMethod->startVerticalLevel() == startVerticalLevel() ) &&
     280                 :          0 :          ( otherMethod->endVerticalLevel() == endVerticalLevel() ) &&
     281                 :          0 :          ( otherMethod->countedFromTop() == countedFromTop() );
     282                 :          0 : }
     283                 :            : 
     284                 :          0 : QgsMesh3dAveragingMethod *QgsMeshMultiLevelsAveragingMethod::clone() const
     285                 :            : {
     286                 :          0 :   return new QgsMeshMultiLevelsAveragingMethod( startVerticalLevel(), endVerticalLevel(), countedFromTop() );
     287                 :          0 : }
     288                 :            : 
     289                 :            : 
     290                 :          0 : int QgsMeshMultiLevelsAveragingMethod::startVerticalLevel() const
     291                 :            : {
     292                 :          0 :   return mStartVerticalLevel;
     293                 :            : }
     294                 :            : 
     295                 :          0 : int QgsMeshMultiLevelsAveragingMethod::endVerticalLevel() const
     296                 :            : {
     297                 :          0 :   return mEndVerticalLevel;
     298                 :            : }
     299                 :            : 
     300                 :          0 : bool QgsMeshMultiLevelsAveragingMethod::hasValidInputs() const
     301                 :            : {
     302                 :          0 :   return mStartVerticalLevel >= 1 && mEndVerticalLevel >= mStartVerticalLevel;
     303                 :            : }
     304                 :            : 
     305                 :          0 : void QgsMeshMultiLevelsAveragingMethod::volumeRangeForFace(
     306                 :            :   double &startVerticalLevel,
     307                 :            :   double &endVerticalLevel,
     308                 :            :   const QVector<double> &verticalLevels
     309                 :            : ) const
     310                 :            : {
     311                 :            :   Q_ASSERT( mStartVerticalLevel <= mEndVerticalLevel );
     312                 :            : 
     313                 :          0 :   if ( countedFromTop() )
     314                 :            :   {
     315                 :          0 :     int startIndex = mStartVerticalLevel - 1;
     316                 :          0 :     if ( startIndex >= 0 && startIndex < verticalLevels.size() )
     317                 :            :     {
     318                 :          0 :       startVerticalLevel = verticalLevels[ startIndex ];
     319                 :          0 :     }
     320                 :            : 
     321                 :          0 :     if ( mEndVerticalLevel >= 0 && mEndVerticalLevel < verticalLevels.size() )
     322                 :            :     {
     323                 :          0 :       endVerticalLevel = verticalLevels[ mEndVerticalLevel ];
     324                 :          0 :     }
     325                 :            :     else
     326                 :            :     {
     327                 :          0 :       endVerticalLevel = verticalLevels[ verticalLevels.size() - 1 ];
     328                 :            :     }
     329                 :          0 :   }
     330                 :            :   else
     331                 :            :   {
     332                 :          0 :     int volumesBelowFaceCount = verticalLevels.size() - 1;
     333                 :          0 :     int startIndex = volumesBelowFaceCount - mEndVerticalLevel;
     334                 :          0 :     if ( startIndex >= 0 && startIndex < verticalLevels.size() )
     335                 :            :     {
     336                 :          0 :       startVerticalLevel = verticalLevels[ startIndex ];
     337                 :          0 :     }
     338                 :            :     else
     339                 :            :     {
     340                 :          0 :       startVerticalLevel = verticalLevels[ 0 ];
     341                 :            :     }
     342                 :            : 
     343                 :          0 :     int endIndex = volumesBelowFaceCount - mStartVerticalLevel + 1;
     344                 :          0 :     if ( endIndex >= 0 && endIndex < verticalLevels.size() )
     345                 :          0 :     {
     346                 :          0 :       endVerticalLevel = verticalLevels[ endIndex ];
     347                 :          0 :     }
     348                 :            :   }
     349                 :          0 : }
     350                 :            : 
     351                 :          0 : QgsMeshSigmaAveragingMethod::QgsMeshSigmaAveragingMethod()
     352                 :          0 :   : QgsMesh3dAveragingMethod( QgsMesh3dAveragingMethod::SigmaAveragingMethod )
     353                 :          0 : {
     354                 :          0 : }
     355                 :            : 
     356                 :          0 : QgsMeshSigmaAveragingMethod::QgsMeshSigmaAveragingMethod( double startFraction, double endFraction )
     357                 :          0 :   : QgsMesh3dAveragingMethod( QgsMesh3dAveragingMethod::SigmaAveragingMethod )
     358                 :          0 :   , mStartFraction( startFraction )
     359                 :          0 :   , mEndFraction( endFraction )
     360                 :          0 : {
     361                 :          0 :   if ( mStartFraction > mEndFraction )
     362                 :            :   {
     363                 :          0 :     std::swap( mStartFraction, mEndFraction );
     364                 :          0 :   }
     365                 :          0 : }
     366                 :            : 
     367                 :          0 : QgsMeshSigmaAveragingMethod::~QgsMeshSigmaAveragingMethod() = default;
     368                 :            : 
     369                 :          0 : QDomElement QgsMeshSigmaAveragingMethod::writeXml( QDomDocument &doc ) const
     370                 :            : {
     371                 :          0 :   QDomElement elem = doc.createElement( QStringLiteral( "sigma-settings" ) );
     372                 :          0 :   elem.setAttribute( QStringLiteral( "start-fraction" ), startFraction() );
     373                 :          0 :   elem.setAttribute( QStringLiteral( "end-fraction" ), endFraction() );
     374                 :          0 :   return elem;
     375                 :          0 : }
     376                 :            : 
     377                 :          0 : void QgsMeshSigmaAveragingMethod::readXml( const QDomElement &elem )
     378                 :            : {
     379                 :          0 :   QDomElement settings = elem.firstChildElement( QStringLiteral( "sigma-settings" ) );
     380                 :          0 :   if ( !settings.isNull() )
     381                 :            :   {
     382                 :          0 :     mStartFraction = settings.attribute( QStringLiteral( "start-fraction" ) ).toDouble();
     383                 :          0 :     mEndFraction = settings.attribute( QStringLiteral( "end-fraction" ) ).toDouble();
     384                 :          0 :     if ( mStartFraction > mEndFraction )
     385                 :            :     {
     386                 :          0 :       std::swap( mStartFraction, mEndFraction );
     387                 :          0 :     }
     388                 :          0 :   }
     389                 :          0 : }
     390                 :            : 
     391                 :          0 : bool QgsMeshSigmaAveragingMethod::equals( const QgsMesh3dAveragingMethod *other ) const
     392                 :            : {
     393                 :          0 :   if ( !other || other->method() != method() )
     394                 :          0 :     return false;
     395                 :            : 
     396                 :          0 :   const QgsMeshSigmaAveragingMethod *otherMethod = static_cast<const QgsMeshSigmaAveragingMethod *>( other );
     397                 :          0 : 
     398                 :          0 :   return qgsDoubleNear( otherMethod->startFraction(), startFraction() ) && qgsDoubleNear( otherMethod->endFraction(), endFraction() ) ;
     399                 :          0 : }
     400                 :            : 
     401                 :          0 : QgsMesh3dAveragingMethod *QgsMeshSigmaAveragingMethod::clone() const
     402                 :            : {
     403                 :          0 :   return new QgsMeshSigmaAveragingMethod( startFraction(), endFraction() );
     404                 :          0 : }
     405                 :            : 
     406                 :          0 : double QgsMeshSigmaAveragingMethod::startFraction() const
     407                 :            : {
     408                 :          0 :   return mStartFraction;
     409                 :            : }
     410                 :            : 
     411                 :          0 : double QgsMeshSigmaAveragingMethod::endFraction() const
     412                 :            : {
     413                 :          0 :   return mEndFraction;
     414                 :            : }
     415                 :            : 
     416                 :          0 : bool QgsMeshSigmaAveragingMethod::hasValidInputs() const
     417                 :            : {
     418                 :          0 :   return mStartFraction >= 0 && mEndFraction >= mStartFraction && mEndFraction <= 1;
     419                 :            : }
     420                 :            : 
     421                 :          0 : void QgsMeshSigmaAveragingMethod::volumeRangeForFace(
     422                 :            :   double &startVerticalLevel,
     423                 :            :   double &endVerticalLevel,
     424                 :            :   const QVector<double> &verticalLevels
     425                 :            : ) const
     426                 :            : {
     427                 :          0 :   const double top = verticalLevels[ 0 ];
     428                 :          0 :   const double bot = verticalLevels[ verticalLevels.size() - 1 ];
     429                 :          0 :   const double diff = top - bot;
     430                 :            : 
     431                 :          0 :   if ( mStartFraction < 0 )
     432                 :          0 :     startVerticalLevel = bot;
     433                 :            :   else
     434                 :          0 :     startVerticalLevel = bot + diff * mStartFraction;
     435                 :            : 
     436                 :          0 :   if ( mEndFraction > 1 )
     437                 :          0 :     endVerticalLevel = top;
     438                 :            :   else
     439                 :          0 :     endVerticalLevel = bot + diff * mEndFraction;
     440                 :          0 : }
     441                 :            : 
     442                 :          0 : bool QgsMeshMultiLevelsAveragingMethod::countedFromTop() const
     443                 :            : {
     444                 :          0 :   return mCountedFromTop;
     445                 :            : }
     446                 :            : 
     447                 :          0 : bool QgsMeshMultiLevelsAveragingMethod::isSingleLevel() const
     448                 :            : {
     449                 :          0 :   return mStartVerticalLevel == mEndVerticalLevel;
     450                 :            : }
     451                 :            : 
     452                 :            : 
     453                 :          0 : QgsMeshRelativeHeightAveragingMethod::QgsMeshRelativeHeightAveragingMethod()
     454                 :          0 :   : QgsMesh3dAveragingMethod( QgsMesh3dAveragingMethod::RelativeHeightAveragingMethod )
     455                 :          0 : {
     456                 :          0 : }
     457                 :            : 
     458                 :          0 : QgsMeshRelativeHeightAveragingMethod::QgsMeshRelativeHeightAveragingMethod( double startDepth, double endDepth, bool countedFromTop )
     459                 :          0 :   : QgsMesh3dAveragingMethod( QgsMesh3dAveragingMethod::RelativeHeightAveragingMethod )
     460                 :          0 :   , mStartHeight( startDepth )
     461                 :          0 :   , mEndHeight( endDepth )
     462                 :          0 :   , mCountedFromTop( countedFromTop )
     463                 :          0 : {
     464                 :          0 :   if ( mStartHeight > mEndHeight )
     465                 :            :   {
     466                 :          0 :     std::swap( mStartHeight, mEndHeight );
     467                 :          0 :   }
     468                 :          0 : }
     469                 :            : 
     470                 :          0 : QgsMeshRelativeHeightAveragingMethod::~QgsMeshRelativeHeightAveragingMethod() = default;
     471                 :            : 
     472                 :          0 : QDomElement QgsMeshRelativeHeightAveragingMethod::writeXml( QDomDocument &doc ) const
     473                 :            : {
     474                 :          0 :   QDomElement elem = doc.createElement( QStringLiteral( "relative-height-settings" ) );
     475                 :          0 :   elem.setAttribute( QStringLiteral( "start-height" ), startHeight() );
     476                 :          0 :   elem.setAttribute( QStringLiteral( "end-height" ), endHeight() );
     477                 :          0 :   return elem;
     478                 :          0 : }
     479                 :            : 
     480                 :          0 : void QgsMeshRelativeHeightAveragingMethod::readXml( const QDomElement &elem )
     481                 :            : {
     482                 :          0 :   QDomElement settings = elem.firstChildElement( QStringLiteral( "relative-height-settings" ) );
     483                 :          0 :   if ( !settings.isNull() )
     484                 :            :   {
     485                 :          0 :     mStartHeight = settings.attribute( QStringLiteral( "start-height" ) ).toDouble();
     486                 :          0 :     mEndHeight = settings.attribute( QStringLiteral( "end-height" ) ).toDouble();
     487                 :          0 :     if ( mStartHeight > mEndHeight )
     488                 :            :     {
     489                 :          0 :       std::swap( mStartHeight, mEndHeight );
     490                 :          0 :     }
     491                 :          0 :   }
     492                 :          0 : }
     493                 :            : 
     494                 :          0 : bool QgsMeshRelativeHeightAveragingMethod::equals( const QgsMesh3dAveragingMethod *other ) const
     495                 :            : {
     496                 :          0 :   if ( !other || other->method() != method() )
     497                 :          0 :     return false;
     498                 :            : 
     499                 :          0 :   const QgsMeshRelativeHeightAveragingMethod *otherMethod = static_cast<const QgsMeshRelativeHeightAveragingMethod *>( other );
     500                 :            : 
     501                 :          0 :   return qgsDoubleNear( otherMethod->startHeight(), startHeight() ) &&
     502                 :          0 :          qgsDoubleNear( otherMethod->endHeight(), endHeight() ) &&
     503                 :          0 :          otherMethod->countedFromTop() == countedFromTop();
     504                 :          0 : }
     505                 :            : 
     506                 :          0 : QgsMesh3dAveragingMethod *QgsMeshRelativeHeightAveragingMethod::clone() const
     507                 :            : {
     508                 :          0 :   return new QgsMeshRelativeHeightAveragingMethod( startHeight(), endHeight(), countedFromTop() );
     509                 :          0 : }
     510                 :            : 
     511                 :          0 : double QgsMeshRelativeHeightAveragingMethod::startHeight() const
     512                 :            : {
     513                 :          0 :   return mStartHeight;
     514                 :            : }
     515                 :            : 
     516                 :          0 : double QgsMeshRelativeHeightAveragingMethod::endHeight() const
     517                 :            : {
     518                 :          0 :   return mEndHeight;
     519                 :            : }
     520                 :            : 
     521                 :          0 : bool QgsMeshRelativeHeightAveragingMethod::hasValidInputs() const
     522                 :            : {
     523                 :          0 :   return mStartHeight >= 0 && mEndHeight >= mStartHeight;
     524                 :            : }
     525                 :            : 
     526                 :          0 : void QgsMeshRelativeHeightAveragingMethod::volumeRangeForFace(
     527                 :            :   double &startVerticalLevel,
     528                 :            :   double &endVerticalLevel,
     529                 :            :   const QVector<double> &verticalLevels ) const
     530                 :            : {
     531                 :          0 :   if ( countedFromTop() )
     532                 :            :   {
     533                 :          0 :     const double top = verticalLevels[ 0 ];
     534                 :          0 :     startVerticalLevel = top - mStartHeight;
     535                 :          0 :     endVerticalLevel = top - mEndHeight;
     536                 :          0 :   }
     537                 :            :   else
     538                 :            :   {
     539                 :          0 :     const double bot = verticalLevels[verticalLevels.size() - 1];
     540                 :          0 :     startVerticalLevel = bot + mStartHeight;
     541                 :          0 :     endVerticalLevel = bot + mEndHeight;
     542                 :            :   }
     543                 :          0 : }
     544                 :            : 
     545                 :          0 : bool QgsMeshRelativeHeightAveragingMethod::countedFromTop() const
     546                 :            : {
     547                 :          0 :   return mCountedFromTop;
     548                 :            : }
     549                 :            : 
     550                 :          0 : QgsMeshElevationAveragingMethod::QgsMeshElevationAveragingMethod()
     551                 :          0 :   : QgsMesh3dAveragingMethod( QgsMesh3dAveragingMethod::ElevationAveragingMethod )
     552                 :          0 : {
     553                 :          0 : }
     554                 :            : 
     555                 :          0 : QgsMeshElevationAveragingMethod::QgsMeshElevationAveragingMethod( double startElevation, double endElevation )
     556                 :          0 :   : QgsMesh3dAveragingMethod( QgsMesh3dAveragingMethod::ElevationAveragingMethod )
     557                 :          0 :   , mStartElevation( startElevation )
     558                 :          0 :   , mEndElevation( endElevation )
     559                 :          0 : {
     560                 :          0 :   if ( mEndElevation > mStartElevation )
     561                 :            :   {
     562                 :          0 :     std::swap( mEndElevation, mStartElevation );
     563                 :          0 :   }
     564                 :          0 : }
     565                 :            : 
     566                 :          0 : QgsMeshElevationAveragingMethod::~QgsMeshElevationAveragingMethod() = default;
     567                 :            : 
     568                 :          0 : QDomElement QgsMeshElevationAveragingMethod::writeXml( QDomDocument &doc ) const
     569                 :            : {
     570                 :          0 :   QDomElement elem = doc.createElement( QStringLiteral( "elevation-settings" ) );
     571                 :          0 :   elem.setAttribute( QStringLiteral( "start-elevation" ), startElevation() );
     572                 :          0 :   elem.setAttribute( QStringLiteral( "end-elevation" ), endElevation() );
     573                 :          0 :   return elem;
     574                 :          0 : }
     575                 :            : 
     576                 :          0 : void QgsMeshElevationAveragingMethod::readXml( const QDomElement &elem )
     577                 :            : {
     578                 :          0 :   QDomElement settings = elem.firstChildElement( QStringLiteral( "elevation-settings" ) );
     579                 :          0 :   if ( !settings.isNull() )
     580                 :            :   {
     581                 :          0 :     mStartElevation = settings.attribute( QStringLiteral( "start-elevation" ) ).toDouble();
     582                 :          0 :     mEndElevation = settings.attribute( QStringLiteral( "end-elevation" ) ).toDouble();
     583                 :          0 :     if ( mEndElevation > mStartElevation )
     584                 :            :     {
     585                 :          0 :       std::swap( mEndElevation, mStartElevation );
     586                 :          0 :     }
     587                 :          0 :   }
     588                 :          0 : }
     589                 :            : 
     590                 :          0 : bool QgsMeshElevationAveragingMethod::equals( const QgsMesh3dAveragingMethod *other ) const
     591                 :            : {
     592                 :          0 :   if ( !other || other->method() != method() )
     593                 :          0 :     return false;
     594                 :            : 
     595                 :          0 :   const QgsMeshElevationAveragingMethod *otherMethod = static_cast<const QgsMeshElevationAveragingMethod *>( other );
     596                 :            : 
     597                 :          0 :   return qgsDoubleNear( otherMethod->startElevation(), startElevation() ) && qgsDoubleNear( otherMethod->endElevation(), endElevation() ) ;
     598                 :          0 : }
     599                 :            : 
     600                 :          0 : QgsMesh3dAveragingMethod *QgsMeshElevationAveragingMethod::clone() const
     601                 :            : {
     602                 :          0 :   return new QgsMeshElevationAveragingMethod( startElevation(), endElevation() );
     603                 :          0 : }
     604                 :            : 
     605                 :          0 : double QgsMeshElevationAveragingMethod::startElevation() const
     606                 :            : {
     607                 :          0 :   return mStartElevation;
     608                 :            : }
     609                 :            : 
     610                 :          0 : double QgsMeshElevationAveragingMethod::endElevation() const
     611                 :            : {
     612                 :          0 :   return mEndElevation;
     613                 :            : }
     614                 :            : 
     615                 :          0 : bool QgsMeshElevationAveragingMethod::hasValidInputs() const
     616                 :            : {
     617                 :          0 :   return mStartElevation <= 0.0 && mEndElevation <= mStartElevation;
     618                 :            : }
     619                 :            : 
     620                 :          0 : void QgsMeshElevationAveragingMethod::volumeRangeForFace(
     621                 :            :   double &startVerticalLevel,
     622                 :            :   double &endVerticalLevel,
     623                 :            :   const QVector<double> &verticalLevels ) const
     624                 :            : {
     625                 :          0 :   Q_UNUSED( verticalLevels )
     626                 :          0 :   startVerticalLevel = mStartElevation;
     627                 :          0 :   endVerticalLevel = mEndElevation;
     628                 :          0 : }

Generated by: LCOV version 1.14