Haversine Formula in C# and in SQL
My blog is now located at http://www.WhoIsSethLong.com
The Haversine Formula class listed below is used to calculate the distance between two latitude/longitude points in either Kilometers or Miles. I’ve seen the formula written in a few other languages but didn’t see any in C#. So, here is the Haversine Formula in C#. Before I show the class, let me give an example of how the class is called and used.
To start we will need 2 latitude/longitude points. I created a struct to hold the latitude/longitude points. Once we have the points, we create the Haversine class and call the Distance method, passing in the points and an enum specifying whether to return the results in Kilometers or Miles. We end up with the following:
Position pos1 = new Position(); pos1.Latitude = 40.7486; pos1.Longitude = -73.9864; Position pos2 = new Position(); pos2.Latitude = 24.7486; pos2.Longitude = -72.9864; Haversine hv = new Haversine(); double result = hv.Distance(pos1, pos2, DistanceType.Kilometers);Here is the code for the class:
using System; namespace HaversineFormula { /// <summary> /// The distance type to return the results in. /// </summary> public enum DistanceType { Miles, Kilometers }; /// <summary> /// Specifies a Latitude / Longitude point. /// </summary> public struct Position { public double Latitude; public double Longitude; } class Haversine { /// <summary> /// Returns the distance in miles or kilometers of any two /// latitude / longitude points. /// </summary> /// <param name=”pos1″></param> /// <param name=”pos2″></param> /// <param name=”type”></param> /// <returns></returns> public double Distance(Position pos1, Position pos2, DistanceType type) { double R = (type == DistanceType.Miles) ? 3960 : 6371; double dLat = this.toRadian(pos2.Latitude – pos1.Latitude); double dLon = this.toRadian(pos2.Longitude – pos1.Longitude); double a = Math.Sin(dLat / 2) * Math.Sin(dLat / 2) + Math.Cos(this.toRadian(pos1.Latitude)) * Math.Cos(this.toRadian(pos2.Latitude)) * Math.Sin(dLon / 2) * Math.Sin(dLon / 2); double c = 2 * Math.Asin(Math.Min(1, Math.Sqrt(a))); double d = R * c; return d; } /// <summary> /// Convert to Radians. /// </summary> /// <param name=”val”></param> /// <returns></returns> private double toRadian(double val) { return (Math.PI / 180) * val; } } }Here is the same formula as a SQL function. I used Microsoft SQL server for this example.
CREATE FUNCTION [dbo].[GetDistance]
( @lat1 Float(8), @long1 Float(8), @lat2 Float(8), @long2 Float(8) ) RETURNS Float(8) AS BEGIN DECLARE @R Float(8); DECLARE @dLat Float(8); DECLARE @dLon Float(8); DECLARE @a Float(8); DECLARE @c Float(8); DECLARE @d Float(8); SET @R = 3960; SET @dLat = RADIANS(@lat2 - @lat1); SET @dLon = RADIANS(@long2 - @long1); SET @a = SIN(@dLat / 2) * SIN(@dLat / 2) + COS(RADIANS(@lat1)) * COS(RADIANS(@lat2)) * SIN(@dLon / 2) * SIN(@dLon / 2); SET @c = 2 * ASIN(MIN(SQRT(@a))); SET @d = @R * @c; RETURN @d; END GO- Seth Long
-
Archives
- May 2008 (1)
- February 2008 (3)
- January 2008 (6)
-
Categories
-
RSS
Entries RSS
Comments RSS
Hello, my name is Seth Long and I’m a Senior Software Engineer for SpeedDate.com in the San Francisco Bay Area.