You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by iv...@apache.org on 2025/09/23 09:37:15 UTC

(lucene) branch main updated: [Tessellator] Fix failure due to hole bridge being coplanar with polygon edge. (#15211)

This is an automated email from the ASF dual-hosted git repository.

ivera pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/lucene.git


The following commit(s) were added to refs/heads/main by this push:
     new d04c5e3530a [Tessellator] Fix failure due to hole bridge being coplanar with polygon edge. (#15211)
d04c5e3530a is described below

commit d04c5e3530a2b0a0d02bc8db45adaa677ee58577
Author: Ignacio Vera <iv...@apache.org>
AuthorDate: Tue Sep 23 11:37:09 2025 +0200

    [Tessellator] Fix failure due to hole bridge being coplanar with polygon edge. (#15211)
    
    The fix changes the strategy for removing co-planar points to do it once after all holes are removed
    instead of doing it for each removed hole.
---
 lucene/CHANGES.txt                                        |   5 +++++
 .../core/src/java/org/apache/lucene/geo/Tessellator.java  |  12 ++++--------
 .../src/test/org/apache/lucene/geo/TestTessellator.java   |   8 +++++++-
 .../org/apache/lucene/tests/geo/github-15205.geojson.gz   | Bin 0 -> 547 bytes
 4 files changed, 16 insertions(+), 9 deletions(-)

diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt
index f5bdf58b280..5946419d28a 100644
--- a/lucene/CHANGES.txt
+++ b/lucene/CHANGES.txt
@@ -173,6 +173,11 @@ Bug Fixes
 * GITHUB#14161: PointInSetQuery's constructor now throws IllegalArgumentException
   instead of UnsupportedOperationException when values are out of order. (Shubham Sharma)
 
+* GITHUB#15205: Fixes regression introduced in GITHUB#13980 where polygons might fail to tessellate
+  because the hole bridge is coplanar with the polygon vertex. The fix changes the strategy for
+  removing co-planar points to do it once after all holes are removed instead of doing it for each
+  removed hole.
+
 Other
 ---------------------
 (No changes)
diff --git a/lucene/core/src/java/org/apache/lucene/geo/Tessellator.java b/lucene/core/src/java/org/apache/lucene/geo/Tessellator.java
index bd7025e979d..697bcdce5ba 100644
--- a/lucene/core/src/java/org/apache/lucene/geo/Tessellator.java
+++ b/lucene/core/src/java/org/apache/lucene/geo/Tessellator.java
@@ -359,8 +359,8 @@ public final class Tessellator {
         throw new IllegalArgumentException("Illegal hole detected: " + polygon);
       }
     }
-    // Return a pointer to the list.
-    return outerNode;
+    // Filter co-planar nodes and return a pointer to the list.
+    return filterPoints(outerNode, null);
   }
 
   /** Finds a bridge between vertices that connects a hole with an outer ring, and links it */
@@ -387,9 +387,7 @@ public final class Tessellator {
           isPointInLine(outerNode, outerNode.next, holeNode)
               || isPointInLine(holeNode, holeNode.next, outerNode);
       // Split the resulting polygon.
-      Node node = splitPolygon(outerNode, holeNode, fromPolygon);
-      // Filter the split nodes.
-      filterPoints(node, node.next);
+      splitPolygon(outerNode, holeNode, fromPolygon);
       return true;
     } else {
       return false;
@@ -431,9 +429,7 @@ public final class Tessellator {
     } while (next != outerNode);
     if (sharedVertex != null) {
       // Split the resulting polygon.
-      Node node = splitPolygon(sharedVertexConnection, sharedVertex, true);
-      // Filter the split nodes.
-      filterPoints(node, node.next);
+      splitPolygon(sharedVertexConnection, sharedVertex, true);
       return true;
     }
     return false;
diff --git a/lucene/core/src/test/org/apache/lucene/geo/TestTessellator.java b/lucene/core/src/test/org/apache/lucene/geo/TestTessellator.java
index 8b0e809d7b3..ec031bdefb7 100644
--- a/lucene/core/src/test/org/apache/lucene/geo/TestTessellator.java
+++ b/lucene/core/src/test/org/apache/lucene/geo/TestTessellator.java
@@ -374,7 +374,7 @@ public class TestTessellator extends LuceneTestCase {
     IllegalArgumentException ex =
         expectThrows(IllegalArgumentException.class, () -> Tessellator.tessellate(polygon, true));
     assertEquals(
-        "Polygon ring self-intersection at lat=40.8278688 lon=14.1990929", ex.getMessage());
+        "Polygon ring self-intersection at lat=40.8277665 lon=14.1993975", ex.getMessage());
   }
 
   public void testComplexPolygon18() throws Exception {
@@ -922,6 +922,12 @@ public class TestTessellator extends LuceneTestCase {
     checkPolygon(wkt);
   }
 
+  public void testComplexPolygon61() throws Exception {
+    String geoJson = GeoTestUtil.readShape("github-15205.geojson.gz");
+    Polygon[] polygons = Polygon.fromGeoJSON(geoJson);
+    checkMultiPolygon(polygons, 1e-11);
+  }
+
   private static class TestCountingMonitor implements Tessellator.Monitor {
     private int count = 0;
     private int splitsStarted = 0;
diff --git a/lucene/test-framework/src/resources/org/apache/lucene/tests/geo/github-15205.geojson.gz b/lucene/test-framework/src/resources/org/apache/lucene/tests/geo/github-15205.geojson.gz
new file mode 100644
index 00000000000..4790f7ca601
Binary files /dev/null and b/lucene/test-framework/src/resources/org/apache/lucene/tests/geo/github-15205.geojson.gz differ