29 QgsMemoryFeatureIterator::QgsMemoryFeatureIterator( QgsMemoryFeatureSource *source,
bool ownSource,
const QgsFeatureRequest &request )
32 if ( mRequest.destinationCrs().isValid() && mRequest.destinationCrs() != mSource->mCrs )
34 mTransform =
QgsCoordinateTransform( mSource->mCrs, mRequest.destinationCrs(), mRequest.transformContext() );
38 mFilterRect = filterRectToSourceCrs( mTransform );
47 if ( !mSource->mSubsetString.isEmpty() )
49 mSubsetExpression = qgis::make_unique< QgsExpression >( mSource->mSubsetString );
50 mSubsetExpression->prepare( &mSource->mExpressionContext );
57 mSelectRectEngine->prepareGeometry();
62 if ( !mFilterRect.isNull() && mSource->mSpatialIndex )
64 mUsingFeatureIdList =
true;
65 mFeatureIdList = mSource->mSpatialIndex->intersects( mFilterRect );
66 QgsDebugMsg(
"Features returned by spatial index: " + QString::number( mFeatureIdList.count() ) );
70 mUsingFeatureIdList =
true;
71 QgsFeatureMap::const_iterator it = mSource->mFeatures.constFind( mRequest.filterFid() );
72 if ( it != mSource->mFeatures.constEnd() )
73 mFeatureIdList.append( mRequest.filterFid() );
77 mUsingFeatureIdList =
true;
78 mFeatureIdList = mRequest.filterFids().toList();
82 mUsingFeatureIdList =
false;
88 QgsMemoryFeatureIterator::~QgsMemoryFeatureIterator()
93 bool QgsMemoryFeatureIterator::fetchFeature(
QgsFeature &feature )
100 if ( mUsingFeatureIdList )
101 return nextFeatureUsingList( feature );
103 return nextFeatureTraverseAll( feature );
107 bool QgsMemoryFeatureIterator::nextFeatureUsingList(
QgsFeature &feature )
109 bool hasFeature =
false;
113 while ( mFeatureIdListIterator != mFeatureIdList.constEnd() )
115 candidate = mSource->mFeatures.value( *mFeatureIdListIterator );
116 if ( !mFilterRect.isNull() )
124 else if ( mSource->mSpatialIndex )
139 if ( hasFeature && mSubsetExpression )
141 mSource->mExpressionContext.setFeature( candidate );
142 if ( !mSubsetExpression->evaluate( &mSource->mExpressionContext ).toBool() )
149 ++mFeatureIdListIterator;
156 ++mFeatureIdListIterator;
164 geometryToDestinationCrs( feature, mTransform );
171 bool QgsMemoryFeatureIterator::nextFeatureTraverseAll(
QgsFeature &feature )
173 bool hasFeature =
false;
176 while ( mSelectIterator != mSource->mFeatures.constEnd() )
178 if ( mFilterRect.isNull() )
188 if ( mSelectIterator->hasGeometry() && mSelectRectEngine->intersects( mSelectIterator->geometry().constGet() ) )
194 if ( mSelectIterator->hasGeometry() && mSelectIterator->geometry().boundingBox().intersects( mFilterRect ) )
199 if ( mSubsetExpression )
201 mSource->mExpressionContext.setFeature( *mSelectIterator );
202 if ( !mSubsetExpression->evaluate( &mSource->mExpressionContext ).toBool() )
215 feature = mSelectIterator.value();
219 geometryToDestinationCrs( feature, mTransform );
227 bool QgsMemoryFeatureIterator::rewind()
232 if ( mUsingFeatureIdList )
233 mFeatureIdListIterator = mFeatureIdList.constBegin();
235 mSelectIterator = mSource->mFeatures.constBegin();
240 bool QgsMemoryFeatureIterator::close()
253 QgsMemoryFeatureSource::QgsMemoryFeatureSource(
const QgsMemoryProvider *p )
254 : mFields( p->mFields )
255 , mFeatures( p->mFeatures )
256 , mSpatialIndex( p->mSpatialIndex ? qgis::make_unique<
QgsSpatialIndex >( *p->mSpatialIndex ) : nullptr )
257 , mSubsetString( p->mSubsetString )
262 mExpressionContext.setFields( mFields );
bool boundingBoxIntersects(const QgsRectangle &rectangle) const
Returns true if the bounding box of this geometry intersects with a rectangle.
Wrapper for iterator of features from vector data provider or vector layer.
Filter using feature IDs.
void setFields(const QgsFields &fields, bool initAttributes=false)
Assign a field map with the feature to allow attribute access by attribute name.
Use exact geometry intersection (slower) instead of bounding boxes.
static QgsExpressionContextScope * projectScope(const QgsProject *project)
Creates a new scope which contains variables and functions relating to a QGIS project.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
bool hasGeometry() const
Returns true if the feature has an associated geometry.
static QgsGeometry fromRect(const QgsRectangle &rect)
Creates a new geometry from a QgsRectangle.
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context...
This class wraps a request for features to a vector layer (or directly its vector data provider)...
static QgsGeometryEngine * createGeometryEngine(const QgsAbstractGeometry *geometry)
Creates and returns a new geometry engine.
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
void setValid(bool validity)
Sets the validity of the feature.
A spatial index for QgsFeature objects.
static QgsProject * instance()
Returns the QgsProject singleton instance.
Custom exception class for Coordinate Reference System related exceptions.
Helper template that cares of two things: 1.