QGIS API Documentation  3.16.0-Hannover (43b64b13f3)
qgsalgorithmtinmeshcreation.cpp
Go to the documentation of this file.
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 
19 #include "qgsprovidermetadata.h"
20 #include "qgsproviderregistry.h"
22 #include "qgsmeshtriangulation.h"
23 #include "qgsmeshlayer.h"
24 #include "qgis.h"
25 
26 QString QgsTinMeshCreationAlgorithm::group() const
27 {
28  return QObject::tr( "Mesh" );
29 }
30 
31 QString QgsTinMeshCreationAlgorithm::groupId() const
32 {
33  return QStringLiteral( "mesh" );
34 }
35 
36 QString QgsTinMeshCreationAlgorithm::shortHelpString() const
37 {
38  return QObject::tr( "TIN mesh creation from vector layers" );
39 }
40 
41 QString QgsTinMeshCreationAlgorithm::name() const
42 {
43  return QStringLiteral( "tinmeshcreation" );
44 }
45 
46 QString QgsTinMeshCreationAlgorithm::displayName() const
47 {
48  return QObject::tr( "TIN Mesh Creation" );
49 }
50 
51 QgsProcessingAlgorithm *QgsTinMeshCreationAlgorithm::createInstance() const
52 {
53  return new QgsTinMeshCreationAlgorithm();
54 }
55 
56 void QgsTinMeshCreationAlgorithm::initAlgorithm( const QVariantMap &configuration )
57 {
58  Q_UNUSED( configuration );
59  addParameter( new QgsProcessingParameterTinInputLayers( QStringLiteral( "SOURCE_DATA" ), QObject::tr( "Input layers" ) ) );
60 
61  QgsProviderMetadata *meta = QgsProviderRegistry::instance()->providerMetadata( QStringLiteral( "mdal" ) );
62 
63  QList<QgsMeshDriverMetadata> driverList;
64  if ( meta )
65  driverList = meta->meshDriversMetadata();
66 
67  for ( const QgsMeshDriverMetadata &driverMeta : driverList )
68  if ( driverMeta.capabilities() & QgsMeshDriverMetadata::CanWriteMeshData )
69  mAvailableFormat.append( driverMeta.name() );
70 
71  addParameter( new QgsProcessingParameterEnum( QStringLiteral( "MESH_FORMAT" ), QObject::tr( "Output format" ), mAvailableFormat, false, 0 ) );
72  addParameter( new QgsProcessingParameterCrs( QStringLiteral( "CRS_OUTPUT" ), QObject::tr( "Output Coordinate System" ), QVariant(), true ) );
73  addParameter( new QgsProcessingParameterFileDestination( QStringLiteral( "OUTPUT_MESH" ), QObject::tr( "Output File" ) ) );
74 }
75 
76 bool QgsTinMeshCreationAlgorithm::prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
77 {
78  const QVariant layersVariant = parameters.value( parameterDefinition( QStringLiteral( "SOURCE_DATA" ) )->name() );
79  if ( layersVariant.type() != QVariant::List )
80  return false;
81 
82  const QVariantList layersList = layersVariant.toList();
83 
84  QgsCoordinateReferenceSystem destinationCrs = parameterAsCrs( parameters, QStringLiteral( "CRS_OUTPUT" ), context );
85  if ( !destinationCrs.isValid() && context.project() )
86  destinationCrs = context.project()->crs();
87 
88  for ( const QVariant &layer : layersList )
89  {
90  if ( feedback && feedback->isCanceled() )
91  return false;
92 
93  if ( layer.type() != QVariant::Map )
94  continue;
95  const QVariantMap layerMap = layer.toMap();
96  const QString layerSource = layerMap.value( QStringLiteral( "source" ) ).toString();
98  static_cast<QgsProcessingParameterTinInputLayers::Type>( layerMap.value( QStringLiteral( "type" ) ).toInt() );
99  int attributeIndex = layerMap.value( QStringLiteral( "attributeIndex" ) ).toInt();
100 
101  std::unique_ptr<QgsProcessingFeatureSource> featureSource( QgsProcessingUtils::variantToSource( layerSource, context ) );
102 
103  if ( !featureSource )
104  continue;
105 
106  const QgsCoordinateTransform transform( featureSource->sourceCrs(), destinationCrs, context.transformContext() );
107  int featureCount = featureSource->featureCount();
108  switch ( type )
109  {
111  mVerticesLayer.append( {featureSource->getFeatures(), transform, attributeIndex, featureCount} );
112  break;
114  mBreakLinesLayer.append( {featureSource->getFeatures(), transform, attributeIndex, featureCount} );
115  break;
116  default:
117  break;
118  }
119  }
120 
121  if ( mVerticesLayer.isEmpty() && mBreakLinesLayer.isEmpty() )
122  return false;
123 
124  return true;
125 }
126 
127 QVariantMap QgsTinMeshCreationAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
128 {
129  QgsMeshTriangulation triangulation;
130  QgsCoordinateReferenceSystem destinationCrs = parameterAsCrs( parameters, QStringLiteral( "CRS_OUTPUT" ), context );
131  if ( !destinationCrs.isValid() && context.project() )
132  destinationCrs = context.project()->crs();
133  triangulation.setCrs( destinationCrs );
134 
135  if ( !mVerticesLayer.isEmpty() && feedback )
136  feedback->setProgressText( QObject::tr( "Adding vertices layer(s) to the triangulation" ) );
137  for ( Layer &l : mVerticesLayer )
138  {
139  if ( feedback && feedback->isCanceled() )
140  break;
141  triangulation.addVertices( l.fit, l.attributeIndex, l.transform, feedback, l.featureCount );
142  }
143 
144  if ( !mBreakLinesLayer.isEmpty() && feedback )
145  feedback->setProgressText( QObject::tr( "Adding break lines layer(s) to the triangulation" ) );
146  for ( Layer &l : mBreakLinesLayer )
147  {
148  if ( feedback && feedback->isCanceled() )
149  break;
150  triangulation.addBreakLines( l.fit, l.attributeIndex, l.transform, feedback, l.featureCount );
151  }
152 
153  if ( feedback && feedback->isCanceled() )
154  return QVariantMap();
155 
156  const QString fileName = parameterAsFile( parameters, QStringLiteral( "OUTPUT_MESH" ), context );
157  int driverIndex = parameterAsEnum( parameters, QStringLiteral( "MESH_FORMAT" ), context );
158  const QString driver = mAvailableFormat.at( driverIndex );
159  if ( feedback )
160  feedback->setProgressText( QObject::tr( "Creating mesh from triangulation" ) );
161  const QgsMesh mesh = triangulation.triangulatedMesh( feedback );
162 
163  if ( feedback && feedback->isCanceled() )
164  return QVariantMap();
165 
166  const QgsProviderMetadata *providerMetadata = QgsProviderRegistry::instance()->providerMetadata( QStringLiteral( "mdal" ) );
167 
168  if ( feedback )
169  feedback->setProgressText( QObject::tr( "Saving mesh to file" ) );
170  if ( providerMetadata )
171  providerMetadata->createMeshData( mesh, fileName, driver, destinationCrs );
172 
173  context.addLayerToLoadOnCompletion( fileName, QgsProcessingContext::LayerDetails( "TIN Mesh",
174  context.project(),
175  "TIN",
177 
178  //SELAFIN format doesn't support saving Z value on mesh vertices, so create a specific dataset group
179  if ( driver == "SELAFIN" )
180  {
181  addZValueDataset( fileName, mesh, driver );
182  }
183 
184  QVariantMap ret;
185  ret[QStringLiteral( "OUTPUT_MESH" )] = fileName;
186 
187  return ret;
188 }
189 
190 void QgsTinMeshCreationAlgorithm::addZValueDataset( const QString &fileName, const QgsMesh &mesh, const QString &driver )
191 {
192  std::unique_ptr<QgsMeshLayer> tempLayer = qgis::make_unique<QgsMeshLayer>( fileName, "temp", "mdal" );
193  QgsMeshZValueDatasetGroup *zValueDatasetGroup = new QgsMeshZValueDatasetGroup( QObject::tr( "Terrain Elevation" ), mesh );
194  tempLayer->addDatasets( zValueDatasetGroup );
195  int datasetGroupIndex = tempLayer->datasetGroupCount() - 1;
196  tempLayer->saveDataset( fileName, datasetGroupIndex, driver );
197 }
198 
199 bool QgsTinMeshCreationAlgorithm::canExecute( QString *errorMessage ) const
200 {
201  if ( mAvailableFormat.count() == 0 )
202  {
203  *errorMessage = QObject::tr( "MDAL not available" );
204  return false;
205  }
206 
207  return true;
208 }
QgsProcessingFeedback::setProgressText
virtual void setProgressText(const QString &text)
Sets a progress report text string.
Definition: qgsprocessingfeedback.cpp:35
qgsalgorithmtinmeshcreation.h
QgsProcessingParameterTinInputLayers::Type
Type
Defines the type of input layer.
Definition: qgsprocessingparametertininputlayers.h:41
QgsProcessingUtils::variantToSource
static QgsProcessingFeatureSource * variantToSource(const QVariant &value, QgsProcessingContext &context, const QVariant &fallbackValue=QVariant())
Converts a variant value to a new feature source.
Definition: qgsprocessingutils.cpp:349
qgsprocessingparametertininputlayers.h
QgsProcessingContext::project
QgsProject * project() const
Returns the project in which the algorithm is being executed.
Definition: qgsprocessingcontext.h:105
QgsMeshDriverMetadata::CanWriteMeshData
@ CanWriteMeshData
If the driver can write mesh data on file.
Definition: qgsprovidermetadata.h:68
QgsProcessingFeedback
Base class for providing feedback from a processing algorithm.
Definition: qgsprocessingfeedback.h:38
QgsProcessingParameterTinInputLayers
A parameter for processing algorithms that need a list of input vector layers to construct a TIN A va...
Definition: qgsprocessingparametertininputlayers.h:36
qgis.h
QgsMesh
Mesh - vertices, edges and faces.
Definition: qgsmeshdataprovider.h:58
QgsMeshDriverMetadata
Holds metadata about mesh driver.
Definition: qgsprovidermetadata.h:55
QgsProcessingUtils::LayerHint::Mesh
@ Mesh
Mesh layer type, since QGIS 3.6.
qgsprovidermetadata.h
QgsProviderMetadata::createMeshData
virtual bool createMeshData(const QgsMesh &mesh, const QString uri, const QString &driverName, const QgsCoordinateReferenceSystem &crs) const
Creates mesh data source, that is the mesh frame stored in file, memory or with other way (depending ...
Definition: qgsprovidermetadata.cpp:158
qgsproviderregistry.h
QgsProcessingParameterCrs
A coordinate reference system parameter for processing algorithms.
Definition: qgsprocessingparameters.h:1538
QgsProcessingContext
Contains information about the context in which a processing algorithm is executed.
Definition: qgsprocessingcontext.h:44
QgsProcessingParameterFileDestination
A generic file based destination parameter, for specifying the destination path for a file (non-map l...
Definition: qgsprocessingparameters.h:3127
QgsProcessingParameterTinInputLayers::Vertices
@ Vertices
Input that adds only vertices.
Definition: qgsprocessingparametertininputlayers.h:42
QgsCoordinateReferenceSystem::isValid
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
Definition: qgscoordinatereferencesystem.cpp:924
QgsProcessingContext::transformContext
QgsCoordinateTransformContext transformContext() const
Returns the coordinate transform context.
Definition: qgsprocessingcontext.h:149
QgsProviderRegistry::providerMetadata
QgsProviderMetadata * providerMetadata(const QString &providerKey) const
Returns metadata of the provider or nullptr if not found.
Definition: qgsproviderregistry.cpp:724
QgsMeshTriangulation::addBreakLines
bool addBreakLines(QgsFeatureIterator &lineFeatureIterator, int valueAttribute, const QgsCoordinateTransform &transformContext, QgsFeedback *feedback=nullptr, long featureCount=1)
Adds break lines from a vector layer, return true if successful.
Definition: qgsmeshtriangulation.cpp:61
QgsMeshTriangulation::triangulatedMesh
QgsMesh triangulatedMesh(QgsFeedback *feedback=nullptr) const
Returns the triangulated mesh.
Definition: qgsmeshtriangulation.cpp:97
QgsProcessingParameterTinInputLayers::BreakLines
@ BreakLines
Input that adds vertices and break lines.
Definition: qgsprocessingparametertininputlayers.h:44
QgsMeshTriangulation
Class that handles mesh creation with Delaunay constrained triangulation.
Definition: qgsmeshtriangulation.h:42
QgsProcessingContext::LayerDetails
Details for layers to load into projects.
Definition: qgsprocessingcontext.h:231
QgsMeshZValueDatasetGroup
Convenient class that can be used to obtain a datasetgroup on vertices that represents the Z value of...
Definition: qgsmeshtriangulation.h:134
QgsCoordinateReferenceSystem
This class represents a coordinate reference system (CRS).
Definition: qgscoordinatereferencesystem.h:206
QgsProviderMetadata
Holds data provider key, description, and associated shared library file or function pointer informat...
Definition: qgsprovidermetadata.h:137
qgsmeshlayer.h
QgsMeshTriangulation::addVertices
bool addVertices(QgsFeatureIterator &vertexFeatureIterator, int valueAttribute, const QgsCoordinateTransform &transform, QgsFeedback *feedback=nullptr, long featureCount=1)
Adds vertices to the triangulation from a feature iterator, return true if successful.
Definition: qgsmeshtriangulation.cpp:37
QgsFeedback::isCanceled
bool isCanceled() const
Tells whether the operation has been canceled already.
Definition: qgsfeedback.h:53
QgsProcessingContext::addLayerToLoadOnCompletion
void addLayerToLoadOnCompletion(const QString &layer, const QgsProcessingContext::LayerDetails &details)
Adds a layer to load (by ID or datasource) into the canvas upon completion of the algorithm or model.
Definition: qgsprocessingcontext.cpp:53
QgsProcessingAlgorithm
Abstract base class for processing algorithms.
Definition: qgsprocessingalgorithm.h:52
qgsmeshtriangulation.h
QgsMeshTriangulation::setCrs
void setCrs(const QgsCoordinateReferenceSystem &crs)
Sets the coordinate reference system used for the triangulation.
Definition: qgsmeshtriangulation.cpp:102
QgsProcessingParameterEnum
An enum based parameter for processing algorithms, allowing for selection from predefined values.
Definition: qgsprocessingparameters.h:2256
QgsProviderMetadata::meshDriversMetadata
virtual QList< QgsMeshDriverMetadata > meshDriversMetadata()
Builds the list of available mesh drivers metadata.
Definition: qgsprovidermetadata.cpp:78
QgsCoordinateTransform
Class for doing transforms between two map coordinate systems.
Definition: qgscoordinatetransform.h:53
QgsProviderRegistry::instance
static QgsProviderRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.
Definition: qgsproviderregistry.cpp:48
QgsProject::crs
QgsCoordinateReferenceSystem crs
Definition: qgsproject.h:100