[c#] Calculating Distance between two Latitude and Longitude GeoCoordinates

I'm calculating the distance between two GeoCoordinates. I'm testing my app against 3-4 other apps. When I'm calculating distance, I tend to get an average of 3.3 miles for my calculation whereas other apps are getting 3.5 miles. It's a big difference for the calculation I'm trying to perform. Are there any good class libraries out there for calculating distance? I'm calculating it like this in C#:

public static double Calculate(double sLatitude,double sLongitude, double eLatitude, 
                               double eLongitude)
{
    var radiansOverDegrees = (Math.PI / 180.0);

    var sLatitudeRadians = sLatitude * radiansOverDegrees;
    var sLongitudeRadians = sLongitude * radiansOverDegrees;
    var eLatitudeRadians = eLatitude * radiansOverDegrees;
    var eLongitudeRadians = eLongitude * radiansOverDegrees;

    var dLongitude = eLongitudeRadians - sLongitudeRadians;
    var dLatitude = eLatitudeRadians - sLatitudeRadians;

    var result1 = Math.Pow(Math.Sin(dLatitude / 2.0), 2.0) + 
                  Math.Cos(sLatitudeRadians) * Math.Cos(eLatitudeRadians) * 
                  Math.Pow(Math.Sin(dLongitude / 2.0), 2.0);

    // Using 3956 as the number of miles around the earth
    var result2 = 3956.0 * 2.0 * 
                  Math.Atan2(Math.Sqrt(result1), Math.Sqrt(1.0 - result1));

    return result2;
}

What could I be doing wrong? Should I calculate it in km first and then convert to miles?

This question is related to c# windows-phone-7 geocoding latitude-longitude

The answer is


Here is the JavaScript version guys and gals

function distanceTo(lat1, lon1, lat2, lon2, unit) {
      var rlat1 = Math.PI * lat1/180
      var rlat2 = Math.PI * lat2/180
      var rlon1 = Math.PI * lon1/180
      var rlon2 = Math.PI * lon2/180
      var theta = lon1-lon2
      var rtheta = Math.PI * theta/180
      var dist = Math.sin(rlat1) * Math.sin(rlat2) + Math.cos(rlat1) * Math.cos(rlat2) * Math.cos(rtheta);
      dist = Math.acos(dist)
      dist = dist * 180/Math.PI
      dist = dist * 60 * 1.1515
      if (unit=="K") { dist = dist * 1.609344 }
      if (unit=="N") { dist = dist * 0.8684 }
      return dist
}

For those who are using Xamarin and don't have access to the GeoCoordinate class, you can use the Android Location class instead:

public static double GetDistanceBetweenCoordinates (double lat1, double lng1, double lat2, double lng2) {
            var coords1 = new Location ("");
            coords1.Latitude = lat1;
            coords1.Longitude = lng1;
            var coords2 = new Location ("");
            coords2.Latitude = lat2;
            coords2.Longitude = lng2;
            return coords1.DistanceTo (coords2);
        }

And here, for those still not satisfied (like me), the original code from .NET-Frameworks GeoCoordinate class, refactored into a standalone method:

public double GetDistance(double longitude, double latitude, double otherLongitude, double otherLatitude)
{
    var d1 = latitude * (Math.PI / 180.0);
    var num1 = longitude * (Math.PI / 180.0);
    var d2 = otherLatitude * (Math.PI / 180.0);
    var num2 = otherLongitude * (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)));
}

You can use this function :

Source : https://www.geodatasource.com/developers/c-sharp

private double distance(double lat1, double lon1, double lat2, double lon2, char unit) {
  if ((lat1 == lat2) && (lon1 == lon2)) {
    return 0;
  }
  else {
    double theta = lon1 - lon2;
    double dist = Math.Sin(deg2rad(lat1)) * Math.Sin(deg2rad(lat2)) + Math.Cos(deg2rad(lat1)) * Math.Cos(deg2rad(lat2)) * Math.Cos(deg2rad(theta));
    dist = Math.Acos(dist);
    dist = rad2deg(dist);
    dist = dist * 60 * 1.1515;
    if (unit == 'K') {
      dist = dist * 1.609344;
    } else if (unit == 'N') {
      dist = dist * 0.8684;
    }
    return (dist);
  }
}

//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
//::  This function converts decimal degrees to radians             :::
//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
private double deg2rad(double deg) {
  return (deg * Math.PI / 180.0);
}

//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
//::  This function converts radians to decimal degrees             :::
//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
private double rad2deg(double rad) {
  return (rad / Math.PI * 180.0);
}

Console.WriteLine(distance(32.9697, -96.80322, 29.46786, -98.53506, "M"));
Console.WriteLine(distance(32.9697, -96.80322, 29.46786, -98.53506, "K"));
Console.WriteLine(distance(32.9697, -96.80322, 29.46786, -98.53506, "N"));

