QGIS API Documentation  3.4.15-Madeira (e83d02e274)
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 {
25 }
26 
28 {
29  bool dataOk = false;
30  if ( mRequest.limit() >= 0 && mFetchedCount >= mRequest.limit() )
31  {
32  return false;
33  }
34 
35  if ( mUseCachedFeatures )
36  {
37  if ( mFeatureIterator != mCachedFeatures.constEnd() )
38  {
39  f = mFeatureIterator->mFeature;
40  ++mFeatureIterator;
41  dataOk = true;
42  }
43  else
44  {
45  dataOk = false;
46  // even the zombie dies at this point...
47  mZombie = false;
48  }
49  }
50  else
51  {
52  switch ( mRequest.filterType() )
53  {
55  dataOk = nextFeatureFilterExpression( f );
56  break;
57 
59  dataOk = nextFeatureFilterFids( f );
60  break;
61 
62  default:
63  dataOk = fetchFeature( f );
64  break;
65  }
66  }
67 
68  if ( dataOk )
69  mFetchedCount++;
70 
71  return dataOk;
72 }
73 
75 {
76  while ( fetchFeature( f ) )
77  {
80  return true;
81  }
82  return false;
83 }
84 
86 {
87  while ( fetchFeature( f ) )
88  {
89  if ( mRequest.filterFids().contains( f.id() ) )
90  return true;
91  }
92  return false;
93 }
94 
96 {
97  if ( transform.isValid() && feature.hasGeometry() )
98  {
99  try
100  {
101  QgsGeometry g = feature.geometry();
102  g.transform( transform );
103  feature.setGeometry( g );
104  }
105  catch ( QgsCsException & )
106  {
107  // transform error
109  {
110  mRequest.transformErrorCallback()( feature );
111  }
112  // remove geometry - we can't reproject so better not return a geometry in a different crs
113  feature.clearGeometry();
114  }
115  }
116 }
117 
119 {
120  if ( mRequest.filterRect().isNull() )
121  return QgsRectangle();
122 
124 }
125 
127 {
128  // Prepare if required the simplification of geometries to fetch:
129  // This code runs here because of 'prepareSimplification()' is virtual and it can be overridden
130  // in inherited iterators who change the default behavior.
131  // It would be better to call this method in the constructor enabling virtual-calls as it is described by example at:
132  // http://www.parashift.com/c%2B%2B-faq-lite/calling-virtuals-from-ctor-idiom.html
133  if ( refs == 0 )
134  {
136 
137  // Should be called as last preparation step since it possibly will already fetch all features
138  setupOrderBy( mRequest.orderBy() );
139  }
140  refs++;
141 }
142 
144 {
145  refs--;
146  if ( !refs )
147  delete this;
148 }
149 
151 {
152  return mCompileFailed;
153 }
154 
156 {
157  Q_UNUSED( simplifyMethod );
158  return false;
159 }
160 
161 void QgsAbstractFeatureIterator::setupOrderBy( const QList<QgsFeatureRequest::OrderByClause> &orderBys )
162 {
163  // Let the provider try using an efficient order by strategy first
164  if ( !orderBys.isEmpty() && !prepareOrderBy( orderBys ) )
165  {
166  // No success from the provider
167 
168  // Prepare the expressions
169  QList<QgsFeatureRequest::OrderByClause> preparedOrderBys( orderBys );
170  QList<QgsFeatureRequest::OrderByClause>::iterator orderByIt( preparedOrderBys.begin() );
171 
172  QgsExpressionContext *expressionContext( mRequest.expressionContext() );
173  do
174  {
175  orderByIt->prepare( expressionContext );
176  }
177  while ( ++orderByIt != preparedOrderBys.end() );
178 
179  // Fetch all features
180  QgsIndexedFeature indexedFeature;
181  indexedFeature.mIndexes.resize( preparedOrderBys.size() );
182 
183  while ( nextFeature( indexedFeature.mFeature ) )
184  {
185  expressionContext->setFeature( indexedFeature.mFeature );
186  int i = 0;
187  Q_FOREACH ( const QgsFeatureRequest::OrderByClause &orderBy, preparedOrderBys )
188  {
189  indexedFeature.mIndexes.replace( i++, orderBy.expression().evaluate( expressionContext ) );
190  }
191 
192  // We need all features, to ignore the limit for this pre-fetch
193  // keep the fetched count at 0.
194  mFetchedCount = 0;
195  mCachedFeatures.append( indexedFeature );
196  }
197 
198  std::sort( mCachedFeatures.begin(), mCachedFeatures.end(), QgsExpressionSorter( preparedOrderBys ) );
199 
200  mFeatureIterator = mCachedFeatures.constBegin();
201  mUseCachedFeatures = true;
202  // The real iterator is closed, we are only serving cached features
203  mZombie = true;
204  }
205 }
206 
207 bool QgsAbstractFeatureIterator::providerCanSimplify( QgsSimplifyMethod::MethodType methodType ) const
208 {
209  Q_UNUSED( methodType )
210  return false;
211 }
212 
213 bool QgsAbstractFeatureIterator::prepareOrderBy( const QList<QgsFeatureRequest::OrderByClause> &orderBys )
214 {
215  Q_UNUSED( orderBys )
216  return false;
217 }
218 
220 {
221 }
222 
224 
226 {
227  if ( this != &other )
228  {
229  if ( mIter )
230  mIter->deref();
231  mIter = other.mIter;
232  if ( mIter )
233  mIter->ref();
234  }
235  return *this;
236 }
237 
239 {
240  return mIter && mIter->isValid();
241 }
QgsFeatureId id
Definition: qgsfeature.h:64
Wrapper for iterator of features from vector data provider or vector layer.
const QgsSimplifyMethod & simplifyMethod() const
Gets simplification method for geometries that will be fetched.
A rectangle specified with double values.
Definition: qgsrectangle.h:40
Filter using feature IDs.
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.
long mFetchedCount
Number of features already fetched by iterator.
QgsRectangle filterRectToSourceCrs(const QgsCoordinateTransform &transform) const SIP_THROW(QgsCsException)
Returns a rectangle representing the original request&#39;s QgsFeatureRequest::filterRect().
const QgsRectangle & filterRect() const
Returns the rectangle from which features will be taken.
virtual bool isValid() const
Will return if this iterator is valid.
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
Gets feature IDs that should be fetched.
bool compileFailed() const
Indicator if there was an error when sending the compiled query to the server.
QVariant evaluate()
Evaluate the feature and return the result.
bool isNull() const
Test if the rectangle is null (all coordinates zero or after call to setMinimal()).
Definition: qgsrectangle.h:435
std::function< void(const QgsFeature &) > transformErrorCallback() const
Returns the callback function to use when encountering a transform error when iterating features and ...
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:106
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:55
Base class for feedback objects to be used for cancellation of something running in a worker thread...
Definition: qgsfeedback.h:44
QgsExpression expression() const
The expression.
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)...
FilterType filterType() const
Returns the filter type which is currently set on this request.
void deref()
Remove reference, delete if refs == 0.
void geometryToDestinationCrs(QgsFeature &feature, const QgsCoordinateTransform &transform) const
Transforms feature&#39;s geometry according to the specified coordinate transform.
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.
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:151
Transform from destination to source CRS.
void setGeometry(const QgsGeometry &geometry)
Set the feature&#39;s geometry.
Definition: qgsfeature.cpp:137
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Definition: qgsfeature.cpp:197
QgsAbstractFeatureIterator * mIter
OrderBy orderBy() const
Returns a list of order by clauses specified for this feature request.
Class for doing transforms between two map coordinate systems.
virtual void setInterruptionChecker(QgsFeedback *interruptionChecker)
Attach an object that can be queried regularly by the iterator to check if it must stopped...
QVector< QVariant > mIndexes
This class contains information about how to simplify geometries fetched from a QgsFeatureIterator.
QgsGeometry geometry
Definition: qgsfeature.h:67
Custom exception class for Coordinate Reference System related exceptions.
Definition: qgsexception.h:65
int refs
reference counting (to allow seamless copying of QgsFeatureIterator instances) TODO QGIS3: make this ...
virtual bool prepareSimplification(const QgsSimplifyMethod &simplifyMethod)
Setup the simplification of geometries to fetch using the specified simplify method.
QgsAbstractFeatureIterator(const QgsFeatureRequest &request)
base class constructor - stores the iteration parameters
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...
QgsExpression * filterExpression() const
Returns the filter expression if set.