Click here to Skip to main content
Click here to Skip to main content
 

Distance between locations using latitude and longitude

By , 16 Dec 2005
Rate this:
Please Sign up or sign in to vote.

Introduction

This code drop is part of a Smash and Grab series. I'll bet there are a lot of other programmers out there that would like to make code available to others, but just don't want to spend hours required to create a full-blown "CodeProject" article. This is an attempt to see if I can make some useful code available to other programmers, and do it in 10 minutes. I encourage others to contribute to "Smash and Grab".

The basic rules are:

  • It should be a C# class, which solves a simple problem.
  • Don't waste the reader's time with GUI stuff and "OnClick" methods.
  • If at all possible, make it a console app with a "Main()" that illustrates its functionality.

The point of this series is to present usable pre-canned classes or techniques which solve a real world problem without going into too much detail about how it works. I mean, who really cares about how System.Collections.ArrayList works, you just use it.

Please fully comment the code so that the person who really cares (and has the time) will be able to understand the underlying algorithm.

Using the code

I wanted a .NET class which would tell me the distance between two locations. There were all sorts of bits of code out on the net which attempted to do this in JavaScript but the programmers obviously could not separate the algorithm from the GUI. This is my humble attempt at a pure non-GUI class which will calculate the distance between two locations.

using System;
using System.Text;

public class CDistanceBetweenLocations
{
    public static double Calc(double Lat1, 
                  double Long1, double Lat2, double Long2)
    {
        /*
            The Haversine formula according to Dr. Math.
            http://mathforum.org/library/drmath/view/51879.html
                
            dlon = lon2 - lon1
            dlat = lat2 - lat1
            a = (sin(dlat/2))^2 + cos(lat1) * cos(lat2) * (sin(dlon/2))^2
            c = 2 * atan2(sqrt(a), sqrt(1-a)) 
            d = R * c
                
            Where
                * dlon is the change in longitude
                * dlat is the change in latitude
                * c is the great circle distance in Radians.
                * R is the radius of a spherical Earth.
                * The locations of the two points in 
                    spherical coordinates (longitude and 
                    latitude) are lon1,lat1 and lon2, lat2.
        */
        double dDistance = Double.MinValue;
        double dLat1InRad = Lat1 * (Math.PI / 180.0);
        double dLong1InRad = Long1 * (Math.PI / 180.0);
        double dLat2InRad = Lat2 * (Math.PI / 180.0);
        double dLong2InRad = Long2 * (Math.PI / 180.0);

        double dLongitude = dLong2InRad - dLong1InRad;
        double dLatitude = dLat2InRad - dLat1InRad;

        // Intermediate result a.
        double a = Math.Pow(Math.Sin(dLatitude / 2.0), 2.0) + 
                   Math.Cos(dLat1InRad) * Math.Cos(dLat2InRad) * 
                   Math.Pow(Math.Sin(dLongitude / 2.0), 2.0);

        // Intermediate result c (great circle distance in Radians).
        double c = 2.0 * Math.Asin(Math.Sqrt(a));

        // Distance.
        // const Double kEarthRadiusMiles = 3956.0;
        const Double kEarthRadiusKms = 6376.5;
        dDistance = kEarthRadiusKms * c;

        return dDistance;
    }

    public static double Calc(string NS1, double Lat1, double Lat1Min, 
           string EW1, double Long1, double Long1Min, string NS2, 
           double Lat2, double Lat2Min, string EW2, 
           double Long2, double Long2Min)
    {
        double NS1Sign = NS1.ToUpper() == "N" ? 1.0 : -1.0;
        double EW1Sign = EW1.ToUpper() == "E" ? 1.0 : -1.0;
        double NS2Sign = NS2.ToUpper() == "N" ? 1.0 : -1.0;
        double EW2Sign = EW2.ToUpper() == "E" ? 1.0 : -1.0;
        return (Calc(
            (Lat1 + (Lat1Min / 60)) * NS1Sign,
            (Long1 + (Long1Min / 60)) * EW1Sign,
            (Lat2 + (Lat2Min / 60)) * NS2Sign,
            (Long2 + (Long2Min / 60)) * EW2Sign
            ));
    }

