diff --git a/Sources/GISTools/Extensions/ArrayExtensions.swift b/Sources/GISTools/Extensions/ArrayExtensions.swift index 0b2bd6e..6a0253a 100644 --- a/Sources/GISTools/Extensions/ArrayExtensions.swift +++ b/Sources/GISTools/Extensions/ArrayExtensions.swift @@ -126,9 +126,13 @@ extension Array { /// let a = [1, 2, 3, 4, 5] /// a.distinctPairs() -> [(1, 2), (3, 4)] /// ``` - func distinctPairs() -> [(first: Element, second: Element)] { + func distinctPairs() -> [(first: Element, second: Element?)] { guard !isEmpty else { return [] } + if count == 1 { + return [(first: self[0], second: nil)] + } + return (0 ..< (self.count / 2)).map { (index) in let i = index * 2 return (first: self[i], second: self[i+1]) @@ -141,9 +145,13 @@ extension Array { /// let a = [1, 2, 3, 4, 5] /// a.overlappingPairs() -> [(1, 2), (2, 3), (3, 4), (4, 5)] /// ``` - func overlappingPairs() -> [(first: Element, second: Element)] { + func overlappingPairs() -> [(first: Element, second: Element?)] { guard !isEmpty else { return [] } + if count == 1 { + return [(first: self[0], second: nil)] + } + return (0 ..< (self.count - 1)).map { (index) in return (first: self[index], second: self[index + 1]) } diff --git a/Sources/GISTools/GeoJson/LineString.swift b/Sources/GISTools/GeoJson/LineString.swift index 3b64ee5..0ac2b2b 100644 --- a/Sources/GISTools/GeoJson/LineString.swift +++ b/Sources/GISTools/GeoJson/LineString.swift @@ -74,11 +74,13 @@ public struct LineString: } } - if current.first != previous.second { - coordinates.append(current.first) - } - if current.second != current.first { - coordinates.append(current.second) + if let current { + if current.first != previous.second { + coordinates.append(current.first) + } + if current.second != current.first { + coordinates.append(current.second) + } } } diff --git a/Sources/GISTools/Turf/LineSegments.swift b/Sources/GISTools/Turf/LineSegments.swift index 7ad3b71..08eeb89 100644 --- a/Sources/GISTools/Turf/LineSegments.swift +++ b/Sources/GISTools/Turf/LineSegments.swift @@ -34,8 +34,9 @@ extension GeoJson { return [] case let lineString as LineString: - return lineString.coordinates.overlappingPairs().map { (first, second) in - LineSegment(first: first, second: second) + return lineString.coordinates.overlappingPairs().compactMap { (first, second) in + guard let second else { return nil } + return LineSegment(first: first, second: second) } case let multiLineString as MultiLineString: @@ -43,8 +44,9 @@ extension GeoJson { case let polygon as Polygon: return polygon.rings.flatMap({ (ring) in - ring.coordinates.overlappingPairs().map { (first, second) in - LineSegment(first: first, second: second) + ring.coordinates.overlappingPairs().compactMap { (first, second) in + guard let second else { return nil } + return LineSegment(first: first, second: second) } }) diff --git a/Tests/GISToolsTests/Extensions/ArrayExtensionsTests.swift b/Tests/GISToolsTests/Extensions/ArrayExtensionsTests.swift index 3ca1300..8130fbd 100644 --- a/Tests/GISToolsTests/Extensions/ArrayExtensionsTests.swift +++ b/Tests/GISToolsTests/Extensions/ArrayExtensionsTests.swift @@ -34,7 +34,7 @@ final class ArrayExtensionsTests: XCTestCase { let smallPairs = small.distinctPairs() XCTAssertEqual(emptyPairs.count, 0) - XCTAssertEqual(smallPairs.count, 0) + XCTAssertEqual(smallPairs.count, 1) } func testOverlappingPairs() { @@ -76,7 +76,7 @@ final class ArrayExtensionsTests: XCTestCase { let smallPairs = small.overlappingPairs() XCTAssertEqual(emptyPairs.count, 0) - XCTAssertEqual(smallPairs.count, 0) + XCTAssertEqual(smallPairs.count, 1) } func testGet() {