@@ -90,12 +90,12 @@ void QgsAtlasComposition::beginRender()
90
90
// select all features with all attributes
91
91
provider->select ( provider->attributeIndexes () );
92
92
93
- // features must be stored in a list, since modifying the layer's extent rewinds nextFeature()
94
- mFeatures . clear ();
95
- QgsFeature feature ;
96
- while ( provider->nextFeature ( feature ) )
93
+ // We cannot use nextFeature() directly since the feature pointer is rewinded by the rendering process
94
+ // We thus store the feature ids for future extraction
95
+ QgsFeature feat ;
96
+ while ( provider->nextFeature ( feat ) )
97
97
{
98
- mFeatures .push_back ( feature );
98
+ mFeatureIds .push_back ( feat. id () );
99
99
}
100
100
101
101
mOrigExtent = mComposerMap ->extent ();
@@ -115,7 +115,7 @@ void QgsAtlasComposition::beginRender()
115
115
116
116
// special columns for expressions
117
117
QgsExpression::setSpecialColumn ( " $numpages" , QVariant ( mComposition ->numPages () ) );
118
- QgsExpression::setSpecialColumn ( " $numfeatures" , QVariant (( int )mFeatures . size () ) );
118
+ QgsExpression::setSpecialColumn ( " $numfeatures" , QVariant (( int )provider-> featureCount () ) );
119
119
}
120
120
121
121
void QgsAtlasComposition::endRender ()
@@ -147,7 +147,11 @@ void QgsAtlasComposition::endRender()
147
147
148
148
size_t QgsAtlasComposition::numFeatures () const
149
149
{
150
- return mFeatures .size ();
150
+ if ( mCoverageLayer )
151
+ {
152
+ return mCoverageLayer ->dataProvider ()->featureCount ();
153
+ }
154
+ return 0 ;
151
155
}
152
156
153
157
void QgsAtlasComposition::prepareForFeature ( size_t featureI )
@@ -157,12 +161,14 @@ void QgsAtlasComposition::prepareForFeature( size_t featureI )
157
161
return ;
158
162
}
159
163
160
- QgsFeature* fit = &mFeatures [featureI];
164
+ QgsVectorDataProvider* provider = mCoverageLayer ->dataProvider ();
165
+ // retrieve the next feature, based on its id
166
+ provider->featureAtId ( mFeatureIds [ featureI ], mCurrentFeature , /* fetchGeometry = */ true , provider->attributeIndexes () );
161
167
162
168
if ( mFilenamePattern .size () > 0 )
163
169
{
164
170
QgsExpression::setSpecialColumn ( " $feature" , QVariant (( int )featureI + 1 ) );
165
- QVariant filenameRes = mFilenameExpr ->evaluate ( &*fit );
171
+ QVariant filenameRes = mFilenameExpr ->evaluate ( &mCurrentFeature );
166
172
if ( mFilenameExpr ->hasEvalError () )
167
173
{
168
174
throw std::runtime_error ( " Filename eval error: " + mFilenameExpr ->evalErrorString ().toStdString () );
@@ -180,7 +186,7 @@ void QgsAtlasComposition::prepareForFeature( size_t featureI )
180
186
// We have to transform the grometry to the destination CRS and ask for the bounding box
181
187
// Note: we cannot directly take the transformation of the bounding box, since transformations are not linear
182
188
183
- QgsGeometry tgeom ( *fit-> geometry () );
189
+ QgsGeometry tgeom ( *mCurrentFeature . geometry () );
184
190
tgeom.transform ( mTransform );
185
191
QgsRectangle geom_rect = tgeom.boundingBox ();
186
192
@@ -243,7 +249,7 @@ void QgsAtlasComposition::prepareForFeature( size_t featureI )
243
249
244
250
for ( QList<QgsComposerLabel*>::iterator lit = labels.begin (); lit != labels.end (); ++lit )
245
251
{
246
- ( *lit )->setExpressionContext ( fit , mCoverageLayer );
252
+ ( *lit )->setExpressionContext ( & mCurrentFeature , mCoverageLayer );
247
253
}
248
254
249
255
// set the new extent (and render)
0 commit comments