    public static void Main(string[] args)
    {
        if (args.Length < 12)
        {
            System.Console.WriteLine("usage: DistanceBetweenLocations" + 
                    " N 43 35.500 W 80 27.800 N 43 35.925 W 80 28.318");
            return;
        }
        System.Console.WriteLine(Calc(
            args[0], 
            System.Double.Parse(args[1]), 
            System.Double.Parse(args[2]), 
            args[3], 
            System.Double.Parse(args[4]), 
            System.Double.Parse(args[5]), 
            args[6], 
            System.Double.Parse(args[7]), 
            System.Double.Parse(args[8]), 
            args[9], 
            System.Double.Parse(args[10]), 
            System.Double.Parse(args[11])));

    }

}

Here is an MS-SQL user defined function. I never really understood why this math functionality was in SQL Server until now! You can use this function in a query statement to find the nearest Tim Horton's!!!

CREATE FUNCTION [dbo].[DistanceBetween] (@Lat1 as real, 
                @Long1 as real, @Lat2 as real, @Long2 as real)
RETURNS real
AS
BEGIN

DECLARE @dLat1InRad as float(53);
SET @dLat1InRad = @Lat1 * (PI()/180.0);
DECLARE @dLong1InRad as float(53);
SET @dLong1InRad = @Long1 * (PI()/180.0);
DECLARE @dLat2InRad as float(53);
SET @dLat2InRad = @Lat2 * (PI()/180.0);
DECLARE @dLong2InRad as float(53);
SET @dLong2InRad = @Long2 * (PI()/180.0);

DECLARE @dLongitude as float(53);
SET @dLongitude = @dLong2InRad - @dLong1InRad;
DECLARE @dLatitude as float(53);
SET @dLatitude = @dLat2InRad - @dLat1InRad;
/* Intermediate result a. */
DECLARE @a as float(53);
SET @a = SQUARE (SIN (@dLatitude / 2.0)) + COS (@dLat1InRad) 
                 * COS (@dLat2InRad) 
                 * SQUARE(SIN (@dLongitude / 2.0));
/* Intermediate result c (great circle distance in Radians). */
DECLARE @c as real;
SET @c = 2.0 * ATN2 (SQRT (@a), SQRT (1.0 - @a));
DECLARE @kEarthRadius as real;
/* SET kEarthRadius = 3956.0 miles */
SET @kEarthRadius = 6376.5;        /* kms */

DECLARE @dDistance as real;
SET @dDistance = @kEarthRadius * @c;
return (@dDistance);
END

OK, this first one took me longer than 10 minutes, but the next one won't.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Gary Dryden
Software Developer (Senior)
Canada Canada
No Biography provided

Comments and Discussions

 
GeneralMy vote of 5 PinmemberBernard Chayer27-Jun-13 5:47 
QuestionDistance between two locations using Latittude and longitude Pinmembers pullareddy21-May-13 2:37 
QuestionThanks for this article Pinmembernguyenlx9018-May-13 3:46 
GeneralMy vote of 4 Pinmember941066242219-Oct-12 20:44 
Questionquestion about the other way around Pinmemberomrivm12-Aug-11 5:30 
Questionquestion Pinmemberfithri1-Aug-11 16:50 
AnswerRe: question PinmemberGary Dryden2-Aug-11 3:46 
QuestionQuestion? PinmemberRichardg327-Jul-11 21:24 
AnswerRe: Question? PinmemberGary Dryden28-Jul-11 2:58 
GeneralSimpler Trig Pinmemberziopino7015-Apr-10 22:08 
AnswerDistance Calculator for Postgre PinmemberThe Swatchster6-Apr-10 6:08 
GeneralFind one bug ! Pinmemberkingdomkao13-Jan-09 14:51 
GeneralRe: Find one bug ! PinmemberMember 21446195-Apr-09 5:22 
GeneralThanks! PinmemberEdithzor29-Jul-08 12:28 
GeneralDirection from one location from other using latitudes and longitudes PinmemberMember 392548028-Mar-08 1:05 
GeneralNo nonsense - straight, working code PinmemberLarsenLP7-Sep-07 0:15 
QuestionMiles or Kilometers? Pinmemberdeanj30-Jul-07 9:10 
AnswerRe: Miles or Kilometers? PinmemberGary Dryden30-Jul-07 12:33 
GeneralFinding lat and long for address Pinmembersides_dale14-Mar-06 15:14 
GeneralRe: Finding lat and long for address PinmemberGary Dryden15-Mar-06 2:25 
GeneralYou PLAGIARIZED Dr. Math's formula! PinmemberBill SerGio, The Infomercial King17-Dec-05 0:43 
GeneralA serious note about this PinmemberBill SerGio, The Infomercial King17-Dec-05 0:04 
GeneralFrom Bill SerGio PinmemberBill SerGio, The Infomercial King16-Dec-05 23:49 
GeneralUnit testing PinprotectorMarc Clifton16-Dec-05 8:40 
GeneralRe: Unit testing - C++ versus C# .NET PinmemberBill SerGio, The Infomercial King17-Dec-05 1:13 
GeneralNot as good as my article PinmemberBill SerGio, The Infomercial King16-Dec-05 5:31 
GeneralRe: Not as good as my article PinmemberHarkos16-Dec-05 10:06 
GeneralFrom Bill SerGio PinmemberBill SerGio, The Infomercial King17-Dec-05 1:01 
GeneralRe: From Bill SerGio PinmemberSimon Capewell22-Dec-05 5:39 
GeneralRe: Not as good as my article Pinmemberjtstogner16-Dec-05 15:20 
GeneralRe: Not as good as my article PinmemberGary Dryden16-Dec-05 15:34 
GeneralRe: Not as good as my article Pinmemberjtstogner16-Dec-05 18:50 
GeneralRe: Not as good as my article PinmemberBill SerGio, The Infomercial King16-Dec-05 23:38 
GeneralRe: Not as good as my article Pinmemberjtstogner17-Dec-05 3:01 
GeneralRe: Not as good as my article PinmemberBill SerGio, The Infomercial King17-Dec-05 3:14 
GeneralRe: Not as good as my article Pinmemberjtstogner17-Dec-05 3:23 
Generalpathetic. Was: Re: Not as good as my article Pinmemberfrugalmail18-Dec-05 7:33 
GeneralRe: pathetic. Was: Re: Not as good as my article Pinmemberjtstogner18-Dec-05 9:29 
GeneralYour English is So BAD! PinmemberBill SerGio, The Infomercial King17-Dec-05 3:49 
GeneralRe: Your English is So BAD! PinmemberRick van Woudenberg15-Jul-07 23:03 
GeneralRe: Your English is So BAD! PinmemberDave1975199527-Sep-07 7:07 
GeneralRe: Your English is So BAD! Pinmembermegavolt1215-Aug-07 22:41 
GeneralAmercans don't support you Pinmembertvproducer316-Aug-07 0:15 
GeneralRe: Amercans don't support you PinmemberDave1975199527-Sep-07 7:18 
GeneralRe: Not as good as my article PinmemberBill SerGio, The Infomercial King17-Dec-05 1:05 
GeneralYou PLAGIARIZED Dr. Math's formula! PinmemberBill SerGio, The Infomercial King17-Dec-05 0:41 
GeneralRe: Not as good as my article PinmemberBill SerGio, The Infomercial King16-Dec-05 23:34 
GeneralRe: Not as good as my article PinmemberSimon Capewell22-Dec-05 3:56 
GeneralRe: Not as good as my article PinmemberBill SerGio, The Infomercial King22-Dec-05 4:45 
GeneralRe: Not as good as my article PinmemberSimon Capewell22-Dec-05 5:06 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web03 | 2.8.140415.2 | Last Updated 16 Dec 2005
Article Copyright 2005 by Gary Dryden
Everything else Copyright © CodeProject, 1999-2014
Terms of Use
Layout: fixed | fluid