1
+ // geohash.js
2
+ // Geohash library for Javascript
3
+ // (c) 2008 David Troy
4
+ // Distributed under the MIT License
5
+
6
+ BITS = [ 16 , 8 , 4 , 2 , 1 ] ;
7
+
8
+ BASE32 = "0123456789bcdefghjkmnpqrstuvwxyz" ;
9
+ NEIGHBORS = { right : { even : "bc01fg45238967deuvhjyznpkmstqrwx" } ,
10
+ left : { even : "238967debc01fg45kmstqrwxuvhjyznp" } ,
11
+ top : { even : "p0r21436x8zb9dcf5h7kjnmqesgutwvy" } ,
12
+ bottom : { even : "14365h7k9dcfesgujnmqp0r2twvyx8zb" } } ;
13
+ BORDERS = { right : { even : "bcfguvyz" } ,
14
+ left : { even : "0145hjnp" } ,
15
+ top : { even : "prxz" } ,
16
+ bottom : { even : "028b" } } ;
17
+
18
+ NEIGHBORS . bottom . odd = NEIGHBORS . left . even ;
19
+ NEIGHBORS . top . odd = NEIGHBORS . right . even ;
20
+ NEIGHBORS . left . odd = NEIGHBORS . bottom . even ;
21
+ NEIGHBORS . right . odd = NEIGHBORS . top . even ;
22
+
23
+ BORDERS . bottom . odd = BORDERS . left . even ;
24
+ BORDERS . top . odd = BORDERS . right . even ;
25
+ BORDERS . left . odd = BORDERS . bottom . even ;
26
+ BORDERS . right . odd = BORDERS . top . even ;
27
+
28
+ function refine_interval ( interval , cd , mask ) {
29
+ if ( cd & mask )
30
+ interval [ 0 ] = ( interval [ 0 ] + interval [ 1 ] ) / 2 ;
31
+ else
32
+ interval [ 1 ] = ( interval [ 0 ] + interval [ 1 ] ) / 2 ;
33
+ }
34
+
35
+ function calculateAdjacent ( srcHash , dir ) {
36
+ srcHash = srcHash . toLowerCase ( ) ;
37
+ var lastChr = srcHash . charAt ( srcHash . length - 1 ) ;
38
+ var type = ( srcHash . length % 2 ) ? 'odd' : 'even' ;
39
+ var base = srcHash . substring ( 0 , srcHash . length - 1 ) ;
40
+ if ( BORDERS [ dir ] [ type ] . indexOf ( lastChr ) != - 1 )
41
+ base = calculateAdjacent ( base , dir ) ;
42
+ return base + BASE32 [ NEIGHBORS [ dir ] [ type ] . indexOf ( lastChr ) ] ;
43
+ }
44
+
45
+ function decodeGeoHash ( geohash ) {
46
+ var is_even = 1 ;
47
+ var lat = [ ] ; var lon = [ ] ;
48
+ lat [ 0 ] = - 90.0 ; lat [ 1 ] = 90.0 ;
49
+ lon [ 0 ] = - 180.0 ; lon [ 1 ] = 180.0 ;
50
+ lat_err = 90.0 ; lon_err = 180.0 ;
51
+
52
+ for ( i = 0 ; i < geohash . length ; i ++ ) {
53
+ c = geohash [ i ] ;
54
+ cd = BASE32 . indexOf ( c ) ;
55
+ for ( j = 0 ; j < 5 ; j ++ ) {
56
+ mask = BITS [ j ] ;
57
+ if ( is_even ) {
58
+ lon_err /= 2 ;
59
+ refine_interval ( lon , cd , mask ) ;
60
+ } else {
61
+ lat_err /= 2 ;
62
+ refine_interval ( lat , cd , mask ) ;
63
+ }
64
+ is_even = ! is_even ;
65
+ }
66
+ }
67
+ lat [ 2 ] = ( lat [ 0 ] + lat [ 1 ] ) / 2 ;
68
+ lon [ 2 ] = ( lon [ 0 ] + lon [ 1 ] ) / 2 ;
69
+
70
+ return { latitude : lat , longitude : lon } ;
71
+ }
72
+
73
+ function encodeGeoHash ( latitude , longitude ) {
74
+ var is_even = 1 ;
75
+ var i = 0 ;
76
+ var lat = [ ] ; var lon = [ ] ;
77
+ var bit = 0 ;
78
+ var ch = 0 ;
79
+ var precision = 12 ;
80
+ geohash = "" ;
81
+
82
+ lat [ 0 ] = - 90.0 ; lat [ 1 ] = 90.0 ;
83
+ lon [ 0 ] = - 180.0 ; lon [ 1 ] = 180.0 ;
84
+
85
+ while ( geohash . length < precision ) {
86
+ if ( is_even ) {
87
+ mid = ( lon [ 0 ] + lon [ 1 ] ) / 2 ;
88
+ if ( longitude > mid ) {
89
+ ch |= BITS [ bit ] ;
90
+ lon [ 0 ] = mid ;
91
+ } else
92
+ lon [ 1 ] = mid ;
93
+ } else {
94
+ mid = ( lat [ 0 ] + lat [ 1 ] ) / 2 ;
95
+ if ( latitude > mid ) {
96
+ ch |= BITS [ bit ] ;
97
+ lat [ 0 ] = mid ;
98
+ } else
99
+ lat [ 1 ] = mid ;
100
+ }
101
+
102
+ is_even = ! is_even ;
103
+ if ( bit < 4 )
104
+ bit ++ ;
105
+ else {
106
+ geohash += BASE32 [ ch ] ;
107
+ bit = 0 ;
108
+ ch = 0 ;
109
+ }
110
+ }
111
+ return geohash ;
112
+ }
0 commit comments