-
Notifications
You must be signed in to change notification settings - Fork 1
/
geohash.js
116 lines (101 loc) · 2.98 KB
/
geohash.js
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
// geohash.js
// Geohash library for Javascript
// (c) 2008 David Troy
// Distributed under the MIT License
(function(globals) {
var BITS = [16, 8, 4, 2, 1];
var BASE32 = "0123456789bcdefghjkmnpqrstuvwxyz";
var NEIGHBORS = { right : { even : "bc01fg45238967deuvhjyznpkmstqrwx" },
left : { even : "238967debc01fg45kmstqrwxuvhjyznp" },
top : { even : "p0r21436x8zb9dcf5h7kjnmqesgutwvy" },
bottom : { even : "14365h7k9dcfesgujnmqp0r2twvyx8zb" } };
var BORDERS = { right : { even : "bcfguvyz" },
left : { even : "0145hjnp" },
top : { even : "prxz" },
bottom : { even : "028b" } };
NEIGHBORS.bottom.odd = NEIGHBORS.left.even;
NEIGHBORS.top.odd = NEIGHBORS.right.even;
NEIGHBORS.left.odd = NEIGHBORS.bottom.even;
NEIGHBORS.right.odd = NEIGHBORS.top.even;
BORDERS.bottom.odd = BORDERS.left.even;
BORDERS.top.odd = BORDERS.right.even;
BORDERS.left.odd = BORDERS.bottom.even;
BORDERS.right.odd = BORDERS.top.even;
function refineInterval(interval, cd, mask) {
if (cd&mask)
interval[0] = (interval[0] + interval[1])/2;
else
interval[1] = (interval[0] + interval[1])/2;
}
globals.calculateAdjacent = function(srcHash, dir) {
srcHash = srcHash.toLowerCase();
var lastChr = srcHash.charAt(srcHash.length-1);
var type = (srcHash.length % 2) ? 'odd' : 'even';
var base = srcHash.substring(0,srcHash.length-1);
if (BORDERS[dir][type].indexOf(lastChr)!=-1)
base = calculateAdjacent(base, dir);
return base + BASE32[NEIGHBORS[dir][type].indexOf(lastChr)];
}
globals.decodeGeoHash = function(geohash) {
var is_even = 1;
var lat = []; var lon = [];
lat[0] = -90.0; lat[1] = 90.0;
lon[0] = -180.0; lon[1] = 180.0;
lat_err = 90.0; lon_err = 180.0;
for (i=0; i<geohash.length; i++) {
c = geohash[i];
cd = BASE32.indexOf(c);
for (j=0; j<5; j++) {
mask = BITS[j];
if (is_even) {
lon_err /= 2;
refineInterval(lon, cd, mask);
} else {
lat_err /= 2;
refineInterval(lat, cd, mask);
}
is_even = !is_even;
}
}
lat[2] = (lat[0] + lat[1])/2;
lon[2] = (lon[0] + lon[1])/2;
return { latitude: lat, longitude: lon};
}
globals.encodeGeoHash = function(latitude, longitude) {
var is_even=1;
var i=0;
var lat = []; var lon = [];
var bit=0;
var ch=0;
var precision = 12;
geohash = "";
lat[0] = -90.0; lat[1] = 90.0;
lon[0] = -180.0; lon[1] = 180.0;
while (geohash.length < precision) {
if (is_even) {
mid = (lon[0] + lon[1]) / 2;
if (longitude > mid) {
ch |= BITS[bit];
lon[0] = mid;
} else
lon[1] = mid;
} else {
mid = (lat[0] + lat[1]) / 2;
if (latitude > mid) {
ch |= BITS[bit];
lat[0] = mid;
} else
lat[1] = mid;
}
is_even = !is_even;
if (bit < 4)
bit++;
else {
geohash += BASE32[ch];
bit = 0;
ch = 0;
}
}
return geohash;
}
}(window));