Skip to content

Commit

Permalink
vk-141-linestring-intersection: refactored LineString.Intersection to…
Browse files Browse the repository at this point in the history
… use hashable struct; added Unit tests; fixed(?) a bug where intersections were not found on end points.
  • Loading branch information
Udumft committed Nov 9, 2021
1 parent 0e89876 commit 0f4b821
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 9 deletions.
25 changes: 18 additions & 7 deletions Sources/Turf/Geometries/LineString.swift
Original file line number Diff line number Diff line change
Expand Up @@ -326,19 +326,30 @@ extension LineString {
- seealso: `Turf.intersection(_:, _:)`
*/
public func intersections(with line: LineString) -> [LocationCoordinate2D] {
var intersections: [String : LocationCoordinate2D] = [:]

var intersections = Set<HashableCoordinate>()
for segment1 in segments {
for segment2 in line.segments {
if let intersection = Turf.intersection(LineSegment(segment1.0, segment1.1),
LineSegment(segment2.0, segment2.1)) {
let key = "\(intersection.latitude),\(intersection.longitude)"
if intersections[key] == nil {
intersections[key] = intersection
}
intersections.insert(.init(intersection))
}
}
}
return Array(intersections.values)
return intersections.map(\.locationCoordinate)
}

private struct HashableCoordinate: Hashable {
let latitude: Double
let longitude: Double

var locationCoordinate: LocationCoordinate2D {
return LocationCoordinate2D(latitude: latitude,
longitude: longitude)
}

init(_ coordinate: LocationCoordinate2D) {
self.latitude = coordinate.latitude
self.longitude = coordinate.longitude
}
}
}
4 changes: 2 additions & 2 deletions Sources/Turf/Turf.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ public func intersection(_ line1: LineSegment, _ line2: LineSegment) -> Location
longitude: line1.0.longitude + a * (line1.1.longitude - line1.0.longitude))

/// True if line 1 is finite and line 2 is infinite.
let intersectsWithLine1 = a > 0 && a < 1
let intersectsWithLine1 = a >= 0 && a <= 1
/// True if line 2 is finite and line 1 is infinite.
let intersectsWithLine2 = b > 0 && b < 1
let intersectsWithLine2 = b >= 0 && b <= 1
return intersectsWithLine1 && intersectsWithLine2 ? intersection : nil
}

Expand Down
17 changes: 17 additions & 0 deletions Tests/TurfTests/LineStringTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -350,4 +350,21 @@ class LineStringTests: XCTestCase {
XCTAssertEqual(slicedCoordinates?.count, 2, "no duplicated coords")
XCTAssertNotEqual(slicedCoordinates?.first, slicedCoordinates?.last, "vertical slice should not collapse to first coordinate")
}

func testIntersections() {
let lineString = LineString([.init(latitude: 2, longitude: 1),
.init(latitude: 2, longitude: 5),
.init(latitude: 2, longitude: 9)])

let intersectingLineString = LineString([.init(latitude: 4, longitude: 1),
.init(latitude: 0, longitude: 5),
.init(latitude: 2, longitude: 9)])

let intersections = lineString.intersections(with: intersectingLineString)

XCTAssertEqual(intersections.sorted(by: { $0.longitude < $1.longitude }),
[.init(latitude: 2, longitude: 3),
.init(latitude: 2, longitude: 9)],
accuracy: 0, "LineString intersections are not correct.")
}
}
7 changes: 7 additions & 0 deletions Tests/TurfTests/TurfTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,13 @@ class TurfTests: XCTestCase {
XCTAssertEqual(a, coord1)
}

func testIntersectionOnEnd() {
let coord1 = LocationCoordinate2D(latitude: 20, longitude: 20)
let a = intersection((LocationCoordinate2D(latitude: 20, longitude: 20), LocationCoordinate2D(latitude: 40, longitude: 40)),
(LocationCoordinate2D(latitude: 20, longitude: 20), LocationCoordinate2D(latitude: 40, longitude: 20)))
XCTAssertEqual(a, coord1)
}

func testCLLocationDegrees() {
let degree: CLLocationDegrees = 100
let a = degree.toRadians()
Expand Down

0 comments on commit 0f4b821

Please sign in to comment.