QGIS API Documentation 3.34.0-Prizren (ffbdd678812)
Loading...
Searching...
No Matches
qgsalgorithmkeepnbiggestparts.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsalgorithmkeepnbiggestparts.cpp
3 ---------------------
4 begin : July 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
20#include "qgsmultisurface.h"
21#include "qgsmultipolygon.h"
22#include <queue>
23
25
26QString QgsKeepNBiggestPartsAlgorithm::name() const
27{
28 return QStringLiteral( "keepnbiggestparts" );
29}
30
31QString QgsKeepNBiggestPartsAlgorithm::displayName() const
32{
33 return QObject::tr( "Keep N biggest parts" );
34}
35
36QStringList QgsKeepNBiggestPartsAlgorithm::tags() const
37{
38 return QObject::tr( "remove,delete,drop,largest,area,filter" ).split( ',' );
39}
40
41QString QgsKeepNBiggestPartsAlgorithm::group() const
42{
43 return QObject::tr( "Vector geometry" );
44}
45
46QString QgsKeepNBiggestPartsAlgorithm::groupId() const
47{
48 return QStringLiteral( "vectorgeometry" );
49}
50
51QString QgsKeepNBiggestPartsAlgorithm::outputName() const
52{
53 return QObject::tr( "Parts" );
54}
55
56QList<int> QgsKeepNBiggestPartsAlgorithm::inputLayerTypes() const
57{
58 return QList<int>() << QgsProcessing::TypeVectorPolygon;
59}
60
61QgsProcessing::SourceType QgsKeepNBiggestPartsAlgorithm::outputLayerType() const
62{
64}
65
66QString QgsKeepNBiggestPartsAlgorithm::shortHelpString() const
67{
68 return QObject::tr( "This algorithm takes a polygon layer and creates a new polygon layer in which multipart "
69 "geometries have been removed, leaving only the n largest (in terms of area) parts." );
70}
71
72QgsKeepNBiggestPartsAlgorithm *QgsKeepNBiggestPartsAlgorithm::createInstance() const
73{
74 return new QgsKeepNBiggestPartsAlgorithm();
75}
76
77QgsProcessingFeatureSource::Flag QgsKeepNBiggestPartsAlgorithm::sourceFlags() const
78{
79 // skip geometry checks - this algorithm can be used to repair geometries
81}
82
83void QgsKeepNBiggestPartsAlgorithm::initParameters( const QVariantMap & )
84{
85 std::unique_ptr< QgsProcessingParameterNumber > partsToKeep = std::make_unique< QgsProcessingParameterNumber >( QStringLiteral( "PARTS" ),
86 QObject::tr( "Parts to keep" ), QgsProcessingParameterNumber::Integer,
87 1.0, false, 1.0 );
88 partsToKeep->setIsDynamic( true );
89 partsToKeep->setDynamicPropertyDefinition( QgsPropertyDefinition( QStringLiteral( "PARTS" ), QObject::tr( "Parts to keep" ), QgsPropertyDefinition::IntegerPositive ) );
90 partsToKeep->setDynamicLayerParameterName( QStringLiteral( "POLYGONS" ) );
91 addParameter( partsToKeep.release() );
92}
93
94QString QgsKeepNBiggestPartsAlgorithm::inputParameterName() const
95{
96 return QStringLiteral( "POLYGONS" );
97}
98
99bool QgsKeepNBiggestPartsAlgorithm::prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback * )
100{
101 mPartsToKeep = parameterAsInt( parameters, QStringLiteral( "PARTS" ), context );
102 mDynamicPartsToKeep = QgsProcessingParameters::isDynamic( parameters, QStringLiteral( "PARTS" ) );
103 if ( mDynamicPartsToKeep )
104 mPartsToKeepProperty = parameters.value( QStringLiteral( "PARTS" ) ).value< QgsProperty >();
105
106 return true;
107}
108
109QgsFeatureList QgsKeepNBiggestPartsAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingContext &context, QgsProcessingFeedback * )
110{
111 QgsFeature f = feature;
112 if ( f.hasGeometry() )
113 {
114 const QgsGeometry geometry = f.geometry();
115
116 QgsGeometry outputGeometry;
117 if ( !geometry.isMultipart() )
118 {
119 outputGeometry = geometry;
120 outputGeometry.convertToMultiType();
121 }
122 else
123 {
124 int nPartsToKeep = mPartsToKeep;
125 if ( mDynamicPartsToKeep )
126 nPartsToKeep = mPartsToKeepProperty.valueAsInt( context.expressionContext(), nPartsToKeep );
127
128 const QgsGeometryCollection *collection = qgsgeometry_cast< const QgsGeometryCollection * >( geometry.constGet() );
129 const int numParts = collection->numGeometries();
130 if ( nPartsToKeep >= numParts )
131 {
132 // nothing to do
133 outputGeometry = geometry;
134 }
135 else
136 {
137 struct GreaterThanByArea
138 {
139 bool operator()( const QgsAbstractGeometry *lhs, const QgsAbstractGeometry *rhs ) const
140 {
141 return lhs->area() < rhs->area();
142 }
143 };
144
145 std::unique_ptr< QgsMultiSurface > res = QgsWkbTypes::isCurvedType( collection->wkbType() ) ? std::make_unique< QgsMultiSurface >() : std::make_unique< QgsMultiPolygon >();
146 std::priority_queue< const QgsAbstractGeometry *, std::vector<const QgsAbstractGeometry *>, GreaterThanByArea > areaQueue;
147 for ( int i = 0; i < numParts; ++i )
148 {
149 areaQueue.push( collection->geometryN( i ) );
150 }
151
152 for ( int i = 0; i < nPartsToKeep; ++i )
153 {
154 const QgsAbstractGeometry *part = areaQueue.top();
155 areaQueue.pop();
156 res->addGeometry( part->clone() );
157 }
158
159 outputGeometry = QgsGeometry( std::move( res ) );
160 }
161 }
162
163 f.setGeometry( outputGeometry );
164 }
165 return QgsFeatureList() << f;
166}
167
168
170
171
Abstract base class for all geometries.
Qgis::WkbType wkbType() const
Returns the WKB type of the geometry.
virtual double area() const
Returns the planar, 2-dimensional area of the geometry.
virtual QgsAbstractGeometry * clone() const =0
Clones the geometry by performing a deep copy.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition qgsfeature.h:56
QgsGeometry geometry
Definition qgsfeature.h:67
bool hasGeometry() const
Returns true if the feature has an associated geometry.
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
int numGeometries() const
Returns the number of geometries within the collection.
const QgsAbstractGeometry * geometryN(int n) const
Returns a const reference to a geometry from within the collection.
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.
bool isMultipart() const
Returns true if WKB of the geometry is of WKBMulti* type.
bool convertToMultiType()
Converts single type geometry into multitype geometry e.g.
Multi polygon geometry collection.
Contains information about the context in which a processing algorithm is executed.
QgsExpressionContext & expressionContext()
Returns the expression context.
Flag
Flags controlling how QgsProcessingFeatureSource fetches features.
@ FlagSkipGeometryValidityChecks
Invalid geometry checks should always be skipped. This flag can be useful for algorithms which always...
Base class for providing feedback from a processing algorithm.
static bool isDynamic(const QVariantMap &parameters, const QString &name)
Returns true if the parameter with matching name is a dynamic parameter, and must be evaluated once f...
SourceType
Data source types enum.
@ TypeVectorPolygon
Vector polygon layers.
Definition for a property.
Definition qgsproperty.h:46
@ IntegerPositive
Positive integer values (including 0)
Definition qgsproperty.h:54
A store for object properties.
static bool isCurvedType(Qgis::WkbType type)
Returns true if the WKB type is a curved type or can contain curved geometries.
QList< QgsFeature > QgsFeatureList
Definition qgsfeature.h:920