Initial Commit
This commit is contained in:
85
packages/geospatial/geo/geo-earth/src/geohash/geohash.ts
Normal file
85
packages/geospatial/geo/geo-earth/src/geohash/geohash.ts
Normal file
@@ -0,0 +1,85 @@
|
||||
const BASE32 = "0123456789bcdefghjkmnpqrstuvwxyz";
|
||||
|
||||
export function encodeGeohash(
|
||||
coord: { latitude: number; longitude: number },
|
||||
precision = 9
|
||||
): string {
|
||||
let minLat = -90;
|
||||
let maxLat = 90;
|
||||
let minLon = -180;
|
||||
let maxLon = 180;
|
||||
let hash = "";
|
||||
let bits = 0;
|
||||
let ch = 0;
|
||||
let evenBit = true;
|
||||
|
||||
while (hash.length < precision) {
|
||||
if (evenBit) {
|
||||
const mid = (minLon + maxLon) / 2;
|
||||
if (coord.longitude >= mid) {
|
||||
ch = (ch << 1) | 1;
|
||||
minLon = mid;
|
||||
} else {
|
||||
ch = ch << 1;
|
||||
maxLon = mid;
|
||||
}
|
||||
} else {
|
||||
const mid = (minLat + maxLat) / 2;
|
||||
if (coord.latitude >= mid) {
|
||||
ch = (ch << 1) | 1;
|
||||
minLat = mid;
|
||||
} else {
|
||||
ch = ch << 1;
|
||||
maxLat = mid;
|
||||
}
|
||||
}
|
||||
evenBit = !evenBit;
|
||||
bits++;
|
||||
if (bits === 5) {
|
||||
hash += BASE32[ch];
|
||||
bits = 0;
|
||||
ch = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
export function decodeGeohash(hash: string): {
|
||||
latitude: number;
|
||||
longitude: number;
|
||||
} {
|
||||
let minLat = -90;
|
||||
let maxLat = 90;
|
||||
let minLon = -180;
|
||||
let maxLon = 180;
|
||||
let evenBit = true;
|
||||
|
||||
for (const char of hash) {
|
||||
const idx = BASE32.indexOf(char);
|
||||
for (let i = 4; i >= 0; i--) {
|
||||
const bit = (idx >> i) & 1;
|
||||
if (evenBit) {
|
||||
const mid = (minLon + maxLon) / 2;
|
||||
if (bit === 1) {
|
||||
minLon = mid;
|
||||
} else {
|
||||
maxLon = mid;
|
||||
}
|
||||
} else {
|
||||
const mid = (minLat + maxLat) / 2;
|
||||
if (bit === 1) {
|
||||
minLat = mid;
|
||||
} else {
|
||||
maxLat = mid;
|
||||
}
|
||||
}
|
||||
evenBit = !evenBit;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
latitude: (minLat + maxLat) / 2,
|
||||
longitude: (minLon + maxLon) / 2,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user