geohash.js 2.8 KB

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