QGIS API Documentation 3.39.0-Master (67e056379ed)
Loading...
Searching...
No Matches
qgsalgorithmextractbylocation.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsalgorithmextractbylocation.cpp
3 ---------------------
4 begin : April 2017
5 copyright : (C) 2017 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#include "qgsgeometryengine.h"
20#include "qgsvectorlayer.h"
22
24
25void QgsLocationBasedAlgorithm::addPredicateParameter()
26{
27 std::unique_ptr< QgsProcessingParameterEnum > predicateParam( new QgsProcessingParameterEnum( QStringLiteral( "PREDICATE" ),
28 QObject::tr( "Where the features (geometric predicate)" ),
29 predicateOptionsList(), true, QVariant::fromValue( QList< int >() << 0 ) ) );
30
31 QVariantMap predicateMetadata;
32 QVariantMap widgetMetadata;
33 widgetMetadata.insert( QStringLiteral( "useCheckBoxes" ), true );
34 widgetMetadata.insert( QStringLiteral( "columns" ), 2 );
35 predicateMetadata.insert( QStringLiteral( "widget_wrapper" ), widgetMetadata );
36 predicateParam->setMetadata( predicateMetadata );
37
38 addParameter( predicateParam.release() );
39}
40
41QgsLocationBasedAlgorithm::Predicate QgsLocationBasedAlgorithm::reversePredicate( QgsLocationBasedAlgorithm::Predicate predicate ) const
42{
43 switch ( predicate )
44 {
45 case Intersects:
46 return Intersects;
47 case Contains:
48 return Within;
49 case Disjoint:
50 return Disjoint;
51 case IsEqual:
52 return IsEqual;
53 case Touches:
54 return Touches;
55 case Overlaps:
56 return Overlaps;
57 case Within:
58 return Contains;
59 case Crosses:
60 return Crosses;
61 }
62 // no warnings
63 return Intersects;
64}
65
66QStringList QgsLocationBasedAlgorithm::predicateOptionsList() const
67{
68 return QStringList() << QObject::tr( "intersect" )
69 << QObject::tr( "contain" )
70 << QObject::tr( "disjoint" )
71 << QObject::tr( "equal" )
72 << QObject::tr( "touch" )
73 << QObject::tr( "overlap" )
74 << QObject::tr( "are within" )
75 << QObject::tr( "cross" );
76}
77
78void QgsLocationBasedAlgorithm::process( const QgsProcessingContext &context, QgsFeatureSource *targetSource,
79 QgsFeatureSource *intersectSource,
80 const QList< int > &selectedPredicates,
81 const std::function < void( const QgsFeature & ) > &handleFeatureFunction,
82 bool onlyRequireTargetIds,
83 QgsProcessingFeedback *feedback,
84 const QgsFeatureIds &skipTargetFeatureIds )
85{
86 // skip if there are no features to select from!
87 if ( mTargetFeatureCount == 0 )
88 return;
89
90 // skip if intersect layer is empty, unless we are looking for disjoints
91 if ( mIntersectFeatureCount == 0 &&
92 !selectedPredicates.contains( Disjoint ) )
93 return;
94
95 if ( mTargetFeatureCount > 0 && mIntersectFeatureCount > 0 &&
96 mTargetFeatureCount < mIntersectFeatureCount )
97 {
98 // joining FEWER features to a layer with MORE features. So we iterate over the FEW features and find matches from the MANY
99 processByIteratingOverTargetSource( context, targetSource, intersectSource,
100 selectedPredicates, handleFeatureFunction,
101 onlyRequireTargetIds, feedback, skipTargetFeatureIds );
102 }
103 else
104 {
105 // default -- iterate over the intersect source and match back to the target source. We do this on the assumption that the most common
106 // use case is joining a points layer to a polygon layer (e.g. findings points within a polygon), so by iterating
107 // over the polygons we can take advantage of prepared geometries for the spatial relationship test.
108
109 // TODO - consider using more heuristics to determine whether it's always best to iterate over the intersect
110 // source.
111 processByIteratingOverIntersectSource( context, targetSource, intersectSource,
112 selectedPredicates, handleFeatureFunction,
113 onlyRequireTargetIds, feedback, skipTargetFeatureIds );
114 }
115}
116
117void QgsLocationBasedAlgorithm::processByIteratingOverTargetSource( const QgsProcessingContext &context, QgsFeatureSource *targetSource,
118 QgsFeatureSource *intersectSource,
119 const QList< int > &selectedPredicates,
120 const std::function < void( const QgsFeature & ) > &handleFeatureFunction,
121 bool onlyRequireTargetIds,
122 QgsProcessingFeedback *feedback,
123 const QgsFeatureIds &skipTargetFeatureIds )
124{
126 feedback->pushWarning( QObject::tr( "No spatial index exists for intersect layer, performance will be severely degraded" ) );
127
128 QgsFeatureIds foundSet;
130 if ( onlyRequireTargetIds )
131 request.setNoAttributes();
132
133 QgsFeatureIterator fIt = targetSource->getFeatures( request );
134 double step = mTargetFeatureCount > 0 ? 100.0 / static_cast< double >( mTargetFeatureCount ) : 1;
135 int current = 0;
136 QgsFeature f;
137 std::unique_ptr< QgsGeometryEngine > engine;
138 while ( fIt.nextFeature( f ) )
139 {
140 if ( feedback->isCanceled() )
141 break;
142
143 // don't check features in skipTargetFeatureIds
144 if ( skipTargetFeatureIds.contains( f.id() ) )
145 continue;
146 if ( !f.hasGeometry() )
147 continue;
148
149 engine.reset();
150
151 QgsRectangle bbox = f.geometry().boundingBox();
152 request = QgsFeatureRequest().setFilterRect( bbox ).setNoAttributes().setDestinationCrs( mTargetCrs, context.transformContext() );
153
154 QgsFeatureIterator testFeatureIt = intersectSource->getFeatures( request );
155 QgsFeature testFeature;
156 bool isMatch = false;
157 bool isDisjoint = true;
158 while ( testFeatureIt.nextFeature( testFeature ) )
159 {
160 if ( feedback->isCanceled() )
161 break;
162
163 if ( !engine )
164 {
165 engine.reset( QgsGeometry::createGeometryEngine( f.geometry().constGet() ) );
166 engine->prepareGeometry();
167 }
168
169 for ( int predicate : selectedPredicates )
170 {
171 switch ( static_cast< Predicate>( predicate ) )
172 {
173 case Intersects:
174 isMatch = engine->intersects( testFeature.geometry().constGet() );
175 break;
176 case Contains:
177 isMatch = engine->contains( testFeature.geometry().constGet() );
178 break;
179 case Disjoint:
180 if ( engine->intersects( testFeature.geometry().constGet() ) )
181 {
182 isDisjoint = false;
183 }
184 break;
185 case IsEqual:
186 isMatch = engine->isEqual( testFeature.geometry().constGet() );
187 break;
188 case Touches:
189 isMatch = engine->touches( testFeature.geometry().constGet() );
190 break;
191 case Overlaps:
192 isMatch = engine->overlaps( testFeature.geometry().constGet() );
193 break;
194 case Within:
195 isMatch = engine->within( testFeature.geometry().constGet() );
196 break;
197 case Crosses:
198 isMatch = engine->crosses( testFeature.geometry().constGet() );
199 break;
200 }
201
202 if ( isMatch )
203 break;
204 }
205
206 if ( isMatch )
207 {
208 foundSet.insert( f.id() );
209 handleFeatureFunction( f );
210 break;
211 }
212 }
213 if ( isDisjoint && selectedPredicates.contains( Disjoint ) )
214 {
215 foundSet.insert( f.id() );
216 handleFeatureFunction( f );
217 }
218
219 current += 1;
220 feedback->setProgress( current * step );
221 }
222}
223
224void QgsLocationBasedAlgorithm::processByIteratingOverIntersectSource( const QgsProcessingContext &context, QgsFeatureSource *targetSource,
225 QgsFeatureSource *intersectSource,
226 const QList< int > &selectedPredicates,
227 const std::function < void( const QgsFeature & ) > &handleFeatureFunction,
228 bool onlyRequireTargetIds,
229 QgsProcessingFeedback *feedback,
230 const QgsFeatureIds &skipTargetFeatureIds )
231{
233 feedback->pushWarning( QObject::tr( "No spatial index exists for input layer, performance will be severely degraded" ) );
234
235 // build a list of 'reversed' predicates, because in this function
236 // we actually test the reverse of what the user wants (allowing us
237 // to prepare geometries and optimise the algorithm)
238 QList< Predicate > predicates;
239 predicates.reserve( selectedPredicates.count() );
240 for ( int i : selectedPredicates )
241 {
242 predicates << reversePredicate( static_cast< Predicate >( i ) );
243 }
244
245 QgsFeatureIds disjointSet;
246 if ( predicates.contains( Disjoint ) )
247 disjointSet = targetSource->allFeatureIds();
248
249 QgsFeatureIds foundSet;
251 QgsFeatureIterator fIt = intersectSource->getFeatures( request );
252 double step = mIntersectFeatureCount > 0 ? 100.0 / static_cast< double >( mIntersectFeatureCount ) : 1;
253 int current = 0;
254 QgsFeature f;
255 std::unique_ptr< QgsGeometryEngine > engine;
256 while ( fIt.nextFeature( f ) )
257 {
258 if ( feedback->isCanceled() )
259 break;
260
261 if ( !f.hasGeometry() )
262 continue;
263
264 engine.reset();
265
266 QgsRectangle bbox = f.geometry().boundingBox();
267 request = QgsFeatureRequest().setFilterRect( bbox );
268 if ( onlyRequireTargetIds )
269 request.setNoAttributes();
270
271 QgsFeatureIterator testFeatureIt = targetSource->getFeatures( request );
272 QgsFeature testFeature;
273 while ( testFeatureIt.nextFeature( testFeature ) )
274 {
275 if ( feedback->isCanceled() )
276 break;
277
278 if ( skipTargetFeatureIds.contains( testFeature.id() ) )
279 {
280 // don't check features in skipTargetFeatureIds
281 continue;
282 }
283 if ( foundSet.contains( testFeature.id() ) )
284 {
285 // already added this one, no need for further tests
286 continue;
287 }
288 if ( predicates.count() == 1 && predicates.at( 0 ) == Disjoint && !disjointSet.contains( testFeature.id() ) )
289 {
290 // calculating only the disjoint set, and we've already eliminated this feature so no need for further tests
291 continue;
292 }
293
294 if ( !engine )
295 {
296 engine.reset( QgsGeometry::createGeometryEngine( f.geometry().constGet() ) );
297 engine->prepareGeometry();
298 }
299
300 bool isMatch = false;
301
302 for ( Predicate predicate : std::as_const( predicates ) )
303 {
304 switch ( predicate )
305 {
306 case Intersects:
307 isMatch = engine->intersects( testFeature.geometry().constGet() );
308 break;
309 case Contains:
310 isMatch = engine->contains( testFeature.geometry().constGet() );
311 break;
312 case Disjoint:
313 if ( engine->intersects( testFeature.geometry().constGet() ) )
314 {
315 disjointSet.remove( testFeature.id() );
316 }
317 break;
318 case IsEqual:
319 isMatch = engine->isEqual( testFeature.geometry().constGet() );
320 break;
321 case Touches:
322 isMatch = engine->touches( testFeature.geometry().constGet() );
323 break;
324 case Overlaps:
325 isMatch = engine->overlaps( testFeature.geometry().constGet() );
326 break;
327 case Within:
328 isMatch = engine->within( testFeature.geometry().constGet() );
329 break;
330 case Crosses:
331 isMatch = engine->crosses( testFeature.geometry().constGet() );
332 break;
333 }
334 if ( isMatch )
335 break;
336 }
337
338 if ( isMatch )
339 {
340 foundSet.insert( testFeature.id() );
341 handleFeatureFunction( testFeature );
342 }
343
344 }
345
346 current += 1;
347 feedback->setProgress( current * step );
348 }
349
350 if ( predicates.contains( Disjoint ) )
351 {
352 disjointSet = disjointSet.subtract( foundSet );
353 QgsFeatureRequest disjointReq = QgsFeatureRequest().setFilterFids( disjointSet );
354 if ( onlyRequireTargetIds )
356 QgsFeatureIterator disjointIt = targetSource->getFeatures( disjointReq );
357 QgsFeature f;
358 while ( disjointIt.nextFeature( f ) )
359 {
360 handleFeatureFunction( f );
361 }
362 }
363}
364
365
366//
367// QgsSelectByLocationAlgorithm
368//
369
370void QgsSelectByLocationAlgorithm::initAlgorithm( const QVariantMap & )
371{
372 QStringList methods = QStringList() << QObject::tr( "creating new selection" )
373 << QObject::tr( "adding to current selection" )
374 << QObject::tr( "selecting within current selection" )
375 << QObject::tr( "removing from current selection" );
376
377 addParameter( new QgsProcessingParameterVectorLayer( QStringLiteral( "INPUT" ), QObject::tr( "Select features from" ),
378 QList< int >() << static_cast< int >( Qgis::ProcessingSourceType::VectorAnyGeometry ) ) );
379 addPredicateParameter();
380 addParameter( new QgsProcessingParameterFeatureSource( QStringLiteral( "INTERSECT" ),
381 QObject::tr( "By comparing to the features from" ),
382 QList< int >() << static_cast< int >( Qgis::ProcessingSourceType::VectorAnyGeometry ) ) );
383
384 addParameter( new QgsProcessingParameterEnum( QStringLiteral( "METHOD" ),
385 QObject::tr( "Modify current selection by" ),
386 methods, false, 0 ) );
387}
388
389QString QgsSelectByLocationAlgorithm::name() const
390{
391 return QStringLiteral( "selectbylocation" );
392}
393
394Qgis::ProcessingAlgorithmFlags QgsSelectByLocationAlgorithm::flags() const
395{
397}
398
399QString QgsSelectByLocationAlgorithm::displayName() const
400{
401 return QObject::tr( "Select by location" );
402}
403
404QStringList QgsSelectByLocationAlgorithm::tags() const
405{
406 return QObject::tr( "select,intersects,intersecting,disjoint,touching,within,contains,overlaps,relation" ).split( ',' );
407}
408
409QString QgsSelectByLocationAlgorithm::group() const
410{
411 return QObject::tr( "Vector selection" );
412}
413
414QString QgsSelectByLocationAlgorithm::groupId() const
415{
416 return QStringLiteral( "vectorselection" );
417}
418
419QString QgsSelectByLocationAlgorithm::shortHelpString() const
420{
421 return QObject::tr( "This algorithm creates a selection in a vector layer. The criteria for selecting "
422 "features is based on the spatial relationship between each feature and the features in an additional layer." );
423}
424
425QgsSelectByLocationAlgorithm *QgsSelectByLocationAlgorithm::createInstance() const
426{
427 return new QgsSelectByLocationAlgorithm();
428}
429
430QVariantMap QgsSelectByLocationAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
431{
432 QgsVectorLayer *selectLayer = parameterAsVectorLayer( parameters, QStringLiteral( "INPUT" ), context );
433 if ( !selectLayer )
434 throw QgsProcessingException( QObject::tr( "Could not load source layer for INPUT" ) );
435
436 Qgis::SelectBehavior method = static_cast< Qgis::SelectBehavior >( parameterAsEnum( parameters, QStringLiteral( "METHOD" ), context ) );
437 std::unique_ptr< QgsFeatureSource > intersectSource( parameterAsSource( parameters, QStringLiteral( "INTERSECT" ), context ) );
438 if ( !intersectSource )
439 throw QgsProcessingException( invalidSourceError( parameters, QStringLiteral( "INTERSECT" ) ) );
440
441 const QList< int > selectedPredicates = parameterAsEnums( parameters, QStringLiteral( "PREDICATE" ), context );
442
443 QgsFeatureIds selectedIds;
444 auto addToSelection = [&]( const QgsFeature & feature )
445 {
446 selectedIds.insert( feature.id() );
447 };
448
449 mTargetCrs = selectLayer->sourceCrs();
450 mTargetFeatureCount = selectLayer->featureCount();
451 mIntersectFeatureCount = intersectSource->featureCount();
452
453 switch ( method )
454 {
457 {
458 // When subsetting or removing we only need to check already selected features
459 std::unique_ptr< QgsVectorLayerSelectedFeatureSource > selectLayerSelected( new QgsVectorLayerSelectedFeatureSource( selectLayer ) );
460 mTargetCrs = selectLayerSelected->sourceCrs();
461 mTargetFeatureCount = selectLayerSelected->featureCount();
462 process( context, selectLayerSelected.get(), intersectSource.get(), selectedPredicates, addToSelection, true, feedback );
463 break;
464 }
466 // When adding we can skip checking already selected features
467 process( context, selectLayer, intersectSource.get(), selectedPredicates, addToSelection, true, feedback, selectLayer->selectedFeatureIds() );
468 break;
470 process( context, selectLayer, intersectSource.get(), selectedPredicates, addToSelection, true, feedback );
471 break;
472 }
473
474 selectLayer->selectByIds( selectedIds, method );
475 QVariantMap results;
476 results.insert( QStringLiteral( "OUTPUT" ), parameters.value( QStringLiteral( "INPUT" ) ) );
477 return results;
478}
479
480
481//
482// QgsExtractByLocationAlgorithm
483//
484
485void QgsExtractByLocationAlgorithm::initAlgorithm( const QVariantMap & )
486{
487 addParameter( new QgsProcessingParameterFeatureSource( QStringLiteral( "INPUT" ),
488 QObject::tr( "Extract features from" ),
489 QList< int >() << static_cast< int >( Qgis::ProcessingSourceType::VectorAnyGeometry ) ) );
490 addPredicateParameter();
491 addParameter( new QgsProcessingParameterFeatureSource( QStringLiteral( "INTERSECT" ),
492 QObject::tr( "By comparing to the features from" ),
493 QList< int >() << static_cast< int >( Qgis::ProcessingSourceType::VectorAnyGeometry ) ) );
494
495 addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "OUTPUT" ), QObject::tr( "Extracted (location)" ) ) );
496}
497
498QString QgsExtractByLocationAlgorithm::name() const
499{
500 return QStringLiteral( "extractbylocation" );
501}
502
503QString QgsExtractByLocationAlgorithm::displayName() const
504{
505 return QObject::tr( "Extract by location" );
506}
507
508QStringList QgsExtractByLocationAlgorithm::tags() const
509{
510 return QObject::tr( "extract,filter,intersects,intersecting,disjoint,touching,within,contains,overlaps,relation" ).split( ',' );
511}
512
513QString QgsExtractByLocationAlgorithm::group() const
514{
515 return QObject::tr( "Vector selection" );
516}
517
518QString QgsExtractByLocationAlgorithm::groupId() const
519{
520 return QStringLiteral( "vectorselection" );
521}
522
523QString QgsExtractByLocationAlgorithm::shortHelpString() const
524{
525 return QObject::tr( "This algorithm creates a new vector layer that only contains matching features from an "
526 "input layer. The criteria for adding features to the resulting layer is defined "
527 "based on the spatial relationship between each feature and the features in an additional layer." );
528}
529
530QgsExtractByLocationAlgorithm *QgsExtractByLocationAlgorithm::createInstance() const
531{
532 return new QgsExtractByLocationAlgorithm();
533}
534
535bool QgsExtractByLocationAlgorithm::prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback * )
536{
537
538 std::unique_ptr< QgsFeatureSource > input( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
539 if ( !input )
540 throw QgsProcessingException( invalidSourceError( parameters, QStringLiteral( "INPUT" ) ) );
541 std::unique_ptr< QgsFeatureSource > intersectSource( parameterAsSource( parameters, QStringLiteral( "INTERSECT" ), context ) );
542 if ( !intersectSource )
543 throw QgsProcessingException( invalidSourceError( parameters, QStringLiteral( "INTERSECT" ) ) );
544
545 mTargetCrs = input->sourceCrs();
546 mTargetFeatureCount = input->featureCount();
547 mIntersectFeatureCount = intersectSource->featureCount();
548
549 return true;
550}
551
552QVariantMap QgsExtractByLocationAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
553{
554 std::unique_ptr< QgsFeatureSource > input( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
555 if ( !input )
556 throw QgsProcessingException( invalidSourceError( parameters, QStringLiteral( "INPUT" ) ) );
557 std::unique_ptr< QgsFeatureSource > intersectSource( parameterAsSource( parameters, QStringLiteral( "INTERSECT" ), context ) );
558 if ( !intersectSource )
559 throw QgsProcessingException( invalidSourceError( parameters, QStringLiteral( "INTERSECT" ) ) );
560
561 const QList< int > selectedPredicates = parameterAsEnums( parameters, QStringLiteral( "PREDICATE" ), context );
562 QString dest;
563 std::unique_ptr< QgsFeatureSink > sink( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, dest, input->fields(), input->wkbType(), mTargetCrs ) );
564
565 if ( !sink )
566 throw QgsProcessingException( invalidSinkError( parameters, QStringLiteral( "OUTPUT" ) ) );
567
568 auto addToSink = [&]( const QgsFeature & feature )
569 {
570 QgsFeature f = feature;
571 if ( !sink->addFeature( f, QgsFeatureSink::FastInsert ) )
572 throw QgsProcessingException( writeFeatureError( sink.get(), parameters, QStringLiteral( "OUTPUT" ) ) );
573 };
574 process( context, input.get(), intersectSource.get(), selectedPredicates, addToSink, false, feedback );
575
576 QVariantMap results;
577 results.insert( QStringLiteral( "OUTPUT" ), dest );
578 return results;
579}
580
582
583
@ VectorAnyGeometry
Any vector layer with geometry.
@ NotPresent
No spatial index exists for the source.
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
QFlags< ProcessingAlgorithmFlag > ProcessingAlgorithmFlags
Flags indicating how and when an algorithm operates and should be exposed to users.
Definition qgis.h:3076
@ NotAvailableInStandaloneTool
Algorithm should not be available from the standalone "qgis_process" tool. Used to flag algorithms wh...
@ NoThreading
Algorithm is not thread safe and cannot be run in a background thread, e.g. for algorithms which mani...
SelectBehavior
Specifies how a selection should be applied.
Definition qgis.h:1441
@ SetSelection
Set selection, removing any existing selection.
@ AddToSelection
Add selection to current selection.
@ IntersectSelection
Modify current selection to include only select features which match.
@ RemoveFromSelection
Remove from current selection.
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
Fetch next feature and stores in f, returns true on success.
This class wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & setFlags(Qgis::FeatureRequestFlags flags)
Sets flags that affect how features will be fetched.
QgsFeatureRequest & setFilterFids(const QgsFeatureIds &fids)
Sets the feature IDs that should be fetched.
QgsFeatureRequest & setDestinationCrs(const QgsCoordinateReferenceSystem &crs, const QgsCoordinateTransformContext &context)
Sets the destination crs for feature's geometries.
QgsFeatureRequest & setNoAttributes()
Set that no attributes will be fetched.
QgsFeatureRequest & setFilterRect(const QgsRectangle &rectangle)
Sets the rectangle from which features will be taken.
@ FastInsert
Use faster inserts, at the cost of updating the passed features to reflect changes made at the provid...
An interface for objects which provide features via a getFeatures method.
virtual Qgis::SpatialIndexPresence hasSpatialIndex() const
Returns an enum value representing the presence of a valid spatial index on the source,...
virtual QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const =0
Returns an iterator for the features in the source.
virtual long long featureCount() const =0
Returns the number of features contained in the source, or -1 if the feature count is unknown.
virtual QgsFeatureIds allFeatureIds() const
Returns a list of all feature IDs for features present in the source.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition qgsfeature.h:58
QgsFeatureId id
Definition qgsfeature.h:66
QgsGeometry geometry
Definition qgsfeature.h:69
bool hasGeometry() const
Returns true if the feature has an associated geometry.
bool isCanceled() const
Tells whether the operation has been canceled already.
Definition qgsfeedback.h:53
void setProgress(double progress)
Sets the current progress for the feedback object.
Definition qgsfeedback.h:61
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
QgsRectangle boundingBox() const
Returns the bounding box of the geometry.
static QgsGeometryEngine * createGeometryEngine(const QgsAbstractGeometry *geometry, double precision=0.0)
Creates and returns a new geometry engine representing the specified geometry using precision on a gr...
virtual Qgis::ProcessingAlgorithmFlags 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.
QgsCoordinateTransformContext transformContext() const
Returns the coordinate transform context.
Custom exception class for processing related exceptions.
Base class for providing feedback from a processing algorithm.
virtual void pushWarning(const QString &warning)
Pushes a warning informational message from the algorithm.
An enum based parameter for processing algorithms, allowing for selection from predefined values.
A feature sink output for processing algorithms.
An input feature source (such as vector layers) parameter for processing algorithms.
A vector layer (with or without geometry) parameter for processing algorithms.
A rectangle specified with double values.
QgsFeatureSource subclass for the selected features from a QgsVectorLayer.
Represents a vector layer which manages a vector based data sets.
long long featureCount(const QString &legendKey) const
Number of features rendered with specified legend key.
QgsCoordinateReferenceSystem sourceCrs() const FINAL
Returns the coordinate reference system for features in the source.
Q_INVOKABLE const QgsFeatureIds & selectedFeatureIds() const
Returns a list of the selected features IDs in this layer.
Q_INVOKABLE void selectByIds(const QgsFeatureIds &ids, Qgis::SelectBehavior behavior=Qgis::SelectBehavior::SetSelection)
Selects matching features using a list of feature IDs.
QSet< QgsFeatureId > QgsFeatureIds