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 if ( mRequest.destinationCrs().isValid() && mRequest.destinationCrs() != mSource->sharedData()->crs() )
53 mTransform =
QgsCoordinateTransform( mSource->sharedData()->crs(), mRequest.destinationCrs(), mRequest.transformContext() );
57 mFilterRect = filterRectToSourceCrs( mTransform );
58 if ( !mRequest.filterRect().isNull() && mFilterRect.isNull() )
74 requestIds = mRequest.filterFids();
78 requestIds.insert( mRequest.filterFid() );
81 if ( !mFilterRect.isNull() )
87 mDeferredFeaturesInFilterRectCheck =
true;
91 switch ( mRequest.spatialFilterType() )
98 if ( !mRequest.referenceGeometry().isEmpty() )
100 mDistanceWithinGeom = mRequest.referenceGeometry();
102 mDistanceWithinEngine->prepareGeometry();
107 mRequestFeatureIdList = qgis::setToList( requestIds );
108 std::sort( mRequestFeatureIdList.begin(), mRequestFeatureIdList.end() );
109 mRemainingFeatureIds = mRequestFeatureIdList;
110 if ( !mRemainingFeatureIds.empty() )
111 mFeatureIterator = mRemainingFeatureIds.at( 0 );
113 mGeometryTestFilterRect = mFilterRect;
116QgsSensorThingsFeatureIterator::~QgsSensorThingsFeatureIterator()
118 QgsSensorThingsFeatureIterator::close();
121bool QgsSensorThingsFeatureIterator::fetchFeature(
QgsFeature &f )
128 if ( mInterruptionChecker && mInterruptionChecker->isCanceled() )
131 if ( mDeferredFeaturesInFilterRectCheck || !mCurrentPage.isEmpty() )
133 const QgsFeatureIds featuresInRect = mSource->sharedData()->getFeatureIdsInExtent( mFilterRect, mInterruptionChecker, mCurrentPage, mNextPage, mAlreadyFetchedIds );
134 mCurrentPage.clear();
136 if ( !mRequestFeatureIdList.isEmpty() )
138 QgsFeatureIds requestIds = qgis::listToSet( mRequestFeatureIdList );
139 requestIds.intersect( featuresInRect );
140 mCurrentPageFeatureIdList = qgis::setToList( requestIds );
144 mCurrentPageFeatureIdList = qgis::setToList( featuresInRect );
146 if ( mCurrentPageFeatureIdList.empty() )
148 if ( mNextPage.isEmpty() )
154 mCurrentPage = mNextPage;
155 return fetchFeature( f );
159 std::sort( mCurrentPageFeatureIdList.begin(), mCurrentPageFeatureIdList.end() );
160 mRemainingFeatureIds = mCurrentPageFeatureIdList;
161 if ( !mRemainingFeatureIds.empty() )
162 mFeatureIterator = mRemainingFeatureIds.at( 0 );
164 mDeferredFeaturesInFilterRectCheck =
false;
174 if ( !mCurrentPageFeatureIdList.empty() && mRemainingFeatureIds.empty() )
176 if ( mNextPage.isEmpty() )
183 mCurrentPage = mNextPage;
184 return fetchFeature( f );
188 switch ( mRequest.filterType() )
192 if ( mRemainingFeatureIds.empty() )
195 bool result = mSource->sharedData()->getFeature( mRequest.filterFid(), f, mInterruptionChecker );
196 mAlreadyFetchedIds.insert( mRequest.filterFid() );
197 if ( mInterruptionChecker && mInterruptionChecker->isCanceled() )
200 geometryToDestinationCrs( f, mTransform );
201 if ( mDistanceWithinEngine && mDistanceWithinEngine->distance( f.
geometry().
constGet() ) > mRequest.distanceWithin() )
207 mRemainingFeatureIds.removeAll( f.
id() );
217 if ( mInterruptionChecker && mInterruptionChecker->isCanceled() )
220 if ( !mCurrentPageFeatureIdList.empty() && mRemainingFeatureIds.empty() )
222 if ( mNextPage.isEmpty() )
229 mCurrentPage = mNextPage;
230 return fetchFeature( f );
234 bool success = mSource->sharedData()->getFeature( mFeatureIterator, f, mInterruptionChecker );
235 mAlreadyFetchedIds.insert( mFeatureIterator );
237 if ( !mCurrentPageFeatureIdList.empty() )
239 mRemainingFeatureIds.removeAll( mFeatureIterator );
240 if ( !mRemainingFeatureIds.empty() )
241 mFeatureIterator = mRemainingFeatureIds.at( 0 );
250 if ( success && !mGeometryTestFilterRect.isNull() )
273 geometryToDestinationCrs( f, mTransform );
276 if ( mDistanceWithinEngine && mDistanceWithinEngine->distance( f.
geometry().
constGet() ) > mRequest.distanceWithin() )
289bool QgsSensorThingsFeatureIterator::rewind()
293 mFeatureIterator = 0;
294 mCurrentPage.clear();
295 mAlreadyFetchedIds.clear();
296 mRemainingFeatureIds = mRequestFeatureIdList;
297 if ( !mRemainingFeatureIds.empty() )
298 mFeatureIterator = mRemainingFeatureIds.at( 0 );
302bool QgsSensorThingsFeatureIterator::close()
311void QgsSensorThingsFeatureIterator::setInterruptionChecker(
QgsFeedback *interruptionChecker )
313 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)
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