26using namespace Qt::StringLiterals;
30QString QgsCoverageCleanAlgorithm::name()
const
32 return u
"coverageclean"_s;
35QString QgsCoverageCleanAlgorithm::displayName()
const
37 return QObject::tr(
"Clean coverage" );
40QStringList QgsCoverageCleanAlgorithm::tags()
const
42 return QObject::tr(
"topological,boundary,repair" ).split(
',' );
45QString QgsCoverageCleanAlgorithm::group()
const
47 return QObject::tr(
"Vector coverage" );
50QString QgsCoverageCleanAlgorithm::groupId()
const
52 return u
"vectorcoverage"_s;
55void QgsCoverageCleanAlgorithm::initAlgorithm(
const QVariantMap & )
58 auto gapWidthParam = std::make_unique<QgsProcessingParameterDistance>( u
"MAXIMUM_GAP_WIDTH"_s, QObject::tr(
"Maximum gap width" ), 0.0, u
"INPUT"_s,
false, 0, 10000000.0 );
59 gapWidthParam->setHelp(
61 "Gaps which are narrower than this distance are merged with an adjacent polygon. Polygon width is determined as twice the radius of the maximum inscribed circle of the gap polygon. Empty holes "
62 "in input polygons are treated as gaps, and may be filled in. Gaps which are not fully enclosed ('inlets') are not removed."
65 auto snappingDistanceParam = std::make_unique<QgsProcessingParameterDistance>( u
"SNAPPING_DISTANCE"_s, QObject::tr(
"Snapping distance" ), QVariant(), u
"INPUT"_s,
true, 0.0, 10000000.0 );
66 snappingDistanceParam->setHelp(
68 "Snapping to nearby vertices and line segment snapping is used to improve noding robustness and eliminate small errors in an efficient way. By default the snapping distance is not set, which "
69 "means that the clean operation uses a very small snapping distance based on the extent of the input data. A distance of zero prevents snapping from being used."
72 auto mergeStrategyParam = std::make_unique<QgsProcessingParameterEnum>(
73 u
"OVERLAP_MERGE_STRATEGY"_s,
74 QObject::tr(
"Overlap merge strategy" ),
75 QStringList() << QObject::tr(
"Longest border" ) << QObject::tr(
"Maximum area" ) << QObject::tr(
"Minimum area" ) << QObject::tr(
"Minimum index" ),
79 mergeStrategyParam->setHelp(
81 "Determines the strategy used to merge gaps with adjacent polygons. Strategies include merging with the polygon sharing the longest border, the polygon with the maximum or minimum area, or the "
82 "first encountered polygon (Minimum Index)."
86 addParameter( gapWidthParam.release() );
87 addParameter( snappingDistanceParam.release() );
88 addParameter( mergeStrategyParam.release() );
93QString QgsCoverageCleanAlgorithm::shortDescription()
const
95 return QObject::tr(
"Cleans a coverage of polygon features to fix cases where the geometries do not exactly align." );
98QString QgsCoverageCleanAlgorithm::shortHelpString()
const
101 "This algorithm operates on a coverage (represented as a list of polygon features) "
102 "to fix cases where the geometry does not in fact exactly match, repairing small "
103 "overlaps and gaps to restore a valid topological coverage.\n\n"
104 "It uses a combination of snapping and gap/overlap merging. Snapping to nearby vertices "
105 "and line segments improves noding robustness and eliminates small errors. If the snapping "
106 "distance is not specified, an automatic distance based on the data extent is used. A distance "
107 "of 0 disables snapping.\n\n"
108 "Gaps and holes that are narrower than the Maximum Gap Width are merged with an adjacent polygon. "
109 "Gaps which are not fully enclosed ('inlets') are not removed.\n\n"
110 "When repairing overlaps and gaps, the Overlap Merge Strategy determines which adjacent "
111 "polygon the problematic area is merged into (e.g., merging with the polygon that shares "
112 "the longest border, or the one with the maximum/minimum area).\n\n"
113 "Polygons that have collapsed during cleaning will be returned as empty polygons."
117QgsCoverageCleanAlgorithm *QgsCoverageCleanAlgorithm::createInstance()
const
119 return new QgsCoverageCleanAlgorithm();
124#if GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR < 14
125 throw QgsProcessingException( QObject::tr(
"This algorithm requires a QGIS build based on GEOS 3.14 or later" ) );
132 std::unique_ptr<QgsProcessingFeatureSource> source( parameterAsSource( parameters, u
"INPUT"_s, context ) );
137 std::unique_ptr<QgsFeatureSink> sink( parameterAsSink( parameters, u
"OUTPUT"_s, context, sinkId, source->fields(), source->wkbType(), source->sourceCrs() ) );
142 QVector<QgsFeature> featuresWithGeom;
143 QVector<QgsFeature> featuresWithoutGeom;
146 const long count = source->featureCount();
149 featuresWithGeom.reserve( count );
153 const double step = count > 0 ? 100.0 / count : 1;
156 feedback->
pushInfo( QObject::tr(
"Collecting features" ) );
169 featuresWithGeom.append( inFeature );
174 featuresWithoutGeom.append( inFeature );
185 if ( parameters.value( u
"SNAPPING_DISTANCE"_s ).isValid() )
187 cleanParameters.
setSnappingDistance( parameterAsDouble( parameters, u
"SNAPPING_DISTANCE"_s, context ) );
189 cleanParameters.
setMaximumGapWidth( parameterAsDouble( parameters, u
"MAXIMUM_GAP_WIDTH"_s, context ) );
190 switch ( parameterAsEnum( parameters, u
"OVERLAP_MERGE_STRATEGY"_s, context ) )
208 feedback->
pushInfo( QObject::tr(
"Cleaning coverage" ) );
209 std::unique_ptr<QgsAbstractGeometry> cleaned;
212 cleaned =
geos.cleanCoverage( cleanParameters, &error, feedback );
221 if ( !error.isEmpty() )
229 feedback->
pushInfo( QObject::tr(
"Storing features" ) );
230 long long featureIndex = 0;
231 for (
auto partsIt = cleaned->const_parts_begin(); partsIt != cleaned->const_parts_end(); ++partsIt )
233 QgsFeature outFeature = featuresWithGeom.value( featureIndex );
240 feedback->
setProgress( featureIndex * step * 0.2 + 80 );
244 for (
const QgsFeature &feature : featuresWithoutGeom )
257 outputs.insert( u
"OUTPUT"_s, sinkId );
@ VectorPolygon
Vector polygon layers.
@ LongestBorder
Polygon with longest common border is selected to merge overlapping polygons into.
@ MaximumArea
Polygon with largest area is selected to merge overlapping polygons into.
@ MinimumArea
Polygon with minimum area is selected to merge overlapping polygons into.
@ MinimumIndex
Polygon with smallest input index is selected to merge overlapping polygons into.
@ SkipGeometryValidityChecks
Invalid geometry checks should always be skipped. This flag can be useful for algorithms which always...
virtual QgsAbstractGeometry * clone() const =0
Clones the geometry by performing a deep copy.
Encapsulates parameters for a coverage cleaning operation.
void setSnappingDistance(double distance)
Sets the snapping distance.
void setOverlapMergeStrategy(Qgis::CoverageCleanOverlapMergeStrategy strategy)
Sets the overlap merge strategy to use during cleaning.
void setMaximumGapWidth(double width)
Sets the maximum gap width.
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.
Wraps a request for features to a vector layer (or directly its vector data provider).
@ 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...
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.
void setProgress(double progress)
Sets the current progress for the feedback object.
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.
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.
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.