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.

Entradas populares de este blog

[VB] - Generar GUID

Esta si es buena... Como se nota que VB es un lenguaje con "solera", es decir, con años pero con robustez. Pero le pasa como al abuelo Cebolleta, tiene experiencia pero para los nuevos tiempos... ains.. le falta algo. Hoy en dia no sabriamos hacer nada sin un buen GUID, sobre todo si lo que queremos es identificar de forma unica y constante algun registro, objeto u otro componente. Usando SQL podemos generar un GUID en un santiamen a traves de la instrucción NEWID() , podemos crear un nuevo GUID en .NET usando la clase GUID.. pero... como lo hacemos con Visual Basic 6? Para empezar, vamos a ver en que se compone un GUID ¿Que es un GUID? Su significado es Globally Unique Identifier, osea Identificador globalmente único. Y su misión es la de proporcionar un identificador, de forma que es practicamente imposible que existan dos iguales en el mundo. Se compone de una palabra de 4 bytes, 3 palabras de 2 bytes y una de 6 bytes. Originalmente fue una idea de Microsoft pa