1
2 """Working with UTM and Lat/Long coordinates
3
4 Based on http://home.hiwaay.net/~taylorc/toolbox/geography/geoutm.html
5
6 """
7
8 from math import sin, cos, sqrt, tan, pi, floor
9
10 __author__ = "P. Tute, C. Taylor"
11 __maintainer__ = "B. Henne"
12 __contact__ = "henne@dcsec.uni-hannover.de"
13 __copyright__ = "(c) 1997-2003 C. Taylor, 2010-2011, DCSec, Leibniz Universitaet Hannover, Germany"
14 __license__ = """
15 The Python code is based on Javascript code of Charles L. Taylor from
16 http://home.hiwaay.net/~taylorc/toolbox/geography/geoutm.html
17 The author allowed us to reuse his code.
18 Original license:
19 The documents, images, and other materials on the Chuck Taylor
20 Web site are copyright (c) 1997-2003 by C. Taylor, unless otherwise noted.
21 Visitors are permitted to download the materials located on the Chuck Taylor
22 Web site to their own systems, on a temporary basis, for the purpose of viewing
23 them or, in the case of software applications, using them in accordance with
24 their intended purpose.
25 Republishing or redistribution of any of the materials located on the Chuck Taylor
26 Web site requires permission from C. Taylor. MoSP has been granted to use the code."""
27
28
29
30 UTMScaleFactor = 0.9996
31 sm_a = 6378137.0
32 sm_b = 6356752.314
33 sm_EccSquared = 6.69437999013e-03
34
35
37 """Calculates the current UTM-zone for a given longitude."""
38 return floor((lon + 180.0) / 6) + 1
39
40
42 """Converts radians to degrees."""
43 return (rad / pi * 180.0)
44
45
47 """Converts degrees to radians."""
48 return (deg / 180.0 * pi)
49
50
52 """Calculates the central meridian for the given UTM-zone."""
53 return deg_to_rad(-183.0 + (zone * 6.0))
54
55
57 """Computes the ellipsoidal distance from the equator to a point at a
58 given latitude.
59
60 Reference: Hoffmann-Wellenhof, B., Lichtenegger, H., and Collins, J.,
61 GPS: Theory and Practice, 3rd ed. New York: Springer-Verlag Wien, 1994."""
62
63
64 n = (sm_a - sm_b) / (sm_a + sm_b)
65
66
67 alpha = (((sm_a + sm_b) / 2.0)
68 * (1.0 + (n**2.0 / 4.0) + (n**4.0 / 64.0)))
69
70
71 beta = ((-3.0 * n / 2.0) + (9.0 * n**3.0 / 16.0)
72 + (-3.0 * n**5.0 / 32.0))
73
74
75 gamma = ((15.0 * n**2.0 / 16.0)
76 + (-15.0 * n**4.0 / 32.0))
77
78
79 delta = ((-35.0 * n**3.0 / 48.0)
80 + (105.0 * n**5.0 / 256.0))
81
82
83 epsilon = (315.0 * n**4.0 / 512.0)
84
85
86 result = (alpha
87 * (phi + (beta * sin(2.0 * phi))
88 + (gamma * sin(4.0 * phi))
89 + (delta * sin(6.0 * phi))
90 + (epsilon * sin(8.0 * phi))))
91
92 return result
93
94
96 """Converts a latitude/longitude pair to x and y coordinates in the
97 Transverse Mercator projection. Note that Transverse Mercator is not
98 the same as UTM a scale factor is required to convert between them.
99
100 Reference: Hoffmann-Wellenhof, B., Lichtenegger, H., and Collins, J.,
101 GPS: Theory and Practice, 3rd ed. New York: Springer-Verlag Wien, 1994."""
102
103
104 ep2 = (sm_a**2.0 - sm_b**2.0) / sm_b**2.0
105
106
107 nu2 = ep2 * cos(phi)**2.0
108
109
110 N = sm_a**2.0 / (sm_b * sqrt(1 + nu2))
111
112
113 t = tan(phi)
114 t2 = t**2.0
115
116
117 l = lambd - lambd0
118
119
120
121
122
123 l3coef = 1.0 - t2 + nu2
124
125 l4coef = 5.0 - t2 + 9 * nu2 + 4.0 * (nu2**2.0)
126
127 l5coef = 5.0 - 18.0 * t2 + (t2**2.0) + 14.0 * nu2 - 58.0 * t2 * nu2
128
129 l6coef = 61.0 - 58.0 * t2 + (t2**2.0) + 270.0 * nu2 - 330.0 * t2 * nu2
130
131 l7coef = 61.0 - 479.0 * t2 + 179.0 * (t2**2.0) - (t2**3.0)
132
133 l8coef = 1385.0 - 3111.0 * t2 + 543.0 * (t2**2.0) - (t2**3.0)
134
135
136 xy[0] = (N * cos(phi) * l + (N / 6.0 * cos(phi)**3.0 * l3coef * l**3.0)
137 + (N / 120.0 * cos(phi)**5.0 * l5coef * l**5.0)
138 + (N / 5040.0 * cos(phi)**7.0 * l7coef * l**7.0))
139
140
141 xy[1] = (ArcLengthOfMeridian(phi)
142 + (t / 2.0 * N * cos(phi)**2.0 * l**2.0)
143 + (t / 24.0 * N * cos(phi)**4.0 * l4coef * l**4.0)
144 + (t / 720.0 * N * cos(phi)**6.0 * l6coef * l**6.0)
145 + (t / 40320.0 * N * cos(phi)**8.0 * l8coef * l**8.0))
146
147 return
148
149
167
168
209
210
212 """Converts x and y coordinates in the Transverse Mercator projection to
213 a latitude/longitude pair. Note that Transverse Mercator is not
214 the same as UTM a scale factor is required to convert between them.
215
216 Reference: Hoffmann-Wellenhof, B., Lichtenegger, H., and Collins, J.,
217 GPS: Theory and Practice, 3rd ed. New York: Springer-Verlag Wien, 1994.
218
219 Remarks:
220 The local variables Nf, nuf2, tf, and tf2 serve the same purpose as
221 N, nu2, t, and t2 in MapLatLonToXY, but they are computed with respect
222 sto the footpoint latitude phif.
223
224 x1frac, x2frac, x2poly, x3poly, etc. are to enhance readability and
225 to optimize computations."""
226
227 philambda = []
228
229
230 phif = FootpointLatitude(y)
231
232
233 ep2 = ((sm_a**2.0 - sm_b**2.0)
234 / sm_b**2.0)
235
236
237 cf = cos(phif)
238
239
240 nuf2 = ep2 * cf**2.0
241
242
243 Nf = sm_a**2.0 / (sm_b * sqrt(1 + nuf2))
244 Nfpow = Nf
245
246
247 tf = tan(phif)
248 tf2 = tf**2
249 tf4 = tf2**2
250
251
252
253 x1frac = 1.0 / (Nfpow * cf)
254
255 Nfpow *= Nf
256 x2frac = tf / (2.0 * Nfpow)
257
258 Nfpow *= Nf
259 x3frac = 1.0 / (6.0 * Nfpow * cf)
260
261 Nfpow *= Nf
262 x4frac = tf / (24.0 * Nfpow)
263
264 Nfpow *= Nf
265 x5frac = 1.0 / (120.0 * Nfpow * cf)
266
267 Nfpow *= Nf
268 x6frac = tf / (720.0 * Nfpow)
269
270 Nfpow *= Nf
271 x7frac = 1.0 / (5040.0 * Nfpow * cf)
272
273 Nfpow *= Nf
274 x8frac = tf / (40320.0 * Nfpow)
275
276
277
278 x2poly = -1.0 - nuf2
279
280 x3poly = -1.0 - 2 * tf2 - nuf2
281
282 x4poly = (5.0 + 3.0 * tf2 + 6.0 * nuf2 - 6.0 * tf2 * nuf2
283 - 3.0 * (nuf2 *nuf2) - 9.0 * tf2 * (nuf2 * nuf2))
284
285 x5poly = 5.0 + 28.0 * tf2 + 24.0 * tf4 + 6.0 * nuf2 + 8.0 * tf2 * nuf2
286
287 x6poly = (-61.0 - 90.0 * tf2 - 45.0 * tf4 - 107.0 * nuf2
288 + 162.0 * tf2 * nuf2)
289
290 x7poly = -61.0 - 662.0 * tf2 - 1320.0 * tf4 - 720.0 * (tf4 * tf2)
291
292 x8poly = 1385.0 + 3633.0 * tf2 + 4095.0 * tf4 + 1575 * (tf4 * tf2)
293
294
295 philambda.append(phif + x2frac * x2poly * x**2
296 + x4frac * x4poly * x**4.0
297 + x6frac * x6poly * x**6.0
298 + x8frac * x8poly * x**8.0)
299
300
301 philambda.append(lambda0 + x1frac * x
302 + x3frac * x3poly * x**3.0
303 + x5frac * x5poly * x**5.0
304 + x7frac * x7poly * x**7.0)
305
306 return philambda
307
308
310 """Converts x and y coordinates in the Universal Transverse Mercator
311 projection to a latitude/longitude pair."""
312
313 x -= 500000.0
314 x /= UTMScaleFactor
315
316
317 if southhemi:
318 y -= 10000000.0
319
320 y /= UTMScaleFactor
321
322 cmeridian = UTMCentralMeridian(zone)
323
324 lat_lon = MapXYToLatLon(x, y, cmeridian)
325 return list(reversed([rad_to_deg(i) for i in lat_lon]))
326