Skip to content

Commit c3f4594

Browse files
committed
✨ Make Feature generic over Geometry too
1 parent 5c90194 commit c3f4594

16 files changed

+121
-78
lines changed

Sources/GeoJSON/GeoJSON+Codable.swift

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -391,7 +391,7 @@ extension Feature {
391391
))
392392
}
393393

394-
let geometry = try container.decodeIfPresent(AnyGeometry.self, forKey: .geometry)
394+
let geometry = try container.decodeIfPresent(Geometry.self, forKey: .geometry)
395395
let properties = try container.decode(Properties.self, forKey: .properties)
396396

397397
self.init(geometry: geometry, properties: properties)
@@ -428,7 +428,10 @@ extension FeatureCollection {
428428
))
429429
}
430430

431-
let features = try container.decodeIfPresent([Feature<Properties>].self, forKey: .features) ?? []
431+
let features = try container.decodeIfPresent(
432+
[Feature<Geometry, Properties>].self,
433+
forKey: .features
434+
) ?? []
432435

433436
self.init(features: features)
434437
}

Sources/GeoJSON/GeoJSON.docc/Documentation.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,12 @@
1515
### Objects
1616

1717
- ``Object``
18+
- ``CodableObject``
1819
- <doc:Geometries>
1920
- ``Feature``
21+
- ``AnyFeature``
2022
- ``FeatureCollection``
23+
- ``AnyFeatureCollection``
2124

2225
### Bounding Boxes
2326

Sources/GeoJSON/GeoJSON.docc/Geometries.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
### Base
66

77
- ``Geometry``
8+
- ``CodableGeometry``
89
- ``AnyGeometry``
910

1011
### Introduced concepts

Sources/GeoJSON/Geometries/GeometryCollection.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
//
88

