Ir al contenido principal

[.NET] Convertir Latitud y Longitud en Grados - Minutos y segundos

Hola a todos.

Esta es una función para convertir un número de posición geográfica en grados, minutos y segundos.

Como algunos pocos recordarán,una posición geográfica esta definida por latitud (Norte / Sur) y longitud (Este / Oeste) teniendo como referencia para la longitud el meridiano de Greenwich (Meridiano 0) y para la latitud la linea del Ecuador (Paralelo 0). Por lo que siempre hablaremos de posición "Grados Norte", o "Grados Este".

Ahora es cuando entra en juego las matemáticas y la trigonometría (he de admitir que me encantan :D ). El hemisferio norte o sur solo tendría 90° Norte o Sur. Por ejemplo, El polo norte está a 90° 0' 0'' N de latitud. La longitud podríamos considerar el 0° 0' 0'' (estamos en el polo norte, por lo que es un solo punto, no hay longitud).

En cambio, si nos movemos alrededor de la tierra por la linea de Ecuador, la latitud será 0° 0' 0'' (ni al norte, ni al sur) pero de Este a Oeste nos moveremos en un rango de 180°. Desde el Meridiano de Greenwich al Meridiano de cambio de fecha (el 180). Por ejemplo, la ciudad de Calacalí, en Ecuador, E 70° 30' 47'' - N 0° 0' 0'' (por algo es llamada la ciudad en la mitad del mundo).

Después de esta breve clase de geografía, vamos a poner en práctica estos conocimientos con las nuevas tecnologías.

En algunas aplicaciones de geoposicionamiento (Latitude de Google, Loopt de Apple, etc..), estas posiciones son dadas en un numero con (mas o menos) 8 decimales. Signo + o -, esto significa que esta al Este u Oeste (si es Longitud) o Norte o Sur (si es Latitud).

Ejemplo:
Puerta del Sol de Madrid.
Latitud: 40.4166846
Longitud: -3.7025638

Lo que tenemos que hacer es convertir esta numeración en Grados Minutos y Segundos.

1) Los grados serán la parte entera
2) Los minutos serán la diferencia de la parte decimal multiplicado por 60
3) Los segundos será lo que queda multiplicado por 60

Ahora lo vemos en código:

double absValue = Math.Abs(Math.Round(position * 1000000));
int sign = Math.Sign(position);


Int Degress = (int)Math.Floor(absValue / 1000000);
Int Minutes = (int)Math.Floor(((absValue / 1000000) - Math.Floor(absValue / 1000000)) * 60);
Decimal Seconds = (Decimal)Math.Floor(((((absValue / 1000000) - Math.Floor(absValue / 1000000)) * 60) - Math.Floor(((absValue / 1000000) - Math.Floor(absValue / 1000000)) * 60)) * 100000) * 60 / 100000;

Pero vamos a ser un poco mas sofisticados. Como es una función para calcular posiciones geográficas, vamos a usar una estructura para contener esta información:


public struct Coordenates
{
public int Degress;
       public int Minutes;
       public decimal Seconds;
       public String Geo; // N,S,E,W
}

El valor Geo tendrá el valor de Norte, Sur, Este y (W)Oeste. Por lo que tenemos que tener algún parámetro para saber si es Latitud o Longitud. Empezamos a definir nuestra función:
public static Coordenates Convert2DegressMinutesSeconds(double position, bool isLong)

Vamos a sobrecargar esta función para que por defecto, lo que vamos a convertir es una Latitud.
public static Coordenates Convert2DegressMinutesSeconds(double position)
{
     // By default, it is a Latitude (North / South)
     return Convert2DegressMinutesSeconds(position, false);
}

y como había dicho antes, si es positivo, y es latitud, estamos hablando de Norte.
Signo
Posición
isLong
Positivo
Norte
False
Negativo
Sur
False
Positivo
Este
True
Negativo
Oeste
True

Esta sería la función final.


public static Coordenates Convert2DegressMinutesSeconds(double position, bool isLong)
{
   Coordenates ret = new Coordenates();

   // Negative: North
   // Positive: South
   // if isLong = true
   // Negative: East
   // Positive: West
   double absValue = Math.Abs(Math.Round(position * 1000000));
   int sign = Math.Sign(position);

   ret.Degress = (int)Math.Floor(absValue / 1000000);
   ret.Minutes = (int)Math.Floor(((absValue / 1000000) - Math.Floor(absValue / 1000000)) * 60);
   ret.Seconds = (Decimal)Math.Floor(((((absValue / 1000000) - Math.Floor(absValue / 1000000)) * 60) - Math.Floor(((absValue / 1000000) - Math.Floor(absValue / 1000000)) * 60)) * 100000) * 60 / 100000;

   if (isLong)
        if (sign > 0)
            ret.Geo = "W";
        else
            ret.Geo = "E";
   else
        if (sign > 0)
            ret.Geo = "N";
        else
            ret.Geo = "S";

  return ret;
}

¿A que es bonita?


Como siempre, la función la puedes encontrar en el siguiente enlace.
KurroSoftware.Common.zip

Comentarios

  1. Muy buen códigos es de gran utilidad

    ResponderEliminar
  2. Así o más difícil...?
    Para qué poner al compilador a realizar la misma operación tantas veces... Math.Floor(absValue / 1000000)...?

    No es mejor usar una notación compacta para mejorar la visibilidad del código...?

    coordinates.Geo = isLongitude
    ? sign > 0 ? "W" : "E"
    : sign > 0 ? "N" : "S"
    ;

    Que esto...?

    if (isLong)
    if (sign > 0)
    ret.Geo = "W";
    else
    ret.Geo = "E";
    else
    if (sign > 0)
    ret.Geo = "N";
    else
    ret.Geo = "S";

    Terminé redactando todo el código desde cero... ¬¬

    ResponderEliminar

Publicar un comentario

Si quieres comentar, criticar, aportar mas informacion o simplemente felicitar, inserta tu comentario a continuacion. Entre todos podemos hacer cosas grandes.