Skip to content

Commit 3b93496

Browse files
committed
✨ Add altitude
1 parent 0493aad commit 3b93496

File tree

4 files changed

+272
-0
lines changed

4 files changed

+272
-0
lines changed

Sources/GeoModels/1D/Altitude.swift

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
//
2+
// Altitude.swift
3+
// SwiftGeo
4+
//
5+
// Created by Rémi Bardon on 08/02/2022.
6+
// Copyright © 2022 Rémi Bardon. All rights reserved.
7+
//
8+
9+
public struct Altitude: Coordinate {
10+
11+
public var meters: Double
12+
13+
public init(meters: Double) {
14+
self.meters = meters
15+
}
16+
17+
}
18+
19+
extension Altitude {
20+
21+
public var value: Double {
22+
get { meters }
23+
set { meters = newValue }
24+
}
25+
26+
public init(value: Double) {
27+
self.init(meters: value)
28+
}
29+
30+
public static func random() -> Self {
31+
return Self.random(in: -100...10_000)
32+
}
33+
34+
}
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
//
2+
// BoundingBox3D.swift
3+
// SwiftGeo
4+
//
5+
// Created by Rémi Bardon on 08/02/2022.
6+
// Copyright © 2022 Rémi Bardon. All rights reserved.
7+
//
8+
9+
public struct BoundingBox3D: Hashable {
10+
11+
public var twoDimensions: BoundingBox2D
12+
public var lowAltitude: Altitude
13+
public var zHeight: Altitude
14+
15+
public var highAltitude: Altitude {
16+
lowAltitude + zHeight
17+
}
18+
public var centerAltitude: Altitude {
19+
lowAltitude + (zHeight / 2.0)
20+
}
21+
22+
public var southWestLow: Coordinate3D {
23+
Coordinate3D(twoDimensions.southWest, altitude: lowAltitude)
24+
}
25+
public var northEastHigh: Coordinate3D {
26+
Coordinate3D(twoDimensions.northEast, altitude: highAltitude)
27+
}
28+
public var center: Coordinate3D {
29+
Coordinate3D(twoDimensions.center, altitude: centerAltitude)
30+
}
31+
32+
public var crosses180thMeridian: Bool {
33+
twoDimensions.crosses180thMeridian
34+
}
35+
36+
public init(_ boundingBox2d: BoundingBox2D, lowAltitude: Altitude, zHeight: Altitude) {
37+
self.twoDimensions = boundingBox2d
38+
self.lowAltitude = lowAltitude
39+
self.zHeight = zHeight
40+
}
41+
42+
public init(
43+
southWestLow: Coordinate3D,
44+
width: Longitude,
45+
height: Latitude,
46+
zHeight: Altitude
47+
) {
48+
self.init(
49+
BoundingBox2D(southWest: southWestLow.twoDimensions, width: width, height: height),
50+
lowAltitude: southWestLow.altitude,
51+
zHeight: zHeight
52+
)
53+
}
54+
55+
public init(
56+
southWestLow: Coordinate3D,
57+
northEastHigh: Coordinate3D
58+
) {
59+
self.init(
60+
southWestLow: southWestLow,
61+
width: northEastHigh.longitude - southWestLow.longitude,
62+
height: northEastHigh.latitude - southWestLow.latitude,
63+
zHeight: northEastHigh.altitude - southWestLow.altitude
64+
)
65+
}
66+
67+
public func offsetBy(
68+
dLat: Latitude = .zero,
69+
dLong: Longitude = .zero,
70+
dAlt: Altitude = .zero
71+
) -> BoundingBox3D {
72+
Self.init(
73+
twoDimensions.offsetBy(dLat: dLat, dLong: dLong),
74+
lowAltitude: lowAltitude + dAlt,
75+
zHeight: zHeight
76+
)
77+
}
78+
public func offsetBy(
79+
dx: Coordinate3D.X = .zero,
80+
dy: Coordinate3D.Y = .zero,
81+
dz: Coordinate3D.Z = .zero
82+
) -> BoundingBox3D {
83+
Self.init(
84+
twoDimensions.offsetBy(dx: dx, dy: dy),
85+
lowAltitude: lowAltitude + dz,
86+
zHeight: zHeight
87+
)
88+
}
89+
90+
}
91+
92+
extension BoundingBox3D: BoundingBox {
93+
94+
public static var zero: BoundingBox3D {
95+
BoundingBox3D(.zero, lowAltitude: .zero, zHeight: .zero)
96+
}
97+
98+
/// The union of bounding boxes gives a new bounding box that encloses the given two.
99+
public func union(_ other: BoundingBox3D) -> BoundingBox3D {
100+
BoundingBox3D(
101+
southWestLow: Coordinate3D(
102+
self.twoDimensions.union(other.twoDimensions).southWest,
103+
altitude: min(self.lowAltitude, other.lowAltitude)
104+
),
105+
northEastHigh: Coordinate3D(
106+
self.twoDimensions.union(other.twoDimensions).northEast,
107+
altitude: max(self.highAltitude, other.highAltitude)
108+
)
109+
)
110+
}
111+
112+
}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
//
2+
// Coordinate3D.swift
3+
// SwiftGeo
4+
//
5+
// Created by Rémi Bardon on 08/02/2022.
6+
// Copyright © 2022 Rémi Bardon. All rights reserved.
7+
//
8+
9+
public struct Coordinate3D: Hashable {
10+
11+
public typealias X = Longitude
12+
public typealias Y = Latitude
13+
public typealias Z = Altitude
14+
15+
public static var zero: Coordinate3D {
16+
Coordinate3D(latitude: .zero, longitude: .zero, altitude: .zero)
17+
}
18+
19+
public var latitude: Latitude
20+
public var longitude: Longitude
21+
public var altitude: Altitude
22+
23+
public var x: X { longitude }
24+
public var y: Y { latitude }
25+
public var z: Z { altitude }
26+
27+
public var withPositiveLongitude: Coordinate3D {
28+
Coordinate3D(latitude: latitude, longitude: longitude.positive, altitude: altitude)
29+
}
30+
31+
public var twoDimensions: Coordinate2D {
32+
Coordinate2D(latitude: latitude, longitude: longitude)
33+
}
34+
35+
public init(
36+
latitude: Latitude,
37+
longitude: Longitude,
38+
altitude: Altitude
39+
) {
40+
self.latitude = latitude
41+
self.longitude = longitude
42+
self.altitude = altitude
43+
}
44+
45+
public init(x: X, y: Y, z: Z) {
46+
self.init(latitude: y, longitude: x, altitude: z)
47+
}
48+
49+
public init(_ coordinate2d: Coordinate2D, altitude: Altitude = .zero) {
50+
self.init(latitude: coordinate2d.latitude, longitude: coordinate2d.longitude, altitude: altitude)
51+
}
52+
53+
public func offsetBy(dLat: Latitude = .zero, dLong: Longitude = .zero, dAlt: Altitude = .zero) -> Coordinate3D {
54+
Coordinate3D(
55+
latitude: latitude + dLat,
56+
longitude: longitude + dLong,
57+
altitude: altitude + dAlt
58+
)
59+
}
60+
public func offsetBy(dx: X = .zero, dy: Y = .zero, dz: Z = .zero) -> Coordinate3D {
61+
Coordinate3D(x: x + dx, y: y + dy, z: z + dz)
62+
}
63+
64+
}
65+
66+
// MARK: - Operators
67+
68+
extension Coordinate3D {
69+
70+
public static func + (lhs: Coordinate3D, rhs: Coordinate3D) -> Coordinate3D {
71+
return lhs.offsetBy(dLat: rhs.latitude, dLong: rhs.longitude, dAlt: rhs.altitude)
72+
}
73+
74+
public static func - (lhs: Coordinate3D, rhs: Coordinate3D) -> Coordinate3D {
75+
return lhs + (-rhs)
76+
}
77+
78+
public prefix static func - (value: Coordinate3D) -> Coordinate3D {
79+
return Coordinate3D(
80+
latitude: -value.latitude,
81+
longitude: -value.longitude,
82+
altitude: -value.altitude
83+
)
84+
}
85+
86+
}