99
/// A [GeoJSON GeometryCollection](https://datatracker.ietf.org/doc/html/rfc7946#section-3.1.8).
10-
public struct GeometryCollection: Geometry {
10+
public struct GeometryCollection: CodableGeometry {
1111

1212
public static var geometryType: GeoJSON.`Type`.Geometry { .geometryCollection }
1313

Sources/GeoJSON/Geometries/LineString.swift

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,17 @@ public protocol LineString: SingleGeometry {
1616

1717
}
1818

19+
extension LineString {
20+
21+
public static var geometryType: GeoJSON.`Type`.Geometry { .lineString }
22+
23+
}
24+
1925
/// A ``LineString`` with ``Point2D``s.
2026
public struct LineString2D: LineString {
2127

2228
public typealias Position = Position2D
2329

24-
public static var geometryType: GeoJSON.`Type`.Geometry { .lineString }
25-
2630
public var coordinates: Coordinates
2731

2832
public var asAnyGeometry: AnyGeometry { .lineString2D(self) }
@@ -46,8 +50,6 @@ public struct LineString3D: LineString {
4650

4751
public typealias Position = Position3D
4852

49-
public static var geometryType: GeoJSON.`Type`.Geometry { .lineString }
50-
5153
public var coordinates: Coordinates
5254

5355
public var asAnyGeometry: AnyGeometry { .lineString3D(self) }

Sources/GeoJSON/Geometries/MultiLineString.swift

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,17 @@ public protocol MultiLineString: SingleGeometry {
1616

1717
}
1818

19+
extension MultiLineString {
20+
21+
public static var geometryType: GeoJSON.`Type`.Geometry { .multiLineString }
22+
23+
}
24+
1925
/// A ``MultiLineString`` with ``Point2D``s.
2026
public struct MultiLineString2D: MultiLineString {
2127

2228
public typealias LineString = LineString2D
2329

24-
public static var geometryType: GeoJSON.`Type`.Geometry { .multiLineString }
25-
2630
public var coordinates: Coordinates
2731

2832
public var asAnyGeometry: AnyGeometry { .multiLineString2D(self) }
@@ -52,8 +56,6 @@ public struct MultiLineString3D: MultiLineString {
5256

5357
public typealias LineString = LineString3D
5458

55-
public static var geometryType: GeoJSON.`Type`.Geometry { .multiLineString }
56-
5759
public var coordinates: Coordinates
5860

5961
public var asAnyGeometry: AnyGeometry { .multiLineString3D(self) }

Sources/GeoJSON/Geometries/MultiPoint.swift

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,17 @@ public protocol MultiPoint: SingleGeometry {
1414

1515
}
1616

17+
extension MultiPoint {
18+
19+
public static var geometryType: GeoJSON.`Type`.Geometry { .multiPoint }
20+
21+
}
22+
1723
/// A ``MultiPoint`` with ``Point2D``s.
1824
public struct MultiPoint2D: MultiPoint {
1925

2026
public typealias Point = Point2D
2127

22-
public static var geometryType: GeoJSON.`Type`.Geometry { .multiPoint }
23-
2428
public var coordinates: Coordinates
2529

2630
public var asAnyGeometry: AnyGeometry { .multiPoint2D(self) }
@@ -36,8 +40,6 @@ public struct MultiPoint3D: MultiPoint {
3640

3741
public typealias Point = Point3D
3842

39-
public static var geometryType: GeoJSON.`Type`.Geometry { .multiPoint }
40-
4143
public var coordinates: Coordinates
4244

4345
public var asAnyGeometry: AnyGeometry { .multiPoint3D(self) }

Sources/GeoJSON/Geometries/MultiPolygon.swift

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,17 @@ public protocol MultiPolygon: SingleGeometry {
1414

1515
}
1616

17+
extension MultiPolygon {
18+
19+
public static var geometryType: GeoJSON.`Type`.Geometry { .multiPolygon }
20+
21+
}
22+
1723
/// A ``MultiPolygon`` with ``Point2D``s.
1824
public struct MultiPolygon2D: MultiPolygon {
1925

2026
public typealias Polygon = Polygon2D
2127

22-
public static var geometryType: GeoJSON.`Type`.Geometry { .multiPolygon }
23-
2428
public var coordinates: Coordinates
2529

2630
public var asAnyGeometry: AnyGeometry { .multiPolygon2D(self) }
@@ -36,8 +40,6 @@ public struct MultiPolygon3D: MultiPolygon {
3640

3741
public typealias Polygon = Polygon3D
3842

39-
public static var geometryType: GeoJSON.`Type`.Geometry { .multiPolygon }
40-
4143
public var coordinates: Coordinates
4244

4345
public var asAnyGeometry: AnyGeometry { .multiPolygon3D(self) }

Sources/GeoJSON/Geometries/Point.swift

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,17 @@ public protocol Point: SingleGeometry {
1414

1515
}
1616

17+
extension Point {
18+
19+
public static var geometryType: GeoJSON.`Type`.Geometry { .point }
20+
21+
}
22+
1723
/// A two-dimensional ``Point`` (with longitude and latitude).
1824
public struct Point2D: Point {
1925

2026
public typealias Position = Position2D
2127

22-
public static var geometryType: GeoJSON.`Type`.Geometry { .point }
23-
2428
public var coordinates: Coordinates
2529

2630
public var asAnyGeometry: AnyGeometry { .point2D(self) }
@@ -36,8 +40,6 @@ public struct Point3D: Point {
3640

3741
public typealias Position = Position3D
3842

39-
public static var geometryType: GeoJSON.`Type`.Geometry { .point }
40-
4143
public var coordinates: Coordinates
4244

4345
public var asAnyGeometry: AnyGeometry { .point3D(self) }

Sources/GeoJSON/Geometries/Polygon.swift

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@ public protocol Polygon: SingleGeometry {
1717

1818
}
1919

20+
extension Polygon {
21+
22+
public static var geometryType: GeoJSON.`Type`.Geometry { .polygon }
23+
24+
}
25+
2026
public struct LinearRingCoordinates<Point: GeoJSON.Point>: Boundable, Hashable, Codable {
2127

2228
public typealias RawValue = NonEmpty<NonEmpty<NonEmpty<NonEmpty<[Point.Coordinates]>>>>
@@ -61,8 +67,6 @@ public struct Polygon2D: Polygon {
6167

6268
public typealias Point = Point2D
6369

64-
public static var geometryType: GeoJSON.`Type`.Geometry { .polygon }
65-
6670
public var coordinates: Coordinates
6771

6872
public var asAnyGeometry: AnyGeometry { .polygon2D(self) }
@@ -78,8 +82,6 @@ public struct Polygon3D: Polygon {
7882

7983
public typealias Point = Point3D
8084

81-
public static var geometryType: GeoJSON.`Type`.Geometry { .polygon }
82-
8385
public var coordinates: Coordinates
8486

8587
public var asAnyGeometry: AnyGeometry { .polygon3D(self) }

Sources/GeoJSON/Objects/Feature.swift

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,23 @@
88

99
/// A [GeoJSON Feature](https://datatracker.ietf.org/doc/html/rfc7946#section-3.2).
1010
public struct Feature<
11-
// Geometry: GeoJSON.Geometry,
12-
// BoundingBox: GeoJSON.BoundingBox,
11+
Geometry: GeoJSON.Geometry & Codable,
1312
Properties: GeoJSON.FeatureProperties
14-
>: GeoJSON.Object {
13+
>: CodableObject {
1514

1615
public static var geoJSONType: GeoJSON.`Type` { .feature }
1716

18-
public var bbox: AnyBoundingBox? { geometry?.bbox }
17+
public var bbox: Geometry.BoundingBox? { geometry?.bbox }
1918

20-
public var geometry: AnyGeometry?
19+
public var geometry: Geometry?
2120
public var properties: Properties
2221

23-
public init(geometry: AnyGeometry?, properties: Properties) {
22+
public init(geometry: Geometry?, properties: Properties) {
2423
self.geometry = geometry
2524
self.properties = properties
2625
}
2726

2827
}
28+
29+
/// A (half) type-erased ``Feature``.
30+
public typealias AnyFeature<Properties: GeoJSON.FeatureProperties> = Feature<AnyGeometry, Properties>

Sources/GeoJSON/Objects/FeatureCollection.swift

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,20 @@
88

99
/// A [GeoJSON FeatureCollection](https://datatracker.ietf.org/doc/html/rfc7946#section-3.3).
1010
public struct FeatureCollection<
11-
// BoundingBox: GeoJSON.BoundingBox,
11+
Geometry: GeoJSON.Geometry & Codable,
1212
Properties: GeoJSON.FeatureProperties
13-
>: GeoJSON.Object {
13+
>: CodableObject {
1414

1515
public static var geoJSONType: GeoJSON.`Type` { .featureCollection }
1616

17-
public var features: [Feature<Properties>]
17+
public var features: [Feature<Geometry, Properties>]
1818

1919
// FIXME: Fix bounding box
2020
public var bbox: AnyBoundingBox? { nil }
2121

2222
}
23+
24+
/// A (half) type-erased ``FeatureCollection``.
25+
public typealias AnyFeatureCollection<
26+
Properties: GeoJSON.FeatureProperties
27+
> = FeatureCollection<AnyGeometry, Properties>

Sources/GeoJSON/Objects/Geometry.swift

Lines changed: 45 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -11,25 +11,29 @@ import Turf
1111
/// A [GeoJSON Geometry](https://datatracker.ietf.org/doc/html/rfc7946#section-3.1).
1212
public protocol Geometry: GeoJSON.Object {
1313

14-
/// The GeoJSON type of this geometry.
15-
static var geometryType: GeoJSON.`Type`.Geometry { get }
16-
1714
var bbox: BoundingBox? { get }
1815

1916
/// This geometry, but type-erased.
2017
var asAnyGeometry: AnyGeometry { get }
2118

2219
}
2320

24-
extension Geometry {
21+
public protocol CodableGeometry: Geometry, CodableObject {
22+
23+
/// The GeoJSON type of this geometry.
24+
static var geometryType: GeoJSON.`Type`.Geometry { get }
25+
26+
}
27+
28+
extension CodableGeometry {
2529

2630
public static var geoJSONType: GeoJSON.`Type` { .geometry(Self.geometryType) }
2731

2832
}
2933

3034
/// A single [GeoJSON Geometry](https://datatracker.ietf.org/doc/html/rfc7946#section-3.1)
3135
/// (not a [GeometryCollection](https://datatracker.ietf.org/doc/html/rfc7946#section-3.1.8)).
32-
public protocol SingleGeometry: Geometry {
36+
public protocol SingleGeometry: CodableGeometry {
3337

3438
associatedtype Coordinates: Boundable & Hashable & Codable
3539
associatedtype BoundingBox = Coordinates.BoundingBox
@@ -47,7 +51,7 @@ extension SingleGeometry {
4751
}
4852

4953
/// A type-erased ``Geometry``.
50-
public enum AnyGeometry: Hashable, Codable {
54+
public enum AnyGeometry: Geometry, Hashable, Codable {
5155

5256
case geometryCollection(GeometryCollection)
5357

@@ -65,37 +69,46 @@ public enum AnyGeometry: Hashable, Codable {
6569
case polygon3D(Polygon3D)
6670
case multiPolygon3D(MultiPolygon3D)
6771

72+
// public var geometryType: GeoJSON.`Type`.Geometry {
73+
// switch self {
74+
// case .geometryCollection(let geo): return geo.geometryType
75+
//
76+
// case .point2D(let geo): return geo.geometryType
77+
// case .multiPoint2D(let geo): return geo.geometryType
78+
// case .lineString2D(let geo): return geo.geometryType
79+
// case .multiLineString2D(let geo): return geo.geometryType
80+
// case .polygon2D(let geo): return geo.geometryType
81+
// case .multiPolygon2D(let geo): return geo.geometryType
82+
//
83+
// case .point3D(let geo): return geo.geometryType
84+
// case .multiPoint3D(let geo): return geo.geometryType
85+
// case .lineString3D(let geo): return geo.geometryType
86+
// case .multiLineString3D(let geo): return geo.geometryType
87+
// case .polygon3D(let geo): return geo.geometryType
88+
// case .multiPolygon3D(let geo): return geo.geometryType
89+
// }
90+
// }
91+
6892
public var bbox: AnyBoundingBox? {
6993
switch self {
70-
case .geometryCollection(let geometryCollection):
71-
return geometryCollection.bbox
94+
case .geometryCollection(let geo): return geo.bbox
7295

73-
case .point2D(let point2D):
74-
return point2D.bbox?.asAny
75-
case .multiPoint2D(let multiPoint2D):
76-
return multiPoint2D.bbox?.asAny
77-
case .lineString2D(let lineString2D):
78-
return lineString2D.bbox?.asAny
79-
case .multiLineString2D(let multiLineString2D):
80-
return multiLineString2D.bbox?.asAny
81-
case .polygon2D(let polygon2D):
82-
return polygon2D.bbox?.asAny
83-
case .multiPolygon2D(let multiPolygon2D):
84-
return multiPolygon2D.bbox?.asAny
96+
case .point2D(let geo): return geo.bbox?.asAny
97+
case .multiPoint2D(let geo): return geo.bbox?.asAny
98+
case .lineString2D(let geo): return geo.bbox?.asAny
99+
case .multiLineString2D(let geo): return geo.bbox?.asAny
100+
case .polygon2D(let geo): return geo.bbox?.asAny
101+
case .multiPolygon2D(let geo): return geo.bbox?.asAny
85102

86-
case .point3D(let point3D):
87-
return point3D.bbox?.asAny
88-
case .multiPoint3D(let multiPoint3D):
89-
return multiPoint3D.bbox?.asAny
90-
case .lineString3D(let lineString3D):
91-
return lineString3D.bbox?.asAny
92-
case .multiLineString3D(let multiLineString3D):
93-
return multiLineString3D.bbox?.asAny
94-
case .polygon3D(let polygon3D):
95-
return polygon3D.bbox?.asAny
96-
case .multiPolygon3D(let multiPolygon3D):
97-
return multiPolygon3D.bbox?.asAny
103+
case .point3D(let geo): return geo.bbox?.asAny
104+
case .multiPoint3D(let geo): return geo.bbox?.asAny
105+
case .lineString3D(let geo): return geo.bbox?.asAny
106+
case .multiLineString3D(let geo): return geo.bbox?.asAny
107+
case .polygon3D(let geo): return geo.bbox?.asAny
108+
case .multiPolygon3D(let geo): return geo.bbox?.asAny
98109
}
99110
}
100111

112+
public var asAnyGeometry: AnyGeometry { self }
113+
101114
}

0 commit comments

Comments
 (0)