source: src/django_gheat/gheat/gmerc.py@ 9750

Last change on this file since 9750 was 9006, checked in by dennisw, 14 years ago

django_gheat - versie van gheat die gebruik maakt van django framework, ondersteunt SQL connecties in tegenstelling tot gheat dat gebruik maakt van sqlite

File size: 4.7 KB
Line 
1"""This is a port of Google's GMercatorProjection.fromLatLngToPixel.
2
3Doco on the original:
4
5 http://code.google.com/apis/maps/documentation/reference.html#GMercatorProjection
6
7
8Here's how I ported it:
9
10 http://blag.whit537.org/2007/07/how-to-hack-on-google-maps.html
11
12
13The goofy variable names below are an artifact of Google's javascript
14obfuscation.
15
16"""
17import math
18
19
20# Constants
21# =========
22# My knowledge of what these mean is undefined.
23
24CBK = [128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304, 8388608, 16777216, 33554432, 67108864, 134217728, 268435456, 536870912, 1073741824, 2147483648, 4294967296, 8589934592, 17179869184, 34359738368, 68719476736, 137438953472]
25CEK = [0.7111111111111111, 1.4222222222222223, 2.8444444444444446, 5.688888888888889, 11.377777777777778, 22.755555555555556, 45.51111111111111, 91.02222222222223, 182.04444444444445, 364.0888888888889, 728.1777777777778, 1456.3555555555556, 2912.711111111111, 5825.422222222222, 11650.844444444445, 23301.68888888889, 46603.37777777778, 93206.75555555556, 186413.51111111112, 372827.02222222224, 745654.0444444445, 1491308.088888889, 2982616.177777778, 5965232.355555556, 11930464.711111112, 23860929.422222223, 47721858.844444446, 95443717.68888889, 190887435.37777779, 381774870.75555557, 763549741.5111111]
26CFK = [40.74366543152521, 81.48733086305042, 162.97466172610083, 325.94932345220167, 651.8986469044033, 1303.7972938088067, 2607.5945876176133, 5215.189175235227, 10430.378350470453, 20860.756700940907, 41721.51340188181, 83443.02680376363, 166886.05360752725, 333772.1072150545, 667544.214430109, 1335088.428860218, 2670176.857720436, 5340353.715440872, 10680707.430881744, 21361414.86176349, 42722829.72352698, 85445659.44705395, 170891318.8941079, 341782637.7882158, 683565275.5764316, 1367130551.1528633, 2734261102.3057265, 5468522204.611453, 10937044409.222906, 21874088818.445812, 43748177636.891624]
27
28
29def ll2px(lat, lng, zoom):
30 """Given two floats and an int, return a 2-tuple of ints.
31
32 Note that the pixel coordinates are tied to the entire map, not to the map
33 section currently in view.
34
35 """
36 assert isinstance(lat, (float, int, long)), \
37 ValueError("lat must be a float")
38 lat = float(lat)
39 assert isinstance(lng, (float, int, long)), \
40 ValueError("lng must be a float")
41 lng = float(lng)
42 assert isinstance(zoom, int), TypeError("zoom must be an int from 0 to 30")
43 assert 0 <= zoom <= 30, ValueError("zoom must be an int from 0 to 30")
44
45 cbk = CBK[zoom]
46
47 x = int(round(cbk + (lng * CEK[zoom])))
48
49 foo = math.sin(lat * math.pi / 180)
50 if foo < -0.9999:
51 foo = -0.9999
52 elif foo > 0.9999:
53 foo = 0.9999
54
55 y = int(round(cbk + (0.5 * math.log((1+foo)/(1-foo)) * (-CFK[zoom]))))
56
57 return (x, y)
58
59
60
61def px2ll(x, y, zoom):
62 """Given three ints, return a 2-tuple of floats.
63
64 Note that the pixel coordinates are tied to the entire map, not to the map
65 section currently in view.
66
67 """
68 assert isinstance(x, (int, long)), \
69 ValueError("px must be a 2-tuple of ints")
70 assert isinstance(y, (int, long)), \
71 ValueError("px must be a 2-tuple of ints")
72 assert isinstance(zoom, int), TypeError("zoom must be an int from 0 to 30")
73 assert 0 <= zoom <= 30, ValueError("zoom must be an int from 0 to 30")
74
75 foo = CBK[zoom]
76 lng = (x - foo) / CEK[zoom]
77 bar = (y - foo) / -CFK[zoom]
78 blam = 2 * math.atan(math.exp(bar)) - math.pi / 2
79 lat = blam / (math.pi / 180)
80
81 return (lat, lng)
82
83
84if __name__ == '__main__':
85
86 # Tests
87 # =====
88 # The un-round numbers were gotten by calling Google's js function.
89
90 data = [ (3, 39.81447, -98.565388, 463, 777)
91 , (3, 40.609538, -80.224528, 568, 771)
92
93 , (0, -90, 180, 256, 330)
94 , (0, -90, -180, 0, 330)
95 , (0, 90, 180, 256, -74)
96 , (0, 90, -180, 0, -74)
97
98 , (1, -90, 180, 512, 660)
99 , (1, -90, -180, 0, 660)
100 , (1, 90, 180, 512, -148)
101 , (1, 90, -180, 0, -148)
102
103 , (2, -90, 180, 1024, 1319)
104 , (2, -90, -180, 0, 1319)
105 , (2, 90, 180, 1024, -295)
106 , (2, 90, -180, 0, -295)
107
108 ]
109
110 def close(floats, floats2):
111 """Compare two sets of floats.
112 """
113 lat_actual = abs(floats[0] - floats2[0])
114 lng_actual = abs(floats[1] - floats2[1])
115 assert lat_actual < 1, (floats[0], floats2[0])
116 assert lng_actual < 1, (floats[1], floats2[1])
117 return True
118
119 for zoom, lat, lng, x, y in data:
120 assert ll2px(lat, lng, zoom) == (x, y), (lat, lng)
121 assert close(px2ll(x, y, zoom), (lat, lng)), (x, y)
Note: See TracBrowser for help on using the repository browser.