GetDistance is the best solution, but in many cases we can't use this Method (e.g. Universal App)

  • Pseudocode of the Algorithm to calculate the distance between to coorindates:

    public static double DistanceTo(double lat1, double lon1, double lat2, double lon2, char unit = 'K')
    {
        double rlat1 = Math.PI*lat1/180;
        double rlat2 = Math.PI*lat2/180;
        double theta = lon1 - lon2;
        double rtheta = Math.PI*theta/180;
        double dist =
            Math.Sin(rlat1)*Math.Sin(rlat2) + Math.Cos(rlat1)*
            Math.Cos(rlat2)*Math.Cos(rtheta);
        dist = Math.Acos(dist);
        dist = dist*180/Math.PI;
        dist = dist*60*1.1515;
    
        switch (unit)
        {
            case 'K': //Kilometers -> default
                return dist*1.609344;
            case 'N': //Nautical Miles 
                return dist*0.8684;
            case 'M': //Miles
                return dist;
        }
    
        return dist;
    }
    
  • Real World C# Implementation, which makes use of an Extension Methods

    Usage:

    var distance = new Coordinates(48.672309, 15.695585)
                    .DistanceTo(
                        new Coordinates(48.237867, 16.389477),
                        UnitOfLength.Kilometers
                    );
    

    Implementation:

    public class Coordinates
    {
        public double Latitude { get; private set; }
        public double Longitude { get; private set; }
    
        public Coordinates(double latitude, double longitude)
        {
            Latitude = latitude;
            Longitude = longitude;
        }
    }
    public static class CoordinatesDistanceExtensions
    {
        public static double DistanceTo(this Coordinates baseCoordinates, Coordinates targetCoordinates)
        {
            return DistanceTo(baseCoordinates, targetCoordinates, UnitOfLength.Kilometers);
        }
    
        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 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;
        }
    } 
    

Calculating Distance between Latitude and Longitude points...

        double Lat1 = Convert.ToDouble(latitude);
        double Long1 = Convert.ToDouble(longitude);

        double Lat2 = 30.678;
        double Long2 = 45.786;
        double circumference = 40000.0; // Earth's circumference at the equator in km
        double distance = 0.0;
        double latitude1Rad = DegreesToRadians(Lat1);
        double latititude2Rad = DegreesToRadians(Lat2);
        double longitude1Rad = DegreesToRadians(Long1);
        double longitude2Rad = DegreesToRadians(Long2);
        double logitudeDiff = Math.Abs(longitude1Rad - longitude2Rad);
        if (logitudeDiff > Math.PI)
        {
            logitudeDiff = 2.0 * Math.PI - logitudeDiff;
        }
        double angleCalculation =
            Math.Acos(
              Math.Sin(latititude2Rad) * Math.Sin(latitude1Rad) +
              Math.Cos(latititude2Rad) * Math.Cos(latitude1Rad) * Math.Cos(logitudeDiff));
        distance = circumference * angleCalculation / (2.0 * Math.PI);
        return distance;

Based on Elliot Wood's function, and if anyone is interested in a C function, this one is working...

#define SIM_Degree_to_Radian(x) ((float)x * 0.017453292F)
#define SIM_PI_VALUE                         (3.14159265359)

float GPS_Distance(float lat1, float lon1, float lat2, float lon2)
{
   float theta;
   float dist;

   theta = lon1 - lon2;

   lat1 = SIM_Degree_to_Radian(lat1);
   lat2 = SIM_Degree_to_Radian(lat2);
   theta = SIM_Degree_to_Radian(theta);

   dist = (sin(lat1) * sin(lat2)) + (cos(lat1) * cos(lat2) * cos(theta));
   dist = acos(dist);

//   dist = dist * 180.0 / SIM_PI_VALUE;
//   dist = dist * 60.0 * 1.1515;
//   /* Convert to km */
//   dist = dist * 1.609344;

   dist *= 6370.693486F;

   return (dist);
}

You may change it to double. It returns the value in km.


When CPU/math computing power is limited:

There are times (such as in my work) when computing power is scarce (e.g. no floating point processor, working with small microcontrollers) where some trig functions can take an exorbitant amount of CPU time (e.g. 3000+ clock cycles), so when I only need an approximation, especially if if the CPU must not be tied up for a long time, I use this to minimize CPU overhead:

/**------------------------------------------------------------------------
 * \brief  Great Circle distance approximation in km over short distances.
 *
 * Can be off by as much as 10%.
 *
 * approx_distance_in_mi = sqrt(x * x + y * y)
 *
 * where x = 69.1 * (lat2 - lat1)
 * and y = 69.1 * (lon2 - lon1) * cos(lat1/57.3)
 *//*----------------------------------------------------------------------*/
double    ApproximateDisatanceBetweenTwoLatLonsInKm(
                  double lat1, double lon1,
                  double lat2, double lon2
                  ) {
    double  ldRadians, ldCosR, x, y;

    ldRadians = (lat1 / 57.3) * 0.017453292519943295769236907684886;
    ldCosR = cos(ldRadians);
    x = 69.1 * (lat2 - lat1);
    y = 69.1 * (lon2 - lon1) * ldCosR;

    return sqrt(x * x + y * y) * 1.609344;  /* Converts mi to km. */
}

