diff --git a/Sources/GeoJSON/GeoJSON+Codable.swift b/Sources/GeoJSON/GeoJSON+Codable.swift index 4a79b1d..e388457 100644 --- a/Sources/GeoJSON/GeoJSON+Codable.swift +++ b/Sources/GeoJSON/GeoJSON+Codable.swift @@ -145,7 +145,7 @@ extension LinearRingCoordinates { fileprivate enum SingleGeometryCodingKeys: String, CodingKey { case geoJSONType = "type" - case coordinates + case coordinates, bbox } extension SingleGeometry { @@ -171,6 +171,7 @@ extension SingleGeometry { try container.encode(Self.geoJSONType, forKey: .geoJSONType) try container.encode(self.coordinates, forKey: .coordinates) + try container.encode(self.bbox, forKey: .bbox) } } diff --git a/Sources/GeoJSON/Helpers/GeoJSON+Boundable.swift b/Sources/GeoJSON/Helpers/GeoJSON+Boundable.swift index 5f24725..3cc1e05 100644 --- a/Sources/GeoJSON/Helpers/GeoJSON+Boundable.swift +++ b/Sources/GeoJSON/Helpers/GeoJSON+Boundable.swift @@ -12,7 +12,7 @@ import Turf extension NonEmpty: Boundable where Collection: Hashable, Element: Boundable { public var _bbox: Element.BoundingBox { - self.reduce(.zero, { $0.union($1.bbox) }) + self.reduce(nil, { $0.union($1.bbox) }) ?? .zero } } diff --git a/Sources/GeoModels/BoundingBox.swift b/Sources/GeoModels/BoundingBox.swift index c4b815d..7d51e48 100644 --- a/Sources/GeoModels/BoundingBox.swift +++ b/Sources/GeoModels/BoundingBox.swift @@ -13,3 +13,11 @@ public protocol BoundingBox: Hashable { func union(_ other: Self) -> Self } + +extension Optional where Wrapped: BoundingBox { + + public func union(_ bbox: Wrapped) -> Wrapped { + self?.union(bbox) ?? bbox + } + +} diff --git a/Sources/Turf/Boundable.swift b/Sources/Turf/Boundable.swift index 3bb48cc..1e8343d 100644 --- a/Sources/Turf/Boundable.swift +++ b/Sources/Turf/Boundable.swift @@ -76,7 +76,7 @@ extension BoundingBox3D: Boundable { //extension Collection: Boundable where Element: Boundable { // // public var _bbox: Element.BoundingBox { -// self.reduce(.zero, { $0.union($1.bbox) }) +// self.reduce(nil, { $0.union($1.bbox) }) ?? .zero // } // //} @@ -84,7 +84,7 @@ extension BoundingBox3D: Boundable { extension Array: Boundable where Element: Boundable { public var _bbox: Element.BoundingBox { - self.reduce(.zero, { $0.union($1.bbox) }) + self.reduce(nil, { $0.union($1.bbox) }) ?? .zero } } @@ -92,7 +92,7 @@ extension Array: Boundable where Element: Boundable { extension Set: Boundable where Element: Boundable { public var _bbox: Element.BoundingBox { - self.reduce(.zero, { $0.union($1.bbox) }) + self.reduce(nil, { $0.union($1.bbox) }) ?? .zero } } diff --git a/Sources/Turf/Turf.swift b/Sources/Turf/Turf.swift index 628bdd2..68d10af 100644 --- a/Sources/Turf/Turf.swift +++ b/Sources/Turf/Turf.swift @@ -68,7 +68,7 @@ public func bbox(for coords: C) -> BoundingBox3D? where C.Element public func bbox(for boundables: C) -> T.BoundingBox? where C.Element == T { guard !boundables.isEmpty else { return nil } - return boundables.reduce(.zero, { $0.union($1.bbox) }) + return boundables.reduce(nil, { $0.union($1.bbox) }) ?? .zero } /// Returns the absolute center of a polygon. diff --git a/Tests/GeoJSONTests/GeoJSON+EncodableTests.swift b/Tests/GeoJSONTests/GeoJSON+EncodableTests.swift index 349ca49..66522eb 100644 --- a/Tests/GeoJSONTests/GeoJSON+EncodableTests.swift +++ b/Tests/GeoJSONTests/GeoJSON+EncodableTests.swift @@ -26,7 +26,8 @@ final class GeoJSONEncodableTests: XCTestCase { XCTAssertEqual(string, [ "{", "\"type\":\"Point\",", - "\"coordinates\":[-1.55366,47.21881]", + "\"coordinates\":[-1.55366,47.21881],", + "\"bbox\":[-1.55366,47.21881,-1.55366,47.21881]", "}", ].joined()) } @@ -41,7 +42,8 @@ final class GeoJSONEncodableTests: XCTestCase { "\"type\":\"MultiPoint\",", "\"coordinates\":[", "[-1.55366,47.21881]", - "]", + "],", + "\"bbox\":[-1.55366,47.21881,-1.55366,47.21881]", "}", ].joined()) } @@ -57,7 +59,8 @@ final class GeoJSONEncodableTests: XCTestCase { "\"coordinates\":[", "[-1.55366,47.21881],", "[2.3529,48.85719]", - "]", + "],", + "\"bbox\":[-1.55366,47.21881,2.3529,48.85719]", "}", ].joined()) } @@ -79,7 +82,8 @@ final class GeoJSONEncodableTests: XCTestCase { "[2.3529,48.85719],", "[5.36468,43.29868]", "]", - "]", + "],", + "\"bbox\":[-1.55366,43.29868,5.36468,48.85719]", "}", ].joined()) } @@ -102,7 +106,8 @@ final class GeoJSONEncodableTests: XCTestCase { "[2.3529,48.85719],", "[-1.55366,47.21881]", "]", - "]", + "],", + "\"bbox\":[-1.55366,43.29868,5.36468,48.85719]", "}", ].joined()) } @@ -133,7 +138,8 @@ final class GeoJSONEncodableTests: XCTestCase { "[-1.55366,47.21881]", "]", "]", - "]", + "],", + "\"bbox\":[-1.55366,43.29868,5.36468,48.85719]", "}", ].joined()) } @@ -155,7 +161,8 @@ final class GeoJSONEncodableTests: XCTestCase { "\"type\":\"Feature\",", "\"geometry\":{", "\"type\":\"Point\",", - "\"coordinates\":[-1.55366,47.21881]", + "\"coordinates\":[-1.55366,47.21881],", + "\"bbox\":[-1.55366,47.21881,-1.55366,47.21881]", "},", "\"bbox\":[-1.55366,47.21881,-1.55366,47.21881]", "}", @@ -183,7 +190,8 @@ final class GeoJSONEncodableTests: XCTestCase { "\"type\":\"Feature\",", "\"geometry\":{", "\"type\":\"Point\",", - "\"coordinates\":[-1.55366,47.21881]", + "\"coordinates\":[-1.55366,47.21881],", + "\"bbox\":[-1.55366,47.21881,-1.55366,47.21881]", "},", "\"bbox\":[-1.55366,47.21881,-1.55366,47.21881]", "}",