27QgsSensorThingsFeatureSource::QgsSensorThingsFeatureSource(
const std::shared_ptr<QgsSensorThingsSharedData> &sharedData )
28 : mSharedData( sharedData )
34 return QgsFeatureIterator(
new QgsSensorThingsFeatureIterator(
this,
false, request ) );
37QgsSensorThingsSharedData *QgsSensorThingsFeatureSource::sharedData()
const
39 return mSharedData.get();
47QgsSensorThingsFeatureIterator::QgsSensorThingsFeatureIterator( QgsSensorThingsFeatureSource *source,
bool ownSource,
const QgsFeatureRequest &request )
49 , mInterruptionChecker( request.feedback() )
51 mTransform = mRequest.calculateTransform( mSource->sharedData()->crs() );
54 mFilterRect = filterRectToSourceCrs( mTransform );
55 if ( !mRequest.filterRect().isNull() && mFilterRect.isNull() )
71 requestIds = mRequest.filterFids();
75 requestIds.insert( mRequest.filterFid() );
78 if ( !mFilterRect.isNull() )
84 mDeferredFeaturesInFilterRectCheck =
true;
88 switch ( mRequest.spatialFilterType() )
95 if ( !mRequest.referenceGeometry().isEmpty() )
97 mDistanceWithinGeom = mRequest.referenceGeometry();
99 mDistanceWithinEngine->prepareGeometry();
104 mRequestFeatureIdList = qgis::setToList( requestIds );
105 std::sort( mRequestFeatureIdList.begin(), mRequestFeatureIdList.end() );
106 mRemainingFeatureIds = mRequestFeatureIdList;
107 if ( !mRemainingFeatureIds.empty() )
108 mFeatureIterator = mRemainingFeatureIds.at( 0 );
110 mGeometryTestFilterRect = mFilterRect;
113QgsSensorThingsFeatureIterator::~QgsSensorThingsFeatureIterator()
115 QgsSensorThingsFeatureIterator::close();
118bool QgsSensorThingsFeatureIterator::fetchFeature(
QgsFeature &f )
125 if ( mInterruptionChecker && mInterruptionChecker->isCanceled() )
128 if ( mDeferredFeaturesInFilterRectCheck || !mCurrentPage.isEmpty() )
130 const QgsFeatureIds featuresInRect = mSource->sharedData()->getFeatureIdsInExtent( mFilterRect, mInterruptionChecker, mCurrentPage, mNextPage, mAlreadyFetchedIds );
131 mCurrentPage.clear();
133 if ( !mRequestFeatureIdList.isEmpty() )
135 QgsFeatureIds requestIds = qgis::listToSet( mRequestFeatureIdList );
136 requestIds.intersect( featuresInRect );
137 mCurrentPageFeatureIdList = qgis::setToList( requestIds );
141 mCurrentPageFeatureIdList = qgis::setToList( featuresInRect );
143 if ( mCurrentPageFeatureIdList.empty() )
145 if ( mNextPage.isEmpty() )
151 mCurrentPage = mNextPage;
152 return fetchFeature( f );
156 std::sort( mCurrentPageFeatureIdList.begin(), mCurrentPageFeatureIdList.end() );
157 mRemainingFeatureIds = mCurrentPageFeatureIdList;
158 if ( !mRemainingFeatureIds.empty() )
159 mFeatureIterator = mRemainingFeatureIds.at( 0 );
161 mDeferredFeaturesInFilterRectCheck =
false;
171 if ( !mCurrentPageFeatureIdList.empty() && mRemainingFeatureIds.empty() )
173 if ( mNextPage.isEmpty() )
180 mCurrentPage = mNextPage;
181 return fetchFeature( f );
185 switch ( mRequest.filterType() )
189 if ( mRemainingFeatureIds.empty() )
192 bool result = mSource->sharedData()->getFeature( mRequest.filterFid(), f, mInterruptionChecker );
193 mAlreadyFetchedIds.insert( mRequest.filterFid() );
194 if ( mInterruptionChecker && mInterruptionChecker->isCanceled() )
197 geometryToDestinationCrs( f, mTransform );
198 if ( mDistanceWithinEngine && mDistanceWithinEngine->distance( f.
geometry().
constGet() ) > mRequest.distanceWithin() )
204 mRemainingFeatureIds.removeAll( f.
id() );
214 if ( mInterruptionChecker && mInterruptionChecker->isCanceled() )
217 if ( !mCurrentPageFeatureIdList.empty() && mRemainingFeatureIds.empty() )
219 if ( mNextPage.isEmpty() )
226 mCurrentPage = mNextPage;
227 return fetchFeature( f );
231 bool success = mSource->sharedData()->getFeature( mFeatureIterator, f, mInterruptionChecker );
232 mAlreadyFetchedIds.insert( mFeatureIterator );
234 if ( !mCurrentPageFeatureIdList.empty() )
236 mRemainingFeatureIds.removeAll( mFeatureIterator );
237 if ( !mRemainingFeatureIds.empty() )
238 mFeatureIterator = mRemainingFeatureIds.at( 0 );
247 if ( success && !mGeometryTestFilterRect.isNull() )
270 geometryToDestinationCrs( f, mTransform );
273 if ( mDistanceWithinEngine && mDistanceWithinEngine->distance( f.
geometry().
constGet() ) > mRequest.distanceWithin() )
286bool QgsSensorThingsFeatureIterator::rewind()
290 mFeatureIterator = 0;
291 mCurrentPage.clear();
292 mAlreadyFetchedIds.clear();
293 mRemainingFeatureIds = mRequestFeatureIdList;
294 if ( !mRemainingFeatureIds.empty() )
295 mFeatureIterator = mRemainingFeatureIds.at( 0 );
299bool QgsSensorThingsFeatureIterator::close()
308void QgsSensorThingsFeatureIterator::setInterruptionChecker(
QgsFeedback *interruptionChecker )
310 mInterruptionChecker = interruptionChecker;
@ Fid
Filter using feature ID.
@ Fids
Filter using feature IDs.
@ Expression
Filter using expression.
@ NoFilter
No filter is applied.
@ ExactIntersect
Use exact geometry intersection (slower) instead of bounding boxes.
@ DistanceWithin
Filter by distance to reference geometry.
@ BoundingBox
Filter using a bounding box.
@ NoFilter
No spatial filtering of features.
Helper template that cares of two things: 1.
Custom exception class for Coordinate Reference System related exceptions.
Wrapper for iterator of features from vector data provider or vector layer.
This class wraps a request for features to a vector layer (or directly its vector data provider).
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
void setValid(bool validity)
Sets the validity of the feature.
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Base class for feedback objects to be used for cancellation of something running in a worker thread.
bool boundingBoxIntersects(const QgsRectangle &rectangle) const
Returns true if the bounding box of this geometry intersects with a rectangle.
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
static QgsGeometryEngine * createGeometryEngine(const QgsAbstractGeometry *geometry, double precision=0.0, Qgis::GeosCreationFlags flags=Qgis::GeosCreationFlag::SkipEmptyInteriorRings)
Creates and returns a new geometry engine representing the specified geometry using precision on a gr...
bool intersects(const QgsRectangle &rectangle) const
Returns true if this geometry exactly intersects with a rectangle.
A rectangle specified with double values.
QSet< QgsFeatureId > QgsFeatureIds