QGIS API Documentation  3.20.0-Odense (decaadbb31)
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  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  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  pointSink->addFeature( f, QgsFeatureSink::FastInsert );
168  }
169  pointCount++;
170  break;
172  if ( lineSink )
173  {
174  lineSink->addFeature( f, QgsFeatureSink::FastInsert );
175  }
176  lineCount++;
177  break;
179  if ( polygonSink )
180  {
181  polygonSink->addFeature( f, QgsFeatureSink::FastInsert );
182  }
183  polygonCount++;
184  break;
187  break;
188  }
189  }
190  else
191  {
192  if ( noGeomSink )
193  {
194  noGeomSink->addFeature( f, QgsFeatureSink::FastInsert );
195  }
196  nullCount++;
197  }
198 
199  feedback->setProgress( current * step );
200  current++;
201  }
202 
203  QVariantMap outputs;
204 
205  if ( pointSink )
206  outputs.insert( QStringLiteral( "POINTS" ), pointSinkId );
207  if ( lineSink )
208  outputs.insert( QStringLiteral( "LINES" ), lineSinkId );
209  if ( polygonSink )
210  outputs.insert( QStringLiteral( "POLYGONS" ), polygonSinkId );
211  if ( noGeomSink )
212  outputs.insert( QStringLiteral( "NO_GEOMETRY" ), noGeomSinkId );
213 
214  outputs.insert( QStringLiteral( "POINT_COUNT" ), pointCount );
215  outputs.insert( QStringLiteral( "LINE_COUNT" ), lineCount );
216  outputs.insert( QStringLiteral( "POLYGON_COUNT" ), polygonCount );
217  outputs.insert( QStringLiteral( "NO_GEOMETRY_COUNT" ), nullCount );
218 
219  return outputs;
220 }
221 
222 
223 
224 //
225 // QgsFilterByLayerTypeAlgorithm
226 //
227 
228 QString QgsFilterByLayerTypeAlgorithm::name() const
229 {
230  return QStringLiteral( "filterlayersbytype" );
231 }
232 
233 QString QgsFilterByLayerTypeAlgorithm::displayName() const
234 {
235  return QObject::tr( "Filter layers by type" );
236 }
237 
238 QStringList QgsFilterByLayerTypeAlgorithm::tags() const
239 {
240  return QObject::tr( "filter,vector,raster,select" ).split( ',' );
241 }
242 
243 QString QgsFilterByLayerTypeAlgorithm::group() const
244 {
245  return QObject::tr( "Modeler tools" );
246 }
247 
248 QString QgsFilterByLayerTypeAlgorithm::groupId() const
249 {
250  return QStringLiteral( "modelertools" );
251 }
252 
253 QgsProcessingAlgorithm::Flags QgsFilterByLayerTypeAlgorithm::flags() const
254 {
255  Flags f = QgsProcessingAlgorithm::flags();
256  f |= FlagHideFromToolbox | FlagPruneModelBranchesBasedOnAlgorithmResults;
257  return f;
258 }
259 
260 void QgsFilterByLayerTypeAlgorithm::initAlgorithm( const QVariantMap & )
261 {
262  addParameter( new QgsProcessingParameterMapLayer( QStringLiteral( "INPUT" ), QObject::tr( "Input layer" ) ) );
263 
264  addParameter( new QgsProcessingParameterVectorDestination( QStringLiteral( "VECTOR" ), QObject::tr( "Vector features" ),
265  QgsProcessing::TypeVectorAnyGeometry, QVariant(), true, false ) );
266 
267  addParameter( new QgsProcessingParameterRasterDestination( QStringLiteral( "RASTER" ), QObject::tr( "Raster layer" ), QVariant(), true, false ) );
268 }
269 
270 QString QgsFilterByLayerTypeAlgorithm::shortHelpString() const
271 {
272  return QObject::tr( "This algorithm filters layer by their type. Incoming layers will be directed to different "
273  "outputs based on whether they are a vector or raster layer." );
274 }
275 
276 QString QgsFilterByLayerTypeAlgorithm::shortDescription() const
277 {
278  return QObject::tr( "Filters layers by type" );
279 }
280 
281 QgsFilterByLayerTypeAlgorithm *QgsFilterByLayerTypeAlgorithm::createInstance() const
282 {
283  return new QgsFilterByLayerTypeAlgorithm();
284 }
285 
286 QVariantMap QgsFilterByLayerTypeAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback * )
287 {
288  const QgsMapLayer *layer = parameterAsLayer( parameters, QStringLiteral( "INPUT" ), context );
289  if ( !layer )
290  throw QgsProcessingException( QObject::tr( "Could not load input layer" ) );
291 
292  QVariantMap outputs;
293 
294  switch ( layer->type() )
295  {
297  outputs.insert( QStringLiteral( "VECTOR" ), parameters.value( QStringLiteral( "INPUT" ) ) );
298  break;
299 
301  outputs.insert( QStringLiteral( "RASTER" ), parameters.value( QStringLiteral( "INPUT" ) ) );
302  break;
303 
309  break;
310  }
311 
312  return outputs;
313 }
314 
316 
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:205
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:127
Base class for all map layer types.
Definition: qgsmaplayer.h:70
QgsMapLayerType type
Definition: qgsmaplayer.h:77
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:1100
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:1146
static bool hasZ(Type type) SIP_HOLDGIL
Tests whether a WKB type contains the z-dimension.
Definition: qgswkbtypes.h:1050
static Type addM(Type type) SIP_HOLDGIL
Adds the m dimension to a WKB type and returns the new type.
Definition: qgswkbtypes.h:1171
@ PointCloudLayer
Added in 3.18.
@ MeshLayer
Added in 3.2.
@ VectorTileLayer
Added in 3.14.
@ AnnotationLayer
Contains freeform, georeferenced annotations. Added in QGIS 3.16.