QGIS API Documentation  3.14.0-Pi (9f7028fd23)
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  const auto constPreparedOrderBys = preparedOrderBys;
188  for ( const QgsFeatureRequest::OrderByClause &orderBy : constPreparedOrderBys )
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 }
238 
240 {
241  return mIter && mIter->isValid();
242 }
QgsExpressionContext
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
Definition: qgsexpressioncontext.h:369
QgsAbstractFeatureIterator::refs
int refs
reference counting (to allow seamless copying of QgsFeatureIterator instances) TODO QGIS3: make this ...
Definition: qgsfeatureiterator.h:171
QgsFeatureRequest::OrderByClause
Definition: qgsfeaturerequest.h:142
QgsGeometry::transform
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.
Definition: qgsgeometry.cpp:2836
QgsSimplifyMethod
Definition: qgssimplifymethod.h:28
QgsFeatureRequest::filterFids
const QgsFeatureIds & filterFids() const
Gets feature IDs that should be fetched.
Definition: qgsfeaturerequest.h:358
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:220
QgsAbstractFeatureIterator::isValid
virtual bool isValid() const
Returns if this iterator is valid.
Definition: qgsfeatureiterator.h:81
QgsFeatureRequest::filterRect
const QgsRectangle & filterRect() const
Returns the rectangle from which features will be taken.
Definition: qgsfeaturerequest.h:348
QgsFeatureRequest::filterType
FilterType filterType() const
Returns the filter type which is currently set on this request.
Definition: qgsfeaturerequest.h:325
qgsfeatureiterator.h
QgsAbstractFeatureIterator::mFetchedCount
long mFetchedCount
Number of features already fetched by iterator.
Definition: qgsfeatureiterator.h:179
QgsFeatureRequest::FilterFids
@ FilterFids
Filter using feature IDs.
Definition: qgsfeaturerequest.h:108
QgsFeature::geometry
QgsGeometry geometry
Definition: qgsfeature.h:71
QgsAbstractFeatureIterator::mRequest
QgsFeatureRequest mRequest
A copy of the feature request.
Definition: qgsfeatureiterator.h:153
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:74
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:876
QgsAbstractFeatureIterator::nextFeature
virtual bool nextFeature(QgsFeature &f)
fetch next feature, return true on success
Definition: qgsfeatureiterator.cpp:27
QgsRectangle
Definition: qgsrectangle.h:41
QgsCoordinateTransform::ReverseTransform
@ ReverseTransform
Transform from destination to source CRS.
Definition: qgscoordinatetransform.h:61
QgsCoordinateTransform::transformBoundingBox
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.
Definition: qgscoordinatetransform.cpp:511
QgsAbstractFeatureIterator::ref
void ref()
Add reference.
Definition: qgsfeatureiterator.cpp:126
QgsFeatureRequest::expressionContext
QgsExpressionContext * expressionContext()
Returns the expression context used to evaluate filter expressions.
Definition: qgsfeaturerequest.h:441
QgsFeature::clearGeometry
void clearGeometry()
Removes any geometry associated with the feature.
Definition: qgsfeature.cpp:151
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:118
QgsFeatureRequest
Definition: qgsfeaturerequest.h:75
QgsAbstractFeatureIterator::mZombie
bool mZombie
A feature iterator may be closed already but still be serving features from the cache.
Definition: qgsfeatureiterator.h:165
QgsCsException
Definition: qgsexception.h:65
qgsexpressionsorter.h
QgsFeature::setGeometry
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
Definition: qgsfeature.cpp:137
QgsFeedback
Definition: qgsfeedback.h:43
QgsFeatureRequest::filterExpression
QgsExpression * filterExpression() const
Returns the filter expression if set.
Definition: qgsfeaturerequest.h:425
QgsFeatureRequest::FilterExpression
@ FilterExpression
Filter using expression.
Definition: qgsfeaturerequest.h:107
QgsAbstractFeatureIterator::geometryToDestinationCrs
void geometryToDestinationCrs(QgsFeature &feature, const QgsCoordinateTransform &transform) const
Transforms feature's geometry according to the specified coordinate transform.
Definition: qgsfeatureiterator.cpp:95
QgsAbstractFeatureIterator::QgsAbstractFeatureIterator
QgsAbstractFeatureIterator(const QgsFeatureRequest &request)
base class constructor - stores the iteration parameters
Definition: qgsfeatureiterator.cpp:22
QgsExpression::evaluate
QVariant evaluate()
Evaluate the feature and return the result.
Definition: qgsexpression.cpp:346
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:85
QgsGeometry
Definition: qgsgeometry.h:122
QgsFeatureRequest::orderBy
OrderBy orderBy() const
Returns a list of order by clauses specified for this feature request.
Definition: qgsfeaturerequest.cpp:167
QgsFeature::hasGeometry
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Definition: qgsfeature.cpp:197
QgsIndexedFeature
Definition: qgsindexedfeature.h:29
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:143
QgsFeatureRequest::simplifyMethod
const QgsSimplifyMethod & simplifyMethod() const
Gets simplification method for geometries that will be fetched.
Definition: qgsfeaturerequest.h:557
QgsFeatureIterator::operator=
QgsFeatureIterator & operator=(const QgsFeatureIterator &other)
Definition: qgsfeatureiterator.cpp:226
QgsAbstractFeatureIterator::compileFailed
bool compileFailed() const
Indicator if there was an error when sending the compiled query to the server.
Definition: qgsfeatureiterator.cpp:150
QgsSimplifyMethod::MethodType
MethodType
Definition: qgssimplifymethod.h:31
qgsexception.h
QgsFeature
Definition: qgsfeature.h:55
QgsIndexedFeature::mIndexes
QVector< QVariant > mIndexes
Definition: qgsindexedfeature.h:32
qgslogger.h
QgsAbstractFeatureIterator::mCompileFailed
bool mCompileFailed
Definition: qgsfeatureiterator.h:184
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:639
QgsFeatureIterator::mIter
QgsAbstractFeatureIterator * mIter
Definition: qgsfeatureiterator.h:346
QgsCoordinateTransform
Definition: qgscoordinatetransform.h:52
QgsFeatureIterator
Definition: qgsfeatureiterator.h:263
QgsRectangle::isNull
bool isNull() const
Test if the rectangle is null (all coordinates zero or after call to setMinimal()).
Definition: qgsrectangle.h:447
QgsFeatureIterator::isValid
bool isValid() const
Will return if this iterator is valid.
Definition: qgsfeatureiterator.cpp:239
QgsAbstractFeatureIterator::prepareSimplification
virtual bool prepareSimplification(const QgsSimplifyMethod &simplifyMethod)
Setup the simplification of geometries to fetch using the specified simplify method.
Definition: qgsfeatureiterator.cpp:155
qgssimplifymethod.h
QgsExpressionContext::setFeature
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
Definition: qgsexpressioncontext.cpp:521
QgsIndexedFeature::mFeature
QgsFeature mFeature
Definition: qgsindexedfeature.h:33
QgsFeatureRequest::limit
long limit() const
Returns the maximum number of features to request, or -1 if no limit set.
Definition: qgsfeaturerequest.h:512