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

           Branch data     Line data    Source code
       1                 :            : /***************************************************************************
       2                 :            :                          qgsalgorithmtinmeshcreation.cpp
       3                 :            :                          ---------------------------
       4                 :            :     begin                : August 2020
       5                 :            :     copyright            : (C) 2020 by Vincent Cloarec
       6                 :            :     email                : vcloarec 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 "qgsalgorithmtinmeshcreation.h"
      19                 :            : #include "qgsprovidermetadata.h"
      20                 :            : #include "qgsproviderregistry.h"
      21                 :            : #include "qgsprocessingparametertininputlayers.h"
      22                 :            : #include "qgsmeshtriangulation.h"
      23                 :            : #include "qgsmeshlayer.h"
      24                 :            : #include "qgis.h"
      25                 :            : 
      26                 :            : ///@cond PRIVATE
      27                 :            : 
      28                 :          0 : QString QgsTinMeshCreationAlgorithm::group() const
      29                 :            : {
      30                 :          0 :   return QObject::tr( "Mesh" );
      31                 :            : }
      32                 :            : 
      33                 :          0 : QString QgsTinMeshCreationAlgorithm::groupId() const
      34                 :            : {
      35                 :          0 :   return QStringLiteral( "mesh" );
      36                 :            : }
      37                 :            : 
      38                 :          0 : QString QgsTinMeshCreationAlgorithm::shortHelpString() const
      39                 :            : {
      40                 :          0 :   return QObject::tr( "TIN mesh creation from vector layers" );
      41                 :            : }
      42                 :            : 
      43                 :          0 : QString QgsTinMeshCreationAlgorithm::name() const
      44                 :            : {
      45                 :          0 :   return QStringLiteral( "tinmeshcreation" );
      46                 :            : }
      47                 :            : 
      48                 :          0 : QString QgsTinMeshCreationAlgorithm::displayName() const
      49                 :            : {
      50                 :          0 :   return QObject::tr( "TIN Mesh Creation" );
      51                 :            : }
      52                 :            : 
      53                 :          0 : QgsProcessingAlgorithm *QgsTinMeshCreationAlgorithm::createInstance() const
      54                 :            : {
      55                 :          0 :   return new QgsTinMeshCreationAlgorithm();
      56                 :            : }
      57                 :            : 
      58                 :          0 : void QgsTinMeshCreationAlgorithm::initAlgorithm( const QVariantMap &configuration )
      59                 :            : {
      60                 :          0 :   Q_UNUSED( configuration );
      61                 :          0 :   addParameter( new QgsProcessingParameterTinInputLayers( QStringLiteral( "SOURCE_DATA" ), QObject::tr( "Input layers" ) ) );
      62                 :            : 
      63                 :          0 :   QgsProviderMetadata *meta = QgsProviderRegistry::instance()->providerMetadata( QStringLiteral( "mdal" ) );
      64                 :            : 
      65                 :          0 :   QList<QgsMeshDriverMetadata> driverList;
      66                 :          0 :   if ( meta )
      67                 :          0 :     driverList = meta->meshDriversMetadata();
      68                 :            : 
      69                 :          0 :   for ( const QgsMeshDriverMetadata &driverMeta : driverList )
      70                 :          0 :     if ( driverMeta.capabilities() & QgsMeshDriverMetadata::CanWriteMeshData )
      71                 :          0 :       mAvailableFormat.append( driverMeta.name() );
      72                 :            : 
      73                 :          0 :   addParameter( new QgsProcessingParameterEnum( QStringLiteral( "MESH_FORMAT" ), QObject::tr( "Output format" ), mAvailableFormat, false, 0 ) );
      74                 :          0 :   addParameter( new QgsProcessingParameterCrs( QStringLiteral( "CRS_OUTPUT" ), QObject::tr( "Output Coordinate System" ), QVariant(), true ) );
      75                 :          0 :   addParameter( new QgsProcessingParameterFileDestination( QStringLiteral( "OUTPUT_MESH" ), QObject::tr( "Output File" ) ) );
      76                 :          0 : }
      77                 :            : 
      78                 :          0 : bool QgsTinMeshCreationAlgorithm::prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
      79                 :            : {
      80                 :          0 :   const QVariant layersVariant = parameters.value( parameterDefinition( QStringLiteral( "SOURCE_DATA" ) )->name() );
      81                 :          0 :   if ( layersVariant.type() != QVariant::List )
      82                 :          0 :     return false;
      83                 :            : 
      84                 :          0 :   const QVariantList layersList = layersVariant.toList();
      85                 :            : 
      86                 :          0 :   QgsCoordinateReferenceSystem destinationCrs = parameterAsCrs( parameters, QStringLiteral( "CRS_OUTPUT" ), context );
      87                 :          0 :   if ( !destinationCrs.isValid() && context.project() )
      88                 :          0 :     destinationCrs = context.project()->crs();
      89                 :            : 
      90                 :          0 :   for ( const QVariant &layer : layersList )
      91                 :            :   {
      92                 :          0 :     if ( feedback && feedback->isCanceled() )
      93                 :          0 :       return false;
      94                 :            : 
      95                 :          0 :     if ( layer.type() != QVariant::Map )
      96                 :          0 :       continue;
      97                 :          0 :     const QVariantMap layerMap = layer.toMap();
      98                 :          0 :     const QString layerSource = layerMap.value( QStringLiteral( "source" ) ).toString();
      99                 :          0 :     const QgsProcessingParameterTinInputLayers::Type type =
     100                 :          0 :       static_cast<QgsProcessingParameterTinInputLayers::Type>( layerMap.value( QStringLiteral( "type" ) ).toInt() );
     101                 :          0 :     int attributeIndex = layerMap.value( QStringLiteral( "attributeIndex" ) ).toInt();
     102                 :            : 
     103                 :          0 :     std::unique_ptr<QgsProcessingFeatureSource> featureSource( QgsProcessingUtils::variantToSource( layerSource, context ) );
     104                 :            : 
     105                 :          0 :     if ( !featureSource )
     106                 :          0 :       continue;
     107                 :            : 
     108                 :          0 :     const QgsCoordinateTransform transform( featureSource->sourceCrs(), destinationCrs, context.transformContext() );
     109                 :          0 :     int featureCount = featureSource->featureCount();
     110                 :          0 :     switch ( type )
     111                 :            :     {
     112                 :            :       case QgsProcessingParameterTinInputLayers::Vertices:
     113                 :          0 :         mVerticesLayer.append( {featureSource->getFeatures(), transform, attributeIndex, featureCount} );
     114                 :          0 :         break;
     115                 :            :       case QgsProcessingParameterTinInputLayers::BreakLines:
     116                 :          0 :         mBreakLinesLayer.append( {featureSource->getFeatures(), transform, attributeIndex, featureCount} );
     117                 :          0 :         break;
     118                 :            :       default:
     119                 :          0 :         break;
     120                 :            :     }
     121                 :          0 :   }
     122                 :            : 
     123                 :          0 :   if ( mVerticesLayer.isEmpty() && mBreakLinesLayer.isEmpty() )
     124                 :          0 :     return false;
     125                 :            : 
     126                 :          0 :   return true;
     127                 :          0 : }
     128                 :            : 
     129                 :          0 : QVariantMap QgsTinMeshCreationAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
     130                 :            : {
     131                 :          0 :   QgsMeshTriangulation triangulation;
     132                 :          0 :   QgsCoordinateReferenceSystem destinationCrs = parameterAsCrs( parameters, QStringLiteral( "CRS_OUTPUT" ), context );
     133                 :          0 :   if ( !destinationCrs.isValid() && context.project() )
     134                 :          0 :     destinationCrs = context.project()->crs();
     135                 :          0 :   triangulation.setCrs( destinationCrs );
     136                 :            : 
     137                 :          0 :   if ( !mVerticesLayer.isEmpty() && feedback )
     138                 :          0 :     feedback->setProgressText( QObject::tr( "Adding vertices layer(s) to the triangulation" ) );
     139                 :          0 :   for ( Layer &l : mVerticesLayer )
     140                 :            :   {
     141                 :          0 :     if ( feedback && feedback->isCanceled() )
     142                 :          0 :       break;
     143                 :          0 :     triangulation.addVertices( l.fit, l.attributeIndex, l.transform, feedback, l.featureCount );
     144                 :            :   }
     145                 :            : 
     146                 :          0 :   if ( !mBreakLinesLayer.isEmpty() && feedback )
     147                 :          0 :     feedback->setProgressText( QObject::tr( "Adding break lines layer(s) to the triangulation" ) );
     148                 :          0 :   for ( Layer &l : mBreakLinesLayer )
     149                 :            :   {
     150                 :          0 :     if ( feedback && feedback->isCanceled() )
     151                 :          0 :       break;
     152                 :          0 :     triangulation.addBreakLines( l.fit, l.attributeIndex, l.transform, feedback, l.featureCount );
     153                 :            :   }
     154                 :            : 
     155                 :          0 :   if ( feedback && feedback->isCanceled() )
     156                 :          0 :     return QVariantMap();
     157                 :            : 
     158                 :          0 :   const QString fileName = parameterAsFile( parameters, QStringLiteral( "OUTPUT_MESH" ), context );
     159                 :          0 :   int driverIndex = parameterAsEnum( parameters, QStringLiteral( "MESH_FORMAT" ), context );
     160                 :          0 :   const QString driver = mAvailableFormat.at( driverIndex );
     161                 :          0 :   if ( feedback )
     162                 :          0 :     feedback->setProgressText( QObject::tr( "Creating mesh from triangulation" ) );
     163                 :          0 :   const QgsMesh mesh = triangulation.triangulatedMesh( feedback );
     164                 :            : 
     165                 :          0 :   if ( feedback && feedback->isCanceled() )
     166                 :          0 :     return QVariantMap();
     167                 :            : 
     168                 :          0 :   const QgsProviderMetadata *providerMetadata = QgsProviderRegistry::instance()->providerMetadata( QStringLiteral( "mdal" ) );
     169                 :            : 
     170                 :          0 :   if ( feedback )
     171                 :          0 :     feedback->setProgressText( QObject::tr( "Saving mesh to file" ) );
     172                 :          0 :   if ( providerMetadata )
     173                 :          0 :     providerMetadata->createMeshData( mesh, fileName, driver, destinationCrs );
     174                 :            : 
     175                 :          0 :   context.addLayerToLoadOnCompletion( fileName, QgsProcessingContext::LayerDetails( "TIN Mesh",
     176                 :          0 :                                       context.project(),
     177                 :          0 :                                       "TIN",
     178                 :            :                                       QgsProcessingUtils::LayerHint::Mesh ) );
     179                 :            : 
     180                 :            :   //SELAFIN format doesn't support saving Z value on mesh vertices, so create a specific dataset group
     181                 :          0 :   if ( driver == "SELAFIN" )
     182                 :            :   {
     183                 :          0 :     addZValueDataset( fileName, mesh, driver );
     184                 :          0 :   }
     185                 :            : 
     186                 :          0 :   QVariantMap ret;
     187                 :          0 :   ret[QStringLiteral( "OUTPUT_MESH" )] = fileName;
     188                 :            : 
     189                 :          0 :   return ret;
     190                 :          0 : }
     191                 :            : 
     192                 :          0 : void QgsTinMeshCreationAlgorithm::addZValueDataset( const QString &fileName, const QgsMesh &mesh, const QString &driver )
     193                 :            : {
     194                 :          0 :   std::unique_ptr<QgsMeshLayer> tempLayer = std::make_unique<QgsMeshLayer>( fileName, "temp", "mdal" );
     195                 :          0 :   QgsMeshZValueDatasetGroup *zValueDatasetGroup = new QgsMeshZValueDatasetGroup( QObject::tr( "Terrain Elevation" ), mesh );
     196                 :          0 :   tempLayer->addDatasets( zValueDatasetGroup );
     197                 :          0 :   int datasetGroupIndex = tempLayer->datasetGroupCount() - 1;
     198                 :          0 :   tempLayer->saveDataset( fileName, datasetGroupIndex, driver );
     199                 :          0 : }
     200                 :            : 
     201                 :          0 : bool QgsTinMeshCreationAlgorithm::canExecute( QString *errorMessage ) const
     202                 :            : {
     203                 :          0 :   if ( mAvailableFormat.count() == 0 )
     204                 :            :   {
     205                 :          0 :     *errorMessage = QObject::tr( "MDAL not available" );
     206                 :          0 :     return false;
     207                 :            :   }
     208                 :            : 
     209                 :          0 :   return true;
     210                 :          0 : }
     211                 :            : 
     212                 :            : ///@endcond PRIVATE

Generated by: LCOV version 1.14