Skip to content

Commit 033bf6f

Browse files
committedJun 16, 2014
Inverted polygons fixes (crashes, geometry checking, memory consuption, CPU efficiency)
1 parent 7ff4888 commit 033bf6f

File tree

1 file changed

+18
-11
lines changed

1 file changed

+18
-11
lines changed
 

‎src/core/symbology-ng/qgsinvertedpolygonrenderer.cpp

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,10 @@ bool QgsInvertedPolygonRenderer::renderFeature( QgsFeature& feature, QgsRenderCo
202202
geom.reset( geom->buffer( 0, 0 ) );
203203
}
204204
}
205+
206+
if ( !geom )
207+
return false; // do not let invalid geometries sneak in!
208+
205209
// add the geometry to the list of geometries for this feature
206210
cFeat.geometries.append( geom.take() );
207211

@@ -221,18 +225,15 @@ void QgsInvertedPolygonRenderer::stopRender( QgsRenderContext& context )
221225

222226
for ( FeatureCategoryVector::iterator cit = mFeaturesCategories.begin(); cit != mFeaturesCategories.end(); ++cit )
223227
{
224-
QgsFeature& feat = cit->feature;
228+
QgsFeature feat = cit->feature; // just a copy, so that we do not accumulate geometries again
225229
if ( mPreprocessingEnabled )
226230
{
227231
// compute the unary union on the polygons
228232
QScopedPointer<QgsGeometry> unioned( QgsGeometry::unaryUnion( cit->geometries ) );
229233
// compute the difference with the extent
230234
QScopedPointer<QgsGeometry> rect( QgsGeometry::fromPolygon( mExtentPolygon ) );
231-
QgsGeometry *final = rect->difference( const_cast<QgsGeometry*>(unioned.data()) );
232-
if ( final )
233-
{
234-
feat.setGeometry( final );
235-
}
235+
QgsGeometry *final = rect->difference( const_cast<QgsGeometry*>( unioned.data() ) );
236+
feat.setGeometry( final );
236237
}
237238
else
238239
{
@@ -248,7 +249,7 @@ void QgsInvertedPolygonRenderer::stopRender( QgsRenderContext& context )
248249
// operations do not need geometries to be valid
249250
QgsMultiPolygon finalMulti;
250251
finalMulti.append( mExtentPolygon );
251-
foreach( QgsGeometry* geom, cit->geometries )
252+
foreach ( QgsGeometry* geom, cit->geometries )
252253
{
253254
QgsMultiPolygon multi;
254255
if (( geom->wkbType() == QGis::WKBPolygon ) ||
@@ -264,8 +265,13 @@ void QgsInvertedPolygonRenderer::stopRender( QgsRenderContext& context )
264265

265266
for ( int i = 0; i < multi.size(); i++ )
266267
{
268+
const QgsPolyline& exterior = multi[i][0];
267269
// add the exterior ring as interior ring to the first polygon
268-
finalMulti[0].append( multi[i][0] );
270+
// make sure it satisfies at least very basic requirements of GEOS
271+
// (otherwise the creation of GEOS geometry will fail)
272+
if ( exterior.count() < 4 || exterior[0] != exterior[exterior.count() - 1] )
273+
continue;
274+
finalMulti[0].append( exterior );
269275

270276
// add interior rings as new polygons
271277
for ( int j = 1; j < multi[i].size(); j++ )
@@ -275,14 +281,15 @@ void QgsInvertedPolygonRenderer::stopRender( QgsRenderContext& context )
275281
finalMulti.append( new_poly );
276282
}
277283
}
278-
feat.setGeometry( QgsGeometry::fromMultiPolygon( finalMulti ) );
279284
}
285+
feat.setGeometry( QgsGeometry::fromMultiPolygon( finalMulti ) );
280286
}
281-
mSubRenderer->renderFeature( feat, mContext );
287+
if ( feat.geometry() )
288+
mSubRenderer->renderFeature( feat, mContext );
282289
}
283290
for ( FeatureCategoryVector::iterator cit = mFeaturesCategories.begin(); cit != mFeaturesCategories.end(); ++cit )
284291
{
285-
foreach( QgsGeometry* g, cit->geometries )
292+
foreach ( QgsGeometry* g, cit->geometries )
286293
{
287294
delete g;
288295
}

0 commit comments

Comments
 (0)
Please sign in to comment.