QGIS API Documentation 4.1.0-Master (376402f9aeb)
Loading...
Searching...
No Matches
qgsalgorithmconcavehullbyfeature.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsalgorithmconcavehullbyfeature.cpp
3 ---------------------
4 begin : May 2025
5 copyright : (C) 2025 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
21
22#include <QString>
23
24using namespace Qt::StringLiterals;
25
27
28QString QgsConcaveHullByFeatureAlgorithm::name() const
29{
30 return u"concavehullbyfeature"_s;
31}
32
33QString QgsConcaveHullByFeatureAlgorithm::displayName() const
34{
35 return QObject::tr( "Concave hull (by feature)" );
36}
37
38QStringList QgsConcaveHullByFeatureAlgorithm::tags() const
39{
40 return QObject::tr( "concave,hull,bounds,bounding,convex" ).split( ',' );
41}
42
43QString QgsConcaveHullByFeatureAlgorithm::group() const
44{
45 return QObject::tr( "Vector geometry" );
46}
47
48QString QgsConcaveHullByFeatureAlgorithm::groupId() const
49{
50 return u"vectorgeometry"_s;
51}
52
53QString QgsConcaveHullByFeatureAlgorithm::outputName() const
54{
55 return QObject::tr( "Concave hulls" );
56}
57
58QString QgsConcaveHullByFeatureAlgorithm::shortHelpString() const
59{
60 return QObject::tr( "This algorithm calculates the concave hull for each feature in an input layer." )
61 + u"\n\n"_s
62 + QObject::tr( "For point and line layers, a concave hull is a polygon which contains all the vertices of the input geometries, but is a better approximation than the convex hull to the area occupied by the input." )
63 + u"\n\n"_s
64 + QObject::tr(
65 "When the input is a polygon layer, the algorithm operates differently: it computes a concave hull that respects the interior of the input polygons. The concave hull does not intersect "
66 "the polygon interiors. The computed hull also fills the empty space between the polygons within a multi-polygon feature."
67 )
68 + u"\n\n"_s
69 + QObject::tr( "See the 'Concave hull (by layer)' algorithm for a concave hull calculation which covers the whole layer or grouped subsets of features." );
70}
71
72QString QgsConcaveHullByFeatureAlgorithm::shortDescription() const
73{
74 return QObject::tr( "Calculates the concave hull for each feature in an input layer." );
75}
76
77QgsConcaveHullByFeatureAlgorithm *QgsConcaveHullByFeatureAlgorithm::createInstance() const
78{
79 return new QgsConcaveHullByFeatureAlgorithm();
80}
81
82void QgsConcaveHullByFeatureAlgorithm::initParameters( const QVariantMap & )
83{
84 auto alphaParam
85 = std::make_unique<QgsProcessingParameterNumber>( u"ALPHA"_s, QObject::tr( "Threshold (0-1, where 1 is equivalent with Convex Hull)" ), Qgis::ProcessingNumberParameterType::Double, 0.3, false, 0, 1 );
86 alphaParam->setHelp(
87 QObject::tr(
88 "Controls the concaveness of the computed hull. A value of 1 produces the convex hull, while a value closer to 0 produces a highly concave hull. For point and line layers, this value "
89 "represents the target percentage of the convex hull area. For polygon layers, it specifies the maximum edge length as a fraction of the difference between the longest and shortest edge "
90 "lengths in the empty space between polygons."
91 )
92 );
93 addParameter( alphaParam.release() );
94
95 auto holesParam = std::make_unique<QgsProcessingParameterBoolean>( u"HOLES"_s, QObject::tr( "Allow holes" ), true );
96 holesParam->setHelp( QObject::tr( "Controls whether the computed concave hull is allowed to contain holes." ) );
97 addParameter( holesParam.release() );
98}
99
100QList<int> QgsConcaveHullByFeatureAlgorithm::inputLayerTypes() const
101{
102 return QList<int>() << static_cast<int>( Qgis::ProcessingSourceType::VectorPoint ) << static_cast<int>( Qgis::ProcessingSourceType::VectorLine ) << static_cast<int>( Qgis::ProcessingSourceType::VectorPolygon );
103}
104
105QgsFields QgsConcaveHullByFeatureAlgorithm::outputFields( const QgsFields &inputFields ) const
106{
107 QgsFields newFields;
108 newFields.append( QgsField( u"area"_s, QMetaType::Type::Double, QString(), 20, 6 ) );
109 newFields.append( QgsField( u"perimeter"_s, QMetaType::Type::Double, QString(), 20, 6 ) );
110 return QgsProcessingUtils::combineFields( inputFields, newFields );
111}
112
113bool QgsConcaveHullByFeatureAlgorithm::prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback * )
114{
115#if GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR < 11
116 throw QgsProcessingException( QObject::tr( "This algorithm requires a QGIS build based on GEOS 3.11 or later" ) );
117#endif
118 mPercentage = parameterAsDouble( parameters, u"ALPHA"_s, context );
119 mAllowHoles = parameterAsBool( parameters, u"HOLES"_s, context );
120 return true;
121}
122
123QgsFeatureList QgsConcaveHullByFeatureAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingContext &, QgsProcessingFeedback *feedback )
124{
125 QgsFeature f = feature;
126 if ( f.hasGeometry() )
127 {
128 QgsGeometry outputGeometry;
130 {
131 const QgsAbstractGeometry *inputGeometry = f.geometry().constGet();
133 if ( !collection || collection->numGeometries() == 1 )
134 {
135 feedback->reportError( QObject::tr( "Cannot calculate concave hull for a single point feature (%1) (try 'Concave hull (by layer)' algorithm instead)." ).arg( f.id() ) );
136 f.clearGeometry();
137 }
138 else
139 {
140 outputGeometry = f.geometry().concaveHull( mPercentage, mAllowHoles );
141 if ( outputGeometry.isNull() && !outputGeometry.lastError().isEmpty() )
142 feedback->reportError( outputGeometry.lastError() );
143 f.setGeometry( outputGeometry );
144 }
145 }
146 else if ( f.geometry().type() == Qgis::GeometryType::Line )
147 {
148 outputGeometry = f.geometry().concaveHull( mPercentage, mAllowHoles );
149 if ( outputGeometry.isNull() && !outputGeometry.lastError().isEmpty() )
150 feedback->reportError( outputGeometry.lastError() );
151 f.setGeometry( outputGeometry );
152 }
153 else if ( f.geometry().type() == Qgis::GeometryType::Polygon )
154 {
155 outputGeometry = f.geometry().concaveHullOfPolygons( mPercentage, mAllowHoles );
156 if ( outputGeometry.isNull() && !outputGeometry.lastError().isEmpty() )
157 feedback->reportError( outputGeometry.lastError() );
158 f.setGeometry( outputGeometry );
159 }
160
161 if ( outputGeometry.type() == Qgis::GeometryType::Polygon )
162 {
163 QgsAttributes attrs = f.attributes();
164 attrs << outputGeometry.constGet()->area() << outputGeometry.constGet()->perimeter();
165 f.setAttributes( attrs );
166 }
167 else
168 {
169 if ( outputGeometry.type() == Qgis::GeometryType::Line )
170 {
171 feedback->pushWarning( QObject::tr( "Concave hull for feature %1 resulted in a linestring, ignoring" ).arg( f.id() ) );
172 }
173 else if ( outputGeometry.type() == Qgis::GeometryType::Point )
174 {
175 feedback->pushWarning( QObject::tr( "Concave hull for feature %1 resulted in a point, ignoring" ).arg( f.id() ) );
176 }
177 QgsAttributes attrs = f.attributes();
178 attrs << QVariant() << QVariant();
179 f.setAttributes( attrs );
180 }
181 }
182 return QgsFeatureList() << f;
183}
184
@ VectorPoint
Vector point layers.
Definition qgis.h:3715
@ VectorPolygon
Vector polygon layers.
Definition qgis.h:3717
@ VectorLine
Vector line layers.
Definition qgis.h:3716
@ 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
Abstract base class for all geometries.
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
void clearGeometry()
Removes any geometry associated with the feature.
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
int numGeometries() const
Returns the number of geometries within the collection.
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.
QgsGeometry concaveHull(double targetPercent, bool allowHoles=false, QgsFeedback *feedback=nullptr) const
Returns a possibly concave polygon that contains all the points in the geometry.
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).
T qgsgeometry_cast(QgsAbstractGeometry *geom)
QList< QgsFeature > QgsFeatureList