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