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