From 4d7f493981a71ad520cbb2ddd6bf5affe6cd59af Mon Sep 17 00:00:00 2001 From: GerdP Date: Mon, 8 Nov 2021 08:19:36 +0000 Subject: [PATCH] fix #20982: Douglas-Peucker implementation is wrong The Douglas-Peucker implementation should calculate the distance to the segment between the end nodes, not the the distance to the line through those nodes. git-svn-id: https://josm.openstreetmap.de/svn/trunk@18316 0c6e7542-c601-0410-84e7-c038aed88b3b --- .../josm/actions/SimplifyWayAction.java | 35 +++++++++++++++---- 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/src/org/openstreetmap/josm/actions/SimplifyWayAction.java b/src/org/openstreetmap/josm/actions/SimplifyWayAction.java index e6767b25020..499aab07c9e 100644 --- a/src/org/openstreetmap/josm/actions/SimplifyWayAction.java +++ b/src/org/openstreetmap/josm/actions/SimplifyWayAction.java @@ -36,6 +36,7 @@ import org.openstreetmap.josm.command.SequenceCommand; import org.openstreetmap.josm.data.SystemOfMeasurement; import org.openstreetmap.josm.data.UndoRedoHandler; +import org.openstreetmap.josm.data.coor.EastNorth; import org.openstreetmap.josm.data.osm.DataSet; import org.openstreetmap.josm.data.osm.Node; import org.openstreetmap.josm.data.osm.OsmPrimitive; @@ -404,24 +405,46 @@ protected static void buildSimplifiedNodeList(List wnew, int from, int to, Node fromN = wnew.get(from); Node toN = wnew.get(to); - + EastNorth p1 = fromN.getEastNorth(); + EastNorth p2 = toN.getEastNorth(); // Get max xte int imax = -1; double xtemax = 0; for (int i = from + 1; i < to; i++) { Node n = wnew.get(i); + EastNorth p = n.getEastNorth(); + double ldx = p2.getX() - p1.getX(); + double ldy = p2.getY() - p1.getY(); + double offset; + //segment zero length + if (ldx == 0 && ldy == 0) + offset = 0; + else { + double pdx = p.getX() - p1.getX(); + double pdy = p.getY() - p1.getY(); + offset = (pdx * ldx + pdy * ldy) / (ldx * ldx + ldy * ldy); + } + final double distRad; // CHECKSTYLE.OFF: SingleSpaceSeparator - double xte = Math.abs(Ellipsoid.WGS84.a - * xtd(fromN.lat() * Math.PI / 180, fromN.lon() * Math.PI / 180, toN.lat() * Math.PI / 180, - toN.lon() * Math.PI / 180, n.lat() * Math.PI / 180, n.lon() * Math.PI / 180)); + if (offset <= 0) { + distRad = dist(fromN.lat() * Math.PI / 180, fromN.lon() * Math.PI / 180, + n.lat() * Math.PI / 180, n.lon() * Math.PI / 180); + } else if (offset >= 1) { + distRad = dist(toN.lat() * Math.PI / 180, toN.lon() * Math.PI / 180, + n.lat() * Math.PI / 180, n.lon() * Math.PI / 180); + } else { + distRad = xtd(fromN.lat() * Math.PI / 180, fromN.lon() * Math.PI / 180, + toN.lat() * Math.PI / 180, toN.lon() * Math.PI / 180, + n.lat() * Math.PI / 180, n.lon() * Math.PI / 180); + } // CHECKSTYLE.ON: SingleSpaceSeparator + double xte = Math.abs(distRad); if (xte > xtemax) { xtemax = xte; imax = i; } } - - if (imax != -1 && xtemax >= threshold) { + if (imax != -1 && Ellipsoid.WGS84.a * xtemax >= threshold) { // Segment cannot be simplified - try shorter segments buildSimplifiedNodeList(wnew, from, imax, threshold, simplifiedNodes); buildSimplifiedNodeList(wnew, imax, to, threshold, simplifiedNodes);