|
16 | 16 | #include "qgstessellator.h"
|
17 | 17 |
|
18 | 18 | #include "qgscurve.h"
|
| 19 | +#include "qgsgeometry.h" |
19 | 20 | #include "qgspoint.h"
|
20 | 21 | #include "qgspolygon.h"
|
21 | 22 |
|
@@ -111,6 +112,42 @@ static void _makeWalls( const QgsCurve &ring, bool ccw, float extrusionHeight, Q
|
111 | 112 |
|
112 | 113 | void QgsTessellator::addPolygon( const QgsPolygonV2 &polygon, float extrusionHeight )
|
113 | 114 | {
|
| 115 | + // At this point we assume that input polygons are valid according to the OGC definition. |
| 116 | + // This means e.g. no duplicate points, polygons are simple (no butterfly shaped polygon with self-intersection), |
| 117 | + // internal rings are inside exterior rings, rings do not cross each other, no dangles. |
| 118 | + |
| 119 | + // There is however an issue with polygons where rings touch: |
| 120 | + // +---+ |
| 121 | + // | | |
| 122 | + // | +-+-+ |
| 123 | + // | | | | |
| 124 | + // | +-+ | |
| 125 | + // | | |
| 126 | + // +-----+ |
| 127 | + // This is a valid polygon with one exterior and one interior ring that touch at one point, |
| 128 | + // but poly2tri library does not allow interior rings touch each other or exterior ring. |
| 129 | + // TODO: Handle the situation better - rather than just detecting the problem, try to fix |
| 130 | + // it by converting touching rings into one ring. |
| 131 | + |
| 132 | + if ( polygon.numInteriorRings() > 0 ) |
| 133 | + { |
| 134 | + QList<QgsGeometry> geomRings; |
| 135 | + geomRings << QgsGeometry( polygon.exteriorRing()->clone() ); |
| 136 | + for ( int i = 0; i < polygon.numInteriorRings(); ++i ) |
| 137 | + geomRings << QgsGeometry( polygon.interiorRing( i )->clone() ); |
| 138 | + |
| 139 | + for ( int i = 0; i < geomRings.count(); ++i ) |
| 140 | + for ( int j = i + 1; j < geomRings.count(); ++j ) |
| 141 | + { |
| 142 | + if ( geomRings[i].intersects( geomRings[j] ) ) |
| 143 | + { |
| 144 | + // skip the polygon - it would cause a crash inside poly2tri library |
| 145 | + qDebug() << "polygon rings intersect each other - skipping"; |
| 146 | + return; |
| 147 | + } |
| 148 | + } |
| 149 | + } |
| 150 | + |
114 | 151 | const QgsCurve *exterior = polygon.exteriorRing();
|
115 | 152 |
|
116 | 153 | QList< std::vector<p2t::Point *> > polylinesToDelete;
|
|
0 commit comments