Files
iD/modules/geo/geo.js
2023-08-02 18:13:49 +02:00

89 lines
2.2 KiB
JavaScript

// constants
var TAU = 2 * Math.PI;
const EQUATORIAL_RADIUS = 6.3781370E6;
const POLAR_RADIUS = 6.3567523E6;
export function geoLatToMeters(dLat) {
return dLat * (TAU * POLAR_RADIUS / 360);
}
export function geoLonToMeters(dLon, atLat) {
return Math.abs(atLat) >= 90 ? 0 :
dLon * (TAU * EQUATORIAL_RADIUS / 360) * Math.abs(Math.cos(atLat * (Math.PI / 180)));
}
export function geoMetersToLat(m) {
return m / (TAU * POLAR_RADIUS / 360);
}
export function geoMetersToLon(m, atLat) {
return Math.abs(atLat) >= 90 ? 0 :
m / (TAU * EQUATORIAL_RADIUS / 360) / Math.abs(Math.cos(atLat * (Math.PI / 180)));
}
export function geoMetersToOffset(meters, tileSize) {
tileSize = tileSize || 256;
return [
meters[0] * tileSize / (TAU * EQUATORIAL_RADIUS),
-meters[1] * tileSize / (TAU * POLAR_RADIUS)
];
}
export function geoOffsetToMeters(offset, tileSize) {
tileSize = tileSize || 256;
return [
offset[0] * TAU * EQUATORIAL_RADIUS / tileSize,
-offset[1] * TAU * POLAR_RADIUS / tileSize
];
}
// Equirectangular approximation of spherical distances on Earth
export function geoSphericalDistance(a, b) {
var x = geoLonToMeters(a[0] - b[0], (a[1] + b[1]) / 2);
var y = geoLatToMeters(a[1] - b[1]);
return Math.sqrt((x * x) + (y * y));
}
// scale to zoom
export function geoScaleToZoom(k, tileSize) {
tileSize = tileSize || 256;
var log2ts = Math.log(tileSize) * Math.LOG2E;
return Math.log(k * TAU) / Math.LN2 - log2ts;
}
// zoom to scale
export function geoZoomToScale(z, tileSize) {
tileSize = tileSize || 256;
return tileSize * Math.pow(2, z) / TAU;
}
// returns info about the node from `nodes` closest to the given `point`
export function geoSphericalClosestNode(nodes, point) {
var minDistance = Infinity, distance;
var indexOfMin;
for (var i in nodes) {
distance = geoSphericalDistance(nodes[i].loc, point);
if (distance < minDistance) {
minDistance = distance;
indexOfMin = i;
}
}
if (indexOfMin !== undefined) {
return { index: indexOfMin, distance: minDistance, node: nodes[indexOfMin] };
} else {
return null;
}
}