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