From 60e3f58307730ed11e1170f41db966626f410786 Mon Sep 17 00:00:00 2001 From: Kristin Cowalcijk Date: Wed, 7 Aug 2024 11:02:50 +0800 Subject: [PATCH] Fix linestring split accuracy problem --- .../sedona/common/utils/GeometrySplitter.java | 18 +++------ .../apache/sedona/common/FunctionsTest.java | 37 +++++++++++++++++++ 2 files changed, 43 insertions(+), 12 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 89c6a08981..7045316fed 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 @@ -148,19 +148,12 @@ private MultiLineString splitLinesByPoints(Geometry lines, Geometry points) { } private MultiLineString splitLinesByLines(Geometry inputLines, Geometry blade) { - // compute the intersection of inputLines and blade - // and pass back to splitLines to handle as points - Geometry intersectionWithBlade = inputLines.intersection(blade); - - if (intersectionWithBlade.isEmpty()) { - // blade and inputLines are disjoint so just return the input as a multilinestring - return (MultiLineString) ensureMultiGeometryOfDimensionN(inputLines, 1); - } else if (intersectionWithBlade.getDimension() != 0) { - logger.warn("Colinear sections detected between source and blade geometry. Returned null."); - return null; + Geometry diff = inputLines.difference(blade); + if (diff instanceof MultiLineString) { + return (MultiLineString) diff; + } else { + return geometryFactory.createMultiLineString(new LineString[] {(LineString) inputLines}); } - - return splitLines(inputLines, intersectionWithBlade); } private MultiPolygon splitPolygonsByLines(Geometry polygons, Geometry blade) { @@ -197,6 +190,7 @@ private void splitLineStringAtCoordinates( Iterator coordIterator = getIteratorForSegmentDirection(pointCoords, lineBuilder.getLastCoordinate(), endCoord); + // line.getPrecisionModel() applyCoordsToLineSegment(lineBuilder, coordIterator, endCoord); } 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 74ec6b433a..8f0f13117b 100644 --- a/common/src/test/java/org/apache/sedona/common/FunctionsTest.java +++ b/common/src/test/java/org/apache/sedona/common/FunctionsTest.java @@ -33,6 +33,8 @@ import org.geotools.referencing.operation.projection.ProjectionException; import org.junit.Test; import org.locationtech.jts.geom.*; +import org.locationtech.jts.geom.prep.PreparedGeometry; +import org.locationtech.jts.geom.prep.PreparedGeometryFactory; import org.locationtech.jts.io.ParseException; import org.locationtech.jts.io.WKTReader; import org.locationtech.jts.io.WKTWriter; @@ -305,6 +307,41 @@ public void splitLineStringByPolygon() { assertEquals(actualResult, expectedResult); } + @Test + public void splitLineStringFpPrecisionIssue() { + LineString lineString = + GEOMETRY_FACTORY.createLineString( + coordArray( + -8.961173822708158, -3.93776773106963, -8.08908227533288, -3.8845245068873444)); + Polygon polygon = + GEOMETRY_FACTORY.createPolygon( + coordArray( + -6.318936372442209, -6.44985859539768, + -8.669092633645995, -3.0659222341103956, + -6.264600073171498, -3.075347218794894, + -5.3654318906014495, -3.1019726170919877, + -5.488002156793005, -5.892626167859213, + -6.318936372442209, -6.44985859539768)); + + Geometry result = Functions.split(lineString, polygon); + assertEquals(2, result.getNumGeometries()); + assertEquals(lineString.getLength(), result.getLength(), 1e-6); + } + + @Test + public void tempTest() { + LineString lineString = + GEOMETRY_FACTORY.createLineString( + coordArray( + -8.961173822708158, -3.93776773106963, -8.08908227533288, -3.8845245068873444)); + Point point = + GEOMETRY_FACTORY.createPoint(new Coordinate(-8.100103048843774, -3.885197350829553)); + PreparedGeometryFactory factory = new PreparedGeometryFactory(); + PreparedGeometry prepLineString = factory.create(lineString); + boolean intersects = prepLineString.intersects(point); + System.out.println(intersects); + } + @Test public void splitPolygonByLineString() { Polygon polygon =