Sources/GeoModels/3D/Line3D.swift

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
//
2+
// Line3D.swift
3+
// SwiftGeo
4+
//
5+
// Created by Rémi Bardon on 08/02/2022.
6+
// Copyright © 2022 Rémi Bardon. All rights reserved.
7+
//
8+
9+
public struct Line3D: Hashable {
10+
11+
public let start: Coordinate3D
12+
public let end: Coordinate3D
13+
14+
public var latitudeDelta: Latitude {
15+
twoDimensions.latitudeDelta
16+
}
17+
public var longitudeDelta: Longitude {
18+
twoDimensions.longitudeDelta
19+
}
20+
public var minimalLongitudeDelta: Longitude {
21+
twoDimensions.minimalLongitudeDelta
22+
}
23+
public var altitudeDelta: Altitude {
24+
end.altitude - start.altitude
25+
}
26+
27+
public var crosses180thMeridian: Bool {
28+
twoDimensions.crosses180thMeridian
29+
}
30+
31+
public var twoDimensions: Line2D {
32+
Line2D(start: start.twoDimensions, end: end.twoDimensions)
33+
}
34+
35+
public init(start: Coordinate3D, end: Coordinate3D) {
36+
self.start = start
37+
self.end = end
38+
}
39+
40+
}

0 commit comments

Comments
 (0)