geonumber
Version:
Library for encoding geographic coordinates as single number with any number of bits
62 lines • 2.23 kB
JavaScript
export function encodeNumber(value, bits) {
const cleanBits = BigInt(bits);
const max = Number(1n << cleanBits);
return BigInt(Math.round(value * max));
}
export function decodeNumber(encoded, bits) {
const cleanBits = BigInt(bits);
const max = Number(1n << cleanBits);
return Number(encoded) / max;
}
export function merge(a, b, bits) {
const cleanBits = BigInt(bits);
let result = 0n;
const oddBits = cleanBits & 1n;
for (let dstBit = 0n; dstBit < cleanBits; dstBit++) {
const srcBit = dstBit >> 1n;
result |= (((((dstBit & 1n) != oddBits) ? a : b) >> srcBit) & 1n) << dstBit;
}
return result;
}
export function split(encoded, bits) {
const cleanBits = BigInt(bits);
let a = 0n;
let b = 0n;
const oddBits = cleanBits & 1n;
for (let srcBit = 0n; srcBit < cleanBits; srcBit++) {
const dstBit = srcBit >> 1n;
if ((srcBit & 1n) == oddBits) {
b |= ((encoded >> srcBit) & 1n) << dstBit;
}
else {
a |= ((encoded >> srcBit) & 1n) << dstBit;
}
}
return [a, b];
}
export function encodeLocation({ lat, lon }, bits) {
const cleanBits = BigInt(bits);
const latBits = cleanBits >> 1n;
const lonBits = cleanBits - latBits;
const normalizedLat = (lat + 90) / 180;
const normalizedLon = (lon + 180) / 360;
const clearedLat = normalizedLat - Math.floor(normalizedLat);
const clearedLon = normalizedLon - Math.floor(normalizedLon);
const encodedLat = encodeNumber(clearedLat, latBits);
const encodedLon = encodeNumber(clearedLon, lonBits);
const merged = merge(encodedLon, encodedLat, cleanBits);
return merged;
}
export function decodeLocation(number, bits) {
const cleanNumber = BigInt(number);
const cleanBits = BigInt(bits);
const latBits = cleanBits >> 1n;
const lonBits = cleanBits - latBits;
const [encodedLon, encodedLat] = split(cleanNumber, cleanBits);
const normalizedLat = decodeNumber(encodedLat, latBits);
const normalizedLon = decodeNumber(encodedLon, lonBits);
const lat = normalizedLat * 180 - 90;
const lon = normalizedLon * 360 - 180;
return { lat, lon };
}
//# sourceMappingURL=index.js.map