QGIS API Documentation 3.34.0-Prizren (ffbdd678812)
Loading...
Searching...
No Matches
qgsfeatureiterator.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsfeatureiterator.cpp
3 ---------------------
4 begin : Juli 2012
5 copyright : (C) 2012 by Martin Dobias
6 email : wonder dot sk at gmail dot com
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15#include "qgsfeatureiterator.h"
16#include "qgslogger.h"
17
18#include "qgssimplifymethod.h"
19#include "qgsexception.h"
20#include "qgslinestring.h"
22#include "qgsfeedback.h"
24
26 : mRequest( request )
27{
28}
29
31{
32 bool dataOk = false;
33 if ( mRequest.limit() >= 0 && mFetchedCount >= mRequest.limit() )
34 {
35 return false;
36 }
37
39 return false;
40
41 if ( mUseCachedFeatures )
42 {
43 if ( mFeatureIterator != mCachedFeatures.constEnd() )
44 {
45 f = mFeatureIterator->mFeature;
46 ++mFeatureIterator;
47 dataOk = true;
48 }
49 else
50 {
51 dataOk = false;
52 // even the zombie dies at this point...
53 mZombie = false;
54 }
55 }
56 else
57 {
58 switch ( mRequest.filterType() )
59 {
61 dataOk = nextFeatureFilterExpression( f );
62 break;
63
65 dataOk = nextFeatureFilterFids( f );
66 break;
67
68 default:
69 dataOk = fetchFeature( f );
70 break;
71 }
72 }
73
74 if ( dataOk )
76
77 return dataOk;
78}
79
81{
82 while ( fetchFeature( f ) )
83 {
86 return true;
87 }
88 return false;
89}
90
92{
93 while ( fetchFeature( f ) )
94 {
95 if ( mRequest.filterFids().contains( f.id() ) )
96 return true;
97 }
98 return false;
99}
100
102{
103 if ( transform.isValid() && feature.hasGeometry() )
104 {
105 try
106 {
107 QgsGeometry g = feature.geometry();
108 g.transform( transform );
109 feature.setGeometry( g );
110 }
111 catch ( QgsCsException & )
112 {
113 // transform error
115 {
116 mRequest.transformErrorCallback()( feature );
117 }
118 // remove geometry - we can't reproject so better not return a geometry in a different crs
119 feature.clearGeometry();
120 }
121 }
122}
123
125{
126 if ( transform.isShortCircuited() )
127 return RequestToSourceCrsResult::Success; // nothing to do
128
129 switch ( request.spatialFilterType() )
130 {
133
135 {
137 request.setFilterRect( newRect );
139 }
140
142 {
143 // we can't safely handle a distance within query, as we cannot transform the
144 // static within tolerance distance from one CRS to a static distance in a different CRS.
145
146 // in this case we transform the request's distance within requirement to a "worst case" bounding box filter, so
147 // that the request itself can still take advantage of spatial indices even when we have to do the distance within check locally
149 request.setFilterRect( newRect );
150
152 }
153 }
154
156}
157
159{
160 if ( mRequest.filterRect().isNull() )
161 return QgsRectangle();
162
163 QgsCoordinateTransform extentTransform = transform;
164 extentTransform.setBallparkTransformsAreAppropriate( true );
166}
167
169{
170 // Prepare if required the simplification of geometries to fetch:
171 // This code runs here because of 'prepareSimplification()' is virtual and it can be overridden
172 // in inherited iterators who change the default behavior.
173 // It would be better to call this method in the constructor enabling virtual-calls as it is described by example at:
174 // http://www.parashift.com/c%2B%2B-faq-lite/calling-virtuals-from-ctor-idiom.html
175 if ( refs == 0 )
176 {
178
179 // Should be called as last preparation step since it possibly will already fetch all features
180 setupOrderBy( mRequest.orderBy() );
181 }
182 refs++;
183}
184
186{
187 refs--;
188 if ( !refs )
189 delete this;
190}
191
196
198{
199 Q_UNUSED( simplifyMethod )
200 return false;
201}
202
203void QgsAbstractFeatureIterator::setupOrderBy( const QList<QgsFeatureRequest::OrderByClause> &orderBys )
204{
205 // Let the provider try using an efficient order by strategy first
206 if ( !orderBys.isEmpty() && !prepareOrderBy( orderBys ) )
207 {
208 // No success from the provider
209
210 // Prepare the expressions
211 QList<QgsFeatureRequest::OrderByClause> preparedOrderBys( orderBys );
212 QList<QgsFeatureRequest::OrderByClause>::iterator orderByIt( preparedOrderBys.begin() );
213
214 QgsExpressionContext *expressionContext( mRequest.expressionContext() );
215 do
216 {
217 orderByIt->prepare( expressionContext );
218 }
219 while ( ++orderByIt != preparedOrderBys.end() );
220
221 // Fetch all features
222 QgsIndexedFeature indexedFeature;
223 indexedFeature.mIndexes.resize( preparedOrderBys.size() );
224
225 while ( nextFeature( indexedFeature.mFeature ) )
226 {
227 expressionContext->setFeature( indexedFeature.mFeature );
228 int i = 0;
229 const auto constPreparedOrderBys = preparedOrderBys;
230 for ( const QgsFeatureRequest::OrderByClause &orderBy : constPreparedOrderBys )
231 {
232 indexedFeature.mIndexes.replace( i++, orderBy.expression().evaluate( expressionContext ) );
233 }
234
235 // We need all features, to ignore the limit for this pre-fetch
236 // keep the fetched count at 0.
237 mFetchedCount = 0;
238 mCachedFeatures.append( indexedFeature );
239 }
240
241 std::sort( mCachedFeatures.begin(), mCachedFeatures.end(), QgsExpressionSorter( preparedOrderBys ) );
242
243 mFeatureIterator = mCachedFeatures.constBegin();
244 mUseCachedFeatures = true;
245 // The real iterator is closed, we are only serving cached features
246 mZombie = true;
247 }
248}
249
250bool QgsAbstractFeatureIterator::providerCanSimplify( QgsSimplifyMethod::MethodType methodType ) const
251{
252 Q_UNUSED( methodType )
253 return false;
254}
255
256bool QgsAbstractFeatureIterator::prepareOrderBy( const QList<QgsFeatureRequest::OrderByClause> &orderBys )
257{
258 Q_UNUSED( orderBys )
259 return false;
260}
261
265
267
269{
270 if ( this != &other )
271 {
272 if ( mIter )
273 mIter->deref();
274 mIter = other.mIter;
275 if ( mIter )
276 mIter->ref();
277 }
278 return *this;
279}
280
282{
283 return mIter && mIter->isValid();
284}
@ DistanceWithin
Filter by distance to reference geometry.
@ BoundingBox
Filter using a bounding box.
@ NoFilter
No spatial filtering of features.
@ Reverse
Reverse/inverse transform (from destination to source)
RequestToSourceCrsResult
Possible results from the updateRequestToSourceCrs() method.
@ Success
Request was successfully updated to the source CRS, or no changes were required.
@ DistanceWithinMustBeCheckedManually
The distance within request cannot be losslessly updated to the source CRS, and callers will need to ...
bool mZombie
A feature iterator may be closed already but still be serving features from the cache.
virtual bool nextFeatureFilterFids(QgsFeature &f)
By default, the iterator will fetch all features and check if the id is in the request.
void geometryToDestinationCrs(QgsFeature &feature, const QgsCoordinateTransform &transform) const
Transforms feature's geometry according to the specified coordinate transform.
QgsRectangle filterRectToSourceCrs(const QgsCoordinateTransform &transform) const
Returns a rectangle representing the original request's QgsFeatureRequest::filterRect().
virtual void setInterruptionChecker(QgsFeedback *interruptionChecker)
Attach an object that can be queried regularly by the iterator to check if it must stopped.
virtual bool fetchFeature(QgsFeature &f)=0
If you write a feature iterator for your provider, this is the method you need to implement!...
long long mFetchedCount
Number of features already fetched by iterator.
virtual bool prepareSimplification(const QgsSimplifyMethod &simplifyMethod)
Setup the simplification of geometries to fetch using the specified simplify method.
void deref()
Remove reference, delete if refs == 0.
QgsFeatureRequest mRequest
A copy of the feature request.
QgsAbstractFeatureIterator(const QgsFeatureRequest &request)
base class constructor - stores the iteration parameters
RequestToSourceCrsResult updateRequestToSourceCrs(QgsFeatureRequest &request, const QgsCoordinateTransform &transform) const
Update a QgsFeatureRequest so that spatial filters are transformed to the source's coordinate referen...
bool compileFailed() const
Indicator if there was an error when sending the compiled query to the server.
virtual bool isValid() const
Returns if this iterator is valid.
int refs
reference counting (to allow seamless copying of QgsFeatureIterator instances)
virtual bool nextFeature(QgsFeature &f)
fetch next feature, return true on success
virtual bool nextFeatureFilterExpression(QgsFeature &f)
By default, the iterator will fetch all features and check if the feature matches the expression.
Class for doing transforms between two map coordinate systems.
void setBallparkTransformsAreAppropriate(bool appropriate)
Sets whether approximate "ballpark" results are appropriate for this coordinate transform.
bool isShortCircuited() const
Returns true if the transform short circuits because the source and destination are equivalent.
QgsRectangle transformBoundingBox(const QgsRectangle &rectangle, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward, bool handle180Crossover=false) const
Transforms a rectangle from the source CRS to the destination CRS.
bool isValid() const
Returns true if the coordinate transform is valid, ie both the source and destination CRS have been s...
Custom exception class for Coordinate Reference System related exceptions.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
QVariant evaluate()
Evaluate the feature and return the result.
Wrapper for iterator of features from vector data provider or vector layer.
QgsAbstractFeatureIterator * mIter
QgsFeatureIterator & operator=(const QgsFeatureIterator &other)
bool isValid() const
Will return if this iterator is valid.
The OrderByClause class represents an order by clause for a QgsFeatureRequest.
This class wraps a request for features to a vector layer (or directly its vector data provider).
QgsRectangle filterRect() const
Returns the rectangle from which features will be taken.
QgsFeedback * feedback() const
Returns the feedback object that can be queried regularly by the iterator to check if it should be ca...
long long limit() const
Returns the maximum number of features to request, or -1 if no limit set.
QgsExpressionContext * expressionContext()
Returns the expression context used to evaluate filter expressions.
std::function< void(const QgsFeature &) > transformErrorCallback() const
Returns the callback function to use when encountering a transform error when iterating features and ...
OrderBy orderBy() const
Returns a list of order by clauses specified for this feature request.
QgsExpression * filterExpression() const
Returns the filter expression (if set).
const QgsSimplifyMethod & simplifyMethod() const
Returns the simplification method for geometries that will be fetched.
Qgis::SpatialFilterType spatialFilterType() const
Returns the spatial filter type which is currently set on this request.
FilterType filterType() const
Returns the attribute/ID filter type which is currently set on this request.
@ FilterFids
Filter using feature IDs.
@ FilterExpression
Filter using expression.
const QgsFeatureIds & filterFids() const
Returns the feature IDs that should be fetched.
QgsFeatureRequest & setFilterRect(const QgsRectangle &rectangle)
Sets the rectangle from which features will be taken.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition qgsfeature.h:56
QgsFeatureId id
Definition qgsfeature.h:64
QgsGeometry geometry
Definition qgsfeature.h:67
void clearGeometry()
Removes any geometry associated with the feature.
bool hasGeometry() const
Returns true if the feature has an associated geometry.
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
Base class for feedback objects to be used for cancellation of something running in a worker thread.
Definition qgsfeedback.h:45
bool isCanceled() const
Tells whether the operation has been canceled already.
Definition qgsfeedback.h:54
A geometry is the spatial representation of a feature.
Qgis::GeometryOperationResult transform(const QgsCoordinateTransform &ct, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward, bool transformZ=false)
Transforms this geometry as described by the coordinate transform ct.
Temporarily used structure to cache order by information.
QVector< QVariant > mIndexes
A rectangle specified with double values.
bool isNull() const
Test if the rectangle is null (holding no spatial information).
This class contains information about how to simplify geometries fetched from a QgsFeatureIterator.
#define BUILTIN_UNREACHABLE
Definition qgis.h:4993