Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Tessellator] Improve the checks that validate the diagonal between two polygon nodes #12353

Merged
merged 1 commit into from
Jun 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought the == false pattern was an elasticsearch pattern, not a lucene pattern?

|| 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.