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 }; }