Credit goes to https://github.com/kristianmandrup/geo_vectors/blob/master/Distance%20calc%20notes.txt.


You can use System.device.Location:

System.device.Location.GeoCoordinate gc = new System.device.Location.GeoCoordinate(){
Latitude = yourLatitudePt1,
Longitude = yourLongitudePt1
};

System.device.Location.GeoCoordinate gc2 = new System.device.Location.GeoCoordinate(){
Latitude = yourLatitudePt2,
Longitude = yourLongitudePt2
};

Double distance = gc2.getDistanceTo(gc);

good luck


This is an old question, nevertheless the answers did not satisfy me regarding to performance and optimization.

Here my optimized C# variant (distance in km, without variables and redundant calculations, very close to mathematical expression of Haversine Formular https://en.wikipedia.org/wiki/Haversine_formula).

Inspired by: https://rosettacode.org/wiki/Haversine_formula#C.23

public static class Haversine
{
    public static double Calculate(double lat1, double lon1, double lat2, double lon2)
    {
        double rad(double angle) => angle * 0.017453292519943295769236907684886127d; // = angle * Math.Pi / 180.0d
        double havf(double diff) => Math.Pow(Math.Sin(rad(diff) / 2d), 2); // = sinĀ²(diff / 2)
        return 12745.6 * Math.Asin(Math.Sqrt(havf(lat2 - lat1) + Math.Cos(rad(lat1)) * Math.Cos(rad(lat2)) * havf(lon2 - lon1))); // earth radius 6.372,8?km x 2 = 12745.6
    }
}

Haversine Formular from Wikipedia


There's this library GeoCoordinate for these platforms:

  • Mono
  • .NET 4.5
  • .NET Core
  • Windows Phone 8.x
  • Universal Windows Platform
  • Xamarin iOS
  • Xamarin Android

Installation is done via NuGet:

PM> Install-Package GeoCoordinate

Usage

GeoCoordinate pin1 = new GeoCoordinate(lat, lng);
GeoCoordinate pin2 = new GeoCoordinate(lat, lng);

double distanceBetween = pin1.GetDistanceTo(pin2);

The distance between the two coordinates, in meters.


Try this:

    public double getDistance(GeoCoordinate p1, GeoCoordinate p2)
    {
        double d = p1.Latitude * 0.017453292519943295;
        double num3 = p1.Longitude * 0.017453292519943295;
        double num4 = p2.Latitude * 0.017453292519943295;
        double num5 = p2.Longitude * 0.017453292519943295;
        double num6 = num5 - num3;
        double num7 = num4 - d;
        double num8 = Math.Pow(Math.Sin(num7 / 2.0), 2.0) + ((Math.Cos(d) * Math.Cos(num4)) * Math.Pow(Math.Sin(num6 / 2.0), 2.0));
        double num9 = 2.0 * Math.Atan2(Math.Sqrt(num8), Math.Sqrt(1.0 - num8));
        return (6376500.0 * num9);
    }

Examples related to c#

How can I convert this one line of ActionScript to C#? Microsoft Advertising SDK doesn't deliverer ads How to use a global array in C#? How to correctly write async method? C# - insert values from file into two arrays Uploading into folder in FTP? Are these methods thread safe? dotnet ef not found in .NET Core 3 HTTP Error 500.30 - ANCM In-Process Start Failure Best way to "push" into C# array

Examples related to windows-phone-7

How to post data using HttpClient? Programmatically set TextBlock Foreground Color Converting a JToken (or string) to a given Type Setting the User-Agent header for a WebClient request How to POST request using RestSharp How can I data bind a list of strings to a ListBox in WPF/WP7? Can we install Android OS on any Windows Phone and vice versa, and same with iPhone and vice versa? Add custom header in HttpWebRequest Calculating Distance between two Latitude and Longitude GeoCoordinates Deserializing JSON array into strongly typed .NET object

Examples related to geocoding

This API project is not authorized to use this API. Please ensure that this API is activated in the APIs Console Create or update mapping in elasticsearch Getting distance between two points based on latitude/longitude Measuring the distance between two coordinates in PHP Why doesn't file_get_contents work? How can I get city name from a latitude and longitude point? Calculating Distance between two Latitude and Longitude GeoCoordinates Given the lat/long coordinates, how can we find out the city/country? Google Maps: how to get country, state/province/region, city given a lat/long value? Get latitude and longitude based on location name with Google Autocomplete API

Examples related to latitude-longitude

How to get a time zone from a location using latitude and longitude coordinates? What are the lengths of Location Coordinates, latitude and longitude? Using Address Instead Of Longitude And Latitude With Google Maps API Google Maps API - how to get latitude and longitude from Autocomplete without showing the map? Which data type for latitude and longitude? Calculating distance between two geographic locations How can I enter latitude and longitude in Google Maps? Calculate the center point of multiple latitude/longitude coordinate pairs How can I get city name from a latitude and longitude point? Calculating Distance between two Latitude and Longitude GeoCoordinates