From 63cfa5dbe5fd1ac663743982c848092ef9d6af40 Mon Sep 17 00:00:00 2001 From: versx Date: Mon, 2 Nov 2020 01:18:44 -0800 Subject: [PATCH] Replace distance algorithm (#57) --- .../CoordinatesDistanceExtensions.cs | 64 +++++++------------ 1 file changed, 24 insertions(+), 40 deletions(-) diff --git a/src/Extensions/CoordinatesDistanceExtensions.cs b/src/Extensions/CoordinatesDistanceExtensions.cs index 7045d8b9..591f0713 100644 --- a/src/Extensions/CoordinatesDistanceExtensions.cs +++ b/src/Extensions/CoordinatesDistanceExtensions.cs @@ -17,47 +17,31 @@ public Coordinates(double latitude, double longitude) public static class CoordinatesDistanceExtensions { - public static double DistanceTo(this Coordinates baseCoordinates, Coordinates targetCoordinates) + /// + /// Returns the distance between the latitude and longitude coordinates that are specified by this Coordinate and + /// another specified Coordinate. + /// + /// + /// The distance between the two coordinates, in meters. + /// + /// The Coordinate for the location to calculate the distance from. + /// The Coordinate for the location to calculate the distance to. + public static double DistanceTo(this Coordinates from, Coordinates to) { - return DistanceTo(baseCoordinates, targetCoordinates, UnitOfLength.Meters); - } - - public static double DistanceTo(this Coordinates baseCoordinates, Coordinates targetCoordinates, UnitOfLength unitOfLength) - { - var baseRad = Math.PI * baseCoordinates.Latitude / 180; - var targetRad = Math.PI * targetCoordinates.Latitude / 180; - var theta = baseCoordinates.Longitude - targetCoordinates.Longitude; - var thetaRad = Math.PI * theta / 180; - - double dist = - Math.Sin(baseRad) * Math.Sin(targetRad) + Math.Cos(baseRad) * - Math.Cos(targetRad) * Math.Cos(thetaRad); - dist = Math.Acos(dist); - - dist = dist * 180 / Math.PI; - dist = dist * 60 * 1.1515; - - return unitOfLength.ConvertFromMiles(dist); - } - } - - public class UnitOfLength - { - public static UnitOfLength Kilometers = new UnitOfLength(1.609344); - public static UnitOfLength Meters = new UnitOfLength(0.01609344); - public static UnitOfLength NauticalMiles = new UnitOfLength(0.8684); - public static UnitOfLength Miles = new UnitOfLength(1); - - private readonly double _fromMilesFactor; - - private UnitOfLength(double fromMilesFactor) - { - _fromMilesFactor = fromMilesFactor; - } - - public double ConvertFromMiles(double input) - { - return input * _fromMilesFactor; + if (double.IsNaN(from.Latitude) || double.IsNaN(from.Longitude) || + double.IsNaN(to.Latitude) || double.IsNaN(to.Longitude)) + { + throw new ArgumentException("Argument latitude or longitude is not a number"); + } + + var d1 = from.Latitude * (Math.PI / 180.0); + var num1 = from.Longitude * (Math.PI / 180.0); + var d2 = to.Latitude * (Math.PI / 180.0); + var num2 = to.Longitude * (Math.PI / 180.0) - num1; + var d3 = Math.Pow(Math.Sin((d2 - d1) / 2.0), 2.0) + + Math.Cos(d1) * Math.Cos(d2) * Math.Pow(Math.Sin(num2 / 2.0), 2.0); + + return 6376500.0 * (2.0 * Math.Atan2(Math.Sqrt(d3), Math.Sqrt(1.0 - d3))); } } } \ No newline at end of file