Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[memory] Fix inefficient memory feature iteration when using a Filter…
…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

(cherry picked from commit 6fb7856)
  • Loading branch information
nyalldawson committed Feb 12, 2019
1 parent 05933ef commit 197625d
Showing 1 changed file with 22 additions and 3 deletions.
25 changes: 22 additions & 3 deletions src/core/providers/memory/qgsmemoryfeatureiterator.cpp
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 197625d

Please sign in to comment.