27using namespace Qt::StringLiterals;
31QString QgsCoverageCleanAlgorithm::name()
const
33 return u
"coverageclean"_s;
36QString QgsCoverageCleanAlgorithm::displayName()
const
38 return QObject::tr(
"Clean coverage" );
41QStringList QgsCoverageCleanAlgorithm::tags()
const
43 return QObject::tr(
"topological,boundary,repair" ).split(
',' );
46QString QgsCoverageCleanAlgorithm::group()
const
48 return QObject::tr(
"Vector coverage" );
51QString QgsCoverageCleanAlgorithm::groupId()
const
53 return u
"vectorcoverage"_s;
56void QgsCoverageCleanAlgorithm::initAlgorithm(
const QVariantMap & )
59 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 );
60 gapWidthParam->setHelp(
62 "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 "
63 "in input polygons are treated as gaps, and may be filled in. Gaps which are not fully enclosed ('inlets') are not removed."
66 auto snappingDistanceParam = std::make_unique<QgsProcessingParameterDistance>( u
"SNAPPING_DISTANCE"_s, QObject::tr(
"Snapping distance" ), QVariant(), u
"INPUT"_s,
true, 0.0, 10000000.0 );
67 snappingDistanceParam->setHelp(
69 "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 "
70 "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."
73 auto mergeStrategyParam = std::make_unique<QgsProcessingParameterEnum>(
74 u
"OVERLAP_MERGE_STRATEGY"_s,
75 QObject::tr(
"Overlap merge strategy" ),
76 QStringList() << QObject::tr(
"Longest border" ) << QObject::tr(
"Maximum area" ) << QObject::tr(
"Minimum area" ) << QObject::tr(
"Minimum index" ),
80 mergeStrategyParam->setHelp(
82 "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 "
83 "first encountered polygon (Minimum Index)."
87 addParameter( gapWidthParam.release() );
88 addParameter( snappingDistanceParam.release() );
89 addParameter( mergeStrategyParam.release() );
94QString QgsCoverageCleanAlgorithm::shortDescription()
const
96 return QObject::tr(
"Cleans a coverage of polygon features to fix cases where the geometries do not exactly align." );
99QString QgsCoverageCleanAlgorithm::shortHelpString()
const
102 "This algorithm operates on a coverage (represented as a list of polygon features) "
103 "to fix cases where the geometry does not in fact exactly match, repairing small "
104 "overlaps and gaps to restore a valid topological coverage.\n\n"
105 "It uses a combination of snapping and gap/overlap merging. Snapping to nearby vertices "
106 "and line segments improves noding robustness and eliminates small errors. If the snapping "
107 "distance is not specified, an automatic distance based on the data extent is used. A distance "
108 "of 0 disables snapping.\n\n"
109 "Gaps and holes that are narrower than the Maximum Gap Width are merged with an adjacent polygon. "
110 "Gaps which are not fully enclosed ('inlets') are not removed.\n\n"
111 "When repairing overlaps and gaps, the Overlap Merge Strategy determines which adjacent "
112 "polygon the problematic area is merged into (e.g., merging with the polygon that shares "
113 "the longest border, or the one with the maximum/minimum area).\n\n"
114 "Polygons that have collapsed during cleaning will be returned as empty polygons."
118QgsCoverageCleanAlgorithm *QgsCoverageCleanAlgorithm::createInstance()
const
120 return new QgsCoverageCleanAlgorithm();
125#if GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR < 14
126 throw QgsProcessingException( QObject::tr(
"This algorithm requires a QGIS build based on GEOS 3.14 or later" ) );
133 QGS_MARK_ALGORITHM_SOURCE
135 std::unique_ptr<QgsProcessingFeatureSource> source( parameterAsSource( parameters, u
"INPUT"_s, context ) );
140 std::unique_ptr<QgsFeatureSink> sink( parameterAsSink( parameters, u
"OUTPUT"_s, context, sinkId, source->fields(), source->wkbType(), source->sourceCrs() ) );
145 QVector<QgsFeature> featuresWithGeom;
146 QVector<QgsFeature> featuresWithoutGeom;
149 const long count = source->featureCount();
152 featuresWithGeom.reserve( count );
156 const double step = count > 0 ? 100.0 / count : 1;
159 feedback->
pushInfo( QObject::tr(
"Collecting features" ) );
172 featuresWithGeom.append( inFeature );
177 featuresWithoutGeom.append( inFeature );
188 if ( parameters.value( u
"SNAPPING_DISTANCE"_s ).isValid() )
190 cleanParameters.
setSnappingDistance( parameterAsDouble( parameters, u
"SNAPPING_DISTANCE"_s, context ) );
192 cleanParameters.
setMaximumGapWidth( parameterAsDouble( parameters, u
"MAXIMUM_GAP_WIDTH"_s, context ) );
193 switch ( parameterAsEnum( parameters, u
"OVERLAP_MERGE_STRATEGY"_s, context ) )
211 feedback->
pushInfo( QObject::tr(
"Cleaning coverage" ) );
212 std::unique_ptr<QgsAbstractGeometry> cleaned;
215 cleaned =
geos.cleanCoverage( cleanParameters, &error, feedback );
224 if ( !error.isEmpty() )
232 feedback->
pushInfo( QObject::tr(
"Storing features" ) );
233 long long featureIndex = 0;
234 for (
auto partsIt = cleaned->const_parts_begin(); partsIt != cleaned->const_parts_end(); ++partsIt )
236 QgsFeature outFeature = featuresWithGeom.value( featureIndex );
243 feedback->
setProgress( featureIndex * step * 0.2 + 80 );
247 for (
const QgsFeature &feature : featuresWithoutGeom )
260 outputs.insert( u
"OUTPUT"_s, sinkId );
264bool QgsCoverageCleanAlgorithm::supportInPlaceEdit(
const QgsMapLayer *layer )
const
266 const QgsVectorLayer *vlayer = qobject_cast<const QgsVectorLayer *>( layer );
@ 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.
QFlags< ProcessingAlgorithmFlag > ProcessingAlgorithmFlags
Flags indicating how and when an algorithm operates and should be exposed to users.
@ SkipGeometryValidityChecks
Invalid geometry checks should always be skipped. This flag can be useful for algorithms which always...
@ SupportsInPlaceEdits
Algorithm supports in-place editing.
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.
Base class for all map layer types.
Custom exception class which is raised when an operation is not supported.
virtual Qgis::ProcessingAlgorithmFlags flags() const
Returns the flags indicating how and when the algorithm operates and should be exposed to users.
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.
Represents a vector layer which manages a vector based dataset.
Q_INVOKABLE Qgis::GeometryType geometryType() const
Returns point, line or polygon.
Contains geos related utilities and functions.