From 658365aaf5cfba7b1d18bfd52b751523053cdad0 Mon Sep 17 00:00:00 2001 From: dsantosmerino-wkl <156185254+dsantosmerino-wkl@users.noreply.github.com> Date: Sat, 4 Jan 2025 00:45:47 +0100 Subject: [PATCH] Fix Douglas Peucker simplifier for XYZM coordinates (#1045) --- .../DouglasPeuckerLineSimplifier.java | 2 +- .../DouglasPeuckerSimplifierTest.java | 14 ++++++++- .../test/java/test/jts/GeometryTestCase.java | 31 +++++++++++++------ 3 files changed, 35 insertions(+), 12 deletions(-) diff --git a/modules/core/src/main/java/org/locationtech/jts/simplify/DouglasPeuckerLineSimplifier.java b/modules/core/src/main/java/org/locationtech/jts/simplify/DouglasPeuckerLineSimplifier.java index d9a8ba04c9..e1121fa5a9 100644 --- a/modules/core/src/main/java/org/locationtech/jts/simplify/DouglasPeuckerLineSimplifier.java +++ b/modules/core/src/main/java/org/locationtech/jts/simplify/DouglasPeuckerLineSimplifier.java @@ -68,7 +68,7 @@ public Coordinate[] simplify() CoordinateList coordList = new CoordinateList(); for (int i = 0; i < pts.length; i++) { if (usePt[i]) - coordList.add(new Coordinate(pts[i])); + coordList.add(pts[i].copy()); } if (! isPreserveEndpoint && CoordinateArrays.isRing(pts)) { diff --git a/modules/core/src/test/java/org/locationtech/jts/simplify/DouglasPeuckerSimplifierTest.java b/modules/core/src/test/java/org/locationtech/jts/simplify/DouglasPeuckerSimplifierTest.java index 08829c2dd5..7fa33786b7 100644 --- a/modules/core/src/test/java/org/locationtech/jts/simplify/DouglasPeuckerSimplifierTest.java +++ b/modules/core/src/test/java/org/locationtech/jts/simplify/DouglasPeuckerSimplifierTest.java @@ -86,6 +86,12 @@ public void testLineStringTiny() { 10, "LINESTRING (0 5, 5 5)"); } + + public void testLineStringWithFourDimensions() { + checkDPXYZM("LINESTRING ZM(0 5 114.6 1709024189000, 1 5 114.6 1709024190000, 2 5 114.5 1709024192000, 5 5 114.5 1709024196000)", + 10, + "LINESTRING ZM(0 5 114.6 1709024189000, 5 5 114.5 1709024196000)"); + } public void testMultiPoint() { checkDPNoChange("MULTIPOINT(80 200, 240 200, 240 60, 80 60, 80 200, 140 199, 120 120)", @@ -166,7 +172,13 @@ private void checkDP(String wkt, double tolerance, String wktExpected) { Geometry expected = read(wktExpected); checkEqual(expected, result); } - + private void checkDPXYZM(String wkt, double tolerance, String wktExpected) { + Geometry geom = read(wkt); + Geometry result = DouglasPeuckerSimplifier.simplify(geom, tolerance); + Geometry expected = read(wktExpected); + checkEqualXYZM(expected, result); + } + private void checkDPNoChange(String wkt, double tolerance) { checkDP(wkt, tolerance, wkt); } diff --git a/modules/core/src/test/java/test/jts/GeometryTestCase.java b/modules/core/src/test/java/test/jts/GeometryTestCase.java index de8201e17a..8b308719a5 100644 --- a/modules/core/src/test/java/test/jts/GeometryTestCase.java +++ b/modules/core/src/test/java/test/jts/GeometryTestCase.java @@ -126,7 +126,7 @@ protected void checkEqual(Geometry expected, Geometry actual, double tolerance) protected void checkEqualXYZ(Geometry expected, Geometry actual) { Geometry actualNorm = actual.norm(); Geometry expectedNorm = expected.norm(); - boolean equal = equalsExactXYZ(actualNorm, expectedNorm); + boolean equal = equalsExactMultipleDimension(actualNorm, expectedNorm, 3); if (! equal) { System.out.format(CHECK_EQUAL_FAIL, writerZ.write(expectedNorm), @@ -134,22 +134,34 @@ protected void checkEqualXYZ(Geometry expected, Geometry actual) { } assertTrue(equal); } + + protected void checkEqualXYZM(Geometry expected, Geometry actual) { + Geometry actualNorm = actual.norm(); + Geometry expectedNorm = expected.norm(); + boolean equal = equalsExactMultipleDimension(actualNorm, expectedNorm, 4); + if (! equal) { + System.out.format(CHECK_EQUAL_FAIL, + writerZ.write(expectedNorm), + writerZ.write(actualNorm) ); + } + assertTrue(equal); + } - private boolean equalsExactXYZ(Geometry a, Geometry b) { + private boolean equalsExactMultipleDimension(Geometry a, Geometry b, int dimension) { if (a.getClass() != b.getClass()) return false; if (a.getNumGeometries() != b.getNumGeometries()) return false; if (a instanceof Point) { - return isEqualDim(((Point) a).getCoordinateSequence(), ((Point) b).getCoordinateSequence(), 3); + return isEqualDim(((Point) a).getCoordinateSequence(), ((Point) b).getCoordinateSequence(), dimension); } else if (a instanceof LineString) { - return isEqualDim(((LineString) a).getCoordinateSequence(), ((LineString) b).getCoordinateSequence(), 3); + return isEqualDim(((LineString) a).getCoordinateSequence(), ((LineString) b).getCoordinateSequence(), dimension); } else if (a instanceof Polygon) { - return equalsExactXYZPolygon( (Polygon) a, (Polygon) b); + return equalsExactMultipleDimensionPolygon( (Polygon) a, (Polygon) b, dimension); } else if (a instanceof GeometryCollection) { for (int i = 0; i < a.getNumGeometries(); i++) { - if (! equalsExactXYZ(a.getGeometryN(i), b.getGeometryN(i))) + if (! equalsExactMultipleDimension(a.getGeometryN(i), b.getGeometryN(i), dimension)) return false; } return true; @@ -157,17 +169,17 @@ else if (a instanceof GeometryCollection) { return false; } - private boolean equalsExactXYZPolygon(Polygon a, Polygon b) { + private boolean equalsExactMultipleDimensionPolygon(Polygon a, Polygon b, int dimension) { LinearRing aShell = a.getExteriorRing(); LinearRing bShell = b.getExteriorRing(); - if (! isEqualDim(aShell.getCoordinateSequence(), bShell.getCoordinateSequence(), 3)) + if (! isEqualDim(aShell.getCoordinateSequence(), bShell.getCoordinateSequence(), dimension)) return false; if (a.getNumInteriorRing() != b.getNumInteriorRing()) return false; for (int i = 0; i < a.getNumInteriorRing(); i++) { LinearRing aHole = a.getInteriorRingN(i); LinearRing bHole = b.getInteriorRingN(i); - if (! isEqualDim(aHole.getCoordinateSequence(), bHole.getCoordinateSequence(), 3)) + if (! isEqualDim(aHole.getCoordinateSequence(), bHole.getCoordinateSequence(), dimension)) return false; } return true; @@ -198,7 +210,6 @@ protected void checkEqualXYZ(Coordinate expected, Coordinate actual) { assertEquals("Coordinate Y", expected.getY(), actual.getY() ); assertEquals("Coordinate Z", expected.getZ(), actual.getZ() ); } - protected void checkEqualXY(String message, Coordinate expected, Coordinate actual) { assertEquals(message + " X", expected.getX(), actual.getX() ); assertEquals(message + " Y", expected.getY(), actual.getY() );