Calculate Distance & Bearing Between Geolocation

Recently, I toyed with “nearby” services based on geolocation. In this post, I will be sharing C# implementation to calculate distance and bearing between geolocation.  

Let’s start with the skeleton class GLatLng below

using System;

namespace GMap
{
    public enum DistanceType : int
    {
        Miles = 0,
        Kilometers = 1
    }
   
    public class GLatLng
    {
        public const double EarthRadiusInMiles = 3956.0;
        public const double EarthRadiusInKilometers = 6367.0;
       
        private double latitude;
        private double longitude;

        public GLatLng(double latitude, double longitude)
        {
            this.latitude = latitude;
            this.longitude = longitude;
        }

        public double DegreeToRadian(double angle) { return Math.PI * angle / 180.0; }

        public double RadianToDegree(double angle) { return 180.0 * angle / Math.PI; }
       
        public double Latitude
        {
            get { return this.latitude; }
            set { this.latitude = value; }
        }
        public double Longitude
        {
            get { return this.longitude; }
            set { this.longitude = value; }
        }
    } // end class GLatLng
}

The following is the method to calculate the distance. You can choose the distance type between miles or kilometers. This uses haversine formula which give great-circle distances between two points on a sphere from their longitudes and latitudes.

public double DistanceTo(double lat, double lng, DistanceType dType)
{
    double R = (dType == DistanceType.Miles) ? EarthRadiusInMiles : EarthRadiusInKilometers;
    double dLat = DegreeToRadian(lat) - DegreeToRadian(this.latitude);
    double dLon = DegreeToRadian(lng) - DegreeToRadian(this.longitude);
    double a = Math.Sin(dLat / 2) * Math.Sin(dLat / 2) + Math.Cos(DegreeToRadian(this.latitude)) * Math.Cos(DegreeToRadian(lat)) * Math.Sin(dLon / 2) * Math.Sin(dLon / 2);
    double c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a));
    double distance = c * R;

    return Math.Round(distance, 2);
} // end DistanceTo

The second way to calculate the distance is based on the rhumb line which generally longer than great-circle routes.

public double RhumbDistanceTo(double lat, double lng, DistanceType dType)
{
    double R = (dType == DistanceType.Miles) ? EarthRadiusInMiles : EarthRadiusInKilometers;
    double lat1 = DegreeToRadian(this.latitude);
    double lat2 = DegreeToRadian(lat);
    double dLat = DegreeToRadian(lat - this.latitude);
    double dLon = DegreeToRadian(Math.Abs(lng - this.longitude));

    double dPhi = Math.Log(Math.Tan(lat2 / 2 + Math.PI / 4) / Math.Tan(lat1 / 2 + Math.PI / 4));
    double q = Math.Cos(lat1);
    if (dPhi != 0) q = dLat / dPhi;  // E-W line gives dPhi=0
    // if dLon over 180° take shorter rhumb across 180° meridian:
    if (dLon > Math.PI) dLon = 2 * Math.PI - dLon;
    double dist = Math.Sqrt(dLat * dLat + q * q * dLon * dLon) * R;

    return dist;
} // end RhumbDistanceTo

Next methods calculate the bearing between geolocation. Similar to distance there are 2 ways to calculate the bearing.


public double RhumbBearingTo(double lat, double lng)
{
    double lat1 = DegreeToRadian(this.latitude);
    double lat2 = DegreeToRadian(lat);
    double dLon = DegreeToRadian(lng - this.longitude);

    double dPhi = Math.Log(Math.Tan(lat2 / 2 + Math.PI / 4) / Math.Tan(lat1 / 2 + Math.PI / 4));
    if (Math.Abs(dLon) > Math.PI) dLon = (dLon > 0) ? -(2 * Math.PI - dLon) : (2 * Math.PI + dLon);
    double brng = Math.Atan2(dLon, dPhi);

    return (RadianToDegree(brng) + 360) % 360;
} // end RhumbBearingTo

public double BearingTo(double lat, double lng)
{
    double lat1 = DegreeToRadian(this.latitude);
    double lat2 = DegreeToRadian(lat);
    double dLon = DegreeToRadian(lng) - DegreeToRadian(this.longitude);

    double y = Math.Sin(dLon) * Math.Cos(lat2);
    double x = Math.Cos(lat1) * Math.Sin(lat2) - Math.Sin(lat1) * Math.Cos(lat2) * Math.Cos(dLon);
    double brng = Math.Atan2(y, x);

    return (RadianToDegree(brng) + 360) % 360;
} // end BearingTo

Advertisements

16 thoughts on “Calculate Distance & Bearing Between Geolocation

  1. Thanks for this post. However, if i want to compute the difference between two or more address (e.g. 113 Ohio avenue, Newyork). That is use the actual addresses rather than the lat, long etc. What do i do?

  2. Please can someone tell me what i need to download to run this sample code? I downloaded google map and i’m still missing some references

  3. After looking for different approachs this is what gives me the results I´ve been looking for, Other solutions dont returns direct solution and requires to implement additional operations.

    This one is Clear, Simply and Direct.

    Thank you very much for sharing.

  4. This website is just awesome. I’ve researched these details a whole lot and I realised that is good written, easy to understand.
    I congratulate you because of this article that I am going
    to recommend to prospects around. I request you to go
    to the gpa-calculator.co site where each university student or
    university student can calculate ratings gpa levels.
    Be great!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s