Está en la página 1de 5

Calcular la distancia entre dos puntos sobre un plano podra llegar

a ser relativamente sencillo. Sin embargo, cuando estos dos


puntos los ubicamos sobre la esfera terrestre, es decir, lo que
pretendemos es calcular la distancia lineal entre dos posiciones
dadas (latitud + longitud), la cosa se complica.

Bsicamente se complica por que en el clculo de la distancia


entre ambas posiciones debemos contemplar la curvatura
terrestre. Es aqu donde entra en escena la Frmula del Haversine.

Sin entrar en demasiados detalles en trminos matemticos,


la Frmula del Haversine es:

R = radio de la Tierra

lat = lat2 lat1

long = long2 long1

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

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

d=Rc

Para utilizar la Frmula del Haversine necesitamos, adems de las


dos posiciones (lat + lon), el radio de la Tierra. Este valor es
relativo a la latitud, pues al no ser la Tierra perfectamente
redonda, el valor del radio ecuatorial es de 6378 km mientras
que el polar es de 6357 km. El radio equivolumen es de 6371
km. Para este post utilizaremos el valor del radio ecuatorial.

Por tanto, lo primero que haremos es representar la


clase Posicin, que no es ms que una clase con un par de
propiedades relativas a la longitud y latitud.

public class Posicion

{
public Posicion(float latitud, float longitud)

Latitud = latitud;

Longitud = longitud;

public float Latitud { get; set; }

public float Longitud { get; set; }

Hablando en C#, lo que pretendo es que, dados dos objetos del


tipo Posicion, pueda hacer algo tal que as para calcular la
distancia entre ambos. Si tenemos el
objeto Igualada representando la ubicacin georeferenciada de la
ciudad y queremos saber la distancia lineal con Granada, haremos
lo siguiente:

[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));

}
Para ello vamos a crear un mtodo extensor
llamado DistanciaKm sobre la clase Posicion, el cual tendr la
responsabilidad de calcular la distancia entre ambas posiciones;
en definitiva, contendr la Frmula del Haversine:

public static class Extensiones

public const float RadioTierraKm = 6378.0F;

public static float DistanciaKm(this Posicion posOrigen, Posicion posDestino)

{ // TODO }

Ahora pasamos ya a las operaciones matemticas. El primer


clculo que debemos hacer es obtener la diferencia entre las
latitudes y longitudes de ambas posiciones. Si P1 con Lat1 y Lon2
y P2 con Lat2 y Lon2, entonces tendremos algo as:

DiferenciaLats = P2.Lat2 P1.Lat1

DiferenciaLongs = P2.Lon2 P2.Lon2

El primer inconveniente que encontramos es que las latitudes y


longitudes se exponen en grados / minutos / segundos y por
tanto debemos pasarlas a Radianes. Si pasamos todo esto a
cdigo dentro del mtodo extensor DistanciaKm tenemos:

public static float DistanciaKm(this Posicion posOrigen, Posicion posDestino)

var difLatitud = (posDestino.Latitud posOrigen.Latitud).EnRadianes();

var difLongitud = (posDestino.Longitud -posOrigen.Longitud).EnRadianes();

}
Como veis hemos vuelto a hacer uso de otro mtodo extensor,
esta vez sobre System.Single o float, y no es ms que:

static float EnRadianes(this float valor)

return Convert.ToSingle(Math.PI / 180) * valor;

El segundo paso es calcular la mitad del cuadrado de la distancia


en lnea recta (acorde a la longitud) entre los dos puntos y que
vamos a representar en la variable implcitamente tipada a y la
distancia del ngulo en radianes representada por c:

public static float DistanciaKm(this Posicion posOrigen, Posicion posDestino)

var difLatitud = (posDestino.Latitud posOrigen.Latitud).EnRadianes();

var difLongitud = (posDestino.Longitud -posOrigen.Longitud).EnRadianes();

En este ltimo punto he vuelto a utilizar otro mtodo extensor


sobre el tipo double llamado AlCuadrado cuya firma es:

static double AlCuadrado(this double valor)

return Math.Pow(valor, 2);

}
Finalmente, la distancia en Km ser dada por el valor obtenido en
c y multiplicado por el radio de la tierra, con lo que el mtodo
DistanciaKm quedar as:

public static float DistanciaKm(this Posicion posOrigen, Posicion posDestino)

var difLatitud = (posDestino.Latitud posOrigen.Latitud).EnRadianes();

var difLongitud = (posDestino.Longitud -posOrigen.Longitud).EnRadianes();

También podría gustarte