87 lines
2.3 KiB
TypeScript
87 lines
2.3 KiB
TypeScript
const EarthRadius = 6371008.8; // in meeter
|
|
const YAxisInversion = 1;
|
|
2;
|
|
|
|
export enum Constant {
|
|
EarthRadiusInM = EarthRadius, //
|
|
EarthRadiusInFt = EarthRadius * 3.28084, //km: 6,378.137 | meters: 6378137
|
|
MeterToFeet = 3.28084,
|
|
}
|
|
|
|
export type Point = {
|
|
x: number;
|
|
y: number;
|
|
};
|
|
|
|
export interface LatLng {
|
|
lat: number;
|
|
lng: number;
|
|
}
|
|
|
|
export function realWorldDistance(p1: Point, p2: Point, unitPixel: { x: number; y: number }) {
|
|
const dx = (p2.x - p1.x) * unitPixel.x;
|
|
const dy = (p2.y - p1.y) * unitPixel.y;
|
|
const realWorldDistance = Math.sqrt(dx * dx + dy * dy);
|
|
return realWorldDistance;
|
|
}
|
|
|
|
/**
|
|
* distance between two geo coords in meeters
|
|
*/
|
|
export function haversineDistance(p1: LatLng, p2: LatLng): number {
|
|
const φ1 = toRadian(p1.lat); // phi 1
|
|
const φ2 = toRadian(p2.lat); // phi 2
|
|
const Δφ = toRadian(p2.lat - p1.lat); // delta phi
|
|
const Δλ = toRadian(p2.lng - p1.lng); // delta lambda
|
|
const a = Math.sin(Δφ / 2) * Math.sin(Δφ / 2) + Math.cos(φ1) * Math.cos(φ2) * Math.sin(Δλ / 2) * Math.sin(Δλ / 2);
|
|
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
|
|
|
return c * Constant.EarthRadiusInFt;
|
|
}
|
|
|
|
export function toRadian(degrees: number) {
|
|
return degrees * (Math.PI / 180);
|
|
}
|
|
|
|
/**
|
|
* convert geo coords to image coordinates
|
|
*/
|
|
export function geoToImgCoord(
|
|
p: LatLng,
|
|
imgW: number,
|
|
imgH: number,
|
|
boxLeft: number,
|
|
boxBottom: number,
|
|
boxRight: number,
|
|
boxTop: number,
|
|
) {
|
|
const xRatio = (p.lng - boxLeft) / (boxRight - boxLeft);
|
|
const yRatio = (p.lat - boxBottom) / (boxTop - boxBottom);
|
|
const pixelX = xRatio * imgW;
|
|
// Y-Axis Inversion i.e. 1 - yRatio, is need because
|
|
// image coordinates typically have the origin (0,0) at the top-left corner, with y increasing downward)
|
|
const pixelY = (YAxisInversion - yRatio) * imgH;
|
|
|
|
// console.log(p, imgW, imgH, boxLeft, boxBottom, boxRight, boxTop, ' = ', pixelX, pixelY);
|
|
return [pixelX, pixelY];
|
|
}
|
|
|
|
/**
|
|
* plane pixel to geo coords
|
|
*/
|
|
export function imgToGeoCoords(
|
|
p: Point,
|
|
imgW: number,
|
|
imgH: number,
|
|
boxLeft: number,
|
|
boxBottom: number,
|
|
boxRight: number,
|
|
boxTop: number,
|
|
): LatLng {
|
|
const xRatio = p.x / imgW;
|
|
const yRatio = YAxisInversion - p.y / imgH;
|
|
const lng = boxLeft + xRatio * (boxRight - boxLeft);
|
|
const lat = boxBottom + yRatio * (boxTop - boxBottom);
|
|
|
|
return { lat, lng };
|
|
} |