QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
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"
21 #include "qgsexpressionsorter_p.h"
22 #include "qgsfeedback.h"
23 #include "qgscoordinatetransform.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 )
75  mFetchedCount++;
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  {
136  QgsRectangle newRect = transform.transformBoundingBox( request.filterRect(), Qgis::TransformDirection::Reverse );
137  request.setFilterRect( newRect );
139  }
141  {
142  // we can't safely handle a distance within query, as we cannot transform the
143  // static within tolerance distance from one CRS to a static distance in a different CRS.
144 
145  // in this case we transform the request's distance within requirement to a "worst case" bounding box filter, so
146  // that the request itself can still take advantage of spatial indices even when we have to do the distance within check locally
147  QgsRectangle newRect = transform.transformBoundingBox( request.filterRect(), Qgis::TransformDirection::Reverse );
148  request.setFilterRect( newRect );
149 
151  }
152  }
153 
155 }
156 
158 {
159  if ( mRequest.filterRect().isNull() )
160  return QgsRectangle();
161 
162  QgsCoordinateTransform extentTransform = transform;
163  extentTransform.setBallparkTransformsAreAppropriate( true );
164  return extentTransform.transformBoundingBox( mRequest.filterRect(), Qgis::TransformDirection::Reverse );
165 }
166 
168 {
169  // Prepare if required the simplification of geometries to fetch:
170  // This code runs here because of 'prepareSimplification()' is virtual and it can be overridden
171  // in inherited iterators who change the default behavior.
172  // It would be better to call this method in the constructor enabling virtual-calls as it is described by example at:
173  // http://www.parashift.com/c%2B%2B-faq-lite/calling-virtuals-from-ctor-idiom.html
174  if ( refs == 0 )
175  {
177 
178  // Should be called as last preparation step since it possibly will already fetch all features
179  setupOrderBy( mRequest.orderBy() );
180  }
181  refs++;
182 }
183 
185 {
186  refs--;
187  if ( !refs )
188  delete this;
189 }
190 
192 {
193  return mCompileFailed;
194 }
195 
197 {
198  Q_UNUSED( simplifyMethod )
199  return false;
200 }
201 
202 void QgsAbstractFeatureIterator::setupOrderBy( const QList<QgsFeatureRequest::OrderByClause> &orderBys )
203 {
204  // Let the provider try using an efficient order by strategy first
205  if ( !orderBys.isEmpty() && !prepareOrderBy( orderBys ) )
206  {
207  // No success from the provider
208 
209  // Prepare the expressions
210  QList<QgsFeatureRequest::OrderByClause> preparedOrderBys( orderBys );
211  QList<QgsFeatureRequest::OrderByClause>::iterator orderByIt( preparedOrderBys.begin() );
212 
213  QgsExpressionContext *expressionContext( mRequest.expressionContext() );
214  do
215  {
216  orderByIt->prepare( expressionContext );
217  }
218  while ( ++orderByIt != preparedOrderBys.end() );
219 
220  // Fetch all features
221  QgsIndexedFeature indexedFeature;
222  indexedFeature.mIndexes.resize( preparedOrderBys.size() );
223 
224  while ( nextFeature( indexedFeature.mFeature ) )
225  {
226  expressionContext->setFeature( indexedFeature.mFeature );
227  int i = 0;
228  const auto constPreparedOrderBys = preparedOrderBys;
229  for ( const QgsFeatureRequest::OrderByClause &orderBy : constPreparedOrderBys )
230  {
231  indexedFeature.mIndexes.replace( i++, orderBy.expression().evaluate( expressionContext ) );
232  }
233 
234  // We need all features, to ignore the limit for this pre-fetch
235  // keep the fetched count at 0.
236  mFetchedCount = 0;
237  mCachedFeatures.append( indexedFeature );
238  }
239 
240  std::sort( mCachedFeatures.begin(), mCachedFeatures.end(), QgsExpressionSorter( preparedOrderBys ) );
241 
242  mFeatureIterator = mCachedFeatures.constBegin();
243  mUseCachedFeatures = true;
244  // The real iterator is closed, we are only serving cached features
245  mZombie = true;
246  }
247 }
248 
249 bool QgsAbstractFeatureIterator::providerCanSimplify( QgsSimplifyMethod::MethodType methodType ) const
250 {
251  Q_UNUSED( methodType )
252  return false;
253 }
254 
255 bool QgsAbstractFeatureIterator::prepareOrderBy( const QList<QgsFeatureRequest::OrderByClause> &orderBys )
256 {
257  Q_UNUSED( orderBys )
258  return false;
259 }
260 
262 {
263 }
264 
266 
268 {
269  if ( this != &other )
270  {
271  if ( mIter )
272  mIter->deref();
273  mIter = other.mIter;
274  if ( mIter )
275  mIter->ref();
276  }
277  return *this;
278 }
279 
281 {
282  return mIter && mIter->isValid();
283 }
QgsExpressionContext
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
Definition: qgsexpressioncontext.h:406
QgsAbstractFeatureIterator::refs
int refs
reference counting (to allow seamless copying of QgsFeatureIterator instances)
Definition: qgsfeatureiterator.h:197
QgsFeatureRequest::OrderByClause
The OrderByClause class represents an order by clause for a QgsFeatureRequest.
Definition: qgsfeaturerequest.h:152
QgsAbstractFeatureIterator::RequestToSourceCrsResult
RequestToSourceCrsResult
Possible results from the updateRequestToSourceCrs() method.
Definition: qgsfeatureiterator.h:99
QgsSimplifyMethod
This class contains information about how to simplify geometries fetched from a QgsFeatureIterator.
Definition: qgssimplifymethod.h:28
QgsFeatureRequest::filterFids
const QgsFeatureIds & filterFids() const
Returns the feature IDs that should be fetched.
Definition: qgsfeaturerequest.h:492
Qgis::SpatialFilterType::NoFilter
@ NoFilter
No spatial filtering of features.
QgsFeatureRequest::feedback
QgsFeedback * feedback() const
Returns the feedback object that can be queried regularly by the iterator to check if it should be ca...
Definition: qgsfeaturerequest.cpp:407
qgslinestring.h
QgsAbstractFeatureIterator::setInterruptionChecker
virtual void setInterruptionChecker(QgsFeedback *interruptionChecker)
Attach an object that can be queried regularly by the iterator to check if it must stopped.
Definition: qgsfeatureiterator.cpp:261
QgsGeometry::transform
Qgis::GeometryOperationResult transform(const QgsCoordinateTransform &ct, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward, bool transformZ=false) SIP_THROW(QgsCsException)
Transforms this geometry as described by the coordinate transform ct.
Definition: qgsgeometry.cpp:3128
QgsAbstractFeatureIterator::isValid
virtual bool isValid() const
Returns if this iterator is valid.
Definition: qgsfeatureiterator.h:81
QgsFeatureRequest::filterType
FilterType filterType() const
Returns the attribute/ID filter type which is currently set on this request.
Definition: qgsfeaturerequest.h:355
qgsfeatureiterator.h
QgsFeatureRequest::FilterFids
@ FilterFids
Filter using feature IDs.
Definition: qgsfeaturerequest.h:118
QgsCoordinateTransform::transformBoundingBox
QgsRectangle transformBoundingBox(const QgsRectangle &rectangle, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward, bool handle180Crossover=false) const SIP_THROW(QgsCsException)
Transforms a rectangle from the source CRS to the destination CRS.
Definition: qgscoordinatetransform.cpp:560
QgsAbstractFeatureIterator::RequestToSourceCrsResult::DistanceWithinMustBeCheckedManually
@ DistanceWithinMustBeCheckedManually
The distance within request cannot be losslessly updated to the source CRS, and callers will need to ...
QgsFeature::geometry
QgsGeometry geometry
Definition: qgsfeature.h:71
QgsFeedback::isCanceled
bool isCanceled() const SIP_HOLDGIL
Tells whether the operation has been canceled already.
Definition: qgsfeedback.h:67
QgsFeatureRequest::filterRect
QgsRectangle filterRect() const
Returns the rectangle from which features will be taken.
Definition: qgsfeaturerequest.cpp:117
QgsAbstractFeatureIterator::mFetchedCount
long long mFetchedCount
Number of features already fetched by iterator.
Definition: qgsfeatureiterator.h:205
QgsAbstractFeatureIterator::mRequest
QgsFeatureRequest mRequest
A copy of the feature request.
Definition: qgsfeatureiterator.h:178
QgsAbstractFeatureIterator::nextFeatureFilterExpression
virtual bool nextFeatureFilterExpression(QgsFeature &f)
By default, the iterator will fetch all features and check if the feature matches the expression.
Definition: qgsfeatureiterator.cpp:80
QgsCoordinateTransform::isValid
bool isValid() const
Returns true if the coordinate transform is valid, ie both the source and destination CRS have been s...
Definition: qgscoordinatetransform.cpp:900
QgsAbstractFeatureIterator::nextFeature
virtual bool nextFeature(QgsFeature &f)
fetch next feature, return true on success
Definition: qgsfeatureiterator.cpp:30
QgsRectangle
A rectangle specified with double values.
Definition: qgsrectangle.h:41
QgsAbstractFeatureIterator::ref
void ref()
Add reference.
Definition: qgsfeatureiterator.cpp:167
QgsFeatureRequest::expressionContext
QgsExpressionContext * expressionContext()
Returns the expression context used to evaluate filter expressions.
Definition: qgsfeaturerequest.h:581
QgsFeature::clearGeometry
void clearGeometry()
Removes any geometry associated with the feature.
Definition: qgsfeature.cpp:184
QgsFeatureRequest::setFilterRect
QgsFeatureRequest & setFilterRect(const QgsRectangle &rectangle)
Sets the rectangle from which features will be taken.
Definition: qgsfeaturerequest.cpp:101
QgsFeature::id
QgsFeatureId id
Definition: qgsfeature.h:68
QgsAbstractFeatureIterator::filterRectToSourceCrs
QgsRectangle filterRectToSourceCrs(const QgsCoordinateTransform &transform) const SIP_THROW(QgsCsException)
Returns a rectangle representing the original request's QgsFeatureRequest::filterRect().
Definition: qgsfeatureiterator.cpp:157
QgsFeatureRequest
This class wraps a request for features to a vector layer (or directly its vector data provider).
Definition: qgsfeaturerequest.h:83
QgsAbstractFeatureIterator::mZombie
bool mZombie
A feature iterator may be closed already but still be serving features from the cache.
Definition: qgsfeatureiterator.h:190
QgsCsException
Custom exception class for Coordinate Reference System related exceptions.
Definition: qgsexception.h:65
QgsFeatureRequest::limit
long long limit() const
Returns the maximum number of features to request, or -1 if no limit set.
Definition: qgsfeaturerequest.h:656
QgsCoordinateTransform::isShortCircuited
bool isShortCircuited() const
Returns true if the transform short circuits because the source and destination are equivalent.
Definition: qgscoordinatetransform.cpp:905
QgsFeature::setGeometry
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
Definition: qgsfeature.cpp:170
QgsCoordinateTransform::setBallparkTransformsAreAppropriate
void setBallparkTransformsAreAppropriate(bool appropriate)
Sets whether approximate "ballpark" results are appropriate for this coordinate transform.
Definition: qgscoordinatetransform.cpp:939
QgsFeedback
Base class for feedback objects to be used for cancellation of something running in a worker thread.
Definition: qgsfeedback.h:44
QgsFeatureRequest::filterExpression
QgsExpression * filterExpression() const
Returns the filter expression (if set).
Definition: qgsfeaturerequest.h:562
qgscoordinatetransform.h
BUILTIN_UNREACHABLE
#define BUILTIN_UNREACHABLE
Definition: qgis.h:2907
QgsFeatureRequest::FilterExpression
@ FilterExpression
Filter using expression.
Definition: qgsfeaturerequest.h:117
QgsAbstractFeatureIterator::geometryToDestinationCrs
void geometryToDestinationCrs(QgsFeature &feature, const QgsCoordinateTransform &transform) const
Transforms feature's geometry according to the specified coordinate transform.
Definition: qgsfeatureiterator.cpp:101
QgsAbstractFeatureIterator::QgsAbstractFeatureIterator
QgsAbstractFeatureIterator(const QgsFeatureRequest &request)
base class constructor - stores the iteration parameters
Definition: qgsfeatureiterator.cpp:25
qgsexpressionsorter_p.h
QgsFeatureRequest::spatialFilterType
Qgis::SpatialFilterType spatialFilterType() const
Returns the spatial filter type which is currently set on this request.
Definition: qgsfeaturerequest.h:369
QgsExpression::evaluate
QVariant evaluate()
Evaluate the feature and return the result.
Definition: qgsexpression.cpp:350
QgsAbstractFeatureIterator::nextFeatureFilterFids
virtual bool nextFeatureFilterFids(QgsFeature &f)
By default, the iterator will fetch all features and check if the id is in the request.
Definition: qgsfeatureiterator.cpp:91
QgsGeometry
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:124
QgsFeatureRequest::orderBy
OrderBy orderBy() const
Returns a list of order by clauses specified for this feature request.
Definition: qgsfeaturerequest.cpp:205
QgsFeature::hasGeometry
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Definition: qgsfeature.cpp:230
QgsIndexedFeature
Temporarily used structure to cache order by information.
Definition: qgsindexedfeature.h:29
Qgis::SpatialFilterType::BoundingBox
@ BoundingBox
Filter using a bounding box.
QgsAbstractFeatureIterator::fetchFeature
virtual bool fetchFeature(QgsFeature &f)=0
If you write a feature iterator for your provider, this is the method you need to implement!...
QgsAbstractFeatureIterator::deref
void deref()
Remove reference, delete if refs == 0.
Definition: qgsfeatureiterator.cpp:184
QgsFeatureRequest::simplifyMethod
const QgsSimplifyMethod & simplifyMethod() const
Returns the simplification method for geometries that will be fetched.
Definition: qgsfeaturerequest.h:765
QgsFeatureIterator::operator=
QgsFeatureIterator & operator=(const QgsFeatureIterator &other)
Definition: qgsfeatureiterator.cpp:267
QgsAbstractFeatureIterator::compileFailed
bool compileFailed() const
Indicator if there was an error when sending the compiled query to the server.
Definition: qgsfeatureiterator.cpp:191
QgsSimplifyMethod::MethodType
MethodType
Definition: qgssimplifymethod.h:31
qgsexception.h
QgsFeature
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition: qgsfeature.h:55
QgsAbstractFeatureIterator::updateRequestToSourceCrs
RequestToSourceCrsResult updateRequestToSourceCrs(QgsFeatureRequest &request, const QgsCoordinateTransform &transform) const SIP_THROW(QgsCsException)
Update a QgsFeatureRequest so that spatial filters are transformed to the source's coordinate referen...
Definition: qgsfeatureiterator.cpp:124
QgsIndexedFeature::mIndexes
QVector< QVariant > mIndexes
Definition: qgsindexedfeature.h:32
qgslogger.h
QgsAbstractFeatureIterator::mCompileFailed
bool mCompileFailed
Definition: qgsfeatureiterator.h:210
QgsFeatureRequest::transformErrorCallback
std::function< void(const QgsFeature &) > transformErrorCallback() const
Returns the callback function to use when encountering a transform error when iterating features and ...
Definition: qgsfeaturerequest.h:847
QgsFeatureIterator::mIter
QgsAbstractFeatureIterator * mIter
Definition: qgsfeatureiterator.h:372
QgsCoordinateTransform
Class for doing transforms between two map coordinate systems.
Definition: qgscoordinatetransform.h:57
QgsFeatureIterator
Wrapper for iterator of features from vector data provider or vector layer.
Definition: qgsfeatureiterator.h:289
qgsfeedback.h
QgsRectangle::isNull
bool isNull() const
Test if the rectangle is null (all coordinates zero or after call to setMinimal()).
Definition: qgsrectangle.h:479
QgsFeatureIterator::isValid
bool isValid() const
Will return if this iterator is valid.
Definition: qgsfeatureiterator.cpp:280
Qgis::SpatialFilterType::DistanceWithin
@ DistanceWithin
Filter by distance to reference geometry.
QgsAbstractFeatureIterator::RequestToSourceCrsResult::Success
@ Success
Request was successfully updated to the source CRS, or no changes were required.
QgsAbstractFeatureIterator::prepareSimplification
virtual bool prepareSimplification(const QgsSimplifyMethod &simplifyMethod)
Setup the simplification of geometries to fetch using the specified simplify method.
Definition: qgsfeatureiterator.cpp:196
qgssimplifymethod.h
QgsExpressionContext::setFeature
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
Definition: qgsexpressioncontext.cpp:525
QgsIndexedFeature::mFeature
QgsFeature mFeature
Definition: qgsindexedfeature.h:33