QGIS API Documentation 4.3.0-Master (ffcfc20b9b4)
Loading...
Searching...
No Matches
qgsalgorithmcoveragevalidate.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsalgorithmcoveragevalidate.cpp
3 ---------------------
4 begin : October 2023
5 copyright : (C) 2023 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
18
20
22#include "qgsgeos.h"
24
25#include <QString>
26
27using namespace Qt::StringLiterals;
28
30
31QString QgsCoverageValidateAlgorithm::name() const
32{
33 return u"coveragevalidate"_s;
34}
35
36QString QgsCoverageValidateAlgorithm::displayName() const
37{
38 return QObject::tr( "Validate coverage" );
39}
40
41QStringList QgsCoverageValidateAlgorithm::tags() const
42{
43 return QObject::tr( "validity,overlaps,gaps,topological,boundary" ).split( ',' );
44}
45
46QString QgsCoverageValidateAlgorithm::group() const
47{
48 return QObject::tr( "Vector coverage" );
49}
50
51QString QgsCoverageValidateAlgorithm::groupId() const
52{
53 return u"vectorcoverage"_s;
54}
55
56void QgsCoverageValidateAlgorithm::initAlgorithm( const QVariantMap & )
57{
58 addParameter( new QgsProcessingParameterFeatureSource( u"INPUT"_s, QObject::tr( "Input layer" ), QList<int>() << static_cast<int>( Qgis::ProcessingSourceType::VectorPolygon ) ) );
59 auto gapWidthParam = std::make_unique<QgsProcessingParameterDistance>( u"GAP_WIDTH"_s, QObject::tr( "Gap width" ), 0.0, u"INPUT"_s, false, 0, 10000000.0 );
60 gapWidthParam->setHelp( QObject::tr( "The maximum width of gaps to detect" ) );
61 addParameter( gapWidthParam.release() );
62
63 addParameter( new QgsProcessingParameterFeatureSink( u"INVALID_EDGES"_s, QObject::tr( "Invalid edges" ), Qgis::ProcessingSourceType::VectorLine, QVariant(), true, true ) );
64 addOutput( new QgsProcessingOutputBoolean( u"IS_VALID"_s, QObject::tr( "Coverage is valid" ) ) );
65}
66
67QString QgsCoverageValidateAlgorithm::shortDescription() const
68{
69 return QObject::tr( "Analyzes a coverage of polygon features to find places where the assumption of exactly matching edges is not met." );
70}
71
72QString QgsCoverageValidateAlgorithm::shortHelpString() const
73{
74 return QObject::tr(
75 "This algorithm analyzes a coverage (represented as a set of polygon features "
76 "with exactly matching edge geometry) to find places where the "
77 "assumption of exactly matching edges is not met.\n\n"
78 "Invalidity includes polygons that overlap "
79 "or that have gaps smaller than the specified gap width."
80 );
81}
82
83QgsCoverageValidateAlgorithm *QgsCoverageValidateAlgorithm::createInstance() const
84{
85 return new QgsCoverageValidateAlgorithm();
86}
87
88QVariantMap QgsCoverageValidateAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
89{
90 QGS_MARK_ALGORITHM_SOURCE
91
92 std::unique_ptr<QgsProcessingFeatureSource> source( parameterAsSource( parameters, u"INPUT"_s, context ) );
93 if ( !source )
94 throw QgsProcessingException( invalidSourceError( parameters, u"INPUT"_s ) );
95
96 const double gapWidth = parameterAsDouble( parameters, u"GAP_WIDTH"_s, context );
97
98 QString sinkId;
99 std::unique_ptr<QgsFeatureSink> sink( parameterAsSink( parameters, u"INVALID_EDGES"_s, context, sinkId, QgsFields(), Qgis::WkbType::LineString, source->sourceCrs() ) );
100 if ( !sink && parameters.value( u"INVALID_EDGES"_s ).isValid() )
101 throw QgsProcessingException( invalidSinkError( parameters, u"INVALID_EDGES"_s ) );
102
103 QgsGeometryCollection collection;
104
105 const long count = source->featureCount();
106 if ( count > 0 )
107 {
108 collection.reserve( count );
109 }
110
111 const double step = count > 0 ? 100.0 / count : 1;
112 int current = 0;
113
114 feedback->pushInfo( QObject::tr( "Collecting features" ) );
115
116 QgsFeature inFeature;
117 QgsFeatureIterator features = source->getFeatures();
118 while ( features.nextFeature( inFeature ) )
119 {
120 if ( feedback->isCanceled() )
121 {
122 break;
123 }
124
125 if ( inFeature.hasGeometry() )
126 {
127 collection.addGeometry( inFeature.geometry().constGet()->clone() );
128 }
129
130 feedback->setProgress( current * step * 0.2 );
131 current++;
132 }
133
134 feedback->pushInfo( QObject::tr( "Validating coverage" ) );
135
136 QgsGeos geos( &collection );
137 QString error;
138 std::unique_ptr<QgsAbstractGeometry> invalidEdges;
140 try
141 {
142 result = geos.validateCoverage( gapWidth, &invalidEdges, &error );
143 }
144 catch ( QgsNotSupportedException &e )
145 {
146 throw QgsProcessingException( e.what() );
147 }
148
149 switch ( result )
150 {
152 feedback->reportError( QObject::tr( "Coverage is not valid" ) );
153 if ( invalidEdges )
154 {
155 if ( sink )
156 {
157 for ( auto partsIt = invalidEdges->const_parts_begin(); partsIt != invalidEdges->const_parts_end(); ++partsIt )
158 {
159 QgsFeature outFeature;
160 outFeature.setGeometry( QgsGeometry( *partsIt ? ( *partsIt )->clone() : nullptr ) );
161 if ( !sink->addFeature( outFeature, QgsFeatureSink::FastInsert ) )
162 throw QgsProcessingException( writeFeatureError( sink.get(), parameters, u"OUTPUT"_s ) );
163 else
164 feedback->featureAddedToSink( u"OUTPUT"_s );
165 }
166 }
167 }
168 break;
170 feedback->pushInfo( QObject::tr( "Coverage is valid" ) );
171 break;
173 if ( !error.isEmpty() )
174 throw QgsProcessingException( QObject::tr( "An error occurred validating coverage: %1" ).arg( error ) );
175 else
176 throw QgsProcessingException( QObject::tr( "An error occurred validating coverage" ) );
177 }
178
179 feedback->setProgress( 100 );
180 if ( sink )
181 {
182 sink->finalize();
183 feedback->featureSinkFinalized( u"OUTPUT"_s );
184 }
185
186 QVariantMap outputs;
187 outputs.insert( u"OUTPUT"_s, sinkId );
188 outputs.insert( u"IS_VALID"_s, result == Qgis::CoverageValidityResult::Valid );
189 return outputs;
190}
191
@ VectorPolygon
Vector polygon layers.
Definition qgis.h:3752
@ VectorLine
Vector line layers.
Definition qgis.h:3751
CoverageValidityResult
Coverage validity results.
Definition qgis.h:2331
@ Valid
Coverage is valid.
Definition qgis.h:2333
@ Invalid
Coverage is invalid. Invalidity includes polygons that overlap, that have gaps smaller than the gap w...
Definition qgis.h:2332
@ Error
An exception occurred while determining validity.
Definition qgis.h:2334
@ LineString
LineString.
Definition qgis.h:297
virtual QgsAbstractGeometry * clone() const =0
Clones the geometry by performing a deep copy.
QString what() const
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
Fetch next feature and stores in f, returns true on success.
@ FastInsert
Use faster inserts, at the cost of updating the passed features to reflect changes made at the provid...
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition qgsfeature.h:60
QgsGeometry geometry
Definition qgsfeature.h:66
bool hasGeometry() const
Returns true if the feature has an associated geometry.
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
bool isCanceled() const
Tells whether the operation has been canceled already.
Definition qgsfeedback.h:56
void setProgress(double progress)
Sets the current progress for the feedback object.
Definition qgsfeedback.h:65
Container of fields for a vector layer.
Definition qgsfields.h:45
void reserve(int size)
Attempts to allocate memory for at least size geometries.
virtual bool addGeometry(QgsAbstractGeometry *g)
Adds a geometry and takes ownership. Returns true in case of success.
A geometry is the spatial representation of a feature.
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
Does vector analysis using the GEOS library and handles import, export, and exception handling.
Definition qgsgeos.h:175
Custom exception class which is raised when an operation is not supported.
Contains information about the context in which a processing algorithm is executed.
Custom exception class for processing related exceptions.
Base class for providing feedback from a processing algorithm.
void featureAddedToSink(const QString &output)
Reports that a feature was added to the the sink associated with the specified algorithm output.
virtual void pushInfo(const QString &info)
Pushes a general informational message from the algorithm.
void featureSinkFinalized(const QString &output)
Reports that a feature sink has been finalized.
virtual void reportError(const QString &error, bool fatalError=false)
Reports that the algorithm encountered an error while executing.
A boolean output for processing algorithms.
A feature sink output for processing algorithms.
An input feature source (such as vector layers) parameter for processing algorithms.
Contains geos related utilities and functions.
Definition qgsgeos.h:112