import { Angle } from './angle'; const EarthRadius = 6371000; export class WGS84 { /// @brief Calculates the Haversine distance /// @param coordinate0 The first coordinate /// @param coordinate1 The second coordinate /// @return The haversine distance in metres static distance( coordinate0: { lat: number; lon: number }, coordinate1: { lat: number; lon: number }, ): number { const lat0 = Angle.deg2rad(coordinate0.lat); const lon0 = Angle.deg2rad(coordinate0.lon); const lat1 = Angle.deg2rad(coordinate1.lat); const lon1 = Angle.deg2rad(coordinate1.lon); const a = 0.5 - Math.cos(lat1 - lat0) * 0.5 + Math.cos(lat0) * Math.cos(lat1) * (1 - Math.cos(lon1 - lon0) * 0.5); return 2 * EarthRadius * Math.asin(Math.sqrt(a)); } /// @brief Projects coordinate based on the distance and bearing /// @param coordinate The root coordinate /// @param distance The distance in metres /// @param bearing The bearing in degree static project( coordinate: { lat: number; lon: number }, distance: number, bearing: number, ): { lat: number; lon: number } { const lat0 = Angle.deg2rad(coordinate.lat); const lon0 = Angle.deg2rad(coordinate.lon); const radians = Angle.deg2rad(bearing); const lat1 = Math.asin( Math.sin(lat0) * Math.cos(distance / EarthRadius) + Math.cos(lat0) * Math.sin(distance / EarthRadius) * Math.cos(radians), ); const lon1 = lon0 + Math.atan2( Math.sin(radians) * Math.sin(distance / EarthRadius) * Math.cos(lat0), Math.cos(distance / EarthRadius) - Math.sin(lat0) * Math.sin(lat1), ); return { lat: Angle.rad2deg(lat1), lon: Angle.rad2deg(lon1) }; } }