Skip to content

How to calculate the distance between two geographic points in C #? (Haversine’s formula)

23 mayo, 2021

Calculating the distance between two points on a plane could be relatively easy. However, when we locate these two points on the terrestrial sphere, that is, what we intend is to calculate the linear distance between two given positions (latitude + longitude), things get complicated.

Basically it is complicated because in the calculation of the distance between both positions we must consider the curvature of the earth. This is where the Haversine Formula comes into play.

Without going into too much detail in mathematical terms, the Haversine formula it is:

R = radius of the Earth

Δlat = lat2− lat1

Δlong = long2− long1

a = sin² (Δlat / 2) + cos (lat1) cos (lat2) sin² (Δlong / 2)

c = 2 atan2 (√a, √ (1 − a))

d = R c

To use the Haversine Formula we need, in addition to the two positions (lat + lon), the radius of the Earth. This value is relative to latitude, because since the Earth is not perfectly round, the value of the equatorial radius is 6378 km while the polar is 6357 km. The Equivolume radius is 6371 km. For this post we will use the equatorial radius value.

Therefore, the first thing we will do is represent the class Position, which is nothing more than a class with a couple of properties related to longitude and latitude.

public class Posicion
{
  public Posicion(float latitud, float longitud)
  {
      Latitud = latitud;
      Longitud = longitud;
  }
  public float Latitud { get; set; }
  public float Longitud { get; set; }
}

Speaking in C #, what I mean is that, given two objects of the type Position, you can do something like this to calculate the distance between the two. If we have the object Equalizer representing the georeferenced location of the city and we want to know the linear distance with grenade, we will do the following:

[Test]
public void Test()
{
  var Igualada = new Posicion(41.57879F,  1.617221F);
  var Granada = new Posicion(37.176487F, -3.597929F);
  float distancia =
      Igualada.DistanciaKm(Granada);
  Assert.AreEqual(664.0D, System.Math.Round(distancia));
}

For this we are going to create an extender method called DistanceKm on the Position class, which will have the responsibility of calculating the distance between both positions; in short, it will contain the Haversine Formula:

public static class Extensiones
{
  public const float RadioTierraKm = 6378.0F;
  public static float DistanciaKm(this Posicion posOrigen, Posicion posDestino)
  { // TODO }
}

Now we move on to the mathematical operations. The first calculation that we must do is to obtain the difference between the latitudes and longitudes of both positions. If P1 with Lat1 and Lon2 and P2 with Lat2 and Lon2, then we will have something like this:

DiferenciaLats = P2.Lat2 – P1.Lat1
DiferenciaLongs = P2.Lon2 – P2.Lon2

The first “drawback” that we find is that latitudes and longitudes are displayed in degrees / minutes / seconds and therefore we must change them to Radians. If we pass all this to code inside the DistanceKm extender method we have:

public static float DistanciaKm(this Posicion posOrigen, Posicion posDestino)
{
  var difLatitud = (posDestino.Latitud – posOrigen.Latitud).EnRadianes();
  var difLongitud = (posDestino.Longitud -posOrigen.Longitud).EnRadianes();
}

As you can see, we have once again made use of another extender method, this time on System.Single or float, and it is nothing more than:

static float EnRadianes(this float valor)
{
  return Convert.ToSingle(Math.PI / 180) * valor;
}

The second step is to calculate the half of the square of the distance in a straight line (according to the length) between the two points and that we are going to represent in the implicitly typed variable “a” and the distance of the angle in radians represented by “c” :

public static float DistanciaKm(this Posicion posOrigen, Posicion posDestino)
{ var difLatitud = (posDestino.Latitud – posOrigen.Latitud).EnRadianes(); var difLongitud = (posDestino.Longitud -posOrigen.Longitud).EnRadianes();

var a = Math.Sin(difLatitud/2).AlCuadrado() + Math.Cos(posOrigen.Latitud.EnRadianes())* Math.Cos(posDestino.Latitud.EnRadianes())* Math.Sin(difLongitud/2).AlCuadrado(); var c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 – a)); }

In this last point I have used another extender method on the double type called Squared whose signature is:

static double  AlCuadrado(this double valor)
{
  return Math.Pow(valor, 2);
}

Finally, the distance in Km will be given by the value obtained in “c” and multiplied by the radius of the earth, with which the DistanceKm method will look like this:

public static float DistanciaKm(this Posicion posOrigen, Posicion posDestino)
{ var difLatitud = (posDestino.Latitud – posOrigen.Latitud).EnRadianes(); var difLongitud = (posDestino.Longitud -posOrigen.Longitud).EnRadianes();

var a = Math.Sin(difLatitud/2).AlCuadrado() + Math.Cos(posOrigen.Latitud.EnRadianes())* Math.Cos(posDestino.Latitud.EnRadianes())* Math.Sin(difLongitud/2).AlCuadrado();

var c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 – a));

return RadioTierraKm*Convert.ToSingle©; }

To consider

Despite the fact that the Haversine Formula is one of the most used for calculating distances between two points (in addition to this, the Spherical Law of Cosine is also used, among others), keep in mind that:

  • The formula assumes that the Earth is completely round, with which it is possible to expect an error rate that could be assumed.
  • During the writing of this post I have found information in which it affirms that the use of the Haversine Formula is less precise to calculate between two positions whose distance is less than 20 km (12 miles).
  • To calculate the distance in miles, it would be necessary to represent the radius of the Earth in nautical miles.