8
8
9
9
import Foundation
10
10
11
- public protocol Conversion < OldCRS, NewCRS> {
12
- associatedtype OldCRS : CoordinateReferenceSystem
13
- associatedtype NewCRS : CoordinateReferenceSystem
11
+ public protocol Conversion < C1, C2> {
12
+ associatedtype C1 : Coordinates
13
+ associatedtype C2 : Coordinates
14
+ associatedtype EPSGRef : EPSGItem
14
15
15
- // static var name: String { get }
16
- // static var code: Int { get }
17
-
18
- static func apply< C1: Coordinates < OldCRS > , C2: Coordinates < NewCRS > > ( on coordinate: C1 ) -> C2
16
+ static func apply( on coordinate: C1 ) -> C2
19
17
}
20
18
21
19
public protocol ReversibleConversion : Conversion {
22
- static func unapply< C1 : Coordinates < OldCRS > , C2 : Coordinates < NewCRS > > ( from coordinate: C2 ) -> C1
20
+ static func unapply( from coordinate: C2 ) -> C1
23
21
}
24
22
25
23
// MARK: EPSG 9659 (Geographic 3D to 2D conversions)
26
24
27
- public enum EPSG9659 < OldCRS, NewCRS> : ReversibleConversion
28
- where OldCRS: GeographicCRS & ThreeDimensionalCRS ,
29
- NewCRS: GeographicCRS & TwoDimensionalCRS ,
30
- NewCRS. Datum. PrimeMeridian == OldCRS . Datum . PrimeMeridian
25
+ public enum EPSG9659Ref : EPSGItem {
26
+ public static let epsgName : String = " Geographic 3D to 2D conversions "
27
+ public static let epsgCode : Int = 9659
28
+ }
29
+
30
+ public enum EPSG9659 < C1, C2> : ReversibleConversion
31
+ where C1: ThreeDimensionalCoordinates ,
32
+ C1. CRS: GeographicCRS ,
33
+ C2: TwoDimensionalCoordinates ,
34
+ C2. CRS: GeographicCRS ,
35
+ C2. CRS. Datum. PrimeMeridian == C1 . CRS . Datum . PrimeMeridian
31
36
{
32
- // FIXME: Static stored properties not supported in generic types
33
- // static let name: String = "Geographic 3D to 2D conversions"
34
- // static let code: Int = 9659
37
+ public typealias EPSGRef = EPSG9659Ref
35
38
36
39
/// Geographic 3D to 2D conversion.
37
40
///
38
41
/// <https://drive.tiny.cloud/1/4m326iu12oa8re9cjiadxonharclteqb4mumfxj71zsttwkx/5e0ec79e-49fa-4e7a-acca-3d6f6c989877> section 4.1.4
39
- public static func apply<
40
- C1: Coordinates < OldCRS > ,
41
- C2: Coordinates < NewCRS >
42
- > ( on coordinate: C1 ) -> C2 {
43
- return C2 . init ( x: . init( coordinate. x) , y: . init( coordinate. y) )
42
+ public static func apply( on coordinate: C1 ) -> C2 {
43
+ return . init( x: . init( coordinate. x) , y: . init( coordinate. y) )
44
44
}
45
45
46
46
/// Geographic 2D to 3D conversion.
47
47
///
48
48
/// <https://drive.tiny.cloud/1/4m326iu12oa8re9cjiadxonharclteqb4mumfxj71zsttwkx/5e0ec79e-49fa-4e7a-acca-3d6f6c989877> section 4.1.1
49
- public static func unapply<
50
- C1: Coordinates < OldCRS > ,
51
- C2: Coordinates < NewCRS >
52
- > ( from coordinate: C2 ) -> C1 {
53
- return C1 . init ( x: . init( Double ( coordinate. x) ) , y: . init( coordinate. y) , z: . init( 0.0 ) )
49
+ public static func unapply( from coordinate: C2 ) -> C1 {
50
+ return . init( x: . init( Double ( coordinate. x) ) , y: . init( coordinate. y) , z: . init( 0.0 ) )
54
51
}
55
52
}
56
53
57
- public extension ThreeDimensionalCoordinate {
54
+ public extension ThreeDimensionalCoordinates where CRS : GeographicCRS {
58
55
func transformed< NewCRS, C: Coordinates < NewCRS > > ( to _: C . Type ) -> C
59
- where CRS : GeographicCRS ,
60
- NewCRS: GeographicCRS & TwoDimensionalCRS ,
56
+ where C : TwoDimensionalCoordinates ,
57
+ NewCRS: GeographicCRS ,
61
58
NewCRS. Datum. PrimeMeridian == CRS . Datum . PrimeMeridian
62
59
{
63
- EPSG9659 < CRS , NewCRS > . apply ( on: self )
60
+ EPSG9659 < Self , C > . apply ( on: self )
64
61
}
65
- func transformed< NewCRS> ( toCRS newCRS: NewCRS . Type ) -> Coordinate2DOf < NewCRS >
66
- where CRS: GeographicCRS ,
67
- NewCRS: GeographicCRS & TwoDimensionalCRS ,
62
+ func transformed< NewCRS> ( toCRS newCRS: NewCRS . Type ) -> Coordinates2D < NewCRS >
63
+ where NewCRS: GeographicCRS & TwoDimensionalCRS ,
68
64
NewCRS. Datum. PrimeMeridian == CRS . Datum . PrimeMeridian
69
65
{
70
- EPSG9659 < CRS , NewCRS > . apply ( on: self )
66
+ EPSG9659 < Self , Coordinates2D < NewCRS > > . apply ( on: self )
71
67
}
72
68
}
73
69
74
- public extension TwoDimensionalCoordinate {
70
+ public extension TwoDimensionalCoordinates where CRS : GeographicCRS {
75
71
func transformed< NewCRS, C: Coordinates < NewCRS > > ( to _: C . Type ) -> C
76
- where CRS : GeographicCRS ,
77
- NewCRS: GeographicCRS & ThreeDimensionalCRS ,
72
+ where C : ThreeDimensionalCoordinates ,
73
+ NewCRS: GeographicCRS ,
78
74
NewCRS. Datum. PrimeMeridian == CRS . Datum . PrimeMeridian
79
75
{
80
- EPSG9659 < NewCRS , CRS > . unapply ( from: self )
76
+ EPSG9659 < C , Self > . unapply ( from: self )
81
77
}
82
- func transformed< NewCRS> ( toCRS newCRS: NewCRS . Type ) -> Coordinate3DOf < NewCRS >
83
- where CRS: GeographicCRS ,
84
- NewCRS: GeographicCRS & ThreeDimensionalCRS ,
78
+ func transformed< NewCRS> ( toCRS newCRS: NewCRS . Type ) -> Coordinates3D < NewCRS >
79
+ where NewCRS: GeographicCRS & ThreeDimensionalCRS ,
85
80
NewCRS. Datum. PrimeMeridian == CRS . Datum . PrimeMeridian
86
81
{
87
- EPSG9659 < NewCRS , CRS > . unapply ( from: self )
82
+ EPSG9659 < Coordinates3D < NewCRS > , Self > . unapply ( from: self )
88
83
}
89
84
}
90
85
91
86
// MARK: EPSG 9602 (Geographic/geocentric conversions)
92
87
93
- public enum EPSG9602 < OldCRS, NewCRS> : ReversibleConversion
94
- where OldCRS: GeographicCRS & ThreeDimensionalCRS ,
95
- NewCRS: GeocentricCRS & ThreeDimensionalCRS ,
96
- NewCRS. Datum. PrimeMeridian == OldCRS . Datum . PrimeMeridian
88
+ public enum EPSG9602Ref : EPSGItem {
89
+ public static let epsgName : String = " Geographic/geocentric conversions "
90
+ public static let epsgCode : Int = 9602
91
+ }
92
+
93
+ public enum EPSG9602 < C1, C2> : ReversibleConversion
94
+ where C1: ThreeDimensionalCoordinates ,
95
+ C1. CRS: GeographicCRS ,
96
+ C2: ThreeDimensionalCoordinates ,
97
+ C2. CRS: GeocentricCRS ,
98
+ C2. CRS. Datum. PrimeMeridian == C1 . CRS . Datum . PrimeMeridian
97
99
{
98
- // FIXME: Static stored properties not supported in generic types
99
- // static let name: String = "Geographic/geocentric conversions"
100
- // static let code: Int = 9602
100
+ public typealias EPSGRef = EPSG9602Ref
101
+
102
+ typealias OldCRS = C1 . CRS
103
+ typealias NewCRS = C2 . CRS
101
104
102
105
/// Geographic to geocentric conversion.
103
106
///
104
107
/// <https://epsg.org/coord-operation-method_9602/Geographic-geocentric-conversions.html>
105
108
/// <https://drive.tiny.cloud/1/4m326iu12oa8re9cjiadxonharclteqb4mumfxj71zsttwkx/5e0ec79e-49fa-4e7a-acca-3d6f6c989877> page 101
106
- public static func apply<
107
- C1: Coordinates < OldCRS > ,
108
- C2: Coordinates < NewCRS >
109
- > ( on coordinate: C1 ) -> C2 {
109
+ public static func apply( on coordinate: C1 ) -> C2 {
110
110
// φ and λ are respectively the latitude and longitude (related to Greenwich) of the point
111
111
let φ = Double ( coordinate. x) . toRadians
112
112
let λ = Double ( coordinate. y) . toRadians
@@ -123,17 +123,14 @@ where OldCRS: GeographicCRS & ThreeDimensionalCRS,
123
123
let y = ( ν + h) * cos( φ) * sin( λ)
124
124
let z = ( ( 1 - e2) * ν + h) * sin( φ)
125
125
126
- return C2 . init ( x: . init( x) , y: . init( y) , z: . init( z) )
126
+ return . init( x: . init( x) , y: . init( y) , z: . init( z) )
127
127
}
128
128
129
129
/// Geocentric to geographic conversion.
130
130
///
131
131
/// <https://epsg.org/coord-operation-method_9602/Geographic-geocentric-conversions.html>
132
132
/// <https://drive.tiny.cloud/1/4m326iu12oa8re9cjiadxonharclteqb4mumfxj71zsttwkx/5e0ec79e-49fa-4e7a-acca-3d6f6c989877> page 101
133
- public static func unapply<
134
- C1: Coordinates < OldCRS > ,
135
- C2: Coordinates < NewCRS >
136
- > ( from coordinate: C2 ) -> C1 {
133
+ public static func unapply( from coordinate: C2 ) -> C1 {
137
134
let x = Double ( coordinate. x)
138
135
let y = Double ( coordinate. y)
139
136
let z = Double ( coordinate. z)
@@ -157,25 +154,25 @@ where OldCRS: GeographicCRS & ThreeDimensionalCRS,
157
154
// h = (p / cos φ) - ν
158
155
let h = ( p / cos( φ) ) - ν
159
156
160
- return C1 . init ( x: . init( φ. fromRadians) , y: . init( λ. fromRadians) , z: . init( h) )
157
+ return . init( x: . init( φ. fromRadians) , y: . init( λ. fromRadians) , z: . init( h) )
161
158
}
162
159
}
163
160
164
- public extension ThreeDimensionalCoordinate {
165
- func transformed< NewCRS> ( toCRS newCRS: NewCRS . Type ) -> Coordinate3DOf < NewCRS >
161
+ public extension ThreeDimensionalCoordinates {
162
+ func transformed< NewCRS> ( toCRS newCRS: NewCRS . Type ) -> Coordinates3D < NewCRS >
166
163
where CRS: GeographicCRS ,
167
164
NewCRS: GeocentricCRS & ThreeDimensionalCRS ,
168
165
NewCRS. Datum. PrimeMeridian == CRS . Datum . PrimeMeridian
169
166
{
170
- EPSG9602 < CRS , NewCRS > . apply ( on: self )
167
+ EPSG9602 < Self , Coordinates3D < NewCRS > > . apply ( on: self )
171
168
}
172
169
173
- func transformed< NewCRS> ( toCRS newCRS: NewCRS . Type ) -> Coordinate3DOf < NewCRS >
170
+ func transformed< NewCRS> ( toCRS newCRS: NewCRS . Type ) -> Coordinates3D < NewCRS >
174
171
where CRS: GeocentricCRS ,
175
172
NewCRS: GeographicCRS & ThreeDimensionalCRS ,
176
173
NewCRS. Datum. PrimeMeridian == CRS . Datum . PrimeMeridian
177
174
{
178
- EPSG9602 < NewCRS , CRS > . unapply ( from: self )
175
+ EPSG9602 < Coordinates3D < NewCRS > , Self > . unapply ( from: self )
179
176
}
180
177
}
181
178
0 commit comments