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

           Branch data     Line data    Source code
       1                 :            : /***************************************************************************
       2                 :            :                          qgsmeshlayerinterpolator.cpp
       3                 :            :                          ----------------------------
       4                 :            :     begin                : April 2018
       5                 :            :     copyright            : (C) 2018 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                 :            : ///@cond PRIVATE
      19                 :            : 
      20                 :            : #include <memory>
      21                 :            : #include <limits>
      22                 :            : 
      23                 :            : #include "qgsmeshlayerinterpolator.h"
      24                 :            : 
      25                 :            : #include "qgis.h"
      26                 :            : #include "qgsrasterinterface.h"
      27                 :            : #include "qgsmaptopixel.h"
      28                 :            : #include "qgsvector.h"
      29                 :            : #include "qgspoint.h"
      30                 :            : #include "qgspointxy.h"
      31                 :            : #include "qgsmeshlayerutils.h"
      32                 :            : #include "qgsmeshlayer.h"
      33                 :            : #include "qgscoordinatetransformcontext.h"
      34                 :            : #include "qgscoordinatetransform.h"
      35                 :            : #include "qgsmeshdataprovider.h"
      36                 :            : 
      37                 :          0 : QgsMeshLayerInterpolator::QgsMeshLayerInterpolator(
      38                 :            :   const QgsTriangularMesh &m,
      39                 :            :   const QVector<double> &datasetValues,
      40                 :            :   const QgsMeshDataBlock &activeFaceFlagValues,
      41                 :            :   QgsMeshDatasetGroupMetadata::DataType dataType,
      42                 :            :   const QgsRenderContext &context,
      43                 :            :   const QSize &size )
      44                 :          0 :   : mTriangularMesh( m ),
      45                 :          0 :     mDatasetValues( datasetValues ),
      46                 :          0 :     mActiveFaceFlagValues( activeFaceFlagValues ),
      47                 :          0 :     mContext( context ),
      48                 :          0 :     mDataType( dataType ),
      49                 :          0 :     mOutputSize( size )
      50                 :          0 : {
      51                 :          0 : }
      52                 :            : 
      53                 :          0 : QgsMeshLayerInterpolator::~QgsMeshLayerInterpolator() = default;
      54                 :            : 
      55                 :          0 : QgsRasterInterface *QgsMeshLayerInterpolator::clone() const
      56                 :            : {
      57                 :          0 :   assert( false ); // we should not need this (hopefully)
      58                 :            :   return nullptr;
      59                 :            : }
      60                 :            : 
      61                 :          0 : Qgis::DataType QgsMeshLayerInterpolator::dataType( int ) const
      62                 :            : {
      63                 :          0 :   return Qgis::Float64;
      64                 :            : }
      65                 :            : 
      66                 :          0 : int QgsMeshLayerInterpolator::bandCount() const
      67                 :            : {
      68                 :          0 :   return 1;
      69                 :            : }
      70                 :            : 
      71                 :          0 : QgsRasterBlock *QgsMeshLayerInterpolator::block( int, const QgsRectangle &extent, int width, int height, QgsRasterBlockFeedback *feedback )
      72                 :            : {
      73                 :          0 :   std::unique_ptr<QgsRasterBlock> outputBlock( new QgsRasterBlock( Qgis::Float64, width, height ) );
      74                 :          0 :   const double noDataValue = std::numeric_limits<double>::quiet_NaN();
      75                 :          0 :   outputBlock->setNoDataValue( noDataValue );
      76                 :          0 :   outputBlock->setIsNoData();  // assume initially that all values are unset
      77                 :          0 :   double *data = reinterpret_cast<double *>( outputBlock->bits() );
      78                 :            : 
      79                 :          0 :   QList<int> spatialIndexTriangles;
      80                 :          0 :   int indexCount;
      81                 :          0 :   if ( mSpatialIndexActive )
      82                 :            :   {
      83                 :          0 :     spatialIndexTriangles = mTriangularMesh.faceIndexesForRectangle( extent );
      84                 :          0 :     indexCount = spatialIndexTriangles.count();
      85                 :          0 :   }
      86                 :            :   else
      87                 :            :   {
      88                 :          0 :     indexCount = mTriangularMesh.triangles().count();
      89                 :            :   }
      90                 :            : 
      91                 :          0 :   if ( mTriangularMesh.contains( QgsMesh::ElementType::Edge ) )
      92                 :            :   {
      93                 :          0 :     return outputBlock.release();
      94                 :            :   }
      95                 :            : 
      96                 :          0 :   const QVector<QgsMeshVertex> &vertices = mTriangularMesh.vertices();
      97                 :            : 
      98                 :            :   // currently expecting that triangulation does not add any new extra vertices on the way
      99                 :          0 :   if ( mDataType == QgsMeshDatasetGroupMetadata::DataType::DataOnVertices )
     100                 :          0 :     Q_ASSERT( mDatasetValues.count() == mTriangularMesh.vertices().count() );
     101                 :            : 
     102                 :          0 :   for ( int i = 0; i < indexCount; ++i )
     103                 :            :   {
     104                 :          0 :     if ( feedback && feedback->isCanceled() )
     105                 :          0 :       break;
     106                 :            : 
     107                 :          0 :     if ( mContext.renderingStopped() )
     108                 :          0 :       break;
     109                 :            : 
     110                 :            :     int triangleIndex;
     111                 :          0 :     if ( mSpatialIndexActive )
     112                 :          0 :       triangleIndex = spatialIndexTriangles[i];
     113                 :            :     else
     114                 :          0 :       triangleIndex = i;
     115                 :            : 
     116                 :          0 :     const QgsMeshFace &face = mTriangularMesh.triangles()[triangleIndex];
     117                 :            : 
     118                 :          0 :     const int v1 = face[0], v2 = face[1], v3 = face[2];
     119                 :          0 :     const QgsPointXY &p1 = vertices[v1], &p2 = vertices[v2], &p3 = vertices[v3];
     120                 :            : 
     121                 :          0 :     const int nativeFaceIndex = mTriangularMesh.trianglesToNativeFaces()[triangleIndex];
     122                 :          0 :     const bool isActive = mActiveFaceFlagValues.active( nativeFaceIndex );
     123                 :          0 :     if ( !isActive )
     124                 :          0 :       continue;
     125                 :            : 
     126                 :          0 :     QgsRectangle bbox = QgsMeshLayerUtils::triangleBoundingBox( p1, p2, p3 );
     127                 :          0 :     if ( !extent.intersects( bbox ) )
     128                 :          0 :       continue;
     129                 :            : 
     130                 :            :     // Get the BBox of the element in pixels
     131                 :            :     int topLim, bottomLim, leftLim, rightLim;
     132                 :          0 :     QgsMeshLayerUtils::boundingBoxToScreenRectangle( mContext.mapToPixel(), mOutputSize, bbox, leftLim, rightLim, topLim, bottomLim );
     133                 :            : 
     134                 :          0 :     double value( 0 ), value1( 0 ), value2( 0 ), value3( 0 );
     135                 :          0 :     const int faceIdx = mTriangularMesh.trianglesToNativeFaces()[triangleIndex];
     136                 :            : 
     137                 :          0 :     if ( mDataType == QgsMeshDatasetGroupMetadata::DataType::DataOnVertices )
     138                 :            :     {
     139                 :          0 :       value1 = mDatasetValues[v1];
     140                 :          0 :       value2 = mDatasetValues[v2];
     141                 :          0 :       value3 = mDatasetValues[v3];
     142                 :          0 :     }
     143                 :            :     else
     144                 :          0 :       value = mDatasetValues[faceIdx];
     145                 :            : 
     146                 :            :     // interpolate in the bounding box of the face
     147                 :          0 :     for ( int j = topLim; j <= bottomLim; j++ )
     148                 :            :     {
     149                 :          0 :       double *line = data + ( j * width );
     150                 :          0 :       for ( int k = leftLim; k <= rightLim; k++ )
     151                 :            :       {
     152                 :            :         double val;
     153                 :          0 :         const QgsPointXY p = mContext.mapToPixel().toMapCoordinates( k, j );
     154                 :          0 :         if ( mDataType == QgsMeshDatasetGroupMetadata::DataType::DataOnVertices )
     155                 :          0 :           val = QgsMeshLayerUtils::interpolateFromVerticesData(
     156                 :          0 :                   p1,
     157                 :          0 :                   p2,
     158                 :          0 :                   p3,
     159                 :          0 :                   value1,
     160                 :          0 :                   value2,
     161                 :          0 :                   value3,
     162                 :            :                   p );
     163                 :            :         else
     164                 :            :         {
     165                 :          0 :           val = QgsMeshLayerUtils::interpolateFromFacesData(
     166                 :          0 :                   p1,
     167                 :          0 :                   p2,
     168                 :          0 :                   p3,
     169                 :          0 :                   value,
     170                 :            :                   p
     171                 :            :                 );
     172                 :            :         }
     173                 :          0 :         if ( !std::isnan( val ) )
     174                 :            :         {
     175                 :          0 :           line[k] = val;
     176                 :          0 :           outputBlock->setIsData( j, k );
     177                 :          0 :         }
     178                 :          0 :       }
     179                 :          0 :     }
     180                 :            : 
     181                 :          0 :   }
     182                 :            : 
     183                 :          0 :   return outputBlock.release();
     184                 :          0 : }
     185                 :            : 
     186                 :          0 : void QgsMeshLayerInterpolator::setSpatialIndexActive( bool active ) {mSpatialIndexActive = active;}
     187                 :            : 
     188                 :            : ///@endcond
     189                 :            : 
     190                 :          0 : QgsRasterBlock *QgsMeshUtils::exportRasterBlock(
     191                 :            :   const QgsMeshLayer &layer,
     192                 :            :   const QgsMeshDatasetIndex &datasetIndex,
     193                 :            :   const QgsCoordinateReferenceSystem &destinationCrs,
     194                 :            :   const QgsCoordinateTransformContext &transformContext,
     195                 :            :   double mapUnitsPerPixel,
     196                 :            :   const QgsRectangle &extent,
     197                 :            :   QgsRasterBlockFeedback *feedback )
     198                 :            : {
     199                 :          0 :   if ( !layer.dataProvider() )
     200                 :          0 :     return nullptr;
     201                 :            : 
     202                 :          0 :   if ( !datasetIndex.isValid() )
     203                 :          0 :     return nullptr;
     204                 :            : 
     205                 :          0 :   int widthPixel = static_cast<int>( extent.width() / mapUnitsPerPixel );
     206                 :          0 :   int heightPixel = static_cast<int>( extent.height() / mapUnitsPerPixel );
     207                 :            : 
     208                 :          0 :   const QgsPointXY center = extent.center();
     209                 :          0 :   QgsMapToPixel mapToPixel( mapUnitsPerPixel,
     210                 :          0 :                             center.x(),
     211                 :          0 :                             center.y(),
     212                 :          0 :                             widthPixel,
     213                 :          0 :                             heightPixel,
     214                 :            :                             0 );
     215                 :          0 :   QgsCoordinateTransform transform( layer.crs(), destinationCrs, transformContext );
     216                 :            : 
     217                 :          0 :   QgsRenderContext renderContext;
     218                 :          0 :   renderContext.setCoordinateTransform( transform );
     219                 :          0 :   renderContext.setMapToPixel( mapToPixel );
     220                 :          0 :   renderContext.setExtent( extent );
     221                 :            : 
     222                 :          0 :   std::unique_ptr<QgsMesh> nativeMesh = std::make_unique<QgsMesh>();
     223                 :          0 :   layer.dataProvider()->populateMesh( nativeMesh.get() );
     224                 :          0 :   std::unique_ptr<QgsTriangularMesh> triangularMesh = std::make_unique<QgsTriangularMesh>();
     225                 :          0 :   triangularMesh->update( nativeMesh.get(), transform );
     226                 :            : 
     227                 :          0 :   const QgsMeshDatasetGroupMetadata metadata = layer.dataProvider()->datasetGroupMetadata( datasetIndex );
     228                 :          0 :   QgsMeshDatasetGroupMetadata::DataType scalarDataType = QgsMeshLayerUtils::datasetValuesType( metadata.dataType() );
     229                 :          0 :   const int count =  QgsMeshLayerUtils::datasetValuesCount( nativeMesh.get(), scalarDataType );
     230                 :          0 :   QgsMeshDataBlock vals = QgsMeshLayerUtils::datasetValues(
     231                 :          0 :                             &layer,
     232                 :          0 :                             datasetIndex,
     233                 :            :                             0,
     234                 :          0 :                             count );
     235                 :          0 :   if ( !vals.isValid() )
     236                 :          0 :     return nullptr;
     237                 :            : 
     238                 :          0 :   QVector<double> datasetValues = QgsMeshLayerUtils::calculateMagnitudes( vals );
     239                 :          0 :   QgsMeshDataBlock activeFaceFlagValues = layer.dataProvider()->areFacesActive(
     240                 :          0 :       datasetIndex,
     241                 :            :       0,
     242                 :          0 :       nativeMesh->faces.count() );
     243                 :            : 
     244                 :          0 :   QgsMeshLayerInterpolator interpolator(
     245                 :          0 :     *( triangularMesh.get() ),
     246                 :            :     datasetValues,
     247                 :            :     activeFaceFlagValues,
     248                 :          0 :     scalarDataType,
     249                 :            :     renderContext,
     250                 :          0 :     QSize( widthPixel, heightPixel )
     251                 :            :   );
     252                 :            : 
     253                 :          0 :   return interpolator.block( 0, extent, widthPixel, heightPixel, feedback );
     254                 :          0 : }
     255                 :            : 
     256                 :          0 : QgsRasterBlock *QgsMeshUtils::exportRasterBlock(
     257                 :            :   const QgsTriangularMesh &triangularMesh,
     258                 :            :   const QgsMeshDataBlock &datasetValues,
     259                 :            :   const QgsMeshDataBlock &activeFlags,
     260                 :            :   const QgsMeshDatasetGroupMetadata::DataType dataType,
     261                 :            :   const QgsCoordinateTransform &transform,
     262                 :            :   double mapUnitsPerPixel,
     263                 :            :   const QgsRectangle &extent,
     264                 :            :   QgsRasterBlockFeedback *feedback )
     265                 :            : {
     266                 :            : 
     267                 :          0 :   int widthPixel = static_cast<int>( extent.width() / mapUnitsPerPixel );
     268                 :          0 :   int heightPixel = static_cast<int>( extent.height() / mapUnitsPerPixel );
     269                 :            : 
     270                 :          0 :   const QgsPointXY center = extent.center();
     271                 :          0 :   QgsMapToPixel mapToPixel( mapUnitsPerPixel,
     272                 :          0 :                             center.x(),
     273                 :          0 :                             center.y(),
     274                 :          0 :                             widthPixel,
     275                 :          0 :                             heightPixel,
     276                 :            :                             0 );
     277                 :            : 
     278                 :          0 :   QgsRenderContext renderContext;
     279                 :          0 :   renderContext.setCoordinateTransform( transform );
     280                 :          0 :   renderContext.setMapToPixel( mapToPixel );
     281                 :          0 :   renderContext.setExtent( extent );
     282                 :            : 
     283                 :          0 :   QVector<double> magnitudes = QgsMeshLayerUtils::calculateMagnitudes( datasetValues );
     284                 :            : 
     285                 :          0 :   QgsMeshLayerInterpolator interpolator(
     286                 :          0 :     triangularMesh,
     287                 :            :     magnitudes,
     288                 :          0 :     activeFlags,
     289                 :          0 :     dataType,
     290                 :            :     renderContext,
     291                 :          0 :     QSize( widthPixel, heightPixel )
     292                 :            :   );
     293                 :            : 
     294                 :          0 :   return interpolator.block( 0, extent, widthPixel, heightPixel, feedback );
     295                 :          0 : }

Generated by: LCOV version 1.14