Skip to content

Commit 28d7c8c

Browse files
committedMay 7, 2018
Fix a crash in tessellator with self-intersecting rings
Self-intersecting polygon rings may crash poly2tri so we skip them (for now)
1 parent ea38c73 commit 28d7c8c

File tree

2 files changed

+30
-6
lines changed

2 files changed

+30
-6
lines changed
 

‎src/3d/qgstessellator.cpp

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,21 @@ static QgsPolygon *_transform_polygon_to_new_base( const QgsPolygon &polygon, co
282282

283283
static bool _check_intersecting_rings( const QgsPolygon &polygon )
284284
{
285+
QList<QgsGeometry> geomRings;
286+
geomRings << QgsGeometry( polygon.exteriorRing()->clone() );
287+
for ( int i = 0; i < polygon.numInteriorRings(); ++i )
288+
geomRings << QgsGeometry( polygon.interiorRing( i )->clone() );
289+
290+
// we need to make sure that the polygon has no rings with self-intersection: that may
291+
// crash the tessellator. The original geometry maybe have been valid and the self-intersection
292+
// was introduced when transforming to a new base (in a rare case when all points are not in the same plane)
293+
294+
for ( int i = 0; i < geomRings.count(); ++i )
295+
{
296+
if ( !geomRings[i].isSimple() )
297+
return false;
298+
}
299+
285300
// At this point we assume that input polygons are valid according to the OGC definition.
286301
// This means e.g. no duplicate points, polygons are simple (no butterfly shaped polygon with self-intersection),
287302
// internal rings are inside exterior rings, rings do not cross each other, no dangles.
@@ -301,11 +316,6 @@ static bool _check_intersecting_rings( const QgsPolygon &polygon )
301316

302317
if ( polygon.numInteriorRings() > 0 )
303318
{
304-
QList<QgsGeometry> geomRings;
305-
geomRings << QgsGeometry( polygon.exteriorRing()->clone() );
306-
for ( int i = 0; i < polygon.numInteriorRings(); ++i )
307-
geomRings << QgsGeometry( polygon.interiorRing( i )->clone() );
308-
309319
for ( int i = 0; i < geomRings.count(); ++i )
310320
for ( int j = i + 1; j < geomRings.count(); ++j )
311321
{
@@ -417,7 +427,7 @@ void QgsTessellator::addPolygon( const QgsPolygon &polygon, float extrusionHeigh
417427
if ( !_check_intersecting_rings( *polygonNew.get() ) )
418428
{
419429
// skip the polygon - it would cause a crash inside poly2tri library
420-
QgsMessageLog::logMessage( QObject::tr( "polygon rings intersect each other - skipping" ), QObject::tr( "3D" ) );
430+
QgsMessageLog::logMessage( QObject::tr( "polygon rings self-intersect or intersect each other - skipping" ), QObject::tr( "3D" ) );
421431
return;
422432
}
423433

‎tests/src/3d/testqgstessellator.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ class TestQgsTessellator : public QObject
132132
void asMultiPolygon();
133133
void testBadCoordinates();
134134
void testIssue17745();
135+
void testCrashSelfIntersection();
135136

136137
private:
137138
};
@@ -302,6 +303,19 @@ void TestQgsTessellator::testIssue17745()
302303
t.addPolygon( p, 0 ); // must not crash - that's all we test here
303304
}
304305

306+
void TestQgsTessellator::testCrashSelfIntersection()
307+
{
308+
// this is a polygon where we get self-intersecting exterior ring that would crash poly2tri if not skipped
309+
310+
QgsTessellator t( 0, 0, true );
311+
QgsPolygon p;
312+
bool resWktRead = p.fromWkt( "PolygonZ ((-744809.80499999970197678 -1042371.96730000153183937 260.460968017578125, -744809.80299999937415123 -1042371.92199999839067459 260.460968017578125, -744810.21599999815225601 -1042381.09099999815225601 260.460968017578125, -744810.21499999985098839 -1042381.0689999982714653 260.460968017578125, -744812.96469999849796295 -1042375.32499999925494194 263.734283447265625, -744809.80499999970197678 -1042371.96730000153183937 260.460968017578125))" );
313+
314+
QVERIFY( resWktRead );
315+
316+
t.addPolygon( p, 0 ); // must not crash - that's all we test here
317+
}
318+
305319

306320
QGSTEST_MAIN( TestQgsTessellator )
307321
#include "testqgstessellator.moc"

0 commit comments

Comments
 (0)
Please sign in to comment.