Skip to content

Commit

Permalink
[Tessellator] Improve the checks that validate the diagonal between t…
Browse files Browse the repository at this point in the history
…wo polygon nodes (#12353)
  • Loading branch information
iverase authored Jun 9, 2023
1 parent 5b63a18 commit 9a2d193
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 9 deletions.
3 changes: 3 additions & 0 deletions lucene/CHANGES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,9 @@ Bug Fixes

* GITHUB#12291: Skip blank lines from stopwords list. (Jerry Chin)

* GITHUB#12352: [Tessellator] Improve the checks that validate the diagonal between two polygon nodes so
the resulting polygons are valid counter clockwise polygons. (Ignacio Vera)

Other
---------------------
(No changes)
Expand Down
23 changes: 14 additions & 9 deletions lucene/core/src/java/org/apache/lucene/geo/Tessellator.java
Original file line number Diff line number Diff line change
Expand Up @@ -1090,17 +1090,22 @@ private static final Node splitPolygon(final Node a, final Node b, boolean edgeF
* Determines whether a diagonal between two polygon nodes lies within a polygon interior. (This
* determines the validity of the ray.) *
*/
private static final boolean isValidDiagonal(final Node a, final Node b) {
private static boolean isValidDiagonal(final Node a, final Node b) {
if (a.next.idx == b.idx
|| a.previous.idx == b.idx
// check next edges are locally visible
|| isLocallyInside(a.previous, b) == false
|| isLocallyInside(b.next, a) == false
// check polygons are CCW in both sides
|| isCWPolygon(a, b) == false
|| isCWPolygon(b, a) == false) {
return false;
}
if (isVertexEquals(a, b)) {
// If points are equal then use it if they are valid polygons
return isCWPolygon(a, b);
return true;
}
return a.next.idx != b.idx
&& a.previous.idx != b.idx
&& isLocallyInside(a, b)
return isLocallyInside(a, b)
&& isLocallyInside(b, a)
&& isLocallyInside(a.previous, b)
&& isLocallyInside(b.next, a)
&& middleInsert(a, a.getX(), a.getY(), b.getX(), b.getY())
// make sure we don't introduce collinear lines
&& area(a.previous.getX(), a.previous.getY(), a.getX(), a.getY(), b.getX(), b.getY()) != 0
Expand All @@ -1114,7 +1119,7 @@ && area(a.getX(), a.getY(), b.getX(), b.getY(), b.previous.getX(), b.previous.ge
/** Determine whether the polygon defined between node start and node end is CW */
private static boolean isCWPolygon(final Node start, final Node end) {
// The polygon must be CW
return (signedArea(start, end) < 0) ? true : false;
return signedArea(start, end) < 0;
}

/** Determine the signed area between node start and node end */
Expand Down
22 changes: 22 additions & 0 deletions lucene/core/src/test/org/apache/lucene/geo/TestTessellator.java
Original file line number Diff line number Diff line change
Expand Up @@ -915,6 +915,28 @@ public void testComplexPolygon54() throws Exception {
}
}

public void testComplexPolygon55() throws Exception {
String geoJson = GeoTestUtil.readShape("github-12352-1.geojson.gz");
Polygon[] polygons = Polygon.fromGeoJSON(geoJson);
for (Polygon polygon : polygons) {
List<Tessellator.Triangle> tessellation =
Tessellator.tessellate(polygon, random().nextBoolean());
assertEquals(area(polygon), area(tessellation), 0.0);
// don't check edges as it takes several minutes
}
}

public void testComplexPolygon56() throws Exception {
String geoJson = GeoTestUtil.readShape("github-12352-2.geojson.gz");
Polygon[] polygons = Polygon.fromGeoJSON(geoJson);
for (Polygon polygon : polygons) {
List<Tessellator.Triangle> tessellation =
Tessellator.tessellate(polygon, random().nextBoolean());
assertEquals(area(polygon), area(tessellation), 0.0);
// don't check edges as it takes several minutes
}
}

private static class TestCountingMonitor implements Tessellator.Monitor {
private int count = 0;
private int splitsStarted = 0;
Expand Down
Binary file not shown.
Binary file not shown.

0 comments on commit 9a2d193

Please sign in to comment.