QGIS API Documentation 4.1.0-Master (376402f9aeb)
Loading...
Searching...
No Matches
qgsalgorithmconcavehullofpolygons.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsalgorithmconcavehullofpolygons.cpp
3 ---------------------
4 begin : March 2026
5 copyright : (C) 2026 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 <QString>
21
22using namespace Qt::StringLiterals;
23
25
26QString QgsConcaveHullOfPolygonsAlgorithm::name() const
27{
28 return u"tightconcavehullofpolygons"_s;
29}
30
31QString QgsConcaveHullOfPolygonsAlgorithm::displayName() const
32{
33 return QObject::tr( "Fill gaps between polygons" );
34}
35
36QStringList QgsConcaveHullOfPolygonsAlgorithm::tags() const
37{
38 return QObject::tr( "concave,hull,bounds,bounding,convex,multipolygons,boundary,fill,holes,between,space,tight,strict" ).split( ',' );
39}
40
41QString QgsConcaveHullOfPolygonsAlgorithm::group() const
42{
43 return QObject::tr( "Vector geometry" );
44}
45
46QString QgsConcaveHullOfPolygonsAlgorithm::groupId() const
47{
48 return u"vectorgeometry"_s;
49}
50
51QString QgsConcaveHullOfPolygonsAlgorithm::outputName() const
52{
53 return QObject::tr( "Tight concave hulls" );
54}
55
56QString QgsConcaveHullOfPolygonsAlgorithm::shortHelpString() const
57{
58 return QObject::tr( "This algorithm calculates a concave hull for each multi-polygon feature in an input layer." )
59 + u"\n\n"_s
60 + QObject::tr(
61 "Unlike the standard Concave Hull algorithm, a tight concave hull is a (possibly) non-convex polygon containing all the input polygons. The computed hull fills the gaps between the "
62 "polygons without intersecting their interiors. It strictly follows the outer boundaries of the input polygons, allowing you to fill gaps between them without distorting their original "
63 "shapes."
64 )
65 + u"\n\n"_s
66 + QObject::tr(
67 "It is particularly useful for cases such as generalizing groups of building outlines, creating 'district' polygons around blocks, or removing gaps and joining disjoint sets of polygons."
68 )
69 + u"\n\n"_s
70 + QObject::tr( "The algorithm works by creating a constrained Delaunay Triangulation of the space between the polygons and removing the longest outer edges until a target criterion is reached." )
71 + u"\n\n"_s
72 + QObject::tr( "The input geometry must be a valid Polygon or MultiPolygon (i.e., the individual polygons must not overlap)." );
73}
74
75QString QgsConcaveHullOfPolygonsAlgorithm::shortDescription() const
76{
77 return QObject::tr( "Constructs a tight concave hull for a set of polygons, filling gaps between them while strictly preserving their original outer boundaries." );
78}
79
80QgsConcaveHullOfPolygonsAlgorithm *QgsConcaveHullOfPolygonsAlgorithm::createInstance() const
81{
82 return new QgsConcaveHullOfPolygonsAlgorithm();
83}
84
85void QgsConcaveHullOfPolygonsAlgorithm::initParameters( const QVariantMap & )
86{
87 auto ratioParam
88 = std::make_unique<QgsProcessingParameterNumber>( u"RATIO"_s, QObject::tr( "Ratio (0-1, where 1 is equivalent with Convex Hull)" ), Qgis::ProcessingNumberParameterType::Double, 0.3, false, 0, 1 );
89 ratioParam->setHelp(
90 QObject::tr(
91 "Specifies the maximum edge length as a fraction of the difference between the longest and shortest edge lengths between the polygons. This normalizes the maximum edge length to be scale-free. "
92 "A value of 1 produces the convex hull; a value of 0 produces the original polygons."
93 )
94 );
95 addParameter( ratioParam.release() );
96
97 auto holesParam = std::make_unique<QgsProcessingParameterBoolean>( u"HOLES"_s, QObject::tr( "Allow holes" ), true );
98 holesParam->setHelp( QObject::tr( "Controls whether the computed concave hull is allowed to contain holes." ) );
99 addParameter( holesParam.release() );
100}
101
102QList<int> QgsConcaveHullOfPolygonsAlgorithm::inputLayerTypes() const
103{
104 return QList<int>() << static_cast<int>( Qgis::ProcessingSourceType::VectorPolygon );
105}
106
107QgsFields QgsConcaveHullOfPolygonsAlgorithm::outputFields( const QgsFields &inputFields ) const
108{
109 QgsFields newFields;
110 newFields.append( QgsField( u"area"_s, QMetaType::Type::Double, QString(), 20, 6 ) );
111 newFields.append( QgsField( u"perimeter"_s, QMetaType::Type::Double, QString(), 20, 6 ) );
112 return QgsProcessingUtils::combineFields( inputFields, newFields );
113}
114
115bool QgsConcaveHullOfPolygonsAlgorithm::prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback * )
116{
117#if GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR < 11
118 throw QgsProcessingException( QObject::tr( "This algorithm requires a QGIS build based on GEOS 3.11 or later" ) );
119#endif
120 mPercentage = parameterAsDouble( parameters, u"RATIO"_s, context );
121 mAllowHoles = parameterAsBool( parameters, u"HOLES"_s, context );
122 return true;
123}
124
125QgsFeatureList QgsConcaveHullOfPolygonsAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingContext &, QgsProcessingFeedback *feedback )
126{
127 QgsFeature f = feature;
128 if ( f.hasGeometry() )
129 {
130 QgsGeometry outputGeometry;
131 outputGeometry = f.geometry().concaveHullOfPolygons( mPercentage, mAllowHoles, true );
132 if ( outputGeometry.isNull() && !outputGeometry.lastError().isEmpty() )
133 feedback->reportError( outputGeometry.lastError() );
134 f.setGeometry( outputGeometry );
135
136 if ( outputGeometry.type() == Qgis::GeometryType::Polygon )
137 {
138 QgsAttributes attrs = f.attributes();
139 attrs << outputGeometry.constGet()->area() << outputGeometry.constGet()->perimeter();
140 f.setAttributes( attrs );
141 }
142 else
143 {
144 if ( outputGeometry.type() == Qgis::GeometryType::Line )
145 {
146 feedback->pushWarning( QObject::tr( "Concave hull for feature %1 resulted in a linestring, ignoring" ).arg( f.id() ) );
147 }
148 else if ( outputGeometry.type() == Qgis::GeometryType::Point )
149 {
150 feedback->pushWarning( QObject::tr( "Concave hull for feature %1 resulted in a point, ignoring" ).arg( f.id() ) );
151 }
152 QgsAttributes attrs = f.attributes();
153 attrs << QVariant() << QVariant();
154 f.setAttributes( attrs );
155 }
156 }
157 return QgsFeatureList() << f;
158}
159
@ VectorPolygon
Vector polygon layers.
Definition qgis.h:3717
@ Point
Points.
Definition qgis.h:380
@ Line
Lines.
Definition qgis.h:381
@ Polygon
Polygons.
Definition qgis.h:382
@ Double
Double/float values.
Definition qgis.h:3988
virtual double perimeter() const
Returns the planar, 2-dimensional perimeter of the geometry.
virtual double area() const
Returns the planar, 2-dimensional area of the geometry.
A vector of attributes.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition qgsfeature.h:60
QgsAttributes attributes
Definition qgsfeature.h:69
QgsFeatureId id
Definition qgsfeature.h:68
void setAttributes(const QgsAttributes &attrs)
Sets the feature's attributes.
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.
Encapsulate a field in an attribute table or data source.
Definition qgsfield.h:56
Container of fields for a vector layer.
Definition qgsfields.h:46
bool append(const QgsField &field, Qgis::FieldOrigin origin=Qgis::FieldOrigin::Provider, int originIndex=-1)
Appends a field.
Definition qgsfields.cpp:75
A geometry is the spatial representation of a feature.
QgsGeometry concaveHullOfPolygons(double lengthRatio, bool allowHoles=false, bool isTight=false, QgsFeedback *feedback=nullptr) const
Constructs a concave hull of a set of polygons, respecting the polygons as constraints.
QString lastError() const
Returns an error string referring to the last error encountered either when this geometry was created...
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
Qgis::GeometryType type
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 pushWarning(const QString &warning)
Pushes a warning informational message from the algorithm.
virtual void reportError(const QString &error, bool fatalError=false)
Reports that the algorithm encountered an error while executing.
static QgsFields combineFields(const QgsFields &fieldsA, const QgsFields &fieldsB, const QString &fieldsBPrefix=QString())
Combines two field lists, avoiding duplicate field names (in a case-insensitive manner).
QList< QgsFeature > QgsFeatureList