From b9d91e47cf1034d7a6a62448df67f31d9af9bfcb Mon Sep 17 00:00:00 2001 From: farfromrefuge Date: Fri, 10 Jun 2022 10:45:12 +0000 Subject: [PATCH] fix: merge line if it needs to be simplified (#244) --- .../onthegomap/planetiler/FeatureMerge.java | 38 ++++++++++++++----- .../planetiler/FeatureMergeTest.java | 33 ++++++++++++++++ 2 files changed, 62 insertions(+), 9 deletions(-) diff --git a/planetiler-core/src/main/java/com/onthegomap/planetiler/FeatureMerge.java b/planetiler-core/src/main/java/com/onthegomap/planetiler/FeatureMerge.java index 0d4dc6f4..1d6bf9c8 100644 --- a/planetiler-core/src/main/java/com/onthegomap/planetiler/FeatureMerge.java +++ b/planetiler-core/src/main/java/com/onthegomap/planetiler/FeatureMerge.java @@ -63,24 +63,43 @@ public class FeatureMerge { *

* Orders grouped output multilinestring by the index of the first element in that group from the input list. * - * @param features all features in a layer - * @param minLength minimum tile pixel length of features to emit, or 0 to emit all merged linestrings - * @param tolerance after merging, simplify linestrings using this pixel tolerance, or -1 to skip simplification step - * @param buffer number of pixels outside the visible tile area to include detail for, or -1 to skip clipping step + * @param features all features in a layer + * @param minLength minimum tile pixel length of features to emit, or 0 to emit all merged linestrings + * @param tolerance after merging, simplify linestrings using this pixel tolerance, or -1 to skip simplification step + * @param buffer number of pixels outside the visible tile area to include detail for, or -1 to skip clipping step + * @param resimplify True if linestrings should be simplified even if they don't get merged with another * @return a new list containing all unaltered features in their original order, then each of the merged groups * ordered by the index of the first element in that group from the input list. */ public static List mergeLineStrings(List features, - double minLength, double tolerance, double buffer) { - return mergeLineStrings(features, attrs -> minLength, tolerance, buffer); + double minLength, double tolerance, double buffer, boolean resimplify) { + return mergeLineStrings(features, attrs -> minLength, tolerance, buffer, resimplify); } /** - * Merges linestrings with the same attributes as {@link #mergeLineStrings(List, double, double, double)} except with - * a dynamic length limit computed by {@code lengthLimitCalculator} for the attributes of each group. + * Merges linestrings with the same attributes as {@link #mergeLineStrings(List, double, double, double, boolean)} + * except sets {@code resimplify=false} by default. + */ + public static List mergeLineStrings(List features, + double minLength, double tolerance, double buffer) { + return mergeLineStrings(features, minLength, tolerance, buffer, false); + } + + /** + * Merges linestrings with the same attributes as {@link #mergeLineStrings(List, Function, double, double, boolean)} + * except sets {@code resimplify=false} by default. */ public static List mergeLineStrings(List features, Function, Double> lengthLimitCalculator, double tolerance, double buffer) { + return mergeLineStrings(features, lengthLimitCalculator, tolerance, buffer, false); + } + + /** + * Merges linestrings with the same attributes as {@link #mergeLineStrings(List, double, double, double, boolean)} + * except with a dynamic length limit computed by {@code lengthLimitCalculator} for the attributes of each group. + */ + public static List mergeLineStrings(List features, + Function, Double> lengthLimitCalculator, double tolerance, double buffer, boolean resimplify) { List result = new ArrayList<>(features.size()); var groupedByAttrs = groupByAttrs(features, result, GeometryType.LINE); for (List groupedFeatures : groupedByAttrs) { @@ -91,7 +110,8 @@ public class FeatureMerge { // - only 1 element in the group // - it doesn't need to be clipped // - and it can't possibly be filtered out for being too short - if (groupedFeatures.size() == 1 && buffer == 0d && lengthLimit == 0) { + // - and it does not need to be simplified + if (groupedFeatures.size() == 1 && buffer == 0d && lengthLimit == 0 && (!resimplify || tolerance == 0)) { result.add(feature1); } else { LineMerger merger = new LineMerger(); diff --git a/planetiler-core/src/test/java/com/onthegomap/planetiler/FeatureMergeTest.java b/planetiler-core/src/test/java/com/onthegomap/planetiler/FeatureMergeTest.java index 6778144b..b080abdc 100644 --- a/planetiler-core/src/test/java/com/onthegomap/planetiler/FeatureMergeTest.java +++ b/planetiler-core/src/test/java/com/onthegomap/planetiler/FeatureMergeTest.java @@ -121,6 +121,39 @@ class FeatureMergeTest { ); } + @Test + void simplifyLineStringIfToleranceIsSet() { + // does not resimplify by default + assertEquals( + List.of( + feature(1, newLineString(10, 10, 20, 20, 30, 30), Map.of("a", 1)) + ), + FeatureMerge.mergeLineStrings( + List.of( + feature(1, newLineString(10, 10, 20, 20, 30, 30), Map.of("a", 1)) + ), + 0, + 1, + 0 + ) + ); + // but does resimplify when resimplify=true + assertEquals( + List.of( + feature(1, newLineString(10, 10, 30, 30), Map.of("a", 1)) + ), + FeatureMerge.mergeLineStrings( + List.of( + feature(1, newLineString(10, 10, 20, 20, 30, 30), Map.of("a", 1)) + ), + 0, + 1, + 0, + true + ) + ); + } + @Test void mergeMultiLineString() { assertEquals(