UNPKG

@ogcio/o11y-sdk-node

Version:

Opentelemetry standard instrumentation SDK for NodeJS based project

61 lines (60 loc) 1.97 kB
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; }