@ogcio/o11y-sdk-node
Version:
Opentelemetry standard instrumentation SDK for NodeJS based project
61 lines (60 loc) • 1.97 kB
JavaScript
const BASE32 = "0123456789bcdefghjkmnpqrstuvwxyz";
const MIN_LAT = -90;
const MAX_LAT = 90;
const MIN_LON = -180;
const MAX_LON = 180;
export const DEFAULT_GEOHASH_PRECISION = 4;
/**
* Encode latitude and longitude into a geohash string.
* Alternates between longitude and latitude bits, bisects the coordinate range, accumulates 5 bits into an index into the BASE32 lookup table, and repeats until the desired precision is reached.
* See https://en.wikipedia.org/wiki/Geohash for algorithm details.
*
* @param lat Latitude (-90 to 90)
* @param lon Longitude (-180 to 180)
* @param precision Number of characters in the geohash (default: 4)
* @returns Geohash string of the given precision, or undefined if inputs are invalid
*/
export function encodeGeohash(lat, lon, precision = DEFAULT_GEOHASH_PRECISION) {
if (lat === undefined ||
lon === undefined ||
!Number.isFinite(lat) ||
!Number.isFinite(lon))
return undefined;
if (!Number.isInteger(precision) || precision < 1 || precision > 8)
return undefined;
if (lat < MIN_LAT || lat > MAX_LAT || lon < MIN_LON || lon > MAX_LON)
return undefined;
let latMin = MIN_LAT;
let latMax = MAX_LAT;
let lonMin = MIN_LON;
let lonMax = MAX_LON;
let hash = "";
let bit = 0;
let ch = 0;
let isLon = true;
while (hash.length < precision) {
const mid = isLon ? (lonMin + lonMax) / 2 : (latMin + latMax) / 2;
const value = isLon ? lon : lat;
if (value >= mid) {
ch |= 1 << (4 - bit);
if (isLon)
lonMin = mid;
else
latMin = mid;
}
else {
if (isLon)
lonMax = mid;
else
latMax = mid;
}
isLon = !isLon;
bit++;
if (bit === 5) {
hash += BASE32[ch];
bit = 0;
ch = 0;
}
}
return hash;
}