Skip to content

Commit

Permalink
✨ Make Feature generic over Geometry too
Browse files Browse the repository at this point in the history
  • Loading branch information
RemiBardon committed Feb 9, 2022
1 parent 5c90194 commit c3f4594
Show file tree
Hide file tree
Showing 16 changed files with 121 additions and 78 deletions.
7 changes: 5 additions & 2 deletions Sources/GeoJSON/GeoJSON+Codable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,7 @@ extension Feature {
))
}

let geometry = try container.decodeIfPresent(AnyGeometry.self, forKey: .geometry)
let geometry = try container.decodeIfPresent(Geometry.self, forKey: .geometry)
let properties = try container.decode(Properties.self, forKey: .properties)

self.init(geometry: geometry, properties: properties)
Expand Down Expand Up @@ -428,7 +428,10 @@ extension FeatureCollection {
))
}

let features = try container.decodeIfPresent([Feature<Properties>].self, forKey: .features) ?? []
let features = try container.decodeIfPresent(
[Feature<Geometry, Properties>].self,
forKey: .features
) ?? []

self.init(features: features)
}
Expand Down
3 changes: 3 additions & 0 deletions Sources/GeoJSON/GeoJSON.docc/Documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,12 @@
### Objects

- ``Object``
- ``CodableObject``
- <doc:Geometries>
- ``Feature``
- ``AnyFeature``
- ``FeatureCollection``
- ``AnyFeatureCollection``

### Bounding Boxes

Expand Down
1 change: 1 addition & 0 deletions Sources/GeoJSON/GeoJSON.docc/Geometries.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
### Base

- ``Geometry``
- ``CodableGeometry``
- ``AnyGeometry``

### Introduced concepts
Expand Down
2 changes: 1 addition & 1 deletion Sources/GeoJSON/Geometries/GeometryCollection.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
//

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

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

Expand Down
10 changes: 6 additions & 4 deletions Sources/GeoJSON/Geometries/LineString.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,17 @@ public protocol LineString: SingleGeometry {

}

extension LineString {

public static var geometryType: GeoJSON.`Type`.Geometry { .lineString }

}

