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

jiayu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sedona.git


The following commit(s) were added to refs/heads/master by this push:
     new 995b5b1774 [GH-2396] Making splitting polygon by line robust by 
removing the computation of line-polygon intersection (#2598)
995b5b1774 is described below

commit 995b5b177443ca35a91605c427f6e7d099cee897
Author: Kristin Cowalcijk <[email protected]>
AuthorDate: Thu Jan 22 16:21:01 2026 +0800

    [GH-2396] Making splitting polygon by line robust by removing the 
computation of line-polygon intersection (#2598)
---
 .../sedona/common/utils/GeometrySplitter.java      | 19 +++++++++-----
 .../org/apache/sedona/common/FunctionsTest.java    | 30 ++++++++++++++++++++++
 2 files changed, 43 insertions(+), 6 deletions(-)

diff --git 
a/common/src/main/java/org/apache/sedona/common/utils/GeometrySplitter.java 
b/common/src/main/java/org/apache/sedona/common/utils/GeometrySplitter.java
index 7045316fed..89473c5d3c 100644
--- a/common/src/main/java/org/apache/sedona/common/utils/GeometrySplitter.java
+++ b/common/src/main/java/org/apache/sedona/common/utils/GeometrySplitter.java
@@ -262,13 +262,9 @@ public final class GeometrySplitter {
   }
 
   private Geometry generateCandidatePolygons(Geometry polygons, Geometry 
blade) {
-    // restrict the blade to only be within the original polygon to
-    // avoid candidate polygons that are impossible
-    Geometry bladeWithinPolygons = blade.intersection(polygons);
-
     // a union will node all the lines at intersections
     // these nodes are required for Polygonizer to work correctly
-    Geometry totalLineWork = polygons.getBoundary().union(bladeWithinPolygons);
+    Geometry totalLineWork = polygons.getBoundary().union(blade);
 
     Polygonizer polygonizer = new Polygonizer();
     polygonizer.add(totalLineWork);
@@ -281,7 +277,18 @@ public final class GeometrySplitter {
     // original geometry to ensure holes in the original geometry are excluded
     for (int i = 0; i < polygons.getNumGeometries(); i++) {
       Geometry candidateResult = polygons.getGeometryN(i);
-      if (candidateResult instanceof Polygon && 
original.contains(candidateResult)) {
+      if (!(candidateResult instanceof Polygon)) {
+        continue;
+      }
+
+      Point pointOnSurface = candidateResult.getInteriorPoint();
+      // getInteriorPoint() may return null for degenerate or empty polygonal 
geometries,
+      // so guard against null before using the point.
+      if (pointOnSurface == null) {
+        continue;
+      }
+
+      if (original.covers(pointOnSurface)) {
         list.add((Polygon) candidateResult);
       }
     }
diff --git a/common/src/test/java/org/apache/sedona/common/FunctionsTest.java 
b/common/src/test/java/org/apache/sedona/common/FunctionsTest.java
index c5eac14c39..c4e6325143 100644
--- a/common/src/test/java/org/apache/sedona/common/FunctionsTest.java
+++ b/common/src/test/java/org/apache/sedona/common/FunctionsTest.java
@@ -531,6 +531,36 @@ public class FunctionsTest extends TestBase {
     assertNull(actualResult);
   }
 
+  @Test
+  public void splitCircleInto2SemiCircles() throws ParseException {
+    String polygonWkt =
+        "POLYGON ((-117.76405581088967 34.111876749328026, -117.76407506132291 
34.11170068822483, "
+            + "-117.76413523652074 34.111531133837936, -117.76423402376724 
34.11137460199335, -117.76436762657538 34.11123710803779, "
+            + "-117.76453091060647 34.11112393568514, -117.76471760098879 
34.11103943398174, -117.76492052345083 34.11098685019075, "
+            + "-117.76513188000408 34.1109682050154, -117.76534354858369 
34.11098421495394, -117.76554739513688 34.11103426476887, "
+            + "-117.76573558617179 34.11111643112786, -117.76590088976099 
34.111227556508084, -117.76603695343799 34.11136337052523, "
+            + "-117.76613854831002 34.11151865402651, -117.76620177000793 
34.11168743964393, -117.76622418874936 34.111863241103265, "
+            + "-117.76620494274577 34.11203930247842, -117.76614477135817 
34.11220885781403, -117.7660459867224 34.11236539113964, "
+            + "-117.76591238492807 34.11250288688306, -117.7657491001595 
34.11261606105824, -117.7655624074007 34.11270056434135, "
+            + "-117.76535948128496 34.112753149228745, -117.76514812035703 
34.11277179485027, -117.76493644734776 34.112755784639766, "
+            + "-117.76473259698435 34.112705733876126, -117.76454440333869 
34.11262356603611, -117.76437909873567 34.11251243886801, "
+            + "-117.76424303579616 34.11237662302835, -117.76414144330062 
34.112221337947354, -117.76407822525644 34.11205255123353, "
+            + "-117.76405581088967 34.111876749328026))";
+    String knifeWkt =
+        "LINESTRING (-117.7640751398563 34.111535124121441, 
-117.76628486838135 34.112204866513046)";
+
+    Geometry polygon = Constructors.geomFromWKT(polygonWkt, 4326);
+    Geometry knife = Constructors.geomFromWKT(knifeWkt, 4326);
+    Geometry resultPolygon = Functions.split(polygon, knife);
+    assertEquals(2, resultPolygon.getNumGeometries());
+
+    double circleArea = polygon.getArea();
+    for (int i = 0; i < resultPolygon.getNumGeometries(); i++) {
+      double actualArea = resultPolygon.getGeometryN(i).getArea();
+      assertEquals(2.0, circleArea / actualArea, 0.1);
+    }
+  }
+
   @Test
   public void dimensionGeometry2D() {
     Point point = GEOMETRY_FACTORY.createPoint(new Coordinate(1, 2));

Reply via email to