Skip to content

Commit

Permalink
More heuristics to determine whether to iterate over target source
Browse files Browse the repository at this point in the history
  • Loading branch information
strk committed Oct 14, 2021
1 parent 8f37bba commit 1cb502a
Showing 1 changed file with 46 additions and 14 deletions.
60 changes: 46 additions & 14 deletions src/analysis/processing/qgsalgorithmdistancewithin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,28 +39,60 @@ void QgsDistanceWithinAlgorithm::process( const QgsProcessingContext &context, Q
bool onlyRequireTargetIds,
QgsProcessingFeedback *feedback, QgsExpressionContext &expressionContext )
{
const bool isDynamicDistance = distanceProperty.isActive();
// By default we will iterate over the reference source and match back
// to the target source. We do this on the assumption that the most common
// use case is joining a points layer to a polygon layer (e.g. findings
// points near a polygon), so by iterating
// over the polygons we can take advantage of prepared geometries for
// the spatial relationship test.
bool iterateOverTarget = false;

//
// Possible reasons to iterate over target are considered here
//
do
{
// If distance is dynamic, we MUST iterate over target
if ( distanceProperty.isActive() )
{
iterateOverTarget = true;
break;
}

// If reference needs reprojection, we MUST iterate over target
if ( targetSource->sourceCrs() != referenceSource->sourceCrs() )
{
iterateOverTarget = true;
break;
}

// if reference is POINTs and target is not, we prefer iterating
// over target, to benefit from preparation
if ( referenceSource->wkbType() == QgsWkbTypes::Point &&
targetSource->wkbType() != QgsWkbTypes::Point )
{
iterateOverTarget = true;
break;
}

if ( targetSource->sourceCrs() != referenceSource->sourceCrs()
|| isDynamicDistance
|| (
targetSource->featureCount() > 0 && referenceSource->featureCount() > 0
&& targetSource->featureCount() < referenceSource->featureCount() ) )
// neither source nor target or both of them are POINTs, we will
// iterate over the source with FEWER features to prepare less
if ( targetSource->featureCount() < referenceSource->featureCount() )
{
iterateOverTarget = true;
break;
}
}
while ( 0 );

if ( iterateOverTarget )
{
// joining FEWER features to a layer with MORE features. So we iterate over the FEW features and find matches from the MANY
// (note that we HAVE to do this if we have layers from two different CRSes, or if we are using dynamic distance!)
processByIteratingOverTargetSource( context, targetSource, referenceSource,
distance, distanceProperty, handleFeatureFunction,
onlyRequireTargetIds, feedback, expressionContext );
}
else
{
// default -- iterate over the reference source and match back to the target source. We do this on the assumption that the most common
// use case is joining a points layer to a polygon layer (e.g. findings points near a polygon), so by iterating
// over the polygons we can take advantage of prepared geometries for the spatial relationship test.

// TODO - consider using more heuristics to determine whether it's always best to iterate over the reference
// source.
processByIteratingOverReferenceSource( context, targetSource, referenceSource,
distance, handleFeatureFunction,
onlyRequireTargetIds, feedback );
Expand Down

0 comments on commit 1cb502a

Please sign in to comment.