/// A ``LineString`` with ``Point2D``s.
public struct LineString2D: LineString {

public typealias Position = Position2D

public static var geometryType: GeoJSON.`Type`.Geometry { .lineString }

public var coordinates: Coordinates

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

public typealias Position = Position3D

public static var geometryType: GeoJSON.`Type`.Geometry { .lineString }

public var coordinates: Coordinates

public var asAnyGeometry: AnyGeometry { .lineString3D(self) }
Expand Down
10 changes: 6 additions & 4 deletions Sources/GeoJSON/Geometries/MultiLineString.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,17 @@ public protocol MultiLineString: SingleGeometry {

}

extension MultiLineString {

public static var geometryType: GeoJSON.`Type`.Geometry { .multiLineString }

}

/// A ``MultiLineString`` with ``Point2D``s.
public struct MultiLineString2D: MultiLineString {

public typealias LineString = LineString2D

public static var geometryType: GeoJSON.`Type`.Geometry { .multiLineString }

public var coordinates: Coordinates

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

public typealias LineString = LineString3D

public static var geometryType: GeoJSON.`Type`.Geometry { .multiLineString }

public var coordinates: Coordinates

public var asAnyGeometry: AnyGeometry { .multiLineString3D(self) }
Expand Down
10 changes: 6 additions & 4 deletions Sources/GeoJSON/Geometries/MultiPoint.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,17 @@ public protocol MultiPoint: SingleGeometry {

}

extension MultiPoint {

public static var geometryType: GeoJSON.`Type`.Geometry { .multiPoint }

}

/// A ``MultiPoint`` with ``Point2D``s.
public struct MultiPoint2D: MultiPoint {

public typealias Point = Point2D

public static var geometryType: GeoJSON.`Type`.Geometry { .multiPoint }

public var coordinates: Coordinates

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

public typealias Point = Point3D

public static var geometryType: GeoJSON.`Type`.Geometry { .multiPoint }

public var coordinates: Coordinates

public var asAnyGeometry: AnyGeometry { .multiPoint3D(self) }
Expand Down
10 changes: 6 additions & 4 deletions Sources/GeoJSON/Geometries/MultiPolygon.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,17 @@ public protocol MultiPolygon: SingleGeometry {

}

extension MultiPolygon {

public static var geometryType: GeoJSON.`Type`.Geometry { .multiPolygon }

}

/// A ``MultiPolygon`` with ``Point2D``s.
public struct MultiPolygon2D: MultiPolygon {

public typealias Polygon = Polygon2D

public static var geometryType: GeoJSON.`Type`.Geometry { .multiPolygon }

public var coordinates: Coordinates

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

public typealias Polygon = Polygon3D

public static var geometryType: GeoJSON.`Type`.Geometry { .multiPolygon }

public var coordinates: Coordinates

public var asAnyGeometry: AnyGeometry { .multiPolygon3D(self) }
Expand Down
10 changes: 6 additions & 4 deletions Sources/GeoJSON/Geometries/Point.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,17 @@ public protocol Point: SingleGeometry {

}

extension Point {

public static var geometryType: GeoJSON.`Type`.Geometry { .point }

}

/// A two-dimensional ``Point`` (with longitude and latitude).
public struct Point2D: Point {

public typealias Position = Position2D

public static var geometryType: GeoJSON.`Type`.Geometry { .point }

public var coordinates: Coordinates

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

public typealias Position = Position3D

public static var geometryType: GeoJSON.`Type`.Geometry { .point }

public var coordinates: Coordinates

public var asAnyGeometry: AnyGeometry { .point3D(self) }
Expand Down
10 changes: 6 additions & 4 deletions Sources/GeoJSON/Geometries/Polygon.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ public protocol Polygon: SingleGeometry {

}

extension Polygon {

public static var geometryType: GeoJSON.`Type`.Geometry { .polygon }

}

public struct LinearRingCoordinates<Point: GeoJSON.Point>: Boundable, Hashable, Codable {

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

public typealias Point = Point2D

public static var geometryType: GeoJSON.`Type`.Geometry { .polygon }

public var coordinates: Coordinates

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

public typealias Point = Point3D

public static var geometryType: GeoJSON.`Type`.Geometry { .polygon }

public var coordinates: Coordinates

public var asAnyGeometry: AnyGeometry { .polygon3D(self) }
Expand Down
14 changes: 8 additions & 6 deletions Sources/GeoJSON/Objects/Feature.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,23 @@

/// A [GeoJSON Feature](https://datatracker.ietf.org/doc/html/rfc7946#section-3.2).
public struct Feature<
// Geometry: GeoJSON.Geometry,
// BoundingBox: GeoJSON.BoundingBox,
Geometry: GeoJSON.Geometry & Codable,
Properties: GeoJSON.FeatureProperties
>: GeoJSON.Object {
>: CodableObject {

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

public var bbox: AnyBoundingBox? { geometry?.bbox }
public var bbox: Geometry.BoundingBox? { geometry?.bbox }

public var geometry: AnyGeometry?
public var geometry: Geometry?
public var properties: Properties

public init(geometry: AnyGeometry?, properties: Properties) {
public init(geometry: Geometry?, properties: Properties) {
self.geometry = geometry
self.properties = properties
}

}

/// A (half) type-erased ``Feature``.
public typealias AnyFeature<Properties: GeoJSON.FeatureProperties> = Feature<AnyGeometry, Properties>
11 changes: 8 additions & 3 deletions Sources/GeoJSON/Objects/FeatureCollection.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,20 @@

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

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

public var features: [Feature<Properties>]
public var features: [Feature<Geometry, Properties>]

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

}

/// A (half) type-erased ``FeatureCollection``.
public typealias AnyFeatureCollection<
Properties: GeoJSON.FeatureProperties
> = FeatureCollection<AnyGeometry, Properties>
77 changes: 45 additions & 32 deletions Sources/GeoJSON/Objects/Geometry.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,29 @@ import Turf
/// A [GeoJSON Geometry](https://datatracker.ietf.org/doc/html/rfc7946#section-3.1).
public protocol Geometry: GeoJSON.Object {

/// The GeoJSON type of this geometry.
static var geometryType: GeoJSON.`Type`.Geometry { get }

var bbox: BoundingBox? { get }

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

}

extension Geometry {
public protocol CodableGeometry: Geometry, CodableObject {

/// The GeoJSON type of this geometry.
static var geometryType: GeoJSON.`Type`.Geometry { get }

}

extension CodableGeometry {

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

}

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

associatedtype Coordinates: Boundable & Hashable & Codable
associatedtype BoundingBox = Coordinates.BoundingBox
Expand All @@ -47,7 +51,7 @@ extension SingleGeometry {
}

/// A type-erased ``Geometry``.
public enum AnyGeometry: Hashable, Codable {
public enum AnyGeometry: Geometry, Hashable, Codable {

case geometryCollection(GeometryCollection)

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

// public var geometryType: GeoJSON.`Type`.Geometry {
// switch self {
// case .geometryCollection(let geo): return geo.geometryType
//
// case .point2D(let geo): return geo.geometryType
// case .multiPoint2D(let geo): return geo.geometryType
// case .lineString2D(let geo): return geo.geometryType
// case .multiLineString2D(let geo): return geo.geometryType
// case .polygon2D(let geo): return geo.geometryType
// case .multiPolygon2D(let geo): return geo.geometryType
//
// case .point3D(let geo): return geo.geometryType
// case .multiPoint3D(let geo): return geo.geometryType
// case .lineString3D(let geo): return geo.geometryType
// case .multiLineString3D(let geo): return geo.geometryType
// case .polygon3D(let geo): return geo.geometryType
// case .multiPolygon3D(let geo): return geo.geometryType
// }
// }

public var bbox: AnyBoundingBox? {
switch self {
case .geometryCollection(let geometryCollection):
return geometryCollection.bbox
case .geometryCollection(let geo): return geo.bbox

case .point2D(let point2D):
return point2D.bbox?.asAny
case .multiPoint2D(let multiPoint2D):
return multiPoint2D.bbox?.asAny
case .lineString2D(let lineString2D):
return lineString2D.bbox?.asAny
case .multiLineString2D(let multiLineString2D):
return multiLineString2D.bbox?.asAny
case .polygon2D(let polygon2D):
return polygon2D.bbox?.asAny
case .multiPolygon2D(let multiPolygon2D):
return multiPolygon2D.bbox?.asAny
case .point2D(let geo): return geo.bbox?.asAny
case .multiPoint2D(let geo): return geo.bbox?.asAny
case .lineString2D(let geo): return geo.bbox?.asAny
case .multiLineString2D(let geo): return geo.bbox?.asAny
case .polygon2D(let geo): return geo.bbox?.asAny
case .multiPolygon2D(let geo): return geo.bbox?.asAny

case .point3D(let point3D):
return point3D.bbox?.asAny
case .multiPoint3D(let multiPoint3D):
return multiPoint3D.bbox?.asAny
case .lineString3D(let lineString3D):
return lineString3D.bbox?.asAny
case .multiLineString3D(let multiLineString3D):
return multiLineString3D.bbox?.asAny
case .polygon3D(let polygon3D):
return polygon3D.bbox?.asAny
case .multiPolygon3D(let multiPolygon3D):
return multiPolygon3D.bbox?.asAny
case .point3D(let geo): return geo.bbox?.asAny
case .multiPoint3D(let geo): return geo.bbox?.asAny
case .lineString3D(let geo): return geo.bbox?.asAny
case .multiLineString3D(let geo): return geo.bbox?.asAny
case .polygon3D(let geo): return geo.bbox?.asAny
case .multiPolygon3D(let geo): return geo.bbox?.asAny
}
}

public var asAnyGeometry: AnyGeometry { self }

}
Loading

0 comments on commit c3f4594

Please sign in to comment.