QGIS API Documentation 3.28.0-Firenze (ed3ad0430f)
qgsalgorithmfilterbygeometry.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsalgorithmfilterbygeometry.cpp
3 ---------------------
4 begin : March 2020
5 copyright : (C) 2020 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
22QString QgsFilterByGeometryAlgorithm::name() const
23{
24 return QStringLiteral( "filterbygeometry" );
25}
26
27QString QgsFilterByGeometryAlgorithm::displayName() const
28{
29 return QObject::tr( "Filter by geometry type" );
30}
31
32QStringList QgsFilterByGeometryAlgorithm::tags() const
33{
34 return QObject::tr( "extract,filter,geometry,linestring,point,polygon" ).split( ',' );
35}
36
37QString QgsFilterByGeometryAlgorithm::group() const
38{
39 return QObject::tr( "Vector selection" );
40}
41
42QString QgsFilterByGeometryAlgorithm::groupId() const
43{
44 return QStringLiteral( "vectorselection" );
45}
46
47void QgsFilterByGeometryAlgorithm::initAlgorithm( const QVariantMap & )
48{
49 addParameter( new QgsProcessingParameterFeatureSource( QStringLiteral( "INPUT" ), QObject::tr( "Input layer" ),
50 QList< int >() << QgsProcessing::TypeVector ) );
51
52 addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "POINTS" ), QObject::tr( "Point features" ),
53 QgsProcessing::TypeVectorPoint, QVariant(), true, true ) );
54
55 addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "LINES" ), QObject::tr( "Line features" ),
56 QgsProcessing::TypeVectorLine, QVariant(), true, true ) );
57
58 addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "POLYGONS" ), QObject::tr( "Polygon features" ),
59 QgsProcessing::TypeVectorPolygon, QVariant(), true, true ) );
60
61 addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "NO_GEOMETRY" ), QObject::tr( "Features with no geometry" ),
62 QgsProcessing::TypeVector, QVariant(), true, true ) );
63
64 addOutput( new QgsProcessingOutputNumber( QStringLiteral( "POINT_COUNT" ), QObject::tr( "Total count of point features" ) ) );
65 addOutput( new QgsProcessingOutputNumber( QStringLiteral( "LINE_COUNT" ), QObject::tr( "Total count of line features" ) ) );
66 addOutput( new QgsProcessingOutputNumber( QStringLiteral( "POLYGON_COUNT" ), QObject::tr( "Total count of polygon features" ) ) );
67 addOutput( new QgsProcessingOutputNumber( QStringLiteral( "NO_GEOMETRY_COUNT" ), QObject::tr( "Total count of features without geometry" ) ) );
68}
69
70QString QgsFilterByGeometryAlgorithm::shortHelpString() const
71{
72 return QObject::tr( "This algorithm filters features by their geometry type. Incoming features will be directed to different "
73 "outputs based on whether they have a point, line or polygon geometry." );
74}
75
76QString QgsFilterByGeometryAlgorithm::shortDescription() const
77{
78 return QObject::tr( "Filters features by geometry type" );
79}
80
81QgsFilterByGeometryAlgorithm *QgsFilterByGeometryAlgorithm::createInstance() const
82{
83 return new QgsFilterByGeometryAlgorithm();
84}
85
86QVariantMap QgsFilterByGeometryAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
87{
88 std::unique_ptr< QgsProcessingFeatureSource > source( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
89 if ( !source )
90 throw QgsProcessingException( invalidSourceError( parameters, QStringLiteral( "INPUT" ) ) );
91
92 const bool hasM = QgsWkbTypes::hasM( source->wkbType() );
93 const bool hasZ = QgsWkbTypes::hasZ( source->wkbType() );
94
98 if ( hasM )
99 {
100 pointType = QgsWkbTypes::addM( pointType );
101 lineType = QgsWkbTypes::addM( lineType );
102 polygonType = QgsWkbTypes::addM( polygonType );
103 }
104 if ( hasZ )
105 {
106 pointType = QgsWkbTypes::addZ( pointType );
107 lineType = QgsWkbTypes::addZ( lineType );
108 polygonType = QgsWkbTypes::addZ( polygonType );
109 }
110
111 QString pointSinkId;
112 std::unique_ptr< QgsFeatureSink > pointSink( parameterAsSink( parameters, QStringLiteral( "POINTS" ), context, pointSinkId, source->fields(),
113 pointType, source->sourceCrs() ) );
114 if ( parameters.value( QStringLiteral( "POINTS" ), QVariant() ).isValid() && !pointSink )
115 throw QgsProcessingException( invalidSinkError( parameters, QStringLiteral( "POINTS" ) ) );
116
117 QString lineSinkId;
118 std::unique_ptr< QgsFeatureSink > lineSink( parameterAsSink( parameters, QStringLiteral( "LINES" ), context, lineSinkId, source->fields(),
119 lineType, source->sourceCrs() ) );
120 if ( parameters.value( QStringLiteral( "LINES" ), QVariant() ).isValid() && !lineSink )
121 throw QgsProcessingException( invalidSinkError( parameters, QStringLiteral( "LINES" ) ) );
122
123 QString polygonSinkId;
124 std::unique_ptr< QgsFeatureSink > polygonSink( parameterAsSink( parameters, QStringLiteral( "POLYGONS" ), context, polygonSinkId, source->fields(),
125 polygonType, source->sourceCrs() ) );
126 if ( parameters.value( QStringLiteral( "POLYGONS" ), QVariant() ).isValid() && !polygonSink )
127 throw QgsProcessingException( invalidSinkError( parameters, QStringLiteral( "POLYGONS" ) ) );
128
129 QString noGeomSinkId;
130 std::unique_ptr< QgsFeatureSink > noGeomSink( parameterAsSink( parameters, QStringLiteral( "NO_GEOMETRY" ), context, noGeomSinkId, source->fields(),
132 if ( parameters.value( QStringLiteral( "NO_GEOMETRY" ), QVariant() ).isValid() && !noGeomSink )
133 throw QgsProcessingException( invalidSinkError( parameters, QStringLiteral( "NO_GEOMETRY" ) ) );
134
135 const long count = source->featureCount();
136 long long pointCount = 0;
137 long long lineCount = 0;
138 long long polygonCount = 0;
139 long long nullCount = 0;
140
141 const double step = count > 0 ? 100.0 / count : 1;
142 int current = 0;
143
144 QgsFeatureIterator it = source->getFeatures();
145 QgsFeature f;
146 while ( it.nextFeature( f ) )
147 {
148 if ( feedback->isCanceled() )
149 {
150 break;
151 }
152
153 if ( f.hasGeometry() )
154 {
155 switch ( f.geometry().type() )
156 {
158 if ( pointSink )
159 {
160 if ( !pointSink->addFeature( f, QgsFeatureSink::FastInsert ) )
161 throw QgsProcessingException( writeFeatureError( pointSink.get(), parameters, QStringLiteral( "POINTS" ) ) );
162 }
163 pointCount++;
164 break;
166 if ( lineSink )
167 {
168 if ( !lineSink->addFeature( f, QgsFeatureSink::FastInsert ) )
169 throw QgsProcessingException( writeFeatureError( lineSink.get(), parameters, QStringLiteral( "LINES" ) ) );
170 }
171 lineCount++;
172 break;
174 if ( polygonSink )
175 {
176 if ( !polygonSink->addFeature( f, QgsFeatureSink::FastInsert ) )
177 throw QgsProcessingException( writeFeatureError( polygonSink.get(), parameters, QStringLiteral( "POLYGONS" ) ) );
178 }
179 polygonCount++;
180 break;
183 break;
184 }
185 }
186 else
187 {
188 if ( noGeomSink )
189 {
190 if ( !noGeomSink->addFeature( f, QgsFeatureSink::FastInsert ) )
191 throw QgsProcessingException( writeFeatureError( noGeomSink.get(), parameters, QStringLiteral( "NO_GEOMETRY" ) ) );
192 }
193 nullCount++;
194 }
195
196 feedback->setProgress( current * step );
197 current++;
198 }
199
200 QVariantMap outputs;
201
202 if ( pointSink )
203 outputs.insert( QStringLiteral( "POINTS" ), pointSinkId );
204 if ( lineSink )
205 outputs.insert( QStringLiteral( "LINES" ), lineSinkId );
206 if ( polygonSink )
207 outputs.insert( QStringLiteral( "POLYGONS" ), polygonSinkId );
208 if ( noGeomSink )
209 outputs.insert( QStringLiteral( "NO_GEOMETRY" ), noGeomSinkId );
210
211 outputs.insert( QStringLiteral( "POINT_COUNT" ), pointCount );
212 outputs.insert( QStringLiteral( "LINE_COUNT" ), lineCount );
213 outputs.insert( QStringLiteral( "POLYGON_COUNT" ), polygonCount );
214 outputs.insert( QStringLiteral( "NO_GEOMETRY_COUNT" ), nullCount );
215
216 return outputs;
217}
218
219
220
221//
222// QgsFilterByLayerTypeAlgorithm
223//
224
225QString QgsFilterByLayerTypeAlgorithm::name() const
226{
227 return QStringLiteral( "filterlayersbytype" );
228}
229
230QString QgsFilterByLayerTypeAlgorithm::displayName() const
231{
232 return QObject::tr( "Filter layers by type" );
233}
234
235QStringList QgsFilterByLayerTypeAlgorithm::tags() const
236{
237 return QObject::tr( "filter,vector,raster,select" ).split( ',' );
238}
239
240QString QgsFilterByLayerTypeAlgorithm::group() const
241{
242 return QObject::tr( "Modeler tools" );
243}
244
245QString QgsFilterByLayerTypeAlgorithm::groupId() const
246{
247 return QStringLiteral( "modelertools" );
248}
249
250QgsProcessingAlgorithm::Flags QgsFilterByLayerTypeAlgorithm::flags() const
251{
253 f |= FlagHideFromToolbox | FlagPruneModelBranchesBasedOnAlgorithmResults;
254 return f;
255}
256
257void QgsFilterByLayerTypeAlgorithm::initAlgorithm( const QVariantMap & )
258{
259 addParameter( new QgsProcessingParameterMapLayer( QStringLiteral( "INPUT" ), QObject::tr( "Input layer" ) ) );
260
261 addParameter( new QgsProcessingParameterVectorDestination( QStringLiteral( "VECTOR" ), QObject::tr( "Vector features" ),
262 QgsProcessing::TypeVectorAnyGeometry, QVariant(), true, false ) );
263
264 addParameter( new QgsProcessingParameterRasterDestination( QStringLiteral( "RASTER" ), QObject::tr( "Raster layer" ), QVariant(), true, false ) );
265}
266
267QString QgsFilterByLayerTypeAlgorithm::shortHelpString() const
268{
269 return QObject::tr( "This algorithm filters layer by their type. Incoming layers will be directed to different "
270 "outputs based on whether they are a vector or raster layer." );
271}
272
273QString QgsFilterByLayerTypeAlgorithm::shortDescription() const
274{
275 return QObject::tr( "Filters layers by type" );
276}
277
278QgsFilterByLayerTypeAlgorithm *QgsFilterByLayerTypeAlgorithm::createInstance() const
279{
280 return new QgsFilterByLayerTypeAlgorithm();
281}
282
283QVariantMap QgsFilterByLayerTypeAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback * )
284{
285 const QgsMapLayer *layer = parameterAsLayer( parameters, QStringLiteral( "INPUT" ), context );
286 if ( !layer )
287 throw QgsProcessingException( QObject::tr( "Could not load input layer" ) );
288
289 QVariantMap outputs;
290
291 switch ( layer->type() )
292 {
294 outputs.insert( QStringLiteral( "VECTOR" ), parameters.value( QStringLiteral( "INPUT" ) ) );
295 break;
296
298 outputs.insert( QStringLiteral( "RASTER" ), parameters.value( QStringLiteral( "INPUT" ) ) );
299 break;
300
307 break;
308 }
309
310 return outputs;
311}
312
314
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
@ 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...
Definition: qgsfeature.h:56
QgsGeometry geometry
Definition: qgsfeature.h:67
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Definition: qgsfeature.cpp:233
bool isCanceled() const SIP_HOLDGIL
Tells whether the operation has been canceled already.
Definition: qgsfeedback.h:54
void setProgress(double progress)
Sets the current progress for the feedback object.
Definition: qgsfeedback.h:63
QgsWkbTypes::GeometryType type
Definition: qgsgeometry.h:167
Base class for all map layer types.
Definition: qgsmaplayer.h:73
QgsMapLayerType type
Definition: qgsmaplayer.h:80
virtual Flags 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.
Definition: qgsexception.h:83
Base class for providing feedback from a processing algorithm.
A numeric output for processing algorithms.
A feature sink output for processing algorithms.
An input feature source (such as vector layers) parameter for processing algorithms.
A map layer parameter for processing algorithms.
A raster layer destination parameter, for specifying the destination path for a raster layer created ...
A vector layer destination parameter, for specifying the destination path for a vector layer created ...
@ TypeVectorLine
Vector line layers.
Definition: qgsprocessing.h:50
@ TypeVectorPolygon
Vector polygon layers.
Definition: qgsprocessing.h:51
@ TypeVector
Tables (i.e. vector layers with or without geometry). When used for a sink this indicates the sink ha...
Definition: qgsprocessing.h:54
@ TypeVectorPoint
Vector point layers.
Definition: qgsprocessing.h:49
@ TypeVectorAnyGeometry
Any vector layer with geometry.
Definition: qgsprocessing.h:48
static bool hasM(Type type) SIP_HOLDGIL
Tests whether a WKB type contains m values.
Definition: qgswkbtypes.h:1130
Type
The WKB type describes the number of dimensions a geometry has.
Definition: qgswkbtypes.h:70
static Type addZ(Type type) SIP_HOLDGIL
Adds the z dimension to a WKB type and returns the new type.
Definition: qgswkbtypes.h:1176
static bool hasZ(Type type) SIP_HOLDGIL
Tests whether a WKB type contains the z-dimension.
Definition: qgswkbtypes.h:1080
static Type addM(Type type) SIP_HOLDGIL
Adds the m dimension to a WKB type and returns the new type.
Definition: qgswkbtypes.h:1201
@ PointCloudLayer
Point cloud layer. Added in QGIS 3.18.
@ MeshLayer
Mesh layer. Added in QGIS 3.2.
@ VectorLayer
Vector layer.
@ RasterLayer
Raster layer.
@ GroupLayer
Composite group layer. Added in QGIS 3.24.
@ VectorTileLayer
Vector tile layer. Added in QGIS 3.14.
@ AnnotationLayer
Contains freeform, georeferenced annotations. Added in QGIS 3.16.
@ PluginLayer
Plugin based layer.