QGIS API Documentation  3.14.0-Pi (9f7028fd23)
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"
21 
23 
24 void QgsLocationBasedAlgorithm::addPredicateParameter()
25 {
26  std::unique_ptr< QgsProcessingParameterEnum > predicateParam( new QgsProcessingParameterEnum( QStringLiteral( "PREDICATE" ),
27  QObject::tr( "Where the features (geometric predicate)" ),
28  predicateOptionsList(), true, QVariant::fromValue( QList< int >() << 0 ) ) );
29 
30  QVariantMap predicateMetadata;
31  QVariantMap widgetMetadata;
32  widgetMetadata.insert( QStringLiteral( "useCheckBoxes" ), true );
33  widgetMetadata.insert( QStringLiteral( "columns" ), 2 );
34  predicateMetadata.insert( QStringLiteral( "widget_wrapper" ), widgetMetadata );
35  predicateParam->setMetadata( predicateMetadata );
36 
37  addParameter( predicateParam.release() );
38 }
39 
40 QgsLocationBasedAlgorithm::Predicate QgsLocationBasedAlgorithm::reversePredicate( QgsLocationBasedAlgorithm::Predicate predicate ) const
41 {
42  switch ( predicate )
43  {
44  case Intersects:
45  return Intersects;
46  case Contains:
47  return Within;
48  case Disjoint:
49  return Disjoint;
50  case IsEqual:
51  return IsEqual;
52  case Touches:
53  return Touches;
54  case Overlaps:
55  return Overlaps;
56  case Within:
57  return Contains;
58  case Crosses:
59  return Crosses;
60  }
61  // no warnings
62  return Intersects;
63 }
64 
65 QStringList QgsLocationBasedAlgorithm::predicateOptionsList() const
66 {
67  return QStringList() << QObject::tr( "intersect" )
68  << QObject::tr( "contain" )
69  << QObject::tr( "disjoint" )
70  << QObject::tr( "equal" )
71  << QObject::tr( "touch" )
72  << QObject::tr( "overlap" )
73  << QObject::tr( "are within" )
74  << QObject::tr( "cross" );
75 }
76 
77 void QgsLocationBasedAlgorithm::process( const QgsProcessingContext &context, QgsFeatureSource *targetSource,
78  QgsFeatureSource *intersectSource,
79  const QList< int > &selectedPredicates,
80  const std::function < void( const QgsFeature & ) > &handleFeatureFunction,
81  bool onlyRequireTargetIds,
82  QgsProcessingFeedback *feedback )
83 {
84 
85  if ( targetSource->featureCount() > 0 && intersectSource->featureCount() > 0
86  && targetSource->featureCount() < intersectSource->featureCount() )
87  {
88  // joining FEWER features to a layer with MORE features. So we iterate over the FEW features and find matches from the MANY
89  processByIteratingOverTargetSource( context, targetSource, intersectSource,
90  selectedPredicates, handleFeatureFunction,
91  onlyRequireTargetIds, feedback );
92  }
93  else
94  {
95  // default -- iterate over the intersect source and match back to the target source. We do this on the assumption that the most common
96  // use case is joining a points layer to a polygon layer (e.g. findings points within a polygon), so by iterating
97  // over the polygons we can take advantage of prepared geometries for the spatial relationship test.
98 
99  // TODO - consider using more heuristics to determine whether it's always best to iterate over the intersect
100  // source.
101  processByIteratingOverIntersectSource( context, targetSource, intersectSource,
102  selectedPredicates, handleFeatureFunction,
103  onlyRequireTargetIds, feedback );
104  }
105 }
106 
107 void QgsLocationBasedAlgorithm::processByIteratingOverTargetSource( const QgsProcessingContext &context, QgsFeatureSource *targetSource,
108  QgsFeatureSource *intersectSource,
109  const QList< int > &selectedPredicates,
110  const std::function < void( const QgsFeature & ) > &handleFeatureFunction,
111  bool onlyRequireTargetIds,
112  QgsProcessingFeedback *feedback )
113 {
114  if ( intersectSource->hasSpatialIndex() == QgsFeatureSource::SpatialIndexNotPresent )
115  feedback->reportError( QObject::tr( "No spatial index exists for intersect layer, performance will be severely degraded" ) );
116 
117  QgsFeatureIds foundSet;
119  if ( onlyRequireTargetIds )
120  request.setNoAttributes();
121 
122  QgsFeatureIterator fIt = targetSource->getFeatures( request );
123  double step = targetSource->featureCount() > 0 ? 100.0 / targetSource->featureCount() : 1;
124  int current = 0;
125  QgsFeature f;
126  std::unique_ptr< QgsGeometryEngine > engine;
127  while ( fIt.nextFeature( f ) )
128  {
129  if ( feedback->isCanceled() )
130  break;
131 
132  if ( !f.hasGeometry() )
133  continue;
134 
135  engine.reset();
136 
137  QgsRectangle bbox = f.geometry().boundingBox();
138  request = QgsFeatureRequest().setFilterRect( bbox ).setNoAttributes().setDestinationCrs( targetSource->sourceCrs(), context.transformContext() );
139 
140  QgsFeatureIterator testFeatureIt = intersectSource->getFeatures( request );
141  QgsFeature testFeature;
142  bool isMatch = false;
143  bool isDisjoint = true;
144  while ( testFeatureIt.nextFeature( testFeature ) )
145  {
146  if ( feedback->isCanceled() )
147  break;
148 
149  if ( !engine )
150  {
151  engine.reset( QgsGeometry::createGeometryEngine( f.geometry().constGet() ) );
152  engine->prepareGeometry();
153  }
154 
155  for ( int predicate : selectedPredicates )
156  {
157  switch ( static_cast< Predicate>( predicate ) )
158  {
159  case Intersects:
160  isMatch = engine->intersects( testFeature.geometry().constGet() );
161  break;
162  case Contains:
163  isMatch = engine->contains( testFeature.geometry().constGet() );
164  break;
165  case Disjoint:
166  if ( engine->intersects( testFeature.geometry().constGet() ) )
167  {
168  isDisjoint = false;
169  }
170  break;
171  case IsEqual:
172  isMatch = engine->isEqual( testFeature.geometry().constGet() );
173  break;
174  case Touches:
175  isMatch = engine->touches( testFeature.geometry().constGet() );
176  break;
177  case Overlaps:
178  isMatch = engine->overlaps( testFeature.geometry().constGet() );
179  break;
180  case Within:
181  isMatch = engine->within( testFeature.geometry().constGet() );
182  break;
183  case Crosses:
184  isMatch = engine->crosses( testFeature.geometry().constGet() );
185  break;
186  }
187 
188  if ( isMatch )
189  break;
190  }
191 
192  if ( isMatch )
193  {
194  foundSet.insert( f.id() );
195  handleFeatureFunction( f );
196  break;
197  }
198  }
199  if ( isDisjoint && selectedPredicates.contains( Disjoint ) )
200  {
201  foundSet.insert( f.id() );
202  handleFeatureFunction( f );
203  }
204 
205  current += 1;
206  feedback->setProgress( current * step );
207  }
208 }
209 
210 void QgsLocationBasedAlgorithm::processByIteratingOverIntersectSource( const QgsProcessingContext &context, QgsFeatureSource *targetSource,
211  QgsFeatureSource *intersectSource,
212  const QList< int > &selectedPredicates,
213  const std::function < void( const QgsFeature & ) > &handleFeatureFunction,
214  bool onlyRequireTargetIds,
215  QgsProcessingFeedback *feedback )
216 {
218  feedback->reportError( QObject::tr( "No spatial index exists for input layer, performance will be severely degraded" ) );
219 
220  // build a list of 'reversed' predicates, because in this function
221  // we actually test the reverse of what the user wants (allowing us
222  // to prepare geometries and optimise the algorithm)
223  QList< Predicate > predicates;
224  predicates.reserve( selectedPredicates.count() );
225  for ( int i : selectedPredicates )
226  {
227  predicates << reversePredicate( static_cast< Predicate >( i ) );
228  }
229 
230  QgsFeatureIds disjointSet;
231  if ( predicates.contains( Disjoint ) )
232  disjointSet = targetSource->allFeatureIds();
233 
234  QgsFeatureIds foundSet;
236  QgsFeatureIterator fIt = intersectSource->getFeatures( request );
237  double step = intersectSource->featureCount() > 0 ? 100.0 / intersectSource->featureCount() : 1;
238  int current = 0;
239  QgsFeature f;
240  std::unique_ptr< QgsGeometryEngine > engine;
241  while ( fIt.nextFeature( f ) )
242  {
243  if ( feedback->isCanceled() )
244  break;
245 
246  if ( !f.hasGeometry() )
247  continue;
248 
249  engine.reset();
250 
251  QgsRectangle bbox = f.geometry().boundingBox();
252  request = QgsFeatureRequest().setFilterRect( bbox );
253  if ( onlyRequireTargetIds )
254  request.setNoAttributes();
255 
256  QgsFeatureIterator testFeatureIt = targetSource->getFeatures( request );
257  QgsFeature testFeature;
258  while ( testFeatureIt.nextFeature( testFeature ) )
259  {
260  if ( feedback->isCanceled() )
261  break;
262 
263  if ( foundSet.contains( testFeature.id() ) )
264  {
265  // already added this one, no need for further tests
266  continue;
267  }
268  if ( predicates.count() == 1 && predicates.at( 0 ) == Disjoint && !disjointSet.contains( testFeature.id() ) )
269  {
270  // calculating only the disjoint set, and we've already eliminated this feature so no need for further tests
271  continue;
272  }
273 
274  if ( !engine )
275  {
276  engine.reset( QgsGeometry::createGeometryEngine( f.geometry().constGet() ) );
277  engine->prepareGeometry();
278  }
279 
280  for ( Predicate predicate : qgis::as_const( predicates ) )
281  {
282  bool isMatch = false;
283  switch ( predicate )
284  {
285  case Intersects:
286  isMatch = engine->intersects( testFeature.geometry().constGet() );
287  break;
288  case Contains:
289  isMatch = engine->contains( testFeature.geometry().constGet() );
290  break;
291  case Disjoint:
292  if ( engine->intersects( testFeature.geometry().constGet() ) )
293  {
294  disjointSet.remove( testFeature.id() );
295  }
296  break;
297  case IsEqual:
298  isMatch = engine->isEqual( testFeature.geometry().constGet() );
299  break;
300  case Touches:
301  isMatch = engine->touches( testFeature.geometry().constGet() );
302  break;
303  case Overlaps:
304  isMatch = engine->overlaps( testFeature.geometry().constGet() );
305  break;
306  case Within:
307  isMatch = engine->within( testFeature.geometry().constGet() );
308  break;
309  case Crosses:
310  isMatch = engine->crosses( testFeature.geometry().constGet() );
311  break;
312  }
313  if ( isMatch )
314  {
315  foundSet.insert( testFeature.id() );
316  handleFeatureFunction( testFeature );
317  }
318  }
319 
320  }
321 
322  current += 1;
323  feedback->setProgress( current * step );
324  }
325 
326  if ( predicates.contains( Disjoint ) )
327  {
328  disjointSet = disjointSet.subtract( foundSet );
329  QgsFeatureRequest disjointReq = QgsFeatureRequest().setFilterFids( disjointSet );
330  if ( onlyRequireTargetIds )
332  QgsFeatureIterator disjointIt = targetSource->getFeatures( disjointReq );
333  QgsFeature f;
334  while ( disjointIt.nextFeature( f ) )
335  {
336  handleFeatureFunction( f );
337  }
338  }
339 }
340 
341 
342 //
343 // QgsSelectByLocationAlgorithm
344 //
345 
346 void QgsSelectByLocationAlgorithm::initAlgorithm( const QVariantMap & )
347 {
348  QStringList methods = QStringList() << QObject::tr( "creating new selection" )
349  << QObject::tr( "adding to current selection" )
350  << QObject::tr( "selecting within current selection" )
351  << QObject::tr( "removing from current selection" );
352 
353  addParameter( new QgsProcessingParameterVectorLayer( QStringLiteral( "INPUT" ), QObject::tr( "Select features from" ),
354  QList< int >() << QgsProcessing::TypeVectorAnyGeometry ) );
355  addPredicateParameter();
356  addParameter( new QgsProcessingParameterFeatureSource( QStringLiteral( "INTERSECT" ),
357  QObject::tr( "By comparing to the features from" ),
358  QList< int >() << QgsProcessing::TypeVectorAnyGeometry ) );
359 
360  addParameter( new QgsProcessingParameterEnum( QStringLiteral( "METHOD" ),
361  QObject::tr( "Modify current selection by" ),
362  methods, false, 0 ) );
363 }
364 
365 QString QgsSelectByLocationAlgorithm::name() const
366 {
367  return QStringLiteral( "selectbylocation" );
368 }
369 
370 QgsProcessingAlgorithm::Flags QgsSelectByLocationAlgorithm::flags() const
371 {
373 }
374 
375 QString QgsSelectByLocationAlgorithm::displayName() const
376 {
377  return QObject::tr( "Select by location" );
378 }
379 
380 QStringList QgsSelectByLocationAlgorithm::tags() const
381 {
382  return QObject::tr( "select,intersects,intersecting,disjoint,touching,within,contains,overlaps,relation" ).split( ',' );
383 }
384 
385 QString QgsSelectByLocationAlgorithm::group() const
386 {
387  return QObject::tr( "Vector selection" );
388 }
389 
390 QString QgsSelectByLocationAlgorithm::groupId() const
391 {
392  return QStringLiteral( "vectorselection" );
393 }
394 
395 QString QgsSelectByLocationAlgorithm::shortHelpString() const
396 {
397  return QObject::tr( "This algorithm creates a selection in a vector layer. The criteria for selecting "
398  "features is based on the spatial relationship between each feature and the features in an additional layer." );
399 }
400 
401 QgsSelectByLocationAlgorithm *QgsSelectByLocationAlgorithm::createInstance() const
402 {
403  return new QgsSelectByLocationAlgorithm();
404 }
405 
406 QVariantMap QgsSelectByLocationAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
407 {
408  QgsVectorLayer *selectLayer = parameterAsVectorLayer( parameters, QStringLiteral( "INPUT" ), context );
409  if ( !selectLayer )
410  throw QgsProcessingException( QObject::tr( "Could not load source layer for INPUT" ) );
411 
412  QgsVectorLayer::SelectBehavior method = static_cast< QgsVectorLayer::SelectBehavior >( parameterAsEnum( parameters, QStringLiteral( "METHOD" ), context ) );
413  std::unique_ptr< QgsFeatureSource > intersectSource( parameterAsSource( parameters, QStringLiteral( "INTERSECT" ), context ) );
414  if ( !intersectSource )
415  throw QgsProcessingException( invalidSourceError( parameters, QStringLiteral( "INTERSECT" ) ) );
416 
417  const QList< int > selectedPredicates = parameterAsEnums( parameters, QStringLiteral( "PREDICATE" ), context );
418 
419  QgsFeatureIds selectedIds;
420  auto addToSelection = [&]( const QgsFeature & feature )
421  {
422  selectedIds.insert( feature.id() );
423  };
424  process( context, selectLayer, intersectSource.get(), selectedPredicates, addToSelection, true, feedback );
425 
426  selectLayer->selectByIds( selectedIds, method );
427  QVariantMap results;
428  results.insert( QStringLiteral( "OUTPUT" ), parameters.value( QStringLiteral( "INPUT" ) ) );
429  return results;
430 }
431 
432 
433 //
434 // QgsExtractByLocationAlgorithm
435 //
436 
437 void QgsExtractByLocationAlgorithm::initAlgorithm( const QVariantMap & )
438 {
439  addParameter( new QgsProcessingParameterVectorLayer( QStringLiteral( "INPUT" ), QObject::tr( "Extract features from" ),
440  QList< int >() << QgsProcessing::TypeVectorAnyGeometry ) );
441  addPredicateParameter();
442  addParameter( new QgsProcessingParameterFeatureSource( QStringLiteral( "INTERSECT" ),
443  QObject::tr( "By comparing to the features from" ),
444  QList< int >() << QgsProcessing::TypeVectorAnyGeometry ) );
445 
446  addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "OUTPUT" ), QObject::tr( "Extracted (location)" ) ) );
447 }
448 
449 QString QgsExtractByLocationAlgorithm::name() const
450 {
451  return QStringLiteral( "extractbylocation" );
452 }
453 
454 QString QgsExtractByLocationAlgorithm::displayName() const
455 {
456  return QObject::tr( "Extract by location" );
457 }
458 
459 QStringList QgsExtractByLocationAlgorithm::tags() const
460 {
461  return QObject::tr( "extract,filter,intersects,intersecting,disjoint,touching,within,contains,overlaps,relation" ).split( ',' );
462 }
463 
464 QString QgsExtractByLocationAlgorithm::group() const
465 {
466  return QObject::tr( "Vector selection" );
467 }
468 
469 QString QgsExtractByLocationAlgorithm::groupId() const
470 {
471  return QStringLiteral( "vectorselection" );
472 }
473 
474 QString QgsExtractByLocationAlgorithm::shortHelpString() const
475 {
476  return QObject::tr( "This algorithm creates a new vector layer that only contains matching features from an "
477  "input layer. The criteria for adding features to the resulting layer is defined "
478  "based on the spatial relationship between each feature and the features in an additional layer." );
479 }
480 
481 QgsExtractByLocationAlgorithm *QgsExtractByLocationAlgorithm::createInstance() const
482 {
483  return new QgsExtractByLocationAlgorithm();
484 }
485 
486 QVariantMap QgsExtractByLocationAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
487 {
488  std::unique_ptr< QgsFeatureSource > input( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
489  if ( !input )
490  throw QgsProcessingException( invalidSourceError( parameters, QStringLiteral( "INPUT" ) ) );
491  std::unique_ptr< QgsFeatureSource > intersectSource( parameterAsSource( parameters, QStringLiteral( "INTERSECT" ), context ) );
492  if ( !intersectSource )
493  throw QgsProcessingException( invalidSourceError( parameters, QStringLiteral( "INTERSECT" ) ) );
494 
495  const QList< int > selectedPredicates = parameterAsEnums( parameters, QStringLiteral( "PREDICATE" ), context );
496  QString dest;
497  std::unique_ptr< QgsFeatureSink > sink( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, dest, input->fields(), input->wkbType(), input->sourceCrs() ) );
498 
499  if ( !sink )
500  throw QgsProcessingException( invalidSinkError( parameters, QStringLiteral( "OUTPUT" ) ) );
501 
502  auto addToSink = [&]( const QgsFeature & feature )
503  {
504  QgsFeature f = feature;
505  sink->addFeature( f, QgsFeatureSink::FastInsert );
506  };
507  process( context, input.get(), intersectSource.get(), selectedPredicates, addToSink, false, feedback );
508 
509  QVariantMap results;
510  results.insert( QStringLiteral( "OUTPUT" ), dest );
511  return results;
512 }
513 
515 
516 
517 
QgsFeatureRequest::NoGeometry
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
Definition: qgsfeaturerequest.h:107
QgsFeedback::setProgress
void setProgress(double progress)
Sets the current progress for the feedback object.
Definition: qgsfeedback.h:75
QgsFeatureSource::hasSpatialIndex
virtual SpatialIndexPresence hasSpatialIndex() const
Returns an enum value representing the presence of a valid spatial index on the source,...
Definition: qgsfeaturesource.cpp:190
QgsFeatureSource::sourceCrs
virtual QgsCoordinateReferenceSystem sourceCrs() const =0
Returns the coordinate reference system for features in the source.
QgsProcessingFeedback
Definition: qgsprocessingfeedback.h:37
QgsFeatureSource::SpatialIndexNotPresent
@ SpatialIndexNotPresent
No spatial index exists for the source.
Definition: qgsfeaturesource.h:190
QgsProcessingFeedback::reportError
virtual void reportError(const QString &error, bool fatalError=false)
Reports that the algorithm encountered an error while executing.
Definition: qgsprocessingfeedback.cpp:39
QgsFeature::geometry
QgsGeometry geometry
Definition: qgsfeature.h:71
QgsFeatureSource
Definition: qgsfeaturesource.h:37
QgsProcessingParameterFeatureSource
Definition: qgsprocessingparameters.h:2612
QgsVectorLayer::selectByIds
Q_INVOKABLE void selectByIds(const QgsFeatureIds &ids, QgsVectorLayer::SelectBehavior behavior=QgsVectorLayer::SetSelection)
Selects matching features using a list of feature IDs.
Definition: qgsvectorlayer.cpp:523
QgsRectangle
Definition: qgsrectangle.h:41
QgsProcessingParameterFeatureSink
Definition: qgsprocessingparameters.h:2773
QgsFeatureSource::allFeatureIds
virtual QgsFeatureIds allFeatureIds() const
Returns a list of all feature IDs for features present in the source.
Definition: qgsfeaturesource.cpp:115
QgsFeatureRequest::setFilterRect
QgsFeatureRequest & setFilterRect(const QgsRectangle &rectangle)
Sets the rectangle from which features will be taken.
Definition: qgsfeaturerequest.cpp:97
QgsFeature::id
QgsFeatureId id
Definition: qgsfeature.h:68
QgsFeatureRequest
Definition: qgsfeaturerequest.h:75
qgsgeometryengine.h
QgsProcessingContext
Definition: qgsprocessingcontext.h:43
QgsProcessing::TypeVectorAnyGeometry
@ TypeVectorAnyGeometry
Any vector layer with geometry.
Definition: qgsprocessing.h:47
QgsFeatureSource::getFeatures
virtual QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const =0
Returns an iterator for the features in the source.
QgsFeatureRequest::setFilterFids
QgsFeatureRequest & setFilterFids(const QgsFeatureIds &fids)
Sets feature IDs that should be fetched.
Definition: qgsfeaturerequest.cpp:110
QgsProcessingContext::transformContext
QgsCoordinateTransformContext transformContext() const
Returns the coordinate transform context.
Definition: qgsprocessingcontext.h:135
QgsGeometry::constGet
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
Definition: qgsgeometry.cpp:128
QgsProcessingParameterVectorLayer
Definition: qgsprocessingparameters.h:2382
QgsVectorLayer::SelectBehavior
SelectBehavior
Selection behavior.
Definition: qgsvectorlayer.h:410
QgsFeatureRequest::setNoAttributes
QgsFeatureRequest & setNoAttributes()
Set that no attributes will be fetched.
Definition: qgsfeaturerequest.cpp:197
QgsFeatureIds
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeatureid.h:34
QgsFeatureSource::featureCount
virtual long featureCount() const =0
Returns the number of features contained in the source, or -1 if the feature count is unknown.
qgsvectorlayer.h
QgsFeedback::isCanceled
bool isCanceled() const
Tells whether the operation has been canceled already.
Definition: qgsfeedback.h:66
QgsGeometry::createGeometryEngine
static QgsGeometryEngine * createGeometryEngine(const QgsAbstractGeometry *geometry)
Creates and returns a new geometry engine.
Definition: qgsgeometry.cpp:3659
QgsProcessingAlgorithm::FlagNoThreading
@ FlagNoThreading
Algorithm is not thread safe and cannot be run in a background thread, e.g. for algorithms which mani...
Definition: qgsprocessingalgorithm.h:75
QgsFeatureIterator::nextFeature
bool nextFeature(QgsFeature &f)
Definition: qgsfeatureiterator.h:373
QgsVectorLayer
Definition: qgsvectorlayer.h:385
QgsFeature::hasGeometry
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Definition: qgsfeature.cpp:197
qgsalgorithmextractbylocation.h
QgsGeometry::boundingBox
QgsRectangle boundingBox() const
Returns the bounding box of the geometry.
Definition: qgsgeometry.cpp:962
QgsFeature
Definition: qgsfeature.h:55
QgsFeatureRequest::setDestinationCrs
QgsFeatureRequest & setDestinationCrs(const QgsCoordinateReferenceSystem &crs, const QgsCoordinateTransformContext &context)
Sets the destination crs for feature's geometries.
Definition: qgsfeaturerequest.cpp:263
QgsProcessingParameterEnum
Definition: qgsprocessingparameters.h:2134
QgsProcessingAlgorithm::flags
virtual Flags flags() const
Returns the flags indicating how and when the algorithm operates and should be exposed to users.
Definition: qgsprocessingalgorithm.cpp:88
QgsFeatureIterator
Definition: qgsfeatureiterator.h:263
QgsFeatureRequest::setFlags
QgsFeatureRequest & setFlags(QgsFeatureRequest::Flags flags)
Sets flags that affect how features will be fetched.
Definition: qgsfeaturerequest.cpp:184
QgsProcessingException
Definition: qgsexception.h:82
QgsFeatureSink::FastInsert
@ FastInsert
Use faster inserts, at the cost of updating the passed features to reflect changes made at the provid...
Definition: qgsfeaturesink.h:70