QGIS API Documentation
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 "qgsgeometrysimplifier.h"
19 #include "qgssimplifymethod.h"
20 
21 #include "qgsexpressionsorter.h"
22 
24  : mRequest( request )
25  , mClosed( false )
26  , mZombie( false )
27  , refs( 0 )
28  , mFetchedCount( 0 )
29  , mCompileStatus( NoCompilation )
30  , mGeometrySimplifier( nullptr )
31  , mLocalSimplification( false )
32  , mUseCachedFeatures( false )
33 {
34 }
35 
37 {
38  delete mGeometrySimplifier;
39 }
40 
42 {
43  bool dataOk = false;
44  if ( mRequest.limit() >= 0 && mFetchedCount >= mRequest.limit() )
45  {
46  return false;
47  }
48 
49  if ( mUseCachedFeatures )
50  {
51  if ( mFeatureIterator != mCachedFeatures.constEnd() )
52  {
53  f = mFeatureIterator->mFeature;
54  ++mFeatureIterator;
55  dataOk = true;
56  }
57  else
58  {
59  dataOk = false;
60  // even the zombie dies at this point...
61  mZombie = false;
62  }
63  }
64  else
65  {
66  switch ( mRequest.filterType() )
67  {
69  dataOk = nextFeatureFilterExpression( f );
70  break;
71 
73  dataOk = nextFeatureFilterFids( f );
74  break;
75 
76  default:
77  dataOk = fetchFeature( f );
78  break;
79  }
80  }
81 
82  // simplify the geometry using the simplifier configured
83  if ( dataOk && mLocalSimplification )
84  {
85  if ( f.constGeometry() )
86  simplify( f );
87  }
88  if ( dataOk )
89  mFetchedCount++;
90 
91  return dataOk;
92 }
93 
95 {
96  while ( fetchFeature( f ) )
97  {
100  return true;
101  }
102  return false;
103 }
104 
106 {
107  while ( fetchFeature( f ) )
108  {
109  if ( mRequest.filterFids().contains( f.id() ) )
110  return true;
111  }
112  return false;
113 }
114 
116 {
117  // Prepare if required the simplification of geometries to fetch:
118  // This code runs here because of 'prepareSimplification()' is virtual and it can be overrided
119  // in inherited iterators who change the default behavior.
120  // It would be better to call this method in the constructor enabling virtual-calls as it is described by example at:
121  // http://www.parashift.com/c%2B%2B-faq-lite/calling-virtuals-from-ctor-idiom.html
122  if ( refs == 0 )
123  {
125 
126  // Should be called as last preparation step since it possibly will already fetch all features
127  setupOrderBy( mRequest.orderBy() );
128  }
129  refs++;
130 }
131 
133 {
134  refs--;
135  if ( !refs )
136  delete this;
137 }
138 
140 {
141  mLocalSimplification = false;
142 
143  delete mGeometrySimplifier;
144  mGeometrySimplifier = nullptr;
145 
146  // setup the simplification of geometries to fetch
147  if ( !( mRequest.flags() & QgsFeatureRequest::NoGeometry ) && simplifyMethod.methodType() != QgsSimplifyMethod::NoSimplification && ( simplifyMethod.forceLocalOptimization() || !providerCanSimplify( simplifyMethod.methodType() ) ) )
148  {
149  mGeometrySimplifier = QgsSimplifyMethod::createGeometrySimplifier( simplifyMethod );
150  mLocalSimplification = nullptr != mGeometrySimplifier;
151  return mLocalSimplification;
152  }
153  return false;
154 }
155 
156 void QgsAbstractFeatureIterator::setupOrderBy( const QList<QgsFeatureRequest::OrderByClause>& orderBys )
157 {
158  // Let the provider try using an efficient order by strategy first
159  if ( !orderBys.isEmpty() && !prepareOrderBy( orderBys ) )
160  {
161  // No success from the provider
162 
163  // Prepare the expressions
164  QList<QgsFeatureRequest::OrderByClause> preparedOrderBys( orderBys );
165  QList<QgsFeatureRequest::OrderByClause>::iterator orderByIt( preparedOrderBys.begin() );
166 
167  QgsExpressionContext* expressionContext( mRequest.expressionContext() );
168  do
169  {
170  orderByIt->expression().prepare( expressionContext );
171  }
172  while ( ++orderByIt != preparedOrderBys.end() );
173 
174  // Fetch all features
175  QgsIndexedFeature indexedFeature;
176  indexedFeature.mIndexes.resize( preparedOrderBys.size() );
177 
178  while ( nextFeature( indexedFeature.mFeature ) )
179  {
180  expressionContext->setFeature( indexedFeature.mFeature );
181  int i = 0;
182  Q_FOREACH ( const QgsFeatureRequest::OrderByClause& orderBy, preparedOrderBys )
183  {
184  indexedFeature.mIndexes.replace( i++, orderBy.expression().evaluate( expressionContext ) );
185  }
186 
187  // We need all features, to ignore the limit for this pre-fetch
188  // keep the fetched count at 0.
189  mFetchedCount = 0;
190  mCachedFeatures.append( indexedFeature );
191  }
192 
193  qSort( mCachedFeatures.begin(), mCachedFeatures.end(), QgsExpressionSorter( preparedOrderBys ) );
194 
195  mFeatureIterator = mCachedFeatures.constBegin();
196  mUseCachedFeatures = true;
197  // The real iterator is closed, we are only serving cached features
198  mZombie = true;
199  }
200 }
201 
202 bool QgsAbstractFeatureIterator::providerCanSimplify( QgsSimplifyMethod::MethodType methodType ) const
203 {
204  Q_UNUSED( methodType )
205  return false;
206 }
207 
208 bool QgsAbstractFeatureIterator::simplify( QgsFeature& feature )
209 {
210  // simplify locally the geometry using the configured simplifier
211  if ( mGeometrySimplifier )
212  {
213  QgsGeometry* geometry = feature.geometry();
214 
215  QGis::GeometryType geometryType = geometry->type();
216  if ( geometryType == QGis::Line || geometryType == QGis::Polygon )
217  return mGeometrySimplifier->simplifyGeometry( geometry );
218  }
219  return false;
220 }
221 
222 bool QgsAbstractFeatureIterator::prepareOrderBy( const QList<QgsFeatureRequest::OrderByClause>& orderBys )
223 {
224  Q_UNUSED( orderBys )
225  return false;
226 }
227 
229 {
230 }
231 
233 
235 {
236  if ( this != &other )
237  {
238  if ( mIter )
239  mIter->deref();
240  mIter = other.mIter;
241  if ( mIter )
242  mIter->ref();
243  }
244  return *this;
245 }
QgsFeatureId id() const
Get the feature ID for this feature.
Definition: qgsfeature.cpp:65
Wrapper for iterator of features from vector data provider or vector layer.
const QgsSimplifyMethod & simplifyMethod() const
Get simplification method for geometries that will be fetched.
const Flags & flags() const
Filter using feature IDs.
GeometryType
Definition: qgis.h:111
Q_DECL_DEPRECATED QVariant evaluate(const QgsFeature *f)
Evaluate the feature and return the result.
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.
const QgsFeatureIds & filterFids() const
Get feature IDs that should be fetched.
QGis::GeometryType type() const
Returns type of the geometry as a QGis::GeometryType.
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:76
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:187
int size() const
virtual bool simplifyGeometry(QgsGeometry *geometry) const =0
Simplifies the specified geometry.
Interface that can be optionaly attached to an iterator so its nextFeature() implementaton can check ...
QgsExpression expression() const
The expression.
void append(const T &value)
void resize(int size)
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)
bool isEmpty() const
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)...
No simplification is applied.
FilterType filterType() const
Return the filter type which is currently set on this request.
void deref()
remove reference, delete if refs == 0
iterator end()
long limit() const
Returns the maximum number of features to request, or -1 if no limit set.
virtual bool nextFeatureFilterFids(QgsFeature &f)
By default, the iterator will fetch all features and check if the id is in the request.
QgsGeometry * geometry()
Get the geometry object associated with this feature.
Definition: qgsfeature.cpp:76
The OrderByClause class represents an order by clause for a QgsFeatureRequest.
bool contains(const T &value) const
QgsFeatureRequest mRequest
A copy of the feature request.
virtual void setInterruptionChecker(QgsInterruptionChecker *interruptionChecker)
Attach an object that can be queried regularly by the iterator to check if it must stopped...
QgsAbstractFeatureIterator * mIter
const QgsGeometry * constGeometry() const
Gets a const pointer to the geometry object associated with this feature.
Definition: qgsfeature.cpp:82
OrderBy orderBy() const
Return a list of order by clauses specified for this feature request.
static QgsAbstractGeometrySimplifier * createGeometrySimplifier(const QgsSimplifyMethod &simplifyMethod)
Creates a geometry simplifier according to specified method.
QVector< QVariant > mIndexes
void replace(int i, const T &value)
This class contains information about how to simplify geometries fetched from a QgsFeatureIterator.
int refs
reference counting (to allow seamless copying of QgsFeatureIterator instances) TODO QGIS3: make this ...
const_iterator constEnd() const
const_iterator constBegin() const
Geometry is not required. It may still be returned if e.g. required for a filter condition.
virtual bool prepareSimplification(const QgsSimplifyMethod &simplifyMethod)
Setup the simplification of geometries to fetch using the specified simplify method.
virtual ~QgsAbstractFeatureIterator()
destructor makes sure that the iterator is closed properly
iterator begin()
QgsAbstractFeatureIterator(const QgsFeatureRequest &request)
base class constructor - stores the iteration parameters
MethodType methodType() const
Gets the simplification type.
bool forceLocalOptimization() const
Gets whether the simplification executes after fetch the geometries from provider, otherwise it executes, when supported, in provider before fetch the geometries.
QgsExpression * filterExpression() const
Returns the filter expression if set.