Coding Notes

Ideas and thoughts from Seth Long

Haversine Formula in C# and in SQL

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


Advertisements

February 5, 2008 Posted by | Algorithms | 18 Comments