@@ -18,6 +18,12 @@ macro pointmotion(Datumₛ, Datumₜ)
18
18
latlonalt′ = pointmotionfwd (Dₛ, Dₜ, latlonalt)
19
19
LatLonAlt {Dₜ} (latlonalt′... )
20
20
end
21
+
22
+ function Base. convert (:: Type{LatLonAlt{Dₛ}} , coords:: LatLonAlt{Dₜ} ) where {Dₛ<: $Datumₛ ,Dₜ<: $Datumₜ }
23
+ latlonalt = (coords. lat, coords. lon, coords. alt)
24
+ latlonalt′ = pointmotionbwd (Dₛ, Dₜ, latlonalt)
25
+ LatLonAlt {Dₛ} (latlonalt′... )
26
+ end
21
27
end
22
28
esc (expr)
23
29
end
@@ -40,6 +46,55 @@ function pointmotionfwd(Datumₛ, Datumₜ, (lat, lon, alt))
40
46
lat′, lon′, alt′
41
47
end
42
48
49
+ # Adapted from PROJ coordinate transformation software
50
+ # Initial PROJ 4.3 public domain code was put as Frank Warmerdam as copyright
51
+ # holder, but he didn't mean to imply he did the work. Essentially all work was
52
+ # done by Gerald Evenden.
53
+
54
+ # reference code: https://github.com/OSGeo/PROJ/blob/master/src/grids.cpp
55
+
56
+ function pointmotionbwd (Datumₛ, Datumₜ, (lat, lon, alt))
57
+ λ = ustrip (deg2rad (lon))
58
+ ϕ = ustrip (deg2rad (lat))
59
+ h = ustrip (m, alt)
60
+ tol = atol (λ)
61
+
62
+ # initial guess
63
+ λₛ, ϕₛ, hₛ = pointmotionparams (Datumₛ, Datumₜ, lat, lon, ϕ, h)
64
+ λᵢ = λ - λₛ
65
+ ϕᵢ = ϕ - ϕₛ
66
+ hᵢ = h - hₛ
67
+ for _ in 1 : MAXITER
68
+ # to check if the guess is equivalent to the original Datumₛ coordinates,
69
+ # forward the guess coordinates to compare them with the Datumₜ input coordinates
70
+ latᵢ = rad2deg (ϕᵢ) * °
71
+ lonᵢ = rad2deg (λᵢ) * °
72
+ λᵢₛ, ϕᵢₛ, hᵢₛ = pointmotionparams (Datumₛ, Datumₜ, latᵢ, lonᵢ, ϕᵢ, hᵢ)
73
+ λᵢ′ = λᵢ + λᵢₛ
74
+ ϕᵢ′ = ϕᵢ + ϕᵢₛ
75
+ hᵢ′ = hᵢ + hᵢₛ
76
+ # difference between forward coordinates and input coordinates for comparison
77
+ λΔ = λᵢ′ - λ
78
+ ϕΔ = ϕᵢ′ - ϕ
79
+ hΔ = hᵢ′ - h
80
+ # if the difference is small, stop the iteration
81
+ if hypot (λΔ, ϕΔ, hΔ) ≤ tol
82
+ break
83
+ end
84
+ # otherwise, subtract the difference and continue
85
+ λᵢ -= λΔ
86
+ ϕᵢ -= ϕΔ
87
+ hᵢ -= hΔ
88
+ end
89
+
90
+ # https://github.com/PainterQubits/Unitful.jl/issues/753
91
+ lonᵢ = rad2deg (λᵢ) * °
92
+ latᵢ = rad2deg (ϕᵢ) * °
93
+ altᵢ = uconvert (unit (alt), hᵢ * m)
94
+
95
+ latᵢ, lonᵢ, altᵢ
96
+ end
97
+
43
98
function pointmotionparams (Datumₛ, Datumₜ, lat, lon, ϕ, h)
44
99
🌎 = ellipsoid (Datumₛ)
45
100
T = numtype (lon)
0 commit comments