From 26b2fb9ff842a3e95251a03767d4c513e26faf0a Mon Sep 17 00:00:00 2001 From: Thomas Rasch Date: Thu, 8 Aug 2024 15:39:49 +0200 Subject: [PATCH] MultiLineString --- Sources/GISTools/Algorithms/LineOverlap.swift | 10 +++- .../Algorithms/LineOverlapTests.swift | 46 +++++++++++-------- 2 files changed, 36 insertions(+), 20 deletions(-) diff --git a/Sources/GISTools/Algorithms/LineOverlap.swift b/Sources/GISTools/Algorithms/LineOverlap.swift index ec7077e..0e3997f 100644 --- a/Sources/GISTools/Algorithms/LineOverlap.swift +++ b/Sources/GISTools/Algorithms/LineOverlap.swift @@ -235,7 +235,7 @@ extension GeoJson { /// /// - Returns: All segments that at least overlap with one other segment. Each segment will only be /// in the result once. - public func overlappingSegments(tolerance: CLLocationDistance = 0.0) -> [LineSegment] { + public func overlappingSegments(tolerance: CLLocationDistance = 0.0) -> MultiLineString? { let tolerance = abs(tolerance) let sortedSegments: [LineSegment] = lineSegments .map { lineSegment in @@ -284,7 +284,13 @@ extension GeoJson { } } - return result.map { sortedSegments[$0] } + var lineStrings: [LineString] = [] + + for range in result.rangeView { + lineStrings.append(LineString(range.map { sortedSegments[$0] })!) + } + + return MultiLineString(lineStrings) } } diff --git a/Tests/GISToolsTests/Algorithms/LineOverlapTests.swift b/Tests/GISToolsTests/Algorithms/LineOverlapTests.swift index 3cbb257..40e0060 100644 --- a/Tests/GISToolsTests/Algorithms/LineOverlapTests.swift +++ b/Tests/GISToolsTests/Algorithms/LineOverlapTests.swift @@ -137,11 +137,10 @@ final class LineOverlapTests: XCTestCase { Coordinate3D(latitude: 12.0, longitude: 12.0), ])! - let overlapping = lineString.overlappingSegments() - XCTAssertEqual(overlapping.count, 0) + XCTAssertNil(lineString.overlappingSegments()?.lineStrings) } - func testSelfOverlap1() { + func testSelfOverlap1() throws { let lineString = LineString([ Coordinate3D(latitude: 0.0, longitude: 0.0), Coordinate3D(latitude: 1.0, longitude: 1.0), // overlap @@ -155,32 +154,33 @@ final class LineOverlapTests: XCTestCase { Coordinate3D(latitude: 0.0, longitude: 1.0), // " ])! - let overlapping = lineString.overlappingSegments() + let overlapping = try XCTUnwrap(lineString.overlappingSegments()?.lineStrings) XCTAssertEqual(overlapping.count, 3) } - func testSelfOverlap2() { + func testSelfOverlap2() throws { let lineString = LineString([ - Coordinate3D(latitude: 0.0, longitude: 0.0), - Coordinate3D(latitude: 8.0, longitude: -8.0), + Coordinate3D(latitude: 0.0, longitude: 0.0), // overlap + Coordinate3D(latitude: 8.0, longitude: -8.0), // " Coordinate3D(latitude: 7.0, longitude: -9.0), Coordinate3D(latitude: 6.0, longitude: -9.0), - Coordinate3D(latitude: 6.0, longitude: -6.0), - Coordinate3D(latitude: 5.0, longitude: -5.0), + Coordinate3D(latitude: 6.0, longitude: -6.0), // overlap + Coordinate3D(latitude: 5.0, longitude: -5.0), // " Coordinate3D(latitude: 5.0, longitude: -7.0), Coordinate3D(latitude: 4.0, longitude: -7.0), - Coordinate3D(latitude: 4.0, longitude: -4.0), - Coordinate3D(latitude: 3.0, longitude: -3.0), + Coordinate3D(latitude: 4.0, longitude: -4.0), // overlap + Coordinate3D(latitude: 3.0, longitude: -3.0), // " Coordinate3D(latitude: 3.0, longitude: -1.0), - Coordinate3D(latitude: 1.0, longitude: -1.0), - Coordinate3D(latitude: 0.0, longitude: 0.0), + Coordinate3D(latitude: 1.0, longitude: -1.0), // overlap + Coordinate3D(latitude: 0.0, longitude: 0.0), // " ])! - let overlapping = lineString.overlappingSegments() + let overlapping = try XCTUnwrap(lineString.overlappingSegments()?.lineStrings) + FeatureCollection(overlapping).dump() XCTAssertEqual(overlapping.count, 4) } - func testSelfOverlap3() { + func testSelfOverlap3() throws { let lineString = LineString([ Coordinate3D(latitude: 0.0, longitude: 0.0), Coordinate3D(latitude: 2.0, longitude: 0.0), @@ -194,11 +194,11 @@ final class LineOverlapTests: XCTestCase { Coordinate3D(latitude: 0.0, longitude: 0.0), ])! - let overlapping = lineString.overlappingSegments() + let overlapping = try XCTUnwrap(lineString.overlappingSegments()?.lineStrings) XCTAssertEqual(overlapping.count, 3) } - func testSelfOverlap3WithSegments() { + func testSelfOverlap3WithSegments() throws { let lineString = LineString([ Coordinate3D(latitude: 0.0, longitude: 0.0), Coordinate3D(latitude: 2.0, longitude: 0.0), @@ -212,8 +212,18 @@ final class LineOverlapTests: XCTestCase { Coordinate3D(latitude: 0.0, longitude: 0.0), ])! - let overlapping = lineString.overlappingSegments() + let overlapping = try XCTUnwrap(lineString.overlappingSegments()?.lineStrings) XCTAssertEqual(overlapping.count, 3) } + func testLongRouteSelfOverlap() throws { + let lineString = try XCTUnwrap(TestData.featureCollection(package: "LineOverlap", name: "LongRoute").features.first) + + let overlapping = try XCTUnwrap(lineString.overlappingSegments(tolerance: 10.0)?.lineStrings) + print(overlapping.count) + print(overlapping.reduce(0.0, { $0 + $1.length })) + print(lineString.length) + + } + }