From 6c2c33821c2582a50a963bc0f7bb64bfe5f6e7f0 Mon Sep 17 00:00:00 2001 From: Oliver Wipfli Date: Sat, 2 Nov 2024 18:29:38 +0100 Subject: [PATCH] Add merge tests --- .../planetiler/util/LoopLineMerger.java | 8 +- .../planetiler/util/LoopLineMergerTest.java | 161 ++++++++++++++++++ 2 files changed, 168 insertions(+), 1 deletion(-) diff --git a/planetiler-core/src/main/java/com/onthegomap/planetiler/util/LoopLineMerger.java b/planetiler-core/src/main/java/com/onthegomap/planetiler/util/LoopLineMerger.java index 686f4e3f49..47301c04e3 100644 --- a/planetiler-core/src/main/java/com/onthegomap/planetiler/util/LoopLineMerger.java +++ b/planetiler-core/src/main/java/com/onthegomap/planetiler/util/LoopLineMerger.java @@ -187,7 +187,13 @@ private List> findAllPaths(Point start, Point end, double maxLe } List path = new ArrayList<>(); path.add(edge); - queue.add(path); + if (maxLength > 0.0) { + if (getLength(path) <= maxLength) { + queue.add(path); + } + } else { + queue.add(path); + } } while (!queue.isEmpty()) { diff --git a/planetiler-core/src/test/java/com/onthegomap/planetiler/util/LoopLineMergerTest.java b/planetiler-core/src/test/java/com/onthegomap/planetiler/util/LoopLineMergerTest.java index ed016169e9..22cd184bcd 100644 --- a/planetiler-core/src/test/java/com/onthegomap/planetiler/util/LoopLineMergerTest.java +++ b/planetiler-core/src/test/java/com/onthegomap/planetiler/util/LoopLineMergerTest.java @@ -80,4 +80,165 @@ void testConcat() { // TODO: handle and test the case when A/B do not share end/start points } + + @Test + void testMerge() { + + // merges two touching linestrings + var merger = new LoopLineMerger(); + merger.add(newLineString(10, 10, 20, 20)); + merger.add(newLineString(20, 20, 30, 30)); + assertEquals( + List.of(newLineString(10, 10, 20, 20, 30, 30)), + merger.getMergedLineStrings(-1, -1) + ); + + // keeps two separate linestrings separate + merger = new LoopLineMerger(); + merger.add(newLineString(10, 10, 20, 20)); + merger.add(newLineString(30, 30, 40, 40)); + assertEquals( + List.of( + newLineString(10, 10, 20, 20), + newLineString(30, 30, 40, 40) + ), + merger.getMergedLineStrings(-1, -1) + ); + + // does not overcount already added linestrings + merger = new LoopLineMerger(); + merger.add(newLineString(10, 10, 20, 20)); + merger.add(newLineString(20, 20, 30, 30)); + merger.add(newLineString(20, 20, 30, 30)); + assertEquals( + List.of(newLineString(10, 10, 20, 20, 30, 30)), + merger.getMergedLineStrings(-1, -1) + ); + + // splits linestrings into linear segments before merging + merger = new LoopLineMerger(); + merger.add(newLineString(10, 10, 20, 20, 30, 30)); + merger.add(newLineString(20, 20, 30, 30, 40, 40)); + assertEquals( + List.of(newLineString(10, 10, 20, 20, 30, 30, 40, 40)), + merger.getMergedLineStrings(-1, -1) + ); + + // rounds coordinates to 1/16 before merging + merger = new LoopLineMerger(); + merger.add(newLineString(10.00043983098, 10, 20, 20)); + merger.add(newLineString(20, 20, 30, 30)); + assertEquals( + List.of(newLineString(10, 10, 20, 20, 30, 30)), + merger.getMergedLineStrings(-1, -1) + ); + + // removes small loops, keeps shortes path + merger = new LoopLineMerger(); + /** + * 10 20 30 40 + * 10 o--o--o + * \ | + * \| + * 20 o--o + */ + merger.add(newLineString( + 10, 10, + 20, 10, + 30, 10, + 30, 20, + 40, 20 + )); + merger.add(newLineString( + 20, 10, + 30, 20 + )); + assertEquals( + List.of( + newLineString( + 10, 10, + 20, 10, + 30, 20, + 40, 20 + ) + ), + merger.getMergedLineStrings(-1, 100) + ); + + // does not remove large loops + merger = new LoopLineMerger(); + /** + * 10 20 30 40 + * 10 o--o--o + * \ | + * \| + * 20 o--o + */ + merger.add(newLineString( + 10, 10, + 20, 10, + 30, 10, + 30, 20, + 40, 20 + )); + merger.add(newLineString( + 20, 10, + 30, 20 + )); + assertEquals( + List.of( + newLineString( + 30, 20, + 40, 20 + ), + newLineString( + 20, 10, + 30, 20 + ), + newLineString( + 20, 10, + 30, 10, + 30, 20 + ), + newLineString( + 10, 10, + 20, 10 + ) + ), + merger.getMergedLineStrings(-1, 0.001) + ); + + // removes linestrings that are too short after merging + merger = new LoopLineMerger(); + merger.add(newLineString(10, 10, 11, 11)); + merger.add(newLineString(20, 20, 30, 30)); + merger.add(newLineString(30, 30, 40, 40)); + assertEquals( + List.of(newLineString(20, 20, 30, 30, 40, 40)), + merger.getMergedLineStrings(10, -1) + ); + + // removes first short stubs, merges again, and only then + // removes non-stubs that are too short + // stub = linestring that has at least one disconnected end + merger = new LoopLineMerger(); + + /** + * 0 20 30 50 + * 0 o----o--o----o + * | | + * 10 o o + */ + merger.add(newLineString(0, 0, 20, 0)); + merger.add(newLineString(20, 0, 30, 0)); + merger.add(newLineString(30, 0, 50, 0)); + merger.add(newLineString(20, 0, 20, 10)); + merger.add(newLineString(30, 0, 30, 10)); + + assertEquals( + List.of(newLineString(0, 0, 20, 0, 30, 0, 50, 0)), + merger.getMergedLineStrings(15, -1) + ); + } + }