QGIS API Documentation  2.99.0-Master (7705179)
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 
23  : mRequest( request )
24  , mClosed( false )
25  , mZombie( false )
26  , refs( 0 )
27  , mFetchedCount( 0 )
28  , mCompileStatus( NoCompilation )
29  , mUseCachedFeatures( false )
30 {
31 }
32 
34 {
35  bool dataOk = false;
36  if ( mRequest.limit() >= 0 && mFetchedCount >= mRequest.limit() )
37  {
38  return false;
39  }
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  {
85  if ( mRequest.filterExpression()->evaluate( mRequest.expressionContext() ).toBool() )
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 ( mRequest.filterRect().isNull() )
127  return QgsRectangle();
128 
130 }
131 
133 {
134  // Prepare if required the simplification of geometries to fetch:
135  // This code runs here because of 'prepareSimplification()' is virtual and it can be overridden
136  // in inherited iterators who change the default behavior.
137  // It would be better to call this method in the constructor enabling virtual-calls as it is described by example at:
138  // http://www.parashift.com/c%2B%2B-faq-lite/calling-virtuals-from-ctor-idiom.html
139  if ( refs == 0 )
140  {
142 
143  // Should be called as last preparation step since it possibly will already fetch all features
144  setupOrderBy( mRequest.orderBy() );
145  }
146  refs++;
147 }
148 
150 {
151  refs--;
152  if ( !refs )
153  delete this;
154 }
155 
157 {
158  Q_UNUSED( simplifyMethod );
159  return false;
160 }
161 
162 void QgsAbstractFeatureIterator::setupOrderBy( const QList<QgsFeatureRequest::OrderByClause> &orderBys )
163 {
164  // Let the provider try using an efficient order by strategy first
165  if ( !orderBys.isEmpty() && !prepareOrderBy( orderBys ) )
166  {
167  // No success from the provider
168 
169  // Prepare the expressions
170  QList<QgsFeatureRequest::OrderByClause> preparedOrderBys( orderBys );
171  QList<QgsFeatureRequest::OrderByClause>::iterator orderByIt( preparedOrderBys.begin() );
172 
173  QgsExpressionContext *expressionContext( mRequest.expressionContext() );
174  do
175  {
176  orderByIt->prepare( expressionContext );
177  }
178  while ( ++orderByIt != preparedOrderBys.end() );
179 
180  // Fetch all features
181  QgsIndexedFeature indexedFeature;
182  indexedFeature.mIndexes.resize( preparedOrderBys.size() );
183 
184  while ( nextFeature( indexedFeature.mFeature ) )
185  {
186  expressionContext->setFeature( indexedFeature.mFeature );
187  int i = 0;
188  Q_FOREACH ( const QgsFeatureRequest::OrderByClause &orderBy, preparedOrderBys )
189  {
190  indexedFeature.mIndexes.replace( i++, orderBy.expression().evaluate( expressionContext ) );
191  }
192 
193  // We need all features, to ignore the limit for this pre-fetch
194  // keep the fetched count at 0.
195  mFetchedCount = 0;
196  mCachedFeatures.append( indexedFeature );
197  }
198 
199  std::sort( mCachedFeatures.begin(), mCachedFeatures.end(), QgsExpressionSorter( preparedOrderBys ) );
200 
201  mFeatureIterator = mCachedFeatures.constBegin();
202  mUseCachedFeatures = true;
203  // The real iterator is closed, we are only serving cached features
204  mZombie = true;
205  }
206 }
207 
208 bool QgsAbstractFeatureIterator::providerCanSimplify( QgsSimplifyMethod::MethodType methodType ) const
209 {
210  Q_UNUSED( methodType )
211  return false;
212 }
213 
214 bool QgsAbstractFeatureIterator::prepareOrderBy( const QList<QgsFeatureRequest::OrderByClause> &orderBys )
215 {
216  Q_UNUSED( orderBys )
217  return false;
218 }
219 
221 {
222 }
223 
225 
227 {
228  if ( this != &other )
229  {
230  if ( mIter )
231  mIter->deref();
232  mIter = other.mIter;
233  if ( mIter )
234  mIter->ref();
235  }
236  return *this;
237 }
QgsFeatureId id
Definition: qgsfeature.h:70
Wrapper for iterator of features from vector data provider or vector layer.
A rectangle specified with double values.
Definition: qgsrectangle.h:38
long limit() const
Returns the maximum number of features to request, or -1 if no limit set.
void geometryToDestinationCrs(QgsFeature &feature, const QgsCoordinateTransform &transform) const
Transforms feature&#39;s geometry according to the specified coordinate transform.
Filter using feature IDs.
long mFetchedCount
Number of features already fetched by iterator.
virtual bool fetchFeature(QgsFeature &f)=0
If you write a feature iterator for your provider, this is the method you need to implement!! ...
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
QgsExpressionContext * expressionContext()
Returns the expression context used to evaluate filter expressions.
QgsRectangle filterRectToSourceCrs(const QgsCoordinateTransform &transform) const
Returns a rectangle representing the original request&#39;s QgsFeatureRequest::filterRect().
QgsRectangle transformBoundingBox(const QgsRectangle &rectangle, TransformDirection direction=ForwardTransform, const bool handle180Crossover=false) const
Transforms a rectangle from the source CRS to the destination CRS.
FilterType filterType() const
Return the filter type which is currently set on this request.
const QgsFeatureIds & filterFids() const
Get feature IDs that should be fetched.
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:92
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:61
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Definition: qgsfeature.cpp:190
const QgsRectangle & filterRect() const
Returns the rectangle from which features will be taken.
bool isValid() const
Returns true if the coordinate transform is valid, ie both the source and destination CRS have been s...
QgsExpression * filterExpression() const
Returns the filter expression if set.
Interface that can be optionally attached to an iterator so its nextFeature() implementaton can check...
virtual bool nextFeature(QgsFeature &f)
fetch next feature, return true on success
Temporarily used structure to cache order by information.
QgsFeatureIterator & operator=(const QgsFeatureIterator &other)
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
virtual bool nextFeatureFilterExpression(QgsFeature &f)
By default, the iterator will fetch all features and check if the feature matches the expression...
bool mZombie
A feature iterator may be closed already but still be serving features from the cache.
This class wraps a request for features to a vector layer (or directly its vector data provider)...
void deref()
Remove reference, delete if refs == 0.
QgsGeometry geometry() const
Returns the geometry associated with this feature.
Definition: qgsfeature.cpp:101
virtual bool nextFeatureFilterFids(QgsFeature &f)
By default, the iterator will fetch all features and check if the id is in the request.
The OrderByClause class represents an order by clause for a QgsFeatureRequest.
QgsFeatureRequest mRequest
A copy of the feature request.
void clearGeometry()
Removes any geometry associated with the feature.
Definition: qgsfeature.cpp:144
QgsExpression expression() const
The expression.
virtual void setInterruptionChecker(QgsInterruptionChecker *interruptionChecker)
Attach an object that can be queried regularly by the iterator to check if it must stopped...
OperationResult transform(const QgsCoordinateTransform &ct)
Transforms this geometry as described by CoordinateTransform ct.
Transform from destination to source CRS.
void setGeometry(const QgsGeometry &geometry)
Set the feature&#39;s geometry.
Definition: qgsfeature.cpp:137
bool isNull() const
Test if the rectangle is null (all coordinates zero or after call to setMinimal()).
QgsAbstractFeatureIterator * mIter
Class for doing transforms between two map coordinate systems.
QVector< QVariant > mIndexes
This class contains information about how to simplify geometries fetched from a QgsFeatureIterator.
Custom exception class for Coordinate Reference System related exceptions.
Definition: qgsexception.h:64
int refs
reference counting (to allow seamless copying of QgsFeatureIterator instances) TODO QGIS3: make this ...
OrderBy orderBy() const
Return a list of order by clauses specified for this feature request.
std::function< void(const QgsFeature &) > transformErrorCallback() const
Returns the callback function to use when encountering a transform error when iterating features and ...
virtual bool prepareSimplification(const QgsSimplifyMethod &simplifyMethod)
Setup the simplification of geometries to fetch using the specified simplify method.
const QgsSimplifyMethod & simplifyMethod() const
Get simplification method for geometries that will be fetched.
QgsAbstractFeatureIterator(const QgsFeatureRequest &request)
base class constructor - stores the iteration parameters