1// geohash.js 2// Geohash library for Javascript 3// (c) 2008 David Troy 4// Distributed under the MIT License 5 6BITS = [16, 8, 4, 2, 1]; 7 8BASE32 = "0123456789bcdefghjkmnpqrstuvwxyz"; 9NEIGHBORS = { right : { even : "bc01fg45238967deuvhjyznpkmstqrwx" }, 10 left : { even : "238967debc01fg45kmstqrwxuvhjyznp" }, 11 top : { even : "p0r21436x8zb9dcf5h7kjnmqesgutwvy" }, 12 bottom : { even : "14365h7k9dcfesgujnmqp0r2twvyx8zb" } }; 13BORDERS = { right : { even : "bcfguvyz" }, 14 left : { even : "0145hjnp" }, 15 top : { even : "prxz" }, 16 bottom : { even : "028b" } }; 17 18NEIGHBORS.bottom.odd = NEIGHBORS.left.even; 19NEIGHBORS.top.odd = NEIGHBORS.right.even; 20NEIGHBORS.left.odd = NEIGHBORS.bottom.even; 21NEIGHBORS.right.odd = NEIGHBORS.top.even; 22 23BORDERS.bottom.odd = BORDERS.left.even; 24BORDERS.top.odd = BORDERS.right.even; 25BORDERS.left.odd = BORDERS.bottom.even; 26BORDERS.right.odd = BORDERS.top.even; 27 28function 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 35function 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 45function 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 73function 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} 113