Skip to content

Commit

Permalink
Only iterate selected/unselected features when removing/adding to sel…
Browse files Browse the repository at this point in the history
…ection
  • Loading branch information
uclaros authored and nyalldawson committed Nov 29, 2021
1 parent f9333a0 commit de44380
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 9 deletions.
41 changes: 35 additions & 6 deletions src/analysis/processing/qgsalgorithmextractbylocation.cpp
Expand Up @@ -18,6 +18,7 @@
#include "qgsalgorithmextractbylocation.h"
#include "qgsgeometryengine.h"
#include "qgsvectorlayer.h"
#include "qgsvectorlayerfeatureiterator.h"

///@cond PRIVATE

Expand Down Expand Up @@ -79,7 +80,8 @@ void QgsLocationBasedAlgorithm::process( const QgsProcessingContext &context, Qg
const QList< int > &selectedPredicates,
const std::function < void( const QgsFeature & ) > &handleFeatureFunction,
bool onlyRequireTargetIds,
QgsProcessingFeedback *feedback )
QgsProcessingFeedback *feedback,
const QgsFeatureIds &skipTargetFeatureIds )
{

if ( targetSource->featureCount() > 0 && intersectSource->featureCount() > 0
Expand All @@ -88,7 +90,7 @@ void QgsLocationBasedAlgorithm::process( const QgsProcessingContext &context, Qg
// joining FEWER features to a layer with MORE features. So we iterate over the FEW features and find matches from the MANY
processByIteratingOverTargetSource( context, targetSource, intersectSource,
selectedPredicates, handleFeatureFunction,
onlyRequireTargetIds, feedback );
onlyRequireTargetIds, feedback, skipTargetFeatureIds );
}
else
{
Expand All @@ -100,7 +102,7 @@ void QgsLocationBasedAlgorithm::process( const QgsProcessingContext &context, Qg
// source.
processByIteratingOverIntersectSource( context, targetSource, intersectSource,
selectedPredicates, handleFeatureFunction,
onlyRequireTargetIds, feedback );
onlyRequireTargetIds, feedback, skipTargetFeatureIds );
}
}

Expand All @@ -109,7 +111,8 @@ void QgsLocationBasedAlgorithm::processByIteratingOverTargetSource( const QgsPro
const QList< int > &selectedPredicates,
const std::function < void( const QgsFeature & ) > &handleFeatureFunction,
bool onlyRequireTargetIds,
QgsProcessingFeedback *feedback )
QgsProcessingFeedback *feedback,
const QgsFeatureIds &skipTargetFeatureIds )
{
if ( intersectSource->hasSpatialIndex() == QgsFeatureSource::SpatialIndexNotPresent )
feedback->pushWarning( QObject::tr( "No spatial index exists for intersect layer, performance will be severely degraded" ) );
Expand All @@ -129,6 +132,9 @@ void QgsLocationBasedAlgorithm::processByIteratingOverTargetSource( const QgsPro
if ( feedback->isCanceled() )
break;

// don't check features in skipTargetFeatureIds
if ( skipTargetFeatureIds.contains( f.id() ) )
continue;
if ( !f.hasGeometry() )
continue;

Expand Down Expand Up @@ -212,7 +218,8 @@ void QgsLocationBasedAlgorithm::processByIteratingOverIntersectSource( const Qgs
const QList< int > &selectedPredicates,
const std::function < void( const QgsFeature & ) > &handleFeatureFunction,
bool onlyRequireTargetIds,
QgsProcessingFeedback *feedback )
QgsProcessingFeedback *feedback,
const QgsFeatureIds &skipTargetFeatureIds )
{
if ( targetSource->hasSpatialIndex() == QgsFeatureSource::SpatialIndexNotPresent )
feedback->pushWarning( QObject::tr( "No spatial index exists for input layer, performance will be severely degraded" ) );
Expand Down Expand Up @@ -260,6 +267,11 @@ void QgsLocationBasedAlgorithm::processByIteratingOverIntersectSource( const Qgs
if ( feedback->isCanceled() )
break;

if ( skipTargetFeatureIds.contains( testFeature.id() ) )
{
// don't check features in skipTargetFeatureIds
continue;
}
if ( foundSet.contains( testFeature.id() ) )
{
// already added this one, no need for further tests
Expand Down Expand Up @@ -425,7 +437,24 @@ QVariantMap QgsSelectByLocationAlgorithm::processAlgorithm( const QVariantMap &p
{
selectedIds.insert( feature.id() );
};
process( context, selectLayer, intersectSource.get(), selectedPredicates, addToSelection, true, feedback );
switch ( method )
{
case Qgis::SelectBehavior::IntersectSelection:
case Qgis::SelectBehavior::RemoveFromSelection:
{
// When subsetting or removing we only need to check already selected features
std::unique_ptr< QgsVectorLayerSelectedFeatureSource > selectLayerSelected( new QgsVectorLayerSelectedFeatureSource( selectLayer ) );
process( context, selectLayerSelected.get(), intersectSource.get(), selectedPredicates, addToSelection, true, feedback );
break;
}
case Qgis::SelectBehavior::AddToSelection:
// When adding we can skip checking already selected features
process( context, selectLayer, intersectSource.get(), selectedPredicates, addToSelection, true, feedback, selectLayer->selectedFeatureIds() );
break;
case Qgis::SelectBehavior::SetSelection:
process( context, selectLayer, intersectSource.get(), selectedPredicates, addToSelection, true, feedback );
break;
}

selectLayer->selectByIds( selectedIds, method );
QVariantMap results;
Expand Down
6 changes: 3 additions & 3 deletions src/analysis/processing/qgsalgorithmextractbylocation.h
Expand Up @@ -50,13 +50,13 @@ class QgsLocationBasedAlgorithm : public QgsProcessingAlgorithm
void addPredicateParameter();
Predicate reversePredicate( Predicate predicate ) const;
QStringList predicateOptionsList() const;
void process( const QgsProcessingContext &context, QgsFeatureSource *targetSource, QgsFeatureSource *intersectSource, const QList<int> &selectedPredicates, const std::function< void( const QgsFeature & )> &handleFeatureFunction, bool onlyRequireTargetIds, QgsProcessingFeedback *feedback );
void process( const QgsProcessingContext &context, QgsFeatureSource *targetSource, QgsFeatureSource *intersectSource, const QList<int> &selectedPredicates, const std::function< void( const QgsFeature & )> &handleFeatureFunction, bool onlyRequireTargetIds, QgsProcessingFeedback *feedback, const QgsFeatureIds &skipTargetFeatureIds = QgsFeatureIds() );


private:

void processByIteratingOverTargetSource( const QgsProcessingContext &context, QgsFeatureSource *targetSource, QgsFeatureSource *intersectSource, const QList<int> &selectedPredicates, const std::function< void( const QgsFeature & )> &handleFeatureFunction, bool onlyRequireTargetIds, QgsProcessingFeedback *feedback );
void processByIteratingOverIntersectSource( const QgsProcessingContext &context, QgsFeatureSource *targetSource, QgsFeatureSource *intersectSource, const QList<int> &selectedPredicates, const std::function< void( const QgsFeature & )> &handleFeatureFunction, bool onlyRequireTargetIds, QgsProcessingFeedback *feedback );
void processByIteratingOverTargetSource( const QgsProcessingContext &context, QgsFeatureSource *targetSource, QgsFeatureSource *intersectSource, const QList<int> &selectedPredicates, const std::function< void( const QgsFeature & )> &handleFeatureFunction, bool onlyRequireTargetIds, QgsProcessingFeedback *feedback, const QgsFeatureIds &skipTargetFeatureIds );
void processByIteratingOverIntersectSource( const QgsProcessingContext &context, QgsFeatureSource *targetSource, QgsFeatureSource *intersectSource, const QList<int> &selectedPredicates, const std::function< void( const QgsFeature & )> &handleFeatureFunction, bool onlyRequireTargetIds, QgsProcessingFeedback *feedback, const QgsFeatureIds &skipTargetFeatureIds );
};


Expand Down

0 comments on commit de44380

Please sign in to comment.