26using namespace Qt::StringLiterals;
30void QgsLocationBasedAlgorithm::addPredicateParameter()
33 = std::make_unique<QgsProcessingParameterEnum>( u
"PREDICATE"_s, QObject::tr(
"Where the features (geometric predicate)" ), predicateOptionsList(),
true, QVariant::fromValue( QList<int>() << 0 ) );
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 );
42 addParameter( predicateParam.release() );
45QgsLocationBasedAlgorithm::Predicate QgsLocationBasedAlgorithm::reversePredicate( QgsLocationBasedAlgorithm::Predicate predicate )
const
70QStringList QgsLocationBasedAlgorithm::predicateOptionsList()
const
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" );
83void QgsLocationBasedAlgorithm::process(
87 const QList<int> &selectedPredicates,
88 const std::function<
void(
const QgsFeature & )> &handleFeatureFunction,
89 bool onlyRequireTargetIds,
95 if ( mTargetFeatureCount == 0 )
99 if ( mIntersectFeatureCount == 0 && !selectedPredicates.contains( Disjoint ) )
102 if ( mTargetFeatureCount > 0 && mIntersectFeatureCount > 0 && mTargetFeatureCount < mIntersectFeatureCount )
105 processByIteratingOverTargetSource( context, targetSource, intersectSource, selectedPredicates, handleFeatureFunction, onlyRequireTargetIds, feedback, skipTargetFeatureIds );
115 processByIteratingOverIntersectSource( context, targetSource, intersectSource, selectedPredicates, handleFeatureFunction, onlyRequireTargetIds, feedback, skipTargetFeatureIds );
119void QgsLocationBasedAlgorithm::processByIteratingOverTargetSource(
123 const QList<int> &selectedPredicates,
124 const std::function<
void(
const QgsFeature & )> &handleFeatureFunction,
125 bool onlyRequireTargetIds,
131 feedback->
pushWarning( QObject::tr(
"No spatial index exists for intersect layer, performance will be severely degraded" ) );
135 if ( onlyRequireTargetIds )
139 double step = mTargetFeatureCount > 0 ? 100.0 /
static_cast<double>( mTargetFeatureCount ) : 1;
142 std::unique_ptr<QgsGeometryEngine> engine;
149 if ( skipTargetFeatureIds.contains( f.
id() ) )
161 bool isMatch =
false;
162 bool isDisjoint =
true;
171 engine->prepareGeometry();
174 for (
int predicate : selectedPredicates )
176 switch (
static_cast<Predicate
>( predicate ) )
213 foundSet.insert( f.
id() );
214 handleFeatureFunction( f );
218 if ( isDisjoint && selectedPredicates.contains( Disjoint ) )
220 foundSet.insert( f.
id() );
221 handleFeatureFunction( f );
229void QgsLocationBasedAlgorithm::processByIteratingOverIntersectSource(
233 const QList<int> &selectedPredicates,
234 const std::function<
void(
const QgsFeature & )> &handleFeatureFunction,
235 bool onlyRequireTargetIds,
241 feedback->
pushWarning( QObject::tr(
"No spatial index exists for input layer, performance will be severely degraded" ) );
246 QList<Predicate> predicates;
247 predicates.reserve( selectedPredicates.count() );
248 for (
int i : selectedPredicates )
250 predicates << reversePredicate( static_cast<Predicate>( i ) );
254 if ( predicates.contains( Disjoint ) )
260 double step = mIntersectFeatureCount > 0 ? 100.0 /
static_cast<double>( mIntersectFeatureCount ) : 1;
263 std::unique_ptr<QgsGeometryEngine> engine;
276 if ( onlyRequireTargetIds )
286 if ( skipTargetFeatureIds.contains( testFeature.
id() ) )
291 if ( foundSet.contains( testFeature.
id() ) )
296 if ( predicates.count() == 1 && predicates.at( 0 ) == Disjoint && !disjointSet.contains( testFeature.
id() ) )
305 engine->prepareGeometry();
308 bool isMatch =
false;
310 for ( Predicate predicate : std::as_const( predicates ) )
323 disjointSet.remove( testFeature.
id() );
348 foundSet.insert( testFeature.
id() );
349 handleFeatureFunction( testFeature );
357 if ( predicates.contains( Disjoint ) )
359 disjointSet = disjointSet.subtract( foundSet );
361 if ( onlyRequireTargetIds )
367 handleFeatureFunction( f );
377void QgsSelectByLocationAlgorithm::initAlgorithm(
const QVariantMap & )
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" );
386 addPredicateParameter();
391 addParameter(
new QgsProcessingParameterEnum( u
"METHOD"_s, QObject::tr(
"Modify current selection by" ), methods,
false, 0 ) );
394QString QgsSelectByLocationAlgorithm::name()
const
396 return u
"selectbylocation"_s;
404QString QgsSelectByLocationAlgorithm::displayName()
const
406 return QObject::tr(
"Select by location" );
409QStringList QgsSelectByLocationAlgorithm::tags()
const
411 return QObject::tr(
"select,intersects,intersecting,disjoint,touching,within,contains,overlaps,relation" ).split(
',' );
414QString QgsSelectByLocationAlgorithm::group()
const
416 return QObject::tr(
"Vector selection" );
419QString QgsSelectByLocationAlgorithm::groupId()
const
421 return u
"vectorselection"_s;
424QString QgsSelectByLocationAlgorithm::shortHelpString()
const
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."
432QString QgsSelectByLocationAlgorithm::shortDescription()
const
434 return QObject::tr(
"Creates a selection in a vector layer based on the spatial relationship with features in an additional layer." );
437QgsSelectByLocationAlgorithm *QgsSelectByLocationAlgorithm::createInstance()
const
439 return new QgsSelectByLocationAlgorithm();
444 QGS_MARK_ALGORITHM_SOURCE
446 QgsVectorLayer *selectLayer = parameterAsVectorLayer( parameters, u
"INPUT"_s, context );
451 std::unique_ptr<QgsFeatureSource> intersectSource( parameterAsSource( parameters, u
"INTERSECT"_s, context ) );
452 if ( !intersectSource )
455 const QList<int> selectedPredicates = parameterAsEnums( parameters, u
"PREDICATE"_s, context );
458 auto addToSelection = [&](
const QgsFeature &feature ) { selectedIds.insert( feature.id() ); };
460 mTargetCrs = selectLayer->sourceCrs();
461 mTargetFeatureCount = selectLayer->featureCount();
462 mIntersectFeatureCount = intersectSource->
featureCount();
470 auto selectLayerSelected = std::make_unique<QgsVectorLayerSelectedFeatureSource>( selectLayer );
471 mTargetCrs = selectLayerSelected->sourceCrs();
472 mTargetFeatureCount = selectLayerSelected->featureCount();
473 process( context, selectLayerSelected.get(), intersectSource.get(), selectedPredicates, addToSelection,
true, feedback );
478 process( context, selectLayer, intersectSource.get(), selectedPredicates, addToSelection,
true, feedback, selectLayer->selectedFeatureIds() );
481 process( context, selectLayer, intersectSource.get(), selectedPredicates, addToSelection,
true, feedback );
485 selectLayer->selectByIds( selectedIds, method );
487 results.insert( u
"OUTPUT"_s, parameters.value( u
"INPUT"_s ) );
496void QgsExtractByLocationAlgorithm::initAlgorithm(
const QVariantMap & )
499 addPredicateParameter();
507QString QgsExtractByLocationAlgorithm::name()
const
509 return u
"extractbylocation"_s;
512QString QgsExtractByLocationAlgorithm::displayName()
const
514 return QObject::tr(
"Extract by location" );
517QStringList QgsExtractByLocationAlgorithm::tags()
const
519 return QObject::tr(
"extract,filter,intersects,intersecting,disjoint,touching,within,contains,overlaps,relation" ).split(
',' );
522QString QgsExtractByLocationAlgorithm::group()
const
524 return QObject::tr(
"Vector selection" );
527QString QgsExtractByLocationAlgorithm::groupId()
const
529 return u
"vectorselection"_s;
532QString QgsExtractByLocationAlgorithm::shortHelpString()
const
535 "This algorithm creates a new vector layer that only contains matching features from an "
536 "input layer. The criteria for adding features to the resulting layer is defined "
537 "based on the spatial relationship between each feature and the features in an additional layer."
541QString QgsExtractByLocationAlgorithm::shortDescription()
const
543 return QObject::tr(
"Creates a vector layer that only contains features matching a spatial relationship with the features in an additional layer." );
546QgsExtractByLocationAlgorithm *QgsExtractByLocationAlgorithm::createInstance()
const
548 return new QgsExtractByLocationAlgorithm();
553 std::unique_ptr<QgsFeatureSource> input( parameterAsSource( parameters, u
"INPUT"_s, context ) );
556 std::unique_ptr<QgsFeatureSource> intersectSource( parameterAsSource( parameters, u
"INTERSECT"_s, context ) );
557 if ( !intersectSource )
560 mTargetCrs = input->sourceCrs();
561 mTargetFeatureCount = input->featureCount();
562 mIntersectFeatureCount = intersectSource->
featureCount();
569 QGS_MARK_ALGORITHM_SOURCE
571 std::unique_ptr<QgsFeatureSource> input( parameterAsSource( parameters, u
"INPUT"_s, context ) );
574 std::unique_ptr<QgsFeatureSource> intersectSource( parameterAsSource( parameters, u
"INTERSECT"_s, context ) );
575 if ( !intersectSource )
578 const QList<int> selectedPredicates = parameterAsEnums( parameters, u
"PREDICATE"_s, context );
580 std::unique_ptr<QgsFeatureSink> sink( parameterAsSink( parameters, u
"OUTPUT"_s, context, dest, input->fields(), input->wkbType(), mTargetCrs ) );
585 auto addToSink = [&](
const QgsFeature &feature ) {
590 process( context, input.get(), intersectSource.get(), selectedPredicates, addToSink,
false, feedback );
596 results.insert( u
"OUTPUT"_s, dest );
@ 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.
@ 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.
@ 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.
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...
bool hasGeometry() const
Returns true if the feature has an associated geometry.
bool isCanceled() const
Tells whether the operation has been canceled already.
void setProgress(double progress)
Sets the current progress for the feedback object.
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.
void featureSinkFinalized(const QString &output)
Reports that a feature sink has been finalized.
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.
QSet< QgsFeatureId > QgsFeatureIds