From 0452ba2f962042a10e31903e1c915fae994c1f5b Mon Sep 17 00:00:00 2001 From: Thomas Rasch Date: Mon, 11 Dec 2023 15:32:01 +0100 Subject: [PATCH] #13: boolean-intersects, boolean-disjoint, polygon-to-line (#40) * #13: boolean-intersects, boolean-disjoint, polygon-to-line --- .../GISTools/Algorithms/BooleanDisjoint.swift | 237 ++++++++++++++++++ .../Algorithms/BooleanIntersects.swift | 14 +- .../GISTools/Algorithms/LineIntersect.swift | 34 ++- .../GISTools/Algorithms/PolygonToLine.swift | 16 ++ Sources/GISTools/GeoJson/BoundingBox.swift | 5 + Sources/GISTools/GeoJson/Feature.swift | 4 +- .../GISTools/GeoJson/FeatureCollection.swift | 4 +- Sources/GISTools/GeoJson/GeoJson.swift | 2 +- Sources/GISTools/GeoJson/LineString.swift | 2 +- .../GISTools/GeoJson/MultiLineString.swift | 3 +- Sources/GISTools/GeoJson/MultiPoint.swift | 3 +- Sources/GISTools/GeoJson/MultiPolygon.swift | 3 +- Sources/GISTools/GeoJson/Polygon.swift | 12 +- Sources/GISTools/GeoJson/Ring.swift | 20 ++ .../Algorithms/BooleanDisjointTests.swift | 83 ++++++ .../BooleanDisjoint/LineString1.geojson | 9 + .../BooleanDisjoint/LineString2.geojson | 9 + .../BooleanDisjoint/LineString3.geojson | 9 + .../BooleanDisjoint/LineString4.geojson | 7 + .../BooleanDisjoint/MultiPoint1.geojson | 7 + .../BooleanDisjoint/MultiPoint2.geojson | 7 + .../BooleanDisjoint/MultiPoint3.geojson | 7 + .../BooleanDisjoint/MultiPoint4.geojson | 7 + .../BooleanDisjoint/MultiPoint5.geojson | 7 + .../BooleanDisjoint/MultiPolygon1.geojson | 23 ++ .../TestData/BooleanDisjoint/Point1.geojson | 4 + .../TestData/BooleanDisjoint/Point2.geojson | 4 + .../TestData/BooleanDisjoint/Point3.geojson | 4 + .../TestData/BooleanDisjoint/Point4.geojson | 4 + .../TestData/BooleanDisjoint/Polygon1.geojson | 12 + .../TestData/BooleanDisjoint/Polygon2.geojson | 12 + .../TestData/BooleanDisjoint/Polygon3.geojson | 12 + 32 files changed, 560 insertions(+), 26 deletions(-) create mode 100644 Sources/GISTools/Algorithms/BooleanDisjoint.swift create mode 100644 Sources/GISTools/Algorithms/PolygonToLine.swift create mode 100644 Tests/GISToolsTests/Algorithms/BooleanDisjointTests.swift create mode 100644 Tests/GISToolsTests/TestData/BooleanDisjoint/LineString1.geojson create mode 100644 Tests/GISToolsTests/TestData/BooleanDisjoint/LineString2.geojson create mode 100644 Tests/GISToolsTests/TestData/BooleanDisjoint/LineString3.geojson create mode 100644 Tests/GISToolsTests/TestData/BooleanDisjoint/LineString4.geojson create mode 100644 Tests/GISToolsTests/TestData/BooleanDisjoint/MultiPoint1.geojson create mode 100644 Tests/GISToolsTests/TestData/BooleanDisjoint/MultiPoint2.geojson create mode 100644 Tests/GISToolsTests/TestData/BooleanDisjoint/MultiPoint3.geojson create mode 100644 Tests/GISToolsTests/TestData/BooleanDisjoint/MultiPoint4.geojson create mode 100644 Tests/GISToolsTests/TestData/BooleanDisjoint/MultiPoint5.geojson create mode 100644 Tests/GISToolsTests/TestData/BooleanDisjoint/MultiPolygon1.geojson create mode 100644 Tests/GISToolsTests/TestData/BooleanDisjoint/Point1.geojson create mode 100644 Tests/GISToolsTests/TestData/BooleanDisjoint/Point2.geojson create mode 100644 Tests/GISToolsTests/TestData/BooleanDisjoint/Point3.geojson create mode 100644 Tests/GISToolsTests/TestData/BooleanDisjoint/Point4.geojson create mode 100644 Tests/GISToolsTests/TestData/BooleanDisjoint/Polygon1.geojson create mode 100644 Tests/GISToolsTests/TestData/BooleanDisjoint/Polygon2.geojson create mode 100644 Tests/GISToolsTests/TestData/BooleanDisjoint/Polygon3.geojson diff --git a/Sources/GISTools/Algorithms/BooleanDisjoint.swift b/Sources/GISTools/Algorithms/BooleanDisjoint.swift new file mode 100644 index 0000000..b6db4d2 --- /dev/null +++ b/Sources/GISTools/Algorithms/BooleanDisjoint.swift @@ -0,0 +1,237 @@ +#if !os(Linux) +import CoreLocation +#endif +import Foundation + +// Ported from https://github.com/Turfjs/turf/tree/master/packages/turf-boolean-disjoint + +extension GeoJson { + + /// Compares two geometries and returns true if they are disjoint. + /// + /// - Parameters: + /// - other: The other geometry + /// + /// - Returns: *true* if the geometries don't overlap, *false* otherwise. + public func isDisjoint(with other: GeoJson) -> Bool { + if let otherBoundingBox = other.boundingBox ?? other.calculateBoundingBox(), + !intersects(otherBoundingBox) + { + return true + } + + return switch self { + case let point as PointGeometry: + point.isPointDisjoint(with: other) + + case let lineString as LineStringGeometry: + lineString.isLineStringDisjoint(with: other) + + case let polygon as PolygonGeometry: + polygon.isPolygonDisjoint(with: other) + + case let geometryCollection as GeometryCollection: + geometryCollection.geometries.allSatisfy { $0.isDisjoint(with: other) } + + case let feature as Feature: + feature.geometry.isDisjoint(with: other) + + case let featureCollection as FeatureCollection: + featureCollection.features.allSatisfy { $0.isDisjoint(with: other) } + + default: + true + } + } + +} + +// MARK: - Private helpers + +extension PointGeometry { + + fileprivate func isPointDisjoint(with other: GeoJson) -> Bool { + let other = other.projected(to: projection) + + switch other { + case let otherPoint as PointGeometry: + for coordinate in allCoordinates { + if otherPoint.allCoordinates.contains(coordinate) { + return false + } + } + + case let otherLineString as LineStringGeometry: + for coordinate in allCoordinates { + if otherLineString.checkIsOnLine(coordinate) { + return false + } + } + + case let otherPolygon as PolygonGeometry: + for coordinate in allCoordinates { + if otherPolygon.contains(coordinate, ignoreBoundary: false) { + return false + } + } + + case let otherGeometryCollection as GeometryCollection: + return otherGeometryCollection.geometries.allSatisfy { $0.isDisjoint(with: self) } + + case let otherFeature as Feature: + return otherFeature.geometry.isDisjoint(with: self) + + case let otherFeatureCollection as FeatureCollection: + return otherFeatureCollection.features.allSatisfy { $0.isDisjoint(with: self) } + + default: + return true + } + + return true + } + +} + +extension LineStringGeometry { + + private func intersects(_ other: LineStringGeometry) -> Bool { + let other = other.projected(to: projection) + + for lineSegment in lineSegments { + for otherLineSegment in other.lineSegments { + if lineSegment.intersects(otherLineSegment) { + return true + } + } + } + + return false + } + + fileprivate func isLineStringDisjoint(with other: GeoJson) -> Bool { + let other = other.projected(to: projection) + + switch other { + case let otherPoint as PointGeometry: + for lineString in lineStrings { + guard otherPoint.isDisjoint(with: lineString) else { + return false + } + } + + case let otherLineString as LineStringGeometry: + for lineString in lineStrings { + if lineString.intersects(otherLineString) { + return false + } + } + + case let otherPolygon as PolygonGeometry: + // Any point inside the polygon + for coordinate in allCoordinates { + if otherPolygon.contains(coordinate, ignoreBoundary: false) { + return false + } + } + + // Any line crosses the polygon + for lineString in lineStrings { + for otherLineString in otherPolygon.polygons.compactMap(\.outerRing?.lineString) { + if lineString.intersects(otherLineString) { + return false + } + } + } + + case let otherGeometryCollection as GeometryCollection: + return otherGeometryCollection.geometries.allSatisfy { $0.isDisjoint(with: self) } + + case let otherFeature as Feature: + return otherFeature.geometry.isDisjoint(with: self) + + case let otherFeatureCollection as FeatureCollection: + return otherFeatureCollection.features.allSatisfy { $0.isDisjoint(with: self) } + + default: + return true + } + + return true + } + +} + +extension PolygonGeometry { + + fileprivate func isPolygonDisjoint(with other: GeoJson) -> Bool { + let other = other.projected(to: projection) + + switch other { + case let otherPoint as PointGeometry: + for polygon in polygons { + guard otherPoint.isDisjoint(with: polygon) else { + return false + } + } + + case let otherLineString as LineStringGeometry: + for polygon in polygons { + guard otherLineString.isDisjoint(with: polygon) else { + return false + } + } + + case let otherPolygon as PolygonGeometry: + // Any point inside the polygon + for polygon in polygons { + guard let coordinates = polygon.outerRing?.coordinates else { + continue + } + + for coordinate in coordinates { + if otherPolygon.contains(coordinate, ignoreBoundary: false) { + return false + } + } + } + + for polygon in otherPolygon.polygons { + guard let coordinates = polygon.outerRing?.coordinates else { + continue + } + + for coordinate in coordinates { + if self.contains(coordinate, ignoreBoundary: false) { + return false + } + } + } + + // Any line crosses the polygon + for polygon in polygons { + guard let lineString = polygon.outerRing?.lineString else { + continue + } + guard lineString.isDisjoint(with: otherPolygon) else { + return false + } + } + + case let otherGeometryCollection as GeometryCollection: + return otherGeometryCollection.geometries.allSatisfy { $0.isDisjoint(with: self) } + + case let otherFeature as Feature: + return otherFeature.geometry.isDisjoint(with: self) + + case let otherFeatureCollection as FeatureCollection: + return otherFeatureCollection.features.allSatisfy { $0.isDisjoint(with: self) } + + default: + return true + } + + return true + } + +} diff --git a/Sources/GISTools/Algorithms/BooleanIntersects.swift b/Sources/GISTools/Algorithms/BooleanIntersects.swift index 1c2c5d6..ef08021 100644 --- a/Sources/GISTools/Algorithms/BooleanIntersects.swift +++ b/Sources/GISTools/Algorithms/BooleanIntersects.swift @@ -5,4 +5,16 @@ import Foundation // Ported from https://github.com/Turfjs/turf/blob/master/packages/turf-boolean-intersects -// TODO +extension GeoJson { + + /// Compares two geometries and returns true if they intersect. + /// + /// - Parameters: + /// - other: The other geometry + /// + /// - Returns: *true* if the geometries intersect, *false* otherwise. + public func intersects(with other: GeoJson) -> Bool { + !isDisjoint(with: other) + } + +} diff --git a/Sources/GISTools/Algorithms/LineIntersect.swift b/Sources/GISTools/Algorithms/LineIntersect.swift index 42f9f65..d49d0fb 100644 --- a/Sources/GISTools/Algorithms/LineIntersect.swift +++ b/Sources/GISTools/Algorithms/LineIntersect.swift @@ -139,14 +139,12 @@ extension GeoJson { /// Returns the intersecting point(s) with the receiver. /// + /// - note: Takes all poygon rings into account, not just the outer ring. + /// /// - Parameter other: The other geometry public func intersections(other: GeoJson) -> [Point] { let other = other.projected(to: projection) - if self is Point || self is MultiPoint || other is Point || other is MultiPoint { - return [] - } - if let otherBoundingBox = other.boundingBox ?? other.calculateBoundingBox(), !intersects(otherBoundingBox) { @@ -155,10 +153,30 @@ extension GeoJson { var result: Set = [] - for lineSegment in lineSegments { - for otherLineSegment in other.lineSegments { - if let intersection = lineSegment.intersection(otherLineSegment) { - result.insert(intersection) + if let point = self as? PointGeometry { + if let otherPoint = other as? PointGeometry { + for coordinate in point.allCoordinates + where otherPoint.allCoordinates.contains(coordinate) + { + result.insert(coordinate) + } + } + else { + for coordinate in point.allCoordinates { + for otherLineSegment in other.lineSegments + where otherLineSegment.checkIsOnSegment(coordinate) + { + result.insert(coordinate) + } + } + } + } + else { + for lineSegment in lineSegments { + for otherLineSegment in other.lineSegments { + if let intersection = lineSegment.intersection(otherLineSegment) { + result.insert(intersection) + } } } } diff --git a/Sources/GISTools/Algorithms/PolygonToLine.swift b/Sources/GISTools/Algorithms/PolygonToLine.swift new file mode 100644 index 0000000..14dbc9e --- /dev/null +++ b/Sources/GISTools/Algorithms/PolygonToLine.swift @@ -0,0 +1,16 @@ +#if !os(Linux) +import CoreLocation +#endif +import Foundation + +extension PolygonGeometry { + + /// Returns a MultiLineString for each polygon. + public var lineStrings: [MultiLineString] { + polygons.compactMap { polygon in + let lineStrings = polygon.rings.map(\.lineString) + return MultiLineString(lineStrings) + } + } + +} diff --git a/Sources/GISTools/GeoJson/BoundingBox.swift b/Sources/GISTools/GeoJson/BoundingBox.swift index 4e71413..07065d0 100644 --- a/Sources/GISTools/GeoJson/BoundingBox.swift +++ b/Sources/GISTools/GeoJson/BoundingBox.swift @@ -260,6 +260,11 @@ extension BoundingBox { extension BoundingBox { + /// All of the bounding box's corner coordinates. + var allCoordinates: [Coordinate3D] { + [southWest, northWest, northEast, southEast] + } + /// Converts the bounding box to a `Polygon` object. public var boundingBoxPolygon: Polygon { Polygon([[southWest, northWest, northEast, southEast, southWest]])! diff --git a/Sources/GISTools/GeoJson/Feature.swift b/Sources/GISTools/GeoJson/Feature.swift index 99d93c2..5522194 100644 --- a/Sources/GISTools/GeoJson/Feature.swift +++ b/Sources/GISTools/GeoJson/Feature.swift @@ -139,7 +139,9 @@ extension Feature { } public func intersects(_ otherBoundingBox: BoundingBox) -> Bool { - if let boundingBox = boundingBox, !boundingBox.intersects(otherBoundingBox) { + if let boundingBox = boundingBox ?? calculateBoundingBox(), + !boundingBox.intersects(otherBoundingBox) + { return false } diff --git a/Sources/GISTools/GeoJson/FeatureCollection.swift b/Sources/GISTools/GeoJson/FeatureCollection.swift index 9c5e2fe..81645c5 100644 --- a/Sources/GISTools/GeoJson/FeatureCollection.swift +++ b/Sources/GISTools/GeoJson/FeatureCollection.swift @@ -143,7 +143,9 @@ extension FeatureCollection { } public func intersects(_ otherBoundingBox: BoundingBox) -> Bool { - if let boundingBox = boundingBox, !boundingBox.intersects(otherBoundingBox) { + if let boundingBox = boundingBox ?? calculateBoundingBox(), + !boundingBox.intersects(otherBoundingBox) + { return false } diff --git a/Sources/GISTools/GeoJson/GeoJson.swift b/Sources/GISTools/GeoJson/GeoJson.swift index 68f138e..c7be5ec 100644 --- a/Sources/GISTools/GeoJson/GeoJson.swift +++ b/Sources/GISTools/GeoJson/GeoJson.swift @@ -138,7 +138,7 @@ public protocol EmptyCreatable { // MARK: - GeoJsonGeometry /// GeoJSON geometry objects: `Point`, `MultiPoint`, `LineString`, `MultiLineString`, -/// `Polygon`, `MultiPolygon`, `GeoJsonGeometry`. +/// `Polygon`, `MultiPolygon`, `GeometryCollection`. public protocol GeoJsonGeometry: GeoJson {} // MARK: - Point, MultiPoint diff --git a/Sources/GISTools/GeoJson/LineString.swift b/Sources/GISTools/GeoJson/LineString.swift index 0ac2b2b..7c5194f 100644 --- a/Sources/GISTools/GeoJson/LineString.swift +++ b/Sources/GISTools/GeoJson/LineString.swift @@ -188,7 +188,7 @@ extension LineString { } public func intersects(_ otherBoundingBox: BoundingBox) -> Bool { - if let boundingBox = boundingBox, + if let boundingBox = boundingBox ?? calculateBoundingBox(), !boundingBox.intersects(otherBoundingBox) { return false diff --git a/Sources/GISTools/GeoJson/MultiLineString.swift b/Sources/GISTools/GeoJson/MultiLineString.swift index cbe8043..1a75cb9 100644 --- a/Sources/GISTools/GeoJson/MultiLineString.swift +++ b/Sources/GISTools/GeoJson/MultiLineString.swift @@ -186,11 +186,12 @@ extension MultiLineString { } public func intersects(_ otherBoundingBox: BoundingBox) -> Bool { - if let boundingBox = boundingBox, + if let boundingBox = boundingBox ?? calculateBoundingBox(), !boundingBox.intersects(otherBoundingBox) { return false } + return lineStrings.contains { $0.intersects(otherBoundingBox) } } diff --git a/Sources/GISTools/GeoJson/MultiPoint.swift b/Sources/GISTools/GeoJson/MultiPoint.swift index 5df0e69..e3a506a 100644 --- a/Sources/GISTools/GeoJson/MultiPoint.swift +++ b/Sources/GISTools/GeoJson/MultiPoint.swift @@ -153,11 +153,12 @@ extension MultiPoint { } public func intersects(_ otherBoundingBox: BoundingBox) -> Bool { - if let boundingBox = boundingBox, + if let boundingBox = boundingBox ?? calculateBoundingBox(), !boundingBox.intersects(otherBoundingBox) { return false } + return coordinates.contains { otherBoundingBox.contains($0) } } diff --git a/Sources/GISTools/GeoJson/MultiPolygon.swift b/Sources/GISTools/GeoJson/MultiPolygon.swift index acd9a45..c3fd8ca 100644 --- a/Sources/GISTools/GeoJson/MultiPolygon.swift +++ b/Sources/GISTools/GeoJson/MultiPolygon.swift @@ -156,11 +156,12 @@ extension MultiPolygon { } public func intersects(_ otherBoundingBox: BoundingBox) -> Bool { - if let boundingBox = boundingBox, + if let boundingBox = boundingBox ?? calculateBoundingBox(), !boundingBox.intersects(otherBoundingBox) { return false } + return polygons.contains { $0.intersects(otherBoundingBox) } } diff --git a/Sources/GISTools/GeoJson/Polygon.swift b/Sources/GISTools/GeoJson/Polygon.swift index 82554f6..5b8d00e 100644 --- a/Sources/GISTools/GeoJson/Polygon.swift +++ b/Sources/GISTools/GeoJson/Polygon.swift @@ -172,22 +172,14 @@ extension Polygon { return BoundingBox(coordinates: coordinates) } - // TODO: This is not (entirely) correct, needs improvement - // Check if one the of the bounding box corners or the center is inside the polygon public func intersects(_ otherBoundingBox: BoundingBox) -> Bool { - if let boundingBox = boundingBox, + if let boundingBox = boundingBox ?? calculateBoundingBox(), !boundingBox.intersects(otherBoundingBox) { return false } - guard let outerRing = self.outerRing else { return false } - - return outerRing.contains(otherBoundingBox.center) - || outerRing.contains(otherBoundingBox.northWest) - || outerRing.contains(otherBoundingBox.northEast) - || outerRing.contains(otherBoundingBox.southEast) - || outerRing.contains(otherBoundingBox.southWest) + return outerRing?.intersects(otherBoundingBox) ?? false } } diff --git a/Sources/GISTools/GeoJson/Ring.swift b/Sources/GISTools/GeoJson/Ring.swift index 2cd2898..c62a7e1 100644 --- a/Sources/GISTools/GeoJson/Ring.swift +++ b/Sources/GISTools/GeoJson/Ring.swift @@ -26,6 +26,10 @@ public struct Ring: /// The receiver's coordinates. public let coordinates: [Coordinate3D] + public var lineString: LineString { + LineString(unchecked: coordinates) + } + /// Try to initialize a Ring with some coordinates. public init?(_ coordinates: [Coordinate3D]) { // TODO: Close the ring, if necessary @@ -53,6 +57,22 @@ extension Ring { } +// MARK: - BoundingBox + +extension Ring { + + public func intersects(_ otherBoundingBox: BoundingBox) -> Bool { + if otherBoundingBox.allCoordinates.contains(where: { contains($0) }) + || contains(otherBoundingBox.center) + { + return true + } + + return lineString.intersects(otherBoundingBox) + } + +} + // MARK: - CoreLocation compatibility #if !os(Linux) diff --git a/Tests/GISToolsTests/Algorithms/BooleanDisjointTests.swift b/Tests/GISToolsTests/Algorithms/BooleanDisjointTests.swift new file mode 100644 index 0000000..321b7f1 --- /dev/null +++ b/Tests/GISToolsTests/Algorithms/BooleanDisjointTests.swift @@ -0,0 +1,83 @@ +@testable import GISTools +import XCTest + +final class BooleanDisjointTests: XCTestCase { + + func testTrue() { + let point1 = TestData.point(package: "BooleanDisjoint", name: "Point1") + let point2 = TestData.point(package: "BooleanDisjoint", name: "Point2") + let multiPoint1 = TestData.multiPoint(package: "BooleanDisjoint", name: "MultiPoint1") + let multiPoint2 = TestData.multiPoint(package: "BooleanDisjoint", name: "MultiPoint2") + let multiPoint3 = TestData.multiPoint(package: "BooleanDisjoint", name: "MultiPoint3") + let lineString1 = TestData.lineString(package: "BooleanDisjoint", name: "LineString1") + let lineString2 = TestData.lineString(package: "BooleanDisjoint", name: "LineString2") + let polygon1 = TestData.polygon(package: "BooleanDisjoint", name: "Polygon1") + let polygon2 = TestData.polygon(package: "BooleanDisjoint", name: "Polygon2") + let multiPolygon1 = TestData.multiPolygon(package: "BooleanDisjoint", name: "MultiPolygon1") + + XCTAssertTrue(point1.isDisjoint(with: point2)) + XCTAssertTrue(point1.isDisjoint(with: multiPoint2)) + XCTAssertTrue(point1.isDisjoint(with: lineString2)) + XCTAssertTrue(point2.isDisjoint(with: point1)) + XCTAssertTrue(point2.isDisjoint(with: polygon1)) + XCTAssertTrue(point2.isDisjoint(with: multiPolygon1)) + + XCTAssertTrue(multiPoint1.isDisjoint(with: multiPoint2)) + XCTAssertTrue(multiPoint2.isDisjoint(with: point1)) + XCTAssertTrue(multiPoint2.isDisjoint(with: multiPoint1)) + XCTAssertTrue(multiPoint3.isDisjoint(with: polygon1)) + + XCTAssertTrue(lineString1.isDisjoint(with: lineString2)) + XCTAssertTrue(lineString1.isDisjoint(with: polygon1)) + XCTAssertTrue(lineString2.isDisjoint(with: point1)) + XCTAssertTrue(lineString2.isDisjoint(with: multiPoint1)) + XCTAssertTrue(lineString2.isDisjoint(with: lineString1)) + + XCTAssertTrue(polygon1.isDisjoint(with: point2)) + XCTAssertTrue(polygon1.isDisjoint(with: multiPoint3)) + XCTAssertTrue(polygon1.isDisjoint(with: lineString1)) + XCTAssertTrue(polygon1.isDisjoint(with: polygon2)) + XCTAssertTrue(polygon2.isDisjoint(with: multiPolygon1)) + XCTAssertTrue(polygon2.isDisjoint(with: polygon1)) + + XCTAssertTrue(multiPolygon1.isDisjoint(with: polygon2)) + XCTAssertTrue(multiPolygon1.isDisjoint(with: point2)) + } + + func testFalse() { + let point3 = TestData.point(package: "BooleanDisjoint", name: "Point3") + let point4 = TestData.point(package: "BooleanDisjoint", name: "Point4") + let multiPoint2 = TestData.multiPoint(package: "BooleanDisjoint", name: "MultiPoint2") + let multiPoint4 = TestData.multiPoint(package: "BooleanDisjoint", name: "MultiPoint4") + let multiPoint5 = TestData.multiPoint(package: "BooleanDisjoint", name: "MultiPoint5") + let lineString2 = TestData.lineString(package: "BooleanDisjoint", name: "LineString2") + let lineString3 = TestData.lineString(package: "BooleanDisjoint", name: "LineString3") + let lineString4 = TestData.lineString(package: "BooleanDisjoint", name: "LineString4") + let polygon1 = TestData.polygon(package: "BooleanDisjoint", name: "Polygon1") + let polygon3 = TestData.polygon(package: "BooleanDisjoint", name: "Polygon3") + let multiPolygon1 = TestData.multiPolygon(package: "BooleanDisjoint", name: "MultiPolygon1") + + XCTAssertFalse(point3.isDisjoint(with: lineString2)) + XCTAssertFalse(point4.isDisjoint(with: lineString2)) + + XCTAssertFalse(multiPoint2.isDisjoint(with: multiPoint4)) + XCTAssertFalse(multiPoint4.isDisjoint(with: lineString2)) + XCTAssertFalse(multiPoint5.isDisjoint(with: polygon1)) + + XCTAssertFalse(lineString2.isDisjoint(with: point3)) + XCTAssertFalse(lineString2.isDisjoint(with: point4)) + XCTAssertFalse(lineString2.isDisjoint(with: lineString3)) + XCTAssertFalse(lineString2.isDisjoint(with: multiPoint4)) + XCTAssertFalse(lineString3.isDisjoint(with: lineString2)) + XCTAssertFalse(lineString3.isDisjoint(with: polygon1)) + XCTAssertFalse(lineString4.isDisjoint(with: polygon1)) + + XCTAssertFalse(polygon1.isDisjoint(with: multiPoint5)) + XCTAssertFalse(polygon1.isDisjoint(with: lineString3)) + XCTAssertFalse(polygon1.isDisjoint(with: lineString4)) + XCTAssertFalse(polygon3.isDisjoint(with: multiPolygon1)) + + XCTAssertFalse(multiPolygon1.isDisjoint(with: polygon3)) + } + +} diff --git a/Tests/GISToolsTests/TestData/BooleanDisjoint/LineString1.geojson b/Tests/GISToolsTests/TestData/BooleanDisjoint/LineString1.geojson new file mode 100644 index 0000000..5292fa4 --- /dev/null +++ b/Tests/GISToolsTests/TestData/BooleanDisjoint/LineString1.geojson @@ -0,0 +1,9 @@ +{ + "type": "LineString", + "coordinates": [ + [0, 0], + [12, 2], + [12, 3], + [12, 4] + ] +} diff --git a/Tests/GISToolsTests/TestData/BooleanDisjoint/LineString2.geojson b/Tests/GISToolsTests/TestData/BooleanDisjoint/LineString2.geojson new file mode 100644 index 0000000..0d0318a --- /dev/null +++ b/Tests/GISToolsTests/TestData/BooleanDisjoint/LineString2.geojson @@ -0,0 +1,9 @@ +{ + "type": "LineString", + "coordinates": [ + [1, 1], + [1, 2], + [1, 3], + [1, 4] + ] +} diff --git a/Tests/GISToolsTests/TestData/BooleanDisjoint/LineString3.geojson b/Tests/GISToolsTests/TestData/BooleanDisjoint/LineString3.geojson new file mode 100644 index 0000000..155b8e9 --- /dev/null +++ b/Tests/GISToolsTests/TestData/BooleanDisjoint/LineString3.geojson @@ -0,0 +1,9 @@ +{ + "type": "LineString", + "coordinates": [ + [0, 2], + [12, 2], + [12, 3], + [12, 4] + ] +} diff --git a/Tests/GISToolsTests/TestData/BooleanDisjoint/LineString4.geojson b/Tests/GISToolsTests/TestData/BooleanDisjoint/LineString4.geojson new file mode 100644 index 0000000..984f940 --- /dev/null +++ b/Tests/GISToolsTests/TestData/BooleanDisjoint/LineString4.geojson @@ -0,0 +1,7 @@ +{ + "type": "LineString", + "coordinates": [ + [1, 2.5], + [2, 2.5] + ] +} diff --git a/Tests/GISToolsTests/TestData/BooleanDisjoint/MultiPoint1.geojson b/Tests/GISToolsTests/TestData/BooleanDisjoint/MultiPoint1.geojson new file mode 100644 index 0000000..de826c5 --- /dev/null +++ b/Tests/GISToolsTests/TestData/BooleanDisjoint/MultiPoint1.geojson @@ -0,0 +1,7 @@ +{ + "type": "MultiPoint", + "coordinates": [ + [2, 2], + [0, 0] + ] +} diff --git a/Tests/GISToolsTests/TestData/BooleanDisjoint/MultiPoint2.geojson b/Tests/GISToolsTests/TestData/BooleanDisjoint/MultiPoint2.geojson new file mode 100644 index 0000000..a3a12bf --- /dev/null +++ b/Tests/GISToolsTests/TestData/BooleanDisjoint/MultiPoint2.geojson @@ -0,0 +1,7 @@ +{ + "type": "MultiPoint", + "coordinates": [ + [1, 1], + [12, 12] + ] +} diff --git a/Tests/GISToolsTests/TestData/BooleanDisjoint/MultiPoint3.geojson b/Tests/GISToolsTests/TestData/BooleanDisjoint/MultiPoint3.geojson new file mode 100644 index 0000000..1b04f81 --- /dev/null +++ b/Tests/GISToolsTests/TestData/BooleanDisjoint/MultiPoint3.geojson @@ -0,0 +1,7 @@ +{ + "type": "MultiPoint", + "coordinates": [ + [-3, -3], + [-2, -2] + ] +} diff --git a/Tests/GISToolsTests/TestData/BooleanDisjoint/MultiPoint4.geojson b/Tests/GISToolsTests/TestData/BooleanDisjoint/MultiPoint4.geojson new file mode 100644 index 0000000..6824d89 --- /dev/null +++ b/Tests/GISToolsTests/TestData/BooleanDisjoint/MultiPoint4.geojson @@ -0,0 +1,7 @@ +{ + "type": "MultiPoint", + "coordinates": [ + [1, 1], + [0, 0] + ] +} diff --git a/Tests/GISToolsTests/TestData/BooleanDisjoint/MultiPoint5.geojson b/Tests/GISToolsTests/TestData/BooleanDisjoint/MultiPoint5.geojson new file mode 100644 index 0000000..81fffb9 --- /dev/null +++ b/Tests/GISToolsTests/TestData/BooleanDisjoint/MultiPoint5.geojson @@ -0,0 +1,7 @@ +{ + "type": "MultiPoint", + "coordinates": [ + [-1, 2], + [-2, -2] + ] +} diff --git a/Tests/GISToolsTests/TestData/BooleanDisjoint/MultiPolygon1.geojson b/Tests/GISToolsTests/TestData/BooleanDisjoint/MultiPolygon1.geojson new file mode 100644 index 0000000..a450c6f --- /dev/null +++ b/Tests/GISToolsTests/TestData/BooleanDisjoint/MultiPolygon1.geojson @@ -0,0 +1,23 @@ +{ + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [122.6953125, -19.186677697957833], + [128.759765625, -19.186677697957833], + [128.759765625, -15.28418511407642], + [122.6953125, -15.28418511407642], + [122.6953125, -19.186677697957833] + ] + ], + [ + [ + [123.74999999999999, -25.918526162075153], + [130.25390625, -25.918526162075153], + [130.25390625, -20.715015145512087], + [123.74999999999999, -20.715015145512087], + [123.74999999999999, -25.918526162075153] + ] + ] + ] +} diff --git a/Tests/GISToolsTests/TestData/BooleanDisjoint/Point1.geojson b/Tests/GISToolsTests/TestData/BooleanDisjoint/Point1.geojson new file mode 100644 index 0000000..9178ba4 --- /dev/null +++ b/Tests/GISToolsTests/TestData/BooleanDisjoint/Point1.geojson @@ -0,0 +1,4 @@ +{ + "type": "Point", + "coordinates": [0, 0] +} diff --git a/Tests/GISToolsTests/TestData/BooleanDisjoint/Point2.geojson b/Tests/GISToolsTests/TestData/BooleanDisjoint/Point2.geojson new file mode 100644 index 0000000..265e199 --- /dev/null +++ b/Tests/GISToolsTests/TestData/BooleanDisjoint/Point2.geojson @@ -0,0 +1,4 @@ +{ + "type": "Point", + "coordinates": [0, 1] +} diff --git a/Tests/GISToolsTests/TestData/BooleanDisjoint/Point3.geojson b/Tests/GISToolsTests/TestData/BooleanDisjoint/Point3.geojson new file mode 100644 index 0000000..4e76297 --- /dev/null +++ b/Tests/GISToolsTests/TestData/BooleanDisjoint/Point3.geojson @@ -0,0 +1,4 @@ +{ + "type": "Point", + "coordinates": [1, 1] +} diff --git a/Tests/GISToolsTests/TestData/BooleanDisjoint/Point4.geojson b/Tests/GISToolsTests/TestData/BooleanDisjoint/Point4.geojson new file mode 100644 index 0000000..e29a504 --- /dev/null +++ b/Tests/GISToolsTests/TestData/BooleanDisjoint/Point4.geojson @@ -0,0 +1,4 @@ +{ + "type": "Point", + "coordinates": [1, 1.5] +} diff --git a/Tests/GISToolsTests/TestData/BooleanDisjoint/Polygon1.geojson b/Tests/GISToolsTests/TestData/BooleanDisjoint/Polygon1.geojson new file mode 100644 index 0000000..81c7857 --- /dev/null +++ b/Tests/GISToolsTests/TestData/BooleanDisjoint/Polygon1.geojson @@ -0,0 +1,12 @@ +{ + "type": "Polygon", + "coordinates": [ + [ + [-1, 2], + [3, 2], + [3, 3], + [-1, 3], + [-1, 2] + ] + ] +} diff --git a/Tests/GISToolsTests/TestData/BooleanDisjoint/Polygon2.geojson b/Tests/GISToolsTests/TestData/BooleanDisjoint/Polygon2.geojson new file mode 100644 index 0000000..5d895d6 --- /dev/null +++ b/Tests/GISToolsTests/TestData/BooleanDisjoint/Polygon2.geojson @@ -0,0 +1,12 @@ +{ + "type": "Polygon", + "coordinates": [ + [ + [116.98242187499999, -24.647017162630352], + [122.87109375, -24.647017162630352], + [122.87109375, -20.34462694382967], + [116.98242187499999, -20.34462694382967], + [116.98242187499999, -24.647017162630352] + ] + ] +} diff --git a/Tests/GISToolsTests/TestData/BooleanDisjoint/Polygon3.geojson b/Tests/GISToolsTests/TestData/BooleanDisjoint/Polygon3.geojson new file mode 100644 index 0000000..fecf9d2 --- /dev/null +++ b/Tests/GISToolsTests/TestData/BooleanDisjoint/Polygon3.geojson @@ -0,0 +1,12 @@ +{ + "type": "Polygon", + "coordinates": [ + [ + [119.20166015624999, -22.776181505086495], + [125.09033203124999, -22.776181505086495], + [125.09033203124999, -18.417078658661257], + [119.20166015624999, -18.417078658661257], + [119.20166015624999, -22.776181505086495] + ] + ] +}