QGIS API Documentation  3.21.0-Master (af9a72eda6)
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 "qgsexpressionsorter.h"
21 #include "qgsfeedback.h"
22 
24  : mRequest( request )
25 {
26 }
27 
29 {
30  bool dataOk = false;
31  if ( mRequest.limit() >= 0 && mFetchedCount >= mRequest.limit() )
32  {
33  return false;
34  }
35 
37  return false;
38 
39  if ( mUseCachedFeatures )
40  {
41  if ( mFeatureIterator != mCachedFeatures.constEnd() )
42  {
43  f = mFeatureIterator->mFeature;
44  ++mFeatureIterator;
45  dataOk = true;
46  }
47  else
48  {
49  dataOk = false;
50  // even the zombie dies at this point...
51  mZombie = false;
52  }
53  }
54  else
55  {
56  switch ( mRequest.filterType() )
57  {
59  dataOk = nextFeatureFilterExpression( f );
60  break;
61 
63  dataOk = nextFeatureFilterFids( f );
64  break;
65 
66  default:
67  dataOk = fetchFeature( f );
68  break;
69  }
70  }
71 
72  if ( dataOk )
73  mFetchedCount++;
74 
75  return dataOk;
76 }
77 
79 {
80  while ( fetchFeature( f ) )
81  {
84  return true;
85  }
86  return false;
87 }
88 
90 {
91  while ( fetchFeature( f ) )
92  {
93  if ( mRequest.filterFids().contains( f.id() ) )
94  return true;
95  }
96  return false;
97 }
98 
100 {
101  if ( transform.isValid() && feature.hasGeometry() )
102  {
103  try
104  {
105  QgsGeometry g = feature.geometry();
106  g.transform( transform );
107  feature.setGeometry( g );
108  }
109  catch ( QgsCsException & )
110  {
111  // transform error
113  {
114  mRequest.transformErrorCallback()( feature );
115  }
116  // remove geometry - we can't reproject so better not return a geometry in a different crs
117  feature.clearGeometry();
118  }
119  }
120 }
121 
123 {
124  if ( mRequest.filterRect().isNull() )
125  return QgsRectangle();
126 
128 }
129 
131 {
132  // Prepare if required the simplification of geometries to fetch:
133  // This code runs here because of 'prepareSimplification()' is virtual and it can be overridden
134  // in inherited iterators who change the default behavior.
135  // It would be better to call this method in the constructor enabling virtual-calls as it is described by example at:
136  // http://www.parashift.com/c%2B%2B-faq-lite/calling-virtuals-from-ctor-idiom.html
137  if ( refs == 0 )
138  {
140 
141  // Should be called as last preparation step since it possibly will already fetch all features
142  setupOrderBy( mRequest.orderBy() );
143  }
144  refs++;
145 }
146 
148 {
149  refs--;
150  if ( !refs )
151  delete this;
152 }
153 
155 {
156  return mCompileFailed;
157 }
158 
160 {
161  Q_UNUSED( simplifyMethod )
162  return false;
163 }
164 
165 void QgsAbstractFeatureIterator::setupOrderBy( const QList<QgsFeatureRequest::OrderByClause> &orderBys )
166 {
167  // Let the provider try using an efficient order by strategy first
168  if ( !orderBys.isEmpty() && !prepareOrderBy( orderBys ) )
169  {
170  // No success from the provider
171 
172  // Prepare the expressions
173  QList<QgsFeatureRequest::OrderByClause> preparedOrderBys( orderBys );
174  QList<QgsFeatureRequest::OrderByClause>::iterator orderByIt( preparedOrderBys.begin() );
175 
176  QgsExpressionContext *expressionContext( mRequest.expressionContext() );
177  do
178  {
179  orderByIt->prepare( expressionContext );
180  }
181  while ( ++orderByIt != preparedOrderBys.end() );
182 
183  // Fetch all features
184  QgsIndexedFeature indexedFeature;
185  indexedFeature.mIndexes.resize( preparedOrderBys.size() );
186 
187  while ( nextFeature( indexedFeature.mFeature ) )
188  {
189  expressionContext->setFeature( indexedFeature.mFeature );
190  int i = 0;
191  const auto constPreparedOrderBys = preparedOrderBys;
192  for ( const QgsFeatureRequest::OrderByClause &orderBy : constPreparedOrderBys )
193  {
194  indexedFeature.mIndexes.replace( i++, orderBy.expression().evaluate( expressionContext ) );
195  }
196 
197  // We need all features, to ignore the limit for this pre-fetch
198  // keep the fetched count at 0.
199  mFetchedCount = 0;
200  mCachedFeatures.append( indexedFeature );
201  }
202 
203  std::sort( mCachedFeatures.begin(), mCachedFeatures.end(), QgsExpressionSorter( preparedOrderBys ) );
204 
205  mFeatureIterator = mCachedFeatures.constBegin();
206  mUseCachedFeatures = true;
207  // The real iterator is closed, we are only serving cached features
208  mZombie = true;
209  }
210 }
211 
212 bool QgsAbstractFeatureIterator::providerCanSimplify( QgsSimplifyMethod::MethodType methodType ) const
213 {
214  Q_UNUSED( methodType )
215  return false;
216 }
217 
218 bool QgsAbstractFeatureIterator::prepareOrderBy( const QList<QgsFeatureRequest::OrderByClause> &orderBys )
219 {
220  Q_UNUSED( orderBys )
221  return false;
222 }
223 
225 {
226 }
227 
229 
231 {
232  if ( this != &other )
233  {
234  if ( mIter )
235  mIter->deref();
236  mIter = other.mIter;
237  if ( mIter )
238  mIter->ref();
239  }
240  return *this;
241 }
242 
244 {
245  return mIter && mIter->isValid();
246 }
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.
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.
QgsRectangle filterRectToSourceCrs(const QgsCoordinateTransform &transform) const SIP_THROW(QgsCsException)
Returns a rectangle representing the original request's QgsFeatureRequest::filterRect().
QgsFeatureRequest mRequest
A copy of the feature request.
QgsAbstractFeatureIterator(const QgsFeatureRequest &request)
base class constructor - stores the iteration parameters
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.
@ ReverseTransform
Transform from destination to source CRS.
QgsRectangle transformBoundingBox(const QgsRectangle &rectangle, TransformDirection direction=ForwardTransform, bool handle180Crossover=false) const SIP_THROW(QgsCsException)
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.
Definition: qgsexception.h:66
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).
const QgsSimplifyMethod & simplifyMethod() const
Gets simplification method for geometries that will be fetched.
QgsExpression * filterExpression() const
Returns the filter expression if set.
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.
OrderBy orderBy() const
Returns a list of order by clauses specified for this feature request.
QgsExpressionContext * expressionContext()
Returns the expression context used to evaluate filter expressions.
const QgsRectangle & filterRect() const
Returns the rectangle from which features will be taken.
FilterType filterType() const
Returns the filter type which is currently set on this request.
const QgsFeatureIds & filterFids() const
Gets feature IDs that should be fetched.
@ FilterFids
Filter using feature IDs.
@ FilterExpression
Filter using expression.
std::function< void(const QgsFeature &) > transformErrorCallback() const
Returns the callback function to use when encountering a transform error when iterating features and ...
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition: qgsfeature.h:56
QgsGeometry geometry
Definition: qgsfeature.h:67
void clearGeometry()
Removes any geometry associated with the feature.
Definition: qgsfeature.cpp:159
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Definition: qgsfeature.cpp:205
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
Definition: qgsfeature.cpp:145
Q_GADGET QgsFeatureId id
Definition: qgsfeature.h:64
Base class for feedback objects to be used for cancellation of something running in a worker thread.
Definition: qgsfeedback.h:45
bool isCanceled() const SIP_HOLDGIL
Tells whether the operation has been canceled already.
Definition: qgsfeedback.h:54
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:124
OperationResult transform(const QgsCoordinateTransform &ct, QgsCoordinateTransform::TransformDirection direction=QgsCoordinateTransform::ForwardTransform, bool transformZ=false) SIP_THROW(QgsCsException)
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.
Definition: qgsrectangle.h:42
bool isNull() const
Test if the rectangle is null (all coordinates zero or after call to setMinimal()).
Definition: qgsrectangle.h:479
This class contains information about how to simplify geometries fetched from a QgsFeatureIterator.