-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathtransformations.go
More file actions
152 lines (116 loc) · 3.85 KB
/
transformations.go
File metadata and controls
152 lines (116 loc) · 3.85 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
// Package lambertgo helps to transform coordinates from Lambert system into the WGS84 system.
package lambertgo
import (
"fmt"
"math"
)
func latitudeISOFromLatitude(lat float64, e float64) float64 {
return math.Log(math.Tan(math.Pi/4+lat/2) * math.Pow((1-e*math.Sin(lat))/(1+e*math.Sin(lat)), e/2))
}
func latitudeFromLatitudeISO(latISO float64, e float64, eps float64) float64 {
phi0 := 2*math.Atan(math.Exp(latISO)) - math.Pi/2
phii := 2*math.Atan(math.Pow((1+e*math.Sin(phi0))/(1-e*math.Sin(phi0)), e/2)*math.Exp(latISO)) - math.Pi/2
delta := 100.0
for delta > eps {
phi0 = phii
phii = 2*math.Atan(math.Pow((1+e*math.Sin(phi0))/(1-e*math.Sin(phi0)), e/2.0)*math.Exp(latISO)) - math.Pi/2
delta = math.Abs(phii - phi0)
}
return phii
}
func (pt *Point) lambertToGeographic(zone Zone, lonMerid float64, e float64, eps float64) {
n := lambertN[zone]
C := lambertC[zone]
xs := lambertXs[zone]
ys := lambertYs[zone]
x := pt.X
y := pt.Y
R := math.Sqrt(((x-xs)*(x-xs) + (y-ys)*(y-ys)))
gamma := math.Atan((x - xs) / (ys - y))
lon := lonMerid + gamma/n
latISO := -1 / n * math.Log(math.Abs(R/C))
lat := latitudeFromLatitudeISO(latISO, e, eps)
pt.X = lon
pt.Y = lat
}
func (pt *Point) geographicToLambert(zone Zone, lonMerid float64, e float64, eps float64) {
n := lambertN[zone]
C := lambertC[zone]
xs := lambertXs[zone]
ys := lambertYs[zone]
lon := pt.X
lat := pt.Y
latIso := latitudeISOFromLatitude(lat, e)
x := xs + C*math.Exp(-n*latIso)*math.Sin(n*(lon-lonMerid))
y := ys - C*math.Exp(-n*latIso)*math.Cos(n*(lon-lonMerid))
pt.X = x
pt.Y = y
}
func lambertNormal(lat float64, a float64, e float64) float64 {
sina := math.Sin(lat)
return a / math.Sqrt(1-e*e*sina*sina)
}
func (pt *Point) geographicToCartesian(a float64, e float64) {
lat := pt.Y
lon := pt.X
he := pt.Z
N := lambertNormal(lat, a, e)
pt.X = (N + he) * math.Cos(lat) * math.Cos(lon)
pt.Y = (N + he) * math.Cos(lat) * math.Sin(lon)
pt.Z = (N*(1-e*e) + he) * math.Sin(lat)
}
func (pt *Point) cartesianToGeographic(meridien float64, a float64, e float64, eps float64) {
x := pt.X
y := pt.Y
z := pt.Z
lon := meridien + math.Atan(y/x)
module := math.Sqrt(x*x + y*y)
phi0 := math.Atan(z / (module * (1 - (a*e*e)/math.Sqrt(x*x+y*y+z*z))))
phii := math.Atan(z / module / (1 - a*e*e*math.Cos(phi0)/(module*math.Sqrt(1-e*e*math.Sin(phi0)*math.Sin(phi0)))))
delta := 100.0
for delta > eps {
phi0 = phii
phii = math.Atan(z / module / (1 - a*e*e*math.Cos(phi0)/(module*math.Sqrt(1-e*e*math.Sin(phi0)*math.Sin(phi0)))))
delta = math.Abs(phii - phi0)
}
he := module/math.Cos(phii) - a/math.Sqrt(1-e*e*math.Sin(phii)*math.Sin(phii))
pt.X = lon
pt.Y = phii
pt.Z = he
pt.Unit = Radian
}
// ToWGS84 converts coordinates expressed in Meter in the lambert system to Radian in the WGS84 system.
// It takes the lambert Zone ine parameters.
func (pt *Point) ToWGS84(zone Zone) {
if pt.Unit != Meter {
fmt.Println("Could not transform Point which is not in METER")
return
}
if Lambert93 == zone {
pt.lambertToGeographic(zone, IERSLongitudeMeridian, EWGS84, DefaultEPS)
pt.Unit = Radian
} else {
pt.lambertToGeographic(zone, ParisLongitudeMeridian, EClarkIGN, DefaultEPS)
pt.Unit = Radian
pt.geographicToCartesian(AClarkIGN, EClarkIGN)
pt.X -= 168
pt.Y -= 60
pt.Z += 320
pt.cartesianToGeographic(GreenwichLongitudeMeridian, AWGS84, EWGS84, DefaultEPS)
}
}
// ToLambert converts coordinates expressed in Radian in the WGS84 system to Meter in the lambert system.
// It takes the lambert Zone in parameters.
func (pt *Point) ToLambert(zone Zone) {
if pt.Unit != Radian {
fmt.Println("Could not transform Point which is not in Radian")
return
}
if Lambert93 == zone {
pt.geographicToLambert(zone, IERSLongitudeMeridian, EWGS84, DefaultEPS)
pt.Unit = Meter
} else {
pt.geographicToLambert(zone, GreenwichLongitudeMeridian, EClarkIGN, DefaultEPS)
pt.Unit = Meter
}
}