wgs84.ts 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. import { Angle } from './angle';
  2. const EarthRadius = 6371000;
  3. export class WGS84 {
  4. /// @brief Calculates the Haversine distance
  5. /// @param coordinate0 The first coordinate
  6. /// @param coordinate1 The second coordinate
  7. /// @return The haversine distance in metres
  8. static distance(
  9. coordinate0: { lat: number; lon: number },
  10. coordinate1: { lat: number; lon: number },
  11. ): number {
  12. const lat0 = Angle.deg2rad(coordinate0.lat);
  13. const lon0 = Angle.deg2rad(coordinate0.lon);
  14. const lat1 = Angle.deg2rad(coordinate1.lat);
  15. const lon1 = Angle.deg2rad(coordinate1.lon);
  16. const a =
  17. 0.5 -
  18. Math.cos(lat1 - lat0) * 0.5 +
  19. Math.cos(lat0) * Math.cos(lat1) * (1 - Math.cos(lon1 - lon0) * 0.5);
  20. return 2 * EarthRadius * Math.asin(Math.sqrt(a));
  21. }
  22. /// @brief Projects coordinate based on the distance and bearing
  23. /// @param coordinate The root coordinate
  24. /// @param distance The distance in metres
  25. /// @param bearing The bearing in degree
  26. static project(
  27. coordinate: { lat: number; lon: number },
  28. distance: number,
  29. bearing: number,
  30. ): { lat: number; lon: number } {
  31. const lat0 = Angle.deg2rad(coordinate.lat);
  32. const lon0 = Angle.deg2rad(coordinate.lon);
  33. const radians = Angle.deg2rad(bearing);
  34. const lat1 = Math.asin(
  35. Math.sin(lat0) * Math.cos(distance / EarthRadius) +
  36. Math.cos(lat0) * Math.sin(distance / EarthRadius) * Math.cos(radians),
  37. );
  38. const lon1 =
  39. lon0 +
  40. Math.atan2(
  41. Math.sin(radians) * Math.sin(distance / EarthRadius) * Math.cos(lat0),
  42. Math.cos(distance / EarthRadius) - Math.sin(lat0) * Math.sin(lat1),
  43. );
  44. return { lat: Angle.rad2deg(lat1), lon: Angle.rad2deg(lon1) };
  45. }
  46. }