QGIS API Documentation 3.28.0-Firenze (ed3ad0430f)
qgsalgorithmfixgeometries.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsalgorithmfixgeometries.cpp
3 -----------------------------
4 begin : April 2017
5 copyright : (C) 2017 by Nyall Dawson
6 email : nyall dot dawson 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 "qgsvectorlayer.h"
20
22
23QString QgsFixGeometriesAlgorithm::name() const
24{
25 return QStringLiteral( "fixgeometries" );
26}
27
28QString QgsFixGeometriesAlgorithm::displayName() const
29{
30 return QObject::tr( "Fix geometries" );
31}
32
33QStringList QgsFixGeometriesAlgorithm::tags() const
34{
35 return QObject::tr( "repair,invalid,geometry,make,valid,error" ).split( ',' );
36}
37
38QString QgsFixGeometriesAlgorithm::group() const
39{
40 return QObject::tr( "Vector geometry" );
41}
42
43QString QgsFixGeometriesAlgorithm::groupId() const
44{
45 return QStringLiteral( "vectorgeometry" );
46}
47
48QgsProcessingFeatureSource::Flag QgsFixGeometriesAlgorithm::sourceFlags() const
49{
51}
52
53QString QgsFixGeometriesAlgorithm::outputName() const
54{
55 return QObject::tr( "Fixed geometries" );
56}
57
58QgsWkbTypes::Type QgsFixGeometriesAlgorithm::outputWkbType( QgsWkbTypes::Type type ) const
59{
61}
62
63QString QgsFixGeometriesAlgorithm::shortHelpString() const
64{
65 return QObject::tr( "This algorithm attempts to create a valid representation of a given invalid geometry without "
66 "losing any of the input vertices. Already-valid geometries are returned without further intervention. "
67 "Always outputs multi-geometry layer.\n\n"
68 "NOTE: M values will be dropped from the output." );
69}
70
71QgsFixGeometriesAlgorithm *QgsFixGeometriesAlgorithm::createInstance() const
72{
73 return new QgsFixGeometriesAlgorithm();
74}
75
76bool QgsFixGeometriesAlgorithm::supportInPlaceEdit( const QgsMapLayer *l ) const
77{
78 const QgsVectorLayer *layer = qobject_cast< const QgsVectorLayer * >( l );
79 if ( !layer )
80 return false;
81
83 return false;
84 // The algorithm would drop M, so disable it if the layer has M
85 return ! QgsWkbTypes::hasM( layer->wkbType() );
86}
87
88void QgsFixGeometriesAlgorithm::initParameters( const QVariantMap & )
89{
90 std::unique_ptr< QgsProcessingParameterEnum> methodParameter = std::make_unique< QgsProcessingParameterEnum >(
91 QStringLiteral( "METHOD" ),
92 QObject::tr( "Repair method" ),
93 QStringList{ QObject::tr( "Linework" ), QObject::tr( "Structure" ) },
94 0,
95 false );
96#if GEOS_VERSION_MAJOR==3 && GEOS_VERSION_MINOR<10
97 methodParameter->setDefaultValue( 0 );
98#else
99 methodParameter->setDefaultValue( 1 );
100#endif
101 addParameter( methodParameter.release() );
102}
103
104bool QgsFixGeometriesAlgorithm::prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback * )
105{
106 mMethod = static_cast< Qgis::MakeValidMethod>( parameterAsInt( parameters, QStringLiteral( "METHOD" ), context ) );
107#if GEOS_VERSION_MAJOR==3 && GEOS_VERSION_MINOR<10
108 if ( mMethod == Qgis::MakeValidMethod::Structure )
109 {
110 throw QgsProcessingException( "The structured method to make geometries valid requires a QGIS build based on GEOS 3.10 or later" );
111 }
112#endif
113 return true;
114}
115
116QgsFeatureList QgsFixGeometriesAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingContext &, QgsProcessingFeedback *feedback )
117{
118 if ( !feature.hasGeometry() )
119 return QgsFeatureList() << feature;
120
121 QgsFeature outputFeature = feature;
122
123 QgsGeometry outputGeometry = outputFeature.geometry().makeValid( mMethod );
124 if ( outputGeometry.isNull() )
125 {
126 feedback->pushInfo( QObject::tr( "makeValid failed for feature %1 " ).arg( feature.id() ) );
127 outputFeature.clearGeometry();
128 return QgsFeatureList() << outputFeature;
129 }
130
131 if ( outputGeometry.wkbType() == QgsWkbTypes::Unknown ||
133 {
134 // keep only the parts of the geometry collection with correct type
135 const QVector< QgsGeometry > tmpGeometries = outputGeometry.asGeometryCollection();
136 QVector< QgsGeometry > matchingParts;
137 for ( const QgsGeometry &g : tmpGeometries )
138 {
139 if ( g.type() == feature.geometry().type() )
140 matchingParts << g;
141 }
142 if ( !matchingParts.empty() )
143 outputGeometry = QgsGeometry::collectGeometry( matchingParts );
144 else
145 outputGeometry = QgsGeometry();
146 }
147
148 if ( outputGeometry.type() != QgsWkbTypes::GeometryType::PointGeometry )
149 {
150 // some data providers are picky about the geometries we pass to them: we can't add single-part geometries
151 // when we promised multi-part geometries, so ensure we have the right type
152 outputGeometry.convertToMultiType();
153 }
154
155 if ( QgsWkbTypes::geometryType( outputGeometry.wkbType() ) != QgsWkbTypes::geometryType( feature.geometry().wkbType() ) )
156 {
157 // don't keep geometries which have different types - e.g. lines converted to points
158 feedback->pushInfo( QObject::tr( "Fixing geometry for feature %1 resulted in %2, geometry has been dropped." ).arg( feature.id() ).arg( QgsWkbTypes::displayString( outputGeometry.wkbType() ) ) );
159 outputFeature.clearGeometry();
160 }
161 else
162 {
163 outputFeature.setGeometry( outputGeometry );
164 }
165 return QgsFeatureList() << outputFeature;
166}
167
MakeValidMethod
Algorithms to use when repairing invalid geometries.
Definition: qgis.h:1046
@ Structure
Structured method, first makes all rings valid and then merges shells and subtracts holes from shells...
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition: qgsfeature.h:56
QgsGeometry geometry
Definition: qgsfeature.h:67
void clearGeometry()
Removes any geometry associated with the feature.
Definition: qgsfeature.cpp:184
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Definition: qgsfeature.cpp:233
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
Definition: qgsfeature.cpp:170
Q_GADGET QgsFeatureId id
Definition: qgsfeature.h:64
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:164
QgsWkbTypes::Type wkbType() const SIP_HOLDGIL
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
static QgsGeometry collectGeometry(const QVector< QgsGeometry > &geometries)
Creates a new multipart geometry from a list of QgsGeometry objects.
QVector< QgsGeometry > asGeometryCollection() const
Returns contents of the geometry as a list of geometries.
Q_GADGET bool isNull
Definition: qgsgeometry.h:166
QgsWkbTypes::GeometryType type
Definition: qgsgeometry.h:167
QgsGeometry makeValid(Qgis::MakeValidMethod method=Qgis::MakeValidMethod::Linework, bool keepCollapsed=false) const SIP_THROW(QgsNotSupportedException)
Attempts to make an invalid geometry valid without losing vertices.
bool convertToMultiType()
Converts single type geometry into multitype geometry e.g.
Base class for all map layer types.
Definition: qgsmaplayer.h:73
Contains information about the context in which a processing algorithm is executed.
Custom exception class for processing related exceptions.
Definition: qgsexception.h:83
bool supportInPlaceEdit(const QgsMapLayer *layer) const override
Checks whether this algorithm supports in-place editing on the given layer Default implementation for...
Flag
Flags controlling how QgsProcessingFeatureSource fetches features.
@ FlagSkipGeometryValidityChecks
Invalid geometry checks should always be skipped. This flag can be useful for algorithms which always...
Base class for providing feedback from a processing algorithm.
virtual void pushInfo(const QString &info)
Pushes a general informational message from the algorithm.
Represents a vector layer which manages a vector based data sets.
Q_INVOKABLE QgsWkbTypes::Type wkbType() const FINAL
Returns the WKBType or WKBUnknown in case of error.
bool isSpatial() const FINAL
Returns true if this is a geometry layer and false in case of NoGeometry (table only) or UnknownGeome...
static GeometryType geometryType(Type type) SIP_HOLDGIL
Returns the geometry type for a WKB type, e.g., both MultiPolygon and CurvePolygon would have a Polyg...
Definition: qgswkbtypes.h:968
static Type promoteNonPointTypesToMulti(Type type) SIP_HOLDGIL
Promotes a WKB geometry type to its multi-type equivalent, with the exception of point geometry types...
Definition: qgswkbtypes.h:451
static bool hasM(Type type) SIP_HOLDGIL
Tests whether a WKB type contains m values.
Definition: qgswkbtypes.h:1130
Type
The WKB type describes the number of dimensions a geometry has.
Definition: qgswkbtypes.h:70
@ GeometryCollection
Definition: qgswkbtypes.h:79
static QString displayString(Type type) SIP_HOLDGIL
Returns a non-translated display string type for a WKB type, e.g., the geometry name used in WKT geom...
static Type flatType(Type type) SIP_HOLDGIL
Returns the flat type for a WKB type.
Definition: qgswkbtypes.h:732
QList< QgsFeature > QgsFeatureList
Definition: qgsfeature.h:922