Skip to content

Commit

Permalink
[memory] Fix inefficient memory feature iteration when using a Filter…
Browse files Browse the repository at this point in the history
…Fids request

The request was not being handled correctly by the provider, resulting
in the provider iterating through every feature in the layer at every
attempt to retrieve a particular feature from a list of IDs.

Greatly speeds up numerous Processing algorithms when working
with temporary outputs
  • Loading branch information
nyalldawson committed Feb 12, 2019
1 parent 916805c commit 6fb7856
Showing 1 changed file with 22 additions and 3 deletions.
25 changes: 22 additions & 3 deletions src/core/providers/memory/qgsmemoryfeatureiterator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,11 @@ QgsMemoryFeatureIterator::QgsMemoryFeatureIterator( QgsMemoryFeatureSource *sour
if ( it != mSource->mFeatures.constEnd() )
mFeatureIdList.append( mRequest.filterFid() );
}
else if ( mRequest.filterType() == QgsFeatureRequest::FilterFids )
{
mUsingFeatureIdList = true;
mFeatureIdList = mRequest.filterFids().toList();
}
else
{
mUsingFeatureIdList = false;
Expand Down Expand Up @@ -105,11 +110,25 @@ bool QgsMemoryFeatureIterator::nextFeatureUsingList( QgsFeature &feature )
// option 1: we have a list of features to traverse
while ( mFeatureIdListIterator != mFeatureIdList.constEnd() )
{
if ( !mFilterRect.isNull() && mRequest.flags() & QgsFeatureRequest::ExactIntersect )
if ( !mFilterRect.isNull() )
{
// do exact check in case we're doing intersection
if ( mSource->mFeatures.value( *mFeatureIdListIterator ).hasGeometry() && mSelectRectEngine->intersects( mSource->mFeatures.value( *mFeatureIdListIterator ).geometry().constGet() ) )
if ( mRequest.flags() & QgsFeatureRequest::ExactIntersect )
{
// do exact check in case we're doing intersection
if ( mSource->mFeatures.value( *mFeatureIdListIterator ).hasGeometry() && mSelectRectEngine->intersects( mSource->mFeatures.value( *mFeatureIdListIterator ).geometry().constGet() ) )
hasFeature = true;
}
else if ( mSource->mSpatialIndex )
{
// using a spatial index - so we already know that the bounding box intersects correctly
hasFeature = true;
}
else
{
// do bounding box check if we aren't using a spatial index
if ( mSource->mFeatures.value( *mFeatureIdListIterator ).hasGeometry() && mSource->mFeatures.value( *mFeatureIdListIterator ).geometry().boundingBoxIntersects( mFilterRect ) )
hasFeature = true;
}
}
else
hasFeature = true;
Expand Down

0 comments on commit 6fb7856

Please sign in to comment.