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

nice Tutorial.

[…] Despite extensive Googling, I was not able to find a nice C# implementation…until I found this one. […]

The code is simple but useful. Could I used it in my source code?

PhaLe

hi,

sure. u may use the code.

magnificent issues altogether, you just won a brand new reader.

What might you suggest about your post that you simply made a few

days ago? Any sure?

Wow, fantastic blog layout! How long have you been blogging for?

you make blogging look easy. The overall look of your site is great,

let alone the content!

Your style is unique compared to other people I have read

stuff from. Many thanks for posting when you have the opportunity, Guess I will just book

mark this blog.

Hi there to every , as I am actually eager of reading this website’s post to be updated on a regular basis. It carries pleasant information.

If some one desires expert view regarding blogging and site-building then i suggest him/her to pay

a quick visit this webpage, Keep up the nice job.

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?

That require knowledge of the street map. I suggest you try Google Map API. https://developers.google.com/maps/documentation/directions/ , the API allows you to input multiple waypoints (address).

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

[…] Despite extensive Googling, I was not able to find a nice C# implementation…until I found this one. […]

Hey! Do you use Twitter? I’d like to follow you if that would be ok.

I’m absolutely enjoying your blog and look forward to new posts.

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.

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!