QGIS API Documentation 3.99.0-Master (357b655ed83)
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( "This algorithm analyzes a coverage (represented as a set of polygon features "
75 "with exactly matching edge geometry) to find places where the "
76 "assumption of exactly matching edges is not met.\n\n"
77 "Invalidity includes polygons that overlap "
78 "or that have gaps smaller than the specified gap width." );
79}
80
81QgsCoverageValidateAlgorithm *QgsCoverageValidateAlgorithm::createInstance() const
82{
83 return new QgsCoverageValidateAlgorithm();
84}
85
86QVariantMap QgsCoverageValidateAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
87{
88 std::unique_ptr<QgsProcessingFeatureSource> source( parameterAsSource( parameters, u"INPUT"_s, context ) );
89 if ( !source )
90 throw QgsProcessingException( invalidSourceError( parameters, u"INPUT"_s ) );
91
92 const double gapWidth = parameterAsDouble( parameters, u"GAP_WIDTH"_s, context );
93
94 QString sinkId;
95 std::unique_ptr<QgsFeatureSink> sink( parameterAsSink( parameters, u"INVALID_EDGES"_s, context, sinkId, QgsFields(), Qgis::WkbType::LineString, source->sourceCrs() ) );
96 if ( !sink && parameters.value( u"INVALID_EDGES"_s ).isValid() )
97 throw QgsProcessingException( invalidSinkError( parameters, u"INVALID_EDGES"_s ) );
98
99 QgsGeometryCollection collection;
100
101 const long count = source->featureCount();
102 if ( count > 0 )
103 {
104 collection.reserve( count );
105 }
106
107 const double step = count > 0 ? 100.0 / count : 1;
108 int current = 0;
109
110 feedback->pushInfo( QObject::tr( "Collecting features" ) );
111
112 QgsFeature inFeature;
113 QgsFeatureIterator features = source->getFeatures();
114 while ( features.nextFeature( inFeature ) )
115 {
116 if ( feedback->isCanceled() )
117 {
118 break;
119 }
120
121 if ( inFeature.hasGeometry() )
122 {
123 collection.addGeometry( inFeature.geometry().constGet()->clone() );
124 }
125
126 feedback->setProgress( current * step * 0.2 );
127 current++;
128 }
129
130 feedback->pushInfo( QObject::tr( "Validating coverage" ) );
131
132 QgsGeos geos( &collection );
133 QString error;
134 std::unique_ptr<QgsAbstractGeometry> invalidEdges;
136 try
137 {
138 result = geos.validateCoverage( gapWidth, &invalidEdges, &error );
139 }
140 catch ( QgsNotSupportedException &e )
141 {
142 throw QgsProcessingException( e.what() );
143 }
144
145 switch ( result )
146 {
148 feedback->reportError( QObject::tr( "Coverage is not valid" ) );
149 if ( invalidEdges )
150 {
151 if ( sink )
152 {
153 for ( auto partsIt = invalidEdges->const_parts_begin(); partsIt != invalidEdges->const_parts_end(); ++partsIt )
154 {
155 QgsFeature outFeature;
156 outFeature.setGeometry( QgsGeometry( *partsIt ? ( *partsIt )->clone() : nullptr ) );
157 if ( !sink->addFeature( outFeature, QgsFeatureSink::FastInsert ) )
158 throw QgsProcessingException( writeFeatureError( sink.get(), parameters, u"OUTPUT"_s ) );
159 }
160 }
161 }
162 break;
164 feedback->pushInfo( QObject::tr( "Coverage is valid" ) );
165 break;
167 if ( !error.isEmpty() )
168 throw QgsProcessingException( QObject::tr( "An error occurred validating coverage: %1" ).arg( error ) );
169 else
170 throw QgsProcessingException( QObject::tr( "An error occurred validating coverage" ) );
171 }
172
173 feedback->setProgress( 100 );
174 if ( sink )
175 sink->finalize();
176
177 QVariantMap outputs;
178 outputs.insert( u"OUTPUT"_s, sinkId );
179 outputs.insert( u"IS_VALID"_s, result == Qgis::CoverageValidityResult::Valid );
180 return outputs;
181}
182
@ VectorPolygon
Vector polygon layers.
Definition qgis.h:3607
@ VectorLine
Vector line layers.
Definition qgis.h:3606
CoverageValidityResult
Coverage validity results.
Definition qgis.h:2225
@ Valid
Coverage is valid.
Definition qgis.h:2227
@ Invalid
Coverage is invalid. Invalidity includes polygons that overlap, that have gaps smaller than the gap w...
Definition qgis.h:2226
@ Error
An exception occurred while determining validity.
Definition qgis.h:2228
@ LineString
LineString.
Definition qgis.h:283
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:71
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:55
void setProgress(double progress)
Sets the current progress for the feedback object.
Definition qgsfeedback.h:63
Container of fields for a vector layer.
Definition qgsfields.h:46
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:141
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.
virtual void pushInfo(const QString &info)
Pushes a general informational message from the algorithm.
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:77