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