QGIS API Documentation 3.99.0-Master (09f76ad7019)
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
20#include "qgis.h"
21#include "qgsfileutils.h"
22#include "qgsmeshlayer.h"
25#include "qgsprovidermetadata.h"
26#include "qgsproviderregistry.h"
27
28#include <QString>
29
30using namespace Qt::StringLiterals;
31
33
34QString QgsTinMeshCreationAlgorithm::group() const
35{
36 return QObject::tr( "Mesh" );
37}
38
39QString QgsTinMeshCreationAlgorithm::groupId() const
40{
41 return u"mesh"_s;
42}
43
44QString QgsTinMeshCreationAlgorithm::shortDescription() const
45{
46 return QObject::tr( "Creates a TIN mesh layer from vector layers." );
47}
48
49QString QgsTinMeshCreationAlgorithm::shortHelpString() const
50{
51 return QObject::tr( "This algorithm creates a TIN mesh layer from vector layers." );
52}
53
54QStringList QgsTinMeshCreationAlgorithm::tags() const
55{
56 return QObject::tr( "tin,mesh,vector,triangulation,irregular,network" ).split( ',' );
57}
58
59QString QgsTinMeshCreationAlgorithm::name() const
60{
61 return u"tinmeshcreation"_s;
62}
63
64QString QgsTinMeshCreationAlgorithm::displayName() const
65{
66 return QObject::tr( "TIN Mesh Creation" );
67}
68
69QgsProcessingAlgorithm *QgsTinMeshCreationAlgorithm::createInstance() const
70{
71 return new QgsTinMeshCreationAlgorithm();
72}
73
74void QgsTinMeshCreationAlgorithm::initAlgorithm( const QVariantMap &configuration )
75{
76 Q_UNUSED( configuration );
77 addParameter( new QgsProcessingParameterTinInputLayers( u"SOURCE_DATA"_s, QObject::tr( "Input layers" ) ) );
78
80
81 QList<QgsMeshDriverMetadata> driverList;
82 if ( meta )
83 driverList = meta->meshDriversMetadata();
84
85 for ( const QgsMeshDriverMetadata &driverMeta : std::as_const( driverList ) )
86 if ( driverMeta.capabilities() & QgsMeshDriverMetadata::CanWriteMeshData )
87 {
88 const QString name = driverMeta.name();
89 mDriverSuffix[name] = driverMeta.writeMeshFrameOnFileSuffix();
90 mAvailableFormat.append( name );
91 }
92
93 addParameter( new QgsProcessingParameterEnum( u"MESH_FORMAT"_s, QObject::tr( "Output format" ), mAvailableFormat, false, 0 ) );
94 addParameter( new QgsProcessingParameterCrs( u"CRS_OUTPUT"_s, QObject::tr( "Output coordinate system" ), QVariant(), true ) );
95 addParameter( new QgsProcessingParameterFileDestination( u"OUTPUT_MESH"_s, QObject::tr( "Output file" ) ) );
96}
97
98bool QgsTinMeshCreationAlgorithm::prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
99{
100 const QVariant layersVariant = parameters.value( parameterDefinition( u"SOURCE_DATA"_s )->name() );
101 if ( layersVariant.userType() != QMetaType::Type::QVariantList )
102 return false;
103
104 const QVariantList layersList = layersVariant.toList();
105
106 QgsCoordinateReferenceSystem destinationCrs = parameterAsCrs( parameters, u"CRS_OUTPUT"_s, context );
107 if ( !destinationCrs.isValid() && context.project() )
108 destinationCrs = context.project()->crs();
109
110 for ( const QVariant &layer : layersList )
111 {
112 if ( feedback && feedback->isCanceled() )
113 return false;
114
115 if ( layer.userType() != QMetaType::Type::QVariantMap )
116 continue;
117 const QVariantMap layerMap = layer.toMap();
118 const QString layerSource = layerMap.value( u"source"_s ).toString();
119 const Qgis::ProcessingTinInputLayerType type = static_cast<Qgis::ProcessingTinInputLayerType>( layerMap.value( u"type"_s ).toInt() );
120 const int attributeIndex = layerMap.value( u"attributeIndex"_s ).toInt();
121
122 std::unique_ptr<QgsProcessingFeatureSource> featureSource( QgsProcessingUtils::variantToSource( layerSource, context ) );
123
124 if ( !featureSource )
125 continue;
126
127 const QgsCoordinateTransform transform( featureSource->sourceCrs(), destinationCrs, context.transformContext() );
128 const long long featureCount = featureSource->featureCount();
129 switch ( type )
130 {
132 mVerticesLayer.append( { featureSource->getFeatures(), transform, attributeIndex, featureCount } );
133 break;
135 mBreakLinesLayer.append( { featureSource->getFeatures(), transform, attributeIndex, featureCount } );
136 break;
137 default:
138 break;
139 }
140 }
141
142 if ( mVerticesLayer.isEmpty() && mBreakLinesLayer.isEmpty() )
143 return false;
144
145 return true;
146}
147
148QVariantMap QgsTinMeshCreationAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
149{
150 QgsMeshTriangulation triangulation;
151 QgsCoordinateReferenceSystem destinationCrs = parameterAsCrs( parameters, u"CRS_OUTPUT"_s, context );
152 if ( !destinationCrs.isValid() && context.project() )
153 destinationCrs = context.project()->crs();
154 triangulation.setCrs( destinationCrs );
155
156 if ( !mVerticesLayer.isEmpty() && feedback )
157 feedback->setProgressText( QObject::tr( "Adding vertices layer(s) to the triangulation" ) );
158 for ( Layer &l : mVerticesLayer )
159 {
160 if ( feedback && feedback->isCanceled() )
161 break;
162 triangulation.addVertices( l.fit, l.attributeIndex, l.transform, feedback, l.featureCount );
163 }
164
165 if ( !mBreakLinesLayer.isEmpty() && feedback )
166 feedback->setProgressText( QObject::tr( "Adding break lines layer(s) to the triangulation" ) );
167 for ( Layer &l : mBreakLinesLayer )
168 {
169 if ( feedback && feedback->isCanceled() )
170 break;
171 triangulation.addBreakLines( l.fit, l.attributeIndex, l.transform, feedback, l.featureCount );
172 }
173
174 if ( feedback && feedback->isCanceled() )
175 return QVariantMap();
176
177 QString fileName = parameterAsFile( parameters, u"OUTPUT_MESH"_s, context );
178 const int driverIndex = parameterAsEnum( parameters, u"MESH_FORMAT"_s, context );
179 const QString driver = mAvailableFormat.at( driverIndex );
180 if ( feedback )
181 feedback->setProgressText( QObject::tr( "Creating mesh from triangulation" ) );
182 const QgsMesh mesh = triangulation.triangulatedMesh( feedback );
183
184 if ( feedback && feedback->isCanceled() )
185 return QVariantMap();
186
187 const QgsProviderMetadata *providerMetadata = QgsProviderRegistry::instance()->providerMetadata( u"mdal"_s );
188
189 fileName = QgsFileUtils::ensureFileNameHasExtension( fileName, QStringList() << mDriverSuffix.value( driver ) );
190
191 if ( feedback )
192 feedback->setProgressText( QObject::tr( "Saving mesh to file" ) );
193 if ( providerMetadata )
194 providerMetadata->createMeshData( mesh, fileName, driver, destinationCrs );
195
197
198 //SELAFIN format doesn't support saving Z value on mesh vertices, so create a specific dataset group
199 if ( driver == "SELAFIN" )
200 {
201 addZValueDataset( fileName, mesh, driver );
202 }
203
204 QVariantMap ret;
205 ret[u"OUTPUT_MESH"_s] = fileName;
206
207 return ret;
208}
209
210void QgsTinMeshCreationAlgorithm::addZValueDataset( const QString &fileName, const QgsMesh &mesh, const QString &driver )
211{
212 auto tempLayer = std::make_unique<QgsMeshLayer>( fileName, "temp", "mdal" );
213 QgsMeshZValueDatasetGroup *zValueDatasetGroup = new QgsMeshZValueDatasetGroup( QObject::tr( "Terrain Elevation" ), mesh );
214 tempLayer->addDatasets( zValueDatasetGroup );
215 const int datasetGroupIndex = tempLayer->datasetGroupCount() - 1;
216 tempLayer->saveDataset( fileName, datasetGroupIndex, driver );
217}
218
219bool QgsTinMeshCreationAlgorithm::canExecute( QString *errorMessage ) const
220{
221 if ( mAvailableFormat.count() == 0 )
222 {
223 *errorMessage = QObject::tr( "MDAL not available" );
224 return false;
225 }
226
227 return true;
228}
229
ProcessingTinInputLayerType
Defines the type of input layer for a Processing TIN input.
Definition qgis.h:3949
@ BreakLines
Input that adds vertices and break lines.
Definition qgis.h:3952
@ Vertices
Input that adds only vertices.
Definition qgis.h:3950
Represents a coordinate reference system (CRS).
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
Handles coordinate transforms between two coordinate systems.
bool isCanceled() const
Tells whether the operation has been canceled already.
Definition qgsfeedback.h:55
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 drivers.
@ CanWriteMeshData
If the driver can write mesh data on file.
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.
Convenience class that can be used to obtain a dataset group on vertices that represents the Z value ...
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:119
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.