LCOV - code coverage report
Current view: top level - analysis/interpolation - qgstininterpolator.cpp (source / functions) Hit Total Coverage
Test: coverage.info.cleaned Lines: 0 176 0.0 %
Date: 2021-04-10 08:29:14 Functions: 0 0 -
Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : /***************************************************************************
       2                 :            :                               qgstininterpolator.cpp
       3                 :            :                               ----------------------
       4                 :            :   begin                : March 10, 2008
       5                 :            :   copyright            : (C) 2008 by Marco Hugentobler
       6                 :            :   email                : marco dot hugentobler at karto dot baug dot ethz dot ch
       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 "qgstininterpolator.h"
      19                 :            : #include "qgsfeatureiterator.h"
      20                 :            : #include "CloughTocherInterpolator.h"
      21                 :            : #include "qgsdualedgetriangulation.h"
      22                 :            : #include "NormVecDecorator.h"
      23                 :            : #include "LinTriangleInterpolator.h"
      24                 :            : #include "qgspoint.h"
      25                 :            : #include "qgsfeature.h"
      26                 :            : #include "qgsgeometry.h"
      27                 :            : #include "qgsvectorlayer.h"
      28                 :            : #include "qgswkbptr.h"
      29                 :            : #include "qgsfeedback.h"
      30                 :            : #include "qgscurve.h"
      31                 :            : #include "qgsmulticurve.h"
      32                 :            : #include "qgscurvepolygon.h"
      33                 :            : #include "qgsmultisurface.h"
      34                 :            : 
      35                 :          0 : QgsTinInterpolator::QgsTinInterpolator( const QList<LayerData> &inputData, TinInterpolation interpolation, QgsFeedback *feedback )
      36                 :          0 :   : QgsInterpolator( inputData )
      37                 :          0 :   , mIsInitialized( false )
      38                 :          0 :   , mFeedback( feedback )
      39                 :          0 :   , mInterpolation( interpolation )
      40                 :          0 : {
      41                 :          0 : }
      42                 :            : 
      43                 :          0 : QgsTinInterpolator::~QgsTinInterpolator()
      44                 :          0 : {
      45                 :          0 :   delete mTriangulation;
      46                 :          0 :   delete mTriangleInterpolator;
      47                 :          0 : }
      48                 :            : 
      49                 :          0 : int QgsTinInterpolator::interpolatePoint( double x, double y, double &result, QgsFeedback * )
      50                 :            : {
      51                 :          0 :   if ( !mIsInitialized )
      52                 :            :   {
      53                 :          0 :     initialize();
      54                 :          0 :   }
      55                 :            : 
      56                 :          0 :   if ( !mTriangleInterpolator )
      57                 :            :   {
      58                 :          0 :     return 1;
      59                 :            :   }
      60                 :            : 
      61                 :          0 :   QgsPoint r( 0, 0, 0 );
      62                 :          0 :   if ( !mTriangleInterpolator->calcPoint( x, y, r ) )
      63                 :            :   {
      64                 :          0 :     return 2;
      65                 :            :   }
      66                 :          0 :   result = r.z();
      67                 :          0 :   return 0;
      68                 :          0 : }
      69                 :            : 
      70                 :          0 : QgsFields QgsTinInterpolator::triangulationFields()
      71                 :            : {
      72                 :          0 :   return QgsTriangulation::triangulationFields();
      73                 :            : }
      74                 :            : 
      75                 :          0 : void QgsTinInterpolator::setTriangulationSink( QgsFeatureSink *sink )
      76                 :            : {
      77                 :          0 :   mTriangulationSink = sink;
      78                 :          0 : }
      79                 :          0 : 
      80                 :          0 : void QgsTinInterpolator::initialize()
      81                 :            : {
      82                 :          0 :   QgsDualEdgeTriangulation *dualEdgeTriangulation = new QgsDualEdgeTriangulation( 100000 );
      83                 :          0 :   if ( mInterpolation == CloughTocher )
      84                 :            :   {
      85                 :          0 :     NormVecDecorator *dec = new NormVecDecorator();
      86                 :          0 :     dec->addTriangulation( dualEdgeTriangulation );
      87                 :          0 :     mTriangulation = dec;
      88                 :          0 :   }
      89                 :            :   else
      90                 :            :   {
      91                 :          0 :     mTriangulation = dualEdgeTriangulation;
      92                 :            :   }
      93                 :            : 
      94                 :            :   //get number of features if we use a progress bar
      95                 :          0 :   int nFeatures = 0;
      96                 :          0 :   int nProcessedFeatures = 0;
      97                 :          0 :   if ( mFeedback )
      98                 :            :   {
      99                 :          0 :     for ( const LayerData &layer :  std::as_const( mLayerData ) )
     100                 :            :     {
     101                 :          0 :       if ( layer.source )
     102                 :            :       {
     103                 :          0 :         nFeatures += layer.source->featureCount();
     104                 :          0 :       }
     105                 :            :     }
     106                 :          0 :   }
     107                 :            : 
     108                 :          0 :   const QgsCoordinateReferenceSystem crs = !mLayerData.empty() ? mLayerData.at( 0 ).source->sourceCrs() : QgsCoordinateReferenceSystem();
     109                 :            : 
     110                 :          0 :   QgsFeature f;
     111                 :          0 :   for ( const LayerData &layer : std::as_const( mLayerData ) )
     112                 :            :   {
     113                 :          0 :     if ( layer.source )
     114                 :            :     {
     115                 :          0 :       QgsAttributeList attList;
     116                 :          0 :       switch ( layer.valueSource )
     117                 :            :       {
     118                 :            :         case QgsInterpolator::ValueAttribute:
     119                 :          0 :           attList.push_back( layer.interpolationAttribute );
     120                 :          0 :           break;
     121                 :            : 
     122                 :            :         case QgsInterpolator::ValueM:
     123                 :            :         case QgsInterpolator::ValueZ:
     124                 :          0 :           break;
     125                 :            :       }
     126                 :            : 
     127                 :          0 :       QgsFeatureIterator fit = layer.source->getFeatures( QgsFeatureRequest().setSubsetOfAttributes( attList ).setDestinationCrs( crs, layer.transformContext ) );
     128                 :            : 
     129                 :          0 :       while ( fit.nextFeature( f ) )
     130                 :            :       {
     131                 :          0 :         if ( mFeedback )
     132                 :            :         {
     133                 :          0 :           if ( mFeedback->isCanceled() )
     134                 :            :           {
     135                 :          0 :             break;
     136                 :            :           }
     137                 :          0 :           if ( nFeatures > 0 )
     138                 :          0 :             mFeedback->setProgress( 100.0 * static_cast< double >( nProcessedFeatures ) / nFeatures );
     139                 :          0 :         }
     140                 :          0 :         insertData( f, layer.valueSource, layer.interpolationAttribute, layer.sourceType );
     141                 :          0 :         ++nProcessedFeatures;
     142                 :            :       }
     143                 :          0 :     }
     144                 :            :   }
     145                 :            : 
     146                 :          0 :   if ( mInterpolation == CloughTocher )
     147                 :            :   {
     148                 :          0 :     CloughTocherInterpolator *ctInterpolator = new CloughTocherInterpolator();
     149                 :          0 :     NormVecDecorator *dec = dynamic_cast<NormVecDecorator *>( mTriangulation );
     150                 :          0 :     if ( dec )
     151                 :            :     {
     152                 :          0 :       dec->estimateFirstDerivatives( mFeedback );
     153                 :          0 :       ctInterpolator->setTriangulation( dec );
     154                 :          0 :       dec->setTriangleInterpolator( ctInterpolator );
     155                 :          0 :       mTriangleInterpolator = ctInterpolator;
     156                 :          0 :     }
     157                 :          0 :   }
     158                 :            :   else //linear
     159                 :            :   {
     160                 :          0 :     mTriangleInterpolator = new LinTriangleInterpolator( dualEdgeTriangulation );
     161                 :            :   }
     162                 :          0 :   mIsInitialized = true;
     163                 :            : 
     164                 :            :   //debug
     165                 :          0 :   if ( mTriangulationSink )
     166                 :            :   {
     167                 :          0 :     dualEdgeTriangulation->saveTriangulation( mTriangulationSink, mFeedback );
     168                 :          0 :   }
     169                 :          0 : }
     170                 :            : 
     171                 :          0 : int QgsTinInterpolator::insertData( const QgsFeature &f, QgsInterpolator::ValueSource source, int attr, SourceType type )
     172                 :            : {
     173                 :          0 :   QgsGeometry g = f.geometry();
     174                 :          0 :   if ( g.isNull() || g.isEmpty() )
     175                 :            :   {
     176                 :          0 :     return 2;
     177                 :            :   }
     178                 :            : 
     179                 :            :   //check attribute value
     180                 :          0 :   double attributeValue = 0;
     181                 :          0 :   bool attributeConversionOk = false;
     182                 :          0 :   switch ( source )
     183                 :            :   {
     184                 :            :     case ValueAttribute:
     185                 :            :     {
     186                 :          0 :       QVariant attributeVariant = f.attribute( attr );
     187                 :          0 :       if ( !attributeVariant.isValid() ) //attribute not found, something must be wrong (e.g. NULL value)
     188                 :            :       {
     189                 :          0 :         return 3;
     190                 :            :       }
     191                 :          0 :       attributeValue = attributeVariant.toDouble( &attributeConversionOk );
     192                 :          0 :       if ( !attributeConversionOk || std::isnan( attributeValue ) ) //don't consider vertices with attributes like 'nan' for the interpolation
     193                 :            :       {
     194                 :          0 :         return 4;
     195                 :            :       }
     196                 :          0 :       break;
     197                 :          0 :     }
     198                 :            : 
     199                 :            :     case ValueM:
     200                 :          0 :       if ( !g.constGet()->isMeasure() )
     201                 :          0 :         return 3;
     202                 :            :       else
     203                 :          0 :         break;
     204                 :            : 
     205                 :            :     case ValueZ:
     206                 :          0 :       if ( !g.constGet()->is3D() )
     207                 :          0 :         return 3;
     208                 :            :       else
     209                 :          0 :         break;
     210                 :            :   }
     211                 :            : 
     212                 :            : 
     213                 :          0 :   switch ( type )
     214                 :            :   {
     215                 :            :     case SourcePoints:
     216                 :            :     {
     217                 :          0 :       if ( addPointsFromGeometry( g, source, attributeValue ) != 0 )
     218                 :          0 :         return -1;
     219                 :          0 :       break;
     220                 :            :     }
     221                 :            : 
     222                 :            :     case SourceBreakLines:
     223                 :            :     case SourceStructureLines:
     224                 :            :     {
     225                 :          0 :       switch ( QgsWkbTypes::geometryType( g.wkbType() ) )
     226                 :            :       {
     227                 :            :         case QgsWkbTypes::PointGeometry:
     228                 :            :         {
     229                 :          0 :           if ( addPointsFromGeometry( g, source, attributeValue ) != 0 )
     230                 :          0 :             return -1;
     231                 :          0 :           break;
     232                 :            :         }
     233                 :            : 
     234                 :            :         case QgsWkbTypes::LineGeometry:
     235                 :            :         case QgsWkbTypes::PolygonGeometry:
     236                 :            :         {
     237                 :            :           // need to extract all rings from input geometry
     238                 :          0 :           std::vector<const QgsCurve *> curves;
     239                 :          0 :           if ( QgsWkbTypes::geometryType( g.wkbType() ) == QgsWkbTypes::PolygonGeometry )
     240                 :            :           {
     241                 :          0 :             std::vector< const QgsCurvePolygon * > polygons;
     242                 :          0 :             if ( g.isMultipart() )
     243                 :            :             {
     244                 :          0 :               const QgsMultiSurface *ms = qgsgeometry_cast< const QgsMultiSurface * >( g.constGet() );
     245                 :          0 :               for ( int i = 0; i < ms->numGeometries(); ++i )
     246                 :            :               {
     247                 :          0 :                 polygons.emplace_back( qgsgeometry_cast< const QgsCurvePolygon * >( ms->geometryN( i ) ) );
     248                 :          0 :               }
     249                 :          0 :             }
     250                 :            :             else
     251                 :            :             {
     252                 :          0 :               polygons.emplace_back( qgsgeometry_cast< const QgsCurvePolygon * >( g.constGet() ) );
     253                 :            :             }
     254                 :            : 
     255                 :          0 :             for ( const QgsCurvePolygon *polygon : polygons )
     256                 :            :             {
     257                 :          0 :               if ( !polygon )
     258                 :          0 :                 continue;
     259                 :            : 
     260                 :          0 :               if ( polygon->exteriorRing() )
     261                 :          0 :                 curves.emplace_back( polygon->exteriorRing() );
     262                 :            : 
     263                 :          0 :               for ( int i = 0; i < polygon->numInteriorRings(); ++i )
     264                 :            :               {
     265                 :          0 :                 curves.emplace_back( polygon->interiorRing( i ) );
     266                 :          0 :               }
     267                 :            :             }
     268                 :          0 :           }
     269                 :            :           else
     270                 :            :           {
     271                 :          0 :             if ( g.isMultipart() )
     272                 :            :             {
     273                 :          0 :               const QgsMultiCurve *mc = qgsgeometry_cast< const QgsMultiCurve * >( g.constGet() );
     274                 :          0 :               for ( int i = 0; i < mc->numGeometries(); ++i )
     275                 :            :               {
     276                 :          0 :                 curves.emplace_back( mc->curveN( i ) );
     277                 :          0 :               }
     278                 :          0 :             }
     279                 :            :             else
     280                 :            :             {
     281                 :          0 :               curves.emplace_back( qgsgeometry_cast< const QgsCurve * >( g.constGet() ) );
     282                 :            :             }
     283                 :            :           }
     284                 :            : 
     285                 :          0 :           for ( const QgsCurve *curve : curves )
     286                 :            :           {
     287                 :          0 :             if ( !curve )
     288                 :          0 :               continue;
     289                 :            : 
     290                 :          0 :             QgsPointSequence linePoints;
     291                 :          0 :             curve->points( linePoints );
     292                 :          0 :             for ( QgsPoint &point : linePoints )
     293                 :            :             {
     294                 :          0 :               switch ( source )
     295                 :            :               {
     296                 :            :                 case ValueAttribute:
     297                 :          0 :                   if ( point.is3D() )
     298                 :          0 :                     point.setZ( attributeValue );
     299                 :            :                   else
     300                 :          0 :                     point.addZValue( attributeValue );
     301                 :          0 :                   break;
     302                 :            : 
     303                 :            :                 case ValueM:
     304                 :          0 :                   if ( point.is3D() )
     305                 :          0 :                     point.setZ( point.m() );
     306                 :            :                   else
     307                 :          0 :                     point.addZValue( point.m() );
     308                 :          0 :                   break;
     309                 :            : 
     310                 :            :                 case ValueZ:
     311                 :          0 :                   break;
     312                 :            :               }
     313                 :            :             }
     314                 :          0 :             mTriangulation->addLine( linePoints, type );
     315                 :          0 :           }
     316                 :            :           break;
     317                 :          0 :         }
     318                 :            :         case QgsWkbTypes::UnknownGeometry:
     319                 :            :         case QgsWkbTypes::NullGeometry:
     320                 :          0 :           break;
     321                 :            :       }
     322                 :          0 :       break;
     323                 :            :     }
     324                 :            :   }
     325                 :            : 
     326                 :          0 :   return 0;
     327                 :          0 : }
     328                 :            : 
     329                 :            : 
     330                 :          0 : int QgsTinInterpolator::addPointsFromGeometry( const QgsGeometry &g, ValueSource source, double attributeValue )
     331                 :            : {
     332                 :            :   // loop through all vertices and add to triangulation
     333                 :          0 :   for ( auto point = g.vertices_begin(); point != g.vertices_end(); ++point )
     334                 :            :   {
     335                 :          0 :     QgsPoint p = *point;
     336                 :          0 :     double z = 0;
     337                 :          0 :     switch ( source )
     338                 :            :     {
     339                 :            :       case ValueAttribute:
     340                 :          0 :         z = attributeValue;
     341                 :          0 :         break;
     342                 :            : 
     343                 :            :       case ValueZ:
     344                 :          0 :         z = p.z();
     345                 :          0 :         break;
     346                 :            : 
     347                 :            :       case ValueM:
     348                 :          0 :         z = p.m();
     349                 :          0 :         break;
     350                 :            :     }
     351                 :          0 :     if ( mTriangulation->addPoint( QgsPoint( p.x(), p.y(), z ) ) == -100 )
     352                 :            :     {
     353                 :          0 :       return -1;
     354                 :            :     }
     355                 :          0 :   }
     356                 :          0 :   return 0;
     357                 :          0 : }

Generated by: LCOV version 1.14