atriusmaps-node-sdk
Version:
This project provides an API to Atrius Personal Wayfinder maps within a Node environment. See the README.md for more information
75 lines (72 loc) • 2 kB
JavaScript
;
const BITS = [16, 8, 4, 2, 1];
const BASE32 = "0123456789bcdefghjkmnpqrstuvwxyz";
const NEIGHBORS = {
right: { even: "bc01fg45238967deuvhjyznpkmstqrwx" },
left: { even: "238967debc01fg45kmstqrwxuvhjyznp" },
top: { even: "p0r21436x8zb9dcf5h7kjnmqesgutwvy" },
bottom: { even: "14365h7k9dcfesgujnmqp0r2twvyx8zb" }
};
const BORDERS = {
right: { even: "bcfguvyz" },
left: { even: "0145hjnp" },
top: { even: "prxz" },
bottom: { even: "028b" }
};
NEIGHBORS.bottom.odd = NEIGHBORS.left.even;
NEIGHBORS.top.odd = NEIGHBORS.right.even;
NEIGHBORS.left.odd = NEIGHBORS.bottom.even;
NEIGHBORS.right.odd = NEIGHBORS.top.even;
BORDERS.bottom.odd = BORDERS.left.even;
BORDERS.top.odd = BORDERS.right.even;
BORDERS.left.odd = BORDERS.bottom.even;
BORDERS.right.odd = BORDERS.top.even;
function calculateAdjacent(srcHash, dir) {
srcHash = srcHash.toLowerCase();
const lastChr = srcHash.charAt(srcHash.length - 1);
const type = srcHash.length % 2 ? "odd" : "even";
let base = srcHash.substring(0, srcHash.length - 1);
if (BORDERS[dir][type].indexOf(lastChr) !== -1) {
base = calculateAdjacent(base, dir);
}
return base + BASE32[NEIGHBORS[dir][type].indexOf(lastChr)];
}
function encode(latitude, longitude, precision = 12) {
let isEven = true;
const lat = [-90, 90];
const lng = [-180, 180];
let bit = 0;
let ch = 0;
let geohash = "";
while (geohash.length < precision) {
let mid;
if (isEven) {
mid = (lng[0] + lng[1]) / 2;
if (longitude > mid) {
ch |= BITS[bit];
lng[0] = mid;
} else {
lng[1] = mid;
}
} else {
mid = (lat[0] + lat[1]) / 2;
if (latitude > mid) {
ch |= BITS[bit];
lat[0] = mid;
} else {
lat[1] = mid;
}
}
isEven = !isEven;
if (bit < 4) {
bit++;
} else {
geohash += BASE32[ch];
bit = 0;
ch = 0;
}
}
return geohash;
}
exports.calculateAdjacent = calculateAdjacent;
exports.encode = encode;