28 QgsMemoryFeatureIterator::QgsMemoryFeatureIterator( QgsMemoryFeatureSource *source,
bool ownSource,
const QgsFeatureRequest &request )
31 if ( mRequest.destinationCrs().isValid() && mRequest.destinationCrs() != mSource->mCrs )
33 mTransform =
QgsCoordinateTransform( mSource->mCrs, mRequest.destinationCrs(), mRequest.transformContext() );
37 mFilterRect = filterRectToSourceCrs( mTransform );
46 if ( !mSource->mSubsetString.isEmpty() )
48 mSubsetExpression = qgis::make_unique< QgsExpression >( mSource->mSubsetString );
49 mSubsetExpression->prepare( &mSource->mExpressionContext );
56 mSelectRectEngine->prepareGeometry();
61 if ( !mFilterRect.isNull() && mSource->mSpatialIndex )
63 mUsingFeatureIdList =
true;
64 mFeatureIdList = mSource->mSpatialIndex->intersects( mFilterRect );
65 QgsDebugMsg(
"Features returned by spatial index: " + QString::number( mFeatureIdList.count() ) );
69 mUsingFeatureIdList =
true;
70 QgsFeatureMap::const_iterator it = mSource->mFeatures.constFind( mRequest.filterFid() );
71 if ( it != mSource->mFeatures.constEnd() )
72 mFeatureIdList.append( mRequest.filterFid() );
76 mUsingFeatureIdList =
true;
77 mFeatureIdList = mRequest.filterFids().toList();
81 mUsingFeatureIdList =
false;
87 QgsMemoryFeatureIterator::~QgsMemoryFeatureIterator()
92 bool QgsMemoryFeatureIterator::fetchFeature(
QgsFeature &feature )
99 if ( mUsingFeatureIdList )
100 return nextFeatureUsingList( feature );
102 return nextFeatureTraverseAll( feature );
106 bool QgsMemoryFeatureIterator::nextFeatureUsingList(
QgsFeature &feature )
108 bool hasFeature =
false;
112 while ( mFeatureIdListIterator != mFeatureIdList.constEnd() )
114 candidate = mSource->mFeatures.value( *mFeatureIdListIterator );
115 if ( !mFilterRect.isNull() )
123 else if ( mSource->mSpatialIndex )
138 if ( hasFeature && mSubsetExpression )
140 mSource->mExpressionContext.setFeature( candidate );
141 if ( !mSubsetExpression->evaluate( &mSource->mExpressionContext ).toBool() )
148 ++mFeatureIdListIterator;
155 ++mFeatureIdListIterator;
163 geometryToDestinationCrs( feature, mTransform );
170 bool QgsMemoryFeatureIterator::nextFeatureTraverseAll(
QgsFeature &feature )
172 bool hasFeature =
false;
175 while ( mSelectIterator != mSource->mFeatures.constEnd() )
177 if ( mFilterRect.isNull() )
187 if ( mSelectIterator->hasGeometry() && mSelectRectEngine->intersects( mSelectIterator->geometry().constGet() ) )
193 if ( mSelectIterator->hasGeometry() && mSelectIterator->geometry().boundingBox().intersects( mFilterRect ) )
198 if ( mSubsetExpression )
200 mSource->mExpressionContext.setFeature( *mSelectIterator );
201 if ( !mSubsetExpression->evaluate( &mSource->mExpressionContext ).toBool() )
214 feature = mSelectIterator.value();
218 geometryToDestinationCrs( feature, mTransform );
226 bool QgsMemoryFeatureIterator::rewind()
231 if ( mUsingFeatureIdList )
232 mFeatureIdListIterator = mFeatureIdList.constBegin();
234 mSelectIterator = mSource->mFeatures.constBegin();
239 bool QgsMemoryFeatureIterator::close()
252 QgsMemoryFeatureSource::QgsMemoryFeatureSource(
const QgsMemoryProvider *p )
253 : mFields( p->mFields )
254 , mFeatures( p->mFeatures )
255 , mSpatialIndex( p->mSpatialIndex ? qgis::make_unique<
QgsSpatialIndex >( *p->mSpatialIndex ) : nullptr )
256 , mSubsetString( p->mSubsetString )
261 mExpressionContext.setFields( mFields );
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...
static QgsGeometry fromRect(const QgsRectangle &rect)
Creates a new geometry from a QgsRectangle.
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context...
bool boundingBoxIntersects(const QgsRectangle &rectangle) const
Returns true if the bounding box of this geometry intersects with a rectangle.
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.
void setValid(bool validity)
Sets the validity of the feature.
A spatial index for QgsFeature objects.
static QgsProject * instance()
Returns the QgsProject singleton instance.
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Custom exception class for Coordinate Reference System related exceptions.
Helper template that cares of two things: 1.