Last active
November 14, 2022 11:47
-
-
Save kijtra/7082b44591133b0c0a94 to your computer and use it in GitHub Desktop.
[JavaScript] Encode or decode GeoHash
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function geohash(lat, lon, len) | |
{ | |
if (len) { | |
len = Number(len); | |
if (len < 1 || len > 12) { | |
return false; | |
} | |
} else { | |
len = 12; | |
} | |
var base32Chars = [ | |
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'b', 'c', 'd', 'e', 'f', 'g', | |
'h', 'j', 'k', 'm', 'n', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' | |
]; | |
var latInterval = [-90.0, 90.0]; | |
var lonInterval = [-180.0, 180.0]; | |
var bits = [16, 8, 4, 2, 1]; | |
var bit = 0; | |
var isEven = true; | |
// Encode | |
if (lon && /^[\d\.]+$/.test(lat + '' + lon)) { | |
var charIndex = 0; | |
var geohash = ''; | |
while (geohash.length < len) { | |
if (isEven) { | |
var middle = (lonInterval[0] + lonInterval[1]) / 2; | |
if (lon > middle) { | |
charIndex |= bits[bit]; | |
lonInterval[0] = middle; | |
} else { | |
lonInterval[1] = middle; | |
} | |
} else { | |
var middle = (latInterval[0] + latInterval[1]) / 2; | |
if (lat > middle) { | |
charIndex |= bits[bit]; | |
latInterval[0] = middle; | |
} else { | |
latInterval[1] = middle; | |
} | |
} | |
if (bit < 4) { | |
bit++; | |
} else { | |
geohash += base32Chars[charIndex]; | |
bit = 0; | |
charIndex = 0; | |
} | |
isEven = isEven ? false : true; | |
} | |
return geohash; | |
} | |
// Decode | |
else if('string' === typeof lat && lat.length <= 12) { | |
var geohash = lat; | |
var base32DecodeMap = {}; | |
for (i = 0, l = base32Chars.length; i < l; i++) { | |
base32DecodeMap[base32Chars[i]] = i; | |
} | |
for (i = 0, l = geohash.length; i < l; i++) { | |
if (!base32DecodeMap[geohash[i]]) { | |
// Invalid GeoHash | |
return false; | |
} | |
var currentChar = base32DecodeMap[geohash[i]]; | |
for (j = 0, jl = bits.length; j < jl; j++) { | |
var mask = bits[j]; | |
if (isEven) { | |
if ((currentChar & mask) !== 0) { | |
lonInterval[0] = (lonInterval[0] + lonInterval[1]) / 2; | |
} else { | |
lonInterval[1] = (lonInterval[0] + lonInterval[1]) / 2; | |
} | |
} else { | |
if ((currentChar & mask) !== 0) { | |
latInterval[0] = (latInterval[0] + latInterval[1]) / 2; | |
} else { | |
latInterval[1] = (latInterval[0] + latInterval[1]) / 2; | |
} | |
} | |
isEven = isEven ? false : true; | |
} | |
} | |
if (true === lon) { | |
return { | |
swlat: latInterval[0], | |
swlon: lonInterval[0], | |
nelat: latInterval[1], | |
nelon: lonInterval[1], | |
}; | |
} else { | |
return { | |
lat: (latInterval[0] + latInterval[1]) / 2, | |
lon: (lonInterval[0] + lonInterval[1]) / 2 | |
}; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment