Skip to content

Commit

Permalink
Reversed overlapping, self overlapping
Browse files Browse the repository at this point in the history
  • Loading branch information
trasch committed Jul 25, 2024
1 parent e3fd74b commit 5f31fb1
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 9 deletions.
45 changes: 41 additions & 4 deletions Sources/GISTools/Algorithms/LineOverlap.swift
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,19 @@ extension LineSegment {
{
return .otherPartialOverlapAtStart
}
else if other.first != first,
checkIsOnSegment(other.first),
other.checkIsOnSegment(first)
{
return .otherPartialOverlapAtStart
}
else if other.second != second,
checkIsOnSegment(other.second),
other.checkIsOnSegment(second)
{
return .otherPartialOverlapAtEnd

}
}
else if tolerance > 0.0 {
if other.nearestCoordinateOnSegment(from: first).distance <= tolerance,
Expand All @@ -83,6 +96,19 @@ extension LineSegment {
{
return .otherPartialOverlapAtStart
}
else if other.first.distance(from: first) > tolerance,
nearestCoordinateOnSegment(from: other.first).distance <= tolerance,
other.nearestCoordinateOnSegment(from: first).distance <= tolerance
{
return .otherPartialOverlapAtStart
}
else if other.second.distance(from: second) > tolerance,
nearestCoordinateOnSegment(from: other.second).distance <= tolerance,
other.nearestCoordinateOnSegment(from: second).distance <= tolerance
{
return .otherPartialOverlapAtEnd

}
}

return .notEqual
Expand All @@ -101,15 +127,16 @@ extension GeoJson {
/// Returns the overlapping segments between the receiver and the other geometry.
///
/// - Parameters:
/// - other: The other geometry, or `nil` for overlapping segments within the receiver
/// - other: The other geometry, or `nil` for overlapping segments with the receiver itself
/// - tolerance: The tolerance, in meters
public func overlappingSegments(
with other: GeoJson,
with other: GeoJson?,
tolerance: CLLocationDistance = 0.0)
-> [SegmentOverlapResult]
{
let tolerance = abs(tolerance)
let other = other.projected(to: projection)
let isSelfMatching = other == nil
let other = other?.projected(to: projection) ?? self

var result: [SegmentOverlapResult] = []

Expand All @@ -120,7 +147,17 @@ extension GeoJson {

let matches = tree.search(inBoundingBox: boundingBox)

var hadSelfSegmentMatch = false

for match in matches {
if isSelfMatching,
!hadSelfSegmentMatch,
segment == match
{
hadSelfSegmentMatch = true
continue
}

let comparison = segment.compare(other: match, tolerance: tolerance)

guard comparison != .notEqual else { continue }
Expand All @@ -135,7 +172,7 @@ extension GeoJson {
return result
}

/// Returns the overlapping segments within the receiver.
/// Returns the overlapping segments with the receiver itself.
///
/// - Parameters:
/// - tolerance: The tolerance, in meters
Expand Down
10 changes: 5 additions & 5 deletions Sources/GISTools/GeoJson/LineSegment.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#if !os(Linux)
import CoreLocation
import CoreLocation
#endif
import Foundation

Expand Down Expand Up @@ -39,7 +39,7 @@ extension LineSegment {

/// The receiver's two coordinates.
public var coordinates: [Coordinate3D] {
return [first, second]
[first, second]
}

}
Expand Down Expand Up @@ -90,7 +90,7 @@ extension LineSegment {
extension LineSegment: BoundingBoxRepresentable {

public func calculateBoundingBox() -> BoundingBox? {
return BoundingBox(coordinates: coordinates)
BoundingBox(coordinates: coordinates)
}

public func intersects(_ otherBoundingBox: BoundingBox) -> Bool {
Expand Down Expand Up @@ -131,12 +131,12 @@ extension LineSegment: BoundingBoxRepresentable {

extension LineSegment: Equatable {

public static func ==(
public static func == (
lhs: LineSegment,
rhs: LineSegment)
-> Bool
{
return lhs.first == rhs.first
lhs.first == rhs.first
&& lhs.second == rhs.second
}

Expand Down
20 changes: 20 additions & 0 deletions Tests/GISToolsTests/Algorithms/LineOverlapTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -198,4 +198,24 @@ final class LineOverlapTests: XCTestCase {
XCTAssertEqual(overlapping.count, 3)
}

func testSelfOverlap3WithSegments() {
let lineString = LineString([
Coordinate3D(latitude: 0.0, longitude: 0.0),
Coordinate3D(latitude: 2.0, longitude: 0.0),
Coordinate3D(latitude: 2.0, longitude: 2.0),
Coordinate3D(latitude: 1.0, longitude: 2.0),
Coordinate3D(latitude: 1.0, longitude: 0.0),
Coordinate3D(latitude: 3.0, longitude: 0.0),
Coordinate3D(latitude: 3.0, longitude: -2.0),
Coordinate3D(latitude: 2.0, longitude: -2.0),
Coordinate3D(latitude: 2.0, longitude: 0.0),
Coordinate3D(latitude: 0.0, longitude: 0.0),
])!

let overlapping = lineString.overlappingSegments(with: nil)
overlapping.forEach({ print("\($0.kind): \($0.segment.coordinates), other: \($0.other.coordinates)") })

XCTAssertEqual(overlapping.count, 6)
}

}

0 comments on commit 5f31fb1

Please sign in to comment.