LUCENE-9417: Tessellator might fail when several holes share are connected to the same vertex (#1614)

This commit is contained in:
Ignacio Vera 2020-06-29 17:46:21 +02:00 committed by GitHub
parent 49a3f0a11d
commit 0cef29f138
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 27 additions and 1 deletions

View File

@ -294,6 +294,9 @@ Bug Fixes
* LUCENE-9400: Tessellator might build illegal polygons when several holes share the shame vertex. (Ignacio Vera)
* LUCENE-9417: Tessellator might build illegal polygons when several holes share are connected to the same
vertex. (Ignacio Vera)
Other
---------------------

View File

@ -360,7 +360,16 @@ final public class Tessellator {
if (hx >= p.getX() && p.getX() >= mx && hx != p.getX()
&& pointInEar(p.getX(), p.getY(), hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy)) {
tan = Math.abs(hy - p.getY()) / (hx - p.getX()); // tangential
if ((tan < tanMin || (tan == tanMin && p.getX() > connection.getX())) && isLocallyInside(p, holeNode)) {
if (isVertexEquals(p, connection) && isLocallyInside(p, holeNode)) {
// make sure we are not crossing the polygon. This might happen when several holes have a bridge to the same polygon vertex
// and this vertex has different vertex.
boolean crosses = GeoUtils.lineCrossesLine(p.getX(), p.getY(), holeNode.getX(), holeNode.getY(),
connection.next.getX(), connection.next.getY(), connection.previous.getX(), connection.previous.getY());
if (crosses == false) {
connection = p;
tanMin = tan;
}
} else if ((tan < tanMin || (tan == tanMin && p.getX() > connection.getX())) && isLocallyInside(p, holeNode)) {
connection = p;
tanMin = tan;
}

View File

@ -581,6 +581,20 @@ public class TestTessellator extends LuceneTestCase {
checkPolygon(wkt);
}
@Nightly
public void testComplexPolygon42() throws Exception {
String geoJson = GeoTestUtil.readShape("lucene-9417.geojson.gz");
Polygon[] polygons =Polygon.fromGeoJSON(geoJson);
for (int i = 0; i < polygons.length; i++) {
List<Tessellator.Triangle> tessellation = Tessellator.tessellate(polygons[i]);
// calculate the area of big polygons have numerical error
assertEquals(area(polygons[i]), area(tessellation), 1e-11);
for (Tessellator.Triangle t : tessellation) {
checkTriangleEdgesFromPolygon(polygons[i], t);
}
}
}
private void checkPolygon(String wkt) throws Exception {
Polygon polygon = (Polygon) SimpleWKTShapeParser.parse(wkt);
List<Tessellator.Triangle> tessellation = Tessellator.tessellate(polygon);