QGIS API Documentation  3.24.2-Tisler (13c1a02865)
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 
22 QString QgsFilterByGeometryAlgorithm::name() const
23 {
24  return QStringLiteral( "filterbygeometry" );
25 }
26 
27 QString QgsFilterByGeometryAlgorithm::displayName() const
28 {
29  return QObject::tr( "Filter by geometry type" );
30 }
31 
32 QStringList QgsFilterByGeometryAlgorithm::tags() const
33 {
34  return QObject::tr( "extract,filter,geometry,linestring,point,polygon" ).split( ',' );
35 }
36 
37 QString QgsFilterByGeometryAlgorithm::group() const
38 {
39  return QObject::tr( "Modeler tools" );
40 }
41 
42 QString QgsFilterByGeometryAlgorithm::groupId() const
43 {
44  return QStringLiteral( "modelertools" );
45 }
46 
47 QgsProcessingAlgorithm::Flags QgsFilterByGeometryAlgorithm::flags() const
48 {
51  return f;
52 }
53 
54 void QgsFilterByGeometryAlgorithm::initAlgorithm( const QVariantMap & )
55 {
56  addParameter( new QgsProcessingParameterFeatureSource( QStringLiteral( "INPUT" ), QObject::tr( "Input layer" ),
57  QList< int >() << QgsProcessing::TypeVector ) );
58 
59  addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "POINTS" ), QObject::tr( "Point features" ),
60  QgsProcessing::TypeVectorPoint, QVariant(), true, true ) );
61 
62  addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "LINES" ), QObject::tr( "Line features" ),
63  QgsProcessing::TypeVectorLine, QVariant(), true, true ) );
64 
65  addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "POLYGONS" ), QObject::tr( "Polygon features" ),
66  QgsProcessing::TypeVectorPolygon, QVariant(), true, true ) );
67 
68  addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "NO_GEOMETRY" ), QObject::tr( "Features with no geometry" ),
69  QgsProcessing::TypeVector, QVariant(), true, true ) );
70 
71  addOutput( new QgsProcessingOutputNumber( QStringLiteral( "POINT_COUNT" ), QObject::tr( "Total count of point features" ) ) );
72  addOutput( new QgsProcessingOutputNumber( QStringLiteral( "LINE_COUNT" ), QObject::tr( "Total count of line features" ) ) );
73  addOutput( new QgsProcessingOutputNumber( QStringLiteral( "POLYGON_COUNT" ), QObject::tr( "Total count of polygon features" ) ) );
74  addOutput( new QgsProcessingOutputNumber( QStringLiteral( "NO_GEOMETRY_COUNT" ), QObject::tr( "Total count of features without geometry" ) ) );
75 }
76 
77 QString QgsFilterByGeometryAlgorithm::shortHelpString() const
78 {
79  return QObject::tr( "This algorithm filters features by their geometry type. Incoming features will be directed to different "
80  "outputs based on whether they have a point, line or polygon geometry." );
81 }
82 
83 QString QgsFilterByGeometryAlgorithm::shortDescription() const
84 {
85  return QObject::tr( "Filters features by geometry type" );
86 }
87 
88 QgsFilterByGeometryAlgorithm *QgsFilterByGeometryAlgorithm::createInstance() const
89 {
90  return new QgsFilterByGeometryAlgorithm();
91 }
92 
93 QVariantMap QgsFilterByGeometryAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
94 {
95  std::unique_ptr< QgsProcessingFeatureSource > source( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
96  if ( !source )
97  throw QgsProcessingException( invalidSourceError( parameters, QStringLiteral( "INPUT" ) ) );
98 
99  const bool hasM = QgsWkbTypes::hasM( source->wkbType() );
100  const bool hasZ = QgsWkbTypes::hasZ( source->wkbType() );
101 
105  if ( hasM )
106  {
107  pointType = QgsWkbTypes::addM( pointType );
108  lineType = QgsWkbTypes::addM( lineType );
109  polygonType = QgsWkbTypes::addM( polygonType );
110  }
111  if ( hasZ )
112  {
113  pointType = QgsWkbTypes::addZ( pointType );
114  lineType = QgsWkbTypes::addZ( lineType );
115  polygonType = QgsWkbTypes::addZ( polygonType );
116  }
117 
118  QString pointSinkId;
119  std::unique_ptr< QgsFeatureSink > pointSink( parameterAsSink( parameters, QStringLiteral( "POINTS" ), context, pointSinkId, source->fields(),
120  pointType, source->sourceCrs() ) );
121  if ( parameters.value( QStringLiteral( "POINTS" ), QVariant() ).isValid() && !pointSink )
122  throw QgsProcessingException( invalidSinkError( parameters, QStringLiteral( "POINTS" ) ) );
123 
124  QString lineSinkId;
125  std::unique_ptr< QgsFeatureSink > lineSink( parameterAsSink( parameters, QStringLiteral( "LINES" ), context, lineSinkId, source->fields(),
126  lineType, source->sourceCrs() ) );
127  if ( parameters.value( QStringLiteral( "LINES" ), QVariant() ).isValid() && !lineSink )
128  throw QgsProcessingException( invalidSinkError( parameters, QStringLiteral( "LINES" ) ) );
129 
130  QString polygonSinkId;
131  std::unique_ptr< QgsFeatureSink > polygonSink( parameterAsSink( parameters, QStringLiteral( "POLYGONS" ), context, polygonSinkId, source->fields(),
132  polygonType, source->sourceCrs() ) );
133  if ( parameters.value( QStringLiteral( "POLYGONS" ), QVariant() ).isValid() && !polygonSink )
134  throw QgsProcessingException( invalidSinkError( parameters, QStringLiteral( "POLYGONS" ) ) );
135 
136  QString noGeomSinkId;
137  std::unique_ptr< QgsFeatureSink > noGeomSink( parameterAsSink( parameters, QStringLiteral( "NO_GEOMETRY" ), context, noGeomSinkId, source->fields(),
139  if ( parameters.value( QStringLiteral( "NO_GEOMETRY" ), QVariant() ).isValid() && !noGeomSink )
140  throw QgsProcessingException( invalidSinkError( parameters, QStringLiteral( "NO_GEOMETRY" ) ) );
141 
142  const long count = source->featureCount();
143  long long pointCount = 0;
144  long long lineCount = 0;
145  long long polygonCount = 0;
146  long long nullCount = 0;
147 
148  const double step = count > 0 ? 100.0 / count : 1;
149  int current = 0;
150 
151  QgsFeatureIterator it = source->getFeatures();
152  QgsFeature f;
153  while ( it.nextFeature( f ) )
154  {
155  if ( feedback->isCanceled() )
156  {
157  break;
158  }
159 
160  if ( f.hasGeometry() )
161  {
162  switch ( f.geometry().type() )
163  {
165  if ( pointSink )
166  {
167  if ( !pointSink->addFeature( f, QgsFeatureSink::FastInsert ) )
168  throw QgsProcessingException( writeFeatureError( pointSink.get(), parameters, QStringLiteral( "POINTS" ) ) );
169  }
170  pointCount++;
171  break;
173  if ( lineSink )
174  {
175  if ( !lineSink->addFeature( f, QgsFeatureSink::FastInsert ) )
176  throw QgsProcessingException( writeFeatureError( lineSink.get(), parameters, QStringLiteral( "LINES" ) ) );
177  }
178  lineCount++;
179  break;
181  if ( polygonSink )
182  {
183  if ( !polygonSink->addFeature( f, QgsFeatureSink::FastInsert ) )
184  throw QgsProcessingException( writeFeatureError( polygonSink.get(), parameters, QStringLiteral( "POLYGONS" ) ) );
185  }
186  polygonCount++;
187  break;
190  break;
191  }
192  }
193  else
194  {
195  if ( noGeomSink )
196  {
197  if ( !noGeomSink->addFeature( f, QgsFeatureSink::FastInsert ) )
198  throw QgsProcessingException( writeFeatureError( noGeomSink.get(), parameters, QStringLiteral( "NO_GEOMETRY" ) ) );
199  }
200  nullCount++;
201  }
202 
203  feedback->setProgress( current * step );
204  current++;
205  }
206 
207  QVariantMap outputs;
208 
209  if ( pointSink )
210  outputs.insert( QStringLiteral( "POINTS" ), pointSinkId );
211  if ( lineSink )
212  outputs.insert( QStringLiteral( "LINES" ), lineSinkId );
213  if ( polygonSink )
214  outputs.insert( QStringLiteral( "POLYGONS" ), polygonSinkId );
215  if ( noGeomSink )
216  outputs.insert( QStringLiteral( "NO_GEOMETRY" ), noGeomSinkId );
217 
218  outputs.insert( QStringLiteral( "POINT_COUNT" ), pointCount );
219  outputs.insert( QStringLiteral( "LINE_COUNT" ), lineCount );
220  outputs.insert( QStringLiteral( "POLYGON_COUNT" ), polygonCount );
221  outputs.insert( QStringLiteral( "NO_GEOMETRY_COUNT" ), nullCount );
222 
223  return outputs;
224 }
225 
226 
227 
228 //
229 // QgsFilterByLayerTypeAlgorithm
230 //
231 
232 QString QgsFilterByLayerTypeAlgorithm::name() const
233 {
234  return QStringLiteral( "filterlayersbytype" );
235 }
236 
237 QString QgsFilterByLayerTypeAlgorithm::displayName() const
238 {
239  return QObject::tr( "Filter layers by type" );
240 }
241 
242 QStringList QgsFilterByLayerTypeAlgorithm::tags() const
243 {
244  return QObject::tr( "filter,vector,raster,select" ).split( ',' );
245 }
246 
247 QString QgsFilterByLayerTypeAlgorithm::group() const
248 {
249  return QObject::tr( "Modeler tools" );
250 }
251 
252 QString QgsFilterByLayerTypeAlgorithm::groupId() const
253 {
254  return QStringLiteral( "modelertools" );
255 }
256 
257 QgsProcessingAlgorithm::Flags QgsFilterByLayerTypeAlgorithm::flags() const
258 {
259  Flags f = QgsProcessingAlgorithm::flags();
260  f |= FlagHideFromToolbox | FlagPruneModelBranchesBasedOnAlgorithmResults;
261  return f;
262 }
263 
264 void QgsFilterByLayerTypeAlgorithm::initAlgorithm( const QVariantMap & )
265 {
266  addParameter( new QgsProcessingParameterMapLayer( QStringLiteral( "INPUT" ), QObject::tr( "Input layer" ) ) );
267 
268  addParameter( new QgsProcessingParameterVectorDestination( QStringLiteral( "VECTOR" ), QObject::tr( "Vector features" ),
269  QgsProcessing::TypeVectorAnyGeometry, QVariant(), true, false ) );
270 
271  addParameter( new QgsProcessingParameterRasterDestination( QStringLiteral( "RASTER" ), QObject::tr( "Raster layer" ), QVariant(), true, false ) );
272 }
273 
274 QString QgsFilterByLayerTypeAlgorithm::shortHelpString() const
275 {
276  return QObject::tr( "This algorithm filters layer by their type. Incoming layers will be directed to different "
277  "outputs based on whether they are a vector or raster layer." );
278 }
279 
280 QString QgsFilterByLayerTypeAlgorithm::shortDescription() const
281 {
282  return QObject::tr( "Filters layers by type" );
283 }
284 
285 QgsFilterByLayerTypeAlgorithm *QgsFilterByLayerTypeAlgorithm::createInstance() const
286 {
287  return new QgsFilterByLayerTypeAlgorithm();
288 }
289 
290 QVariantMap QgsFilterByLayerTypeAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback * )
291 {
292  const QgsMapLayer *layer = parameterAsLayer( parameters, QStringLiteral( "INPUT" ), context );
293  if ( !layer )
294  throw QgsProcessingException( QObject::tr( "Could not load input layer" ) );
295 
296  QVariantMap outputs;
297 
298  switch ( layer->type() )
299  {
301  outputs.insert( QStringLiteral( "VECTOR" ), parameters.value( QStringLiteral( "INPUT" ) ) );
302  break;
303 
305  outputs.insert( QStringLiteral( "RASTER" ), parameters.value( QStringLiteral( "INPUT" ) ) );
306  break;
307 
314  break;
315  }
316 
317  return outputs;
318 }
319 
321 
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:223
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:128
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.
@ FlagHideFromToolbox
Algorithm should be hidden from the toolbox.
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.