Ir al contenido principal

[.NET] Usar el servicio de Google Geocoding

Hola de nuevo.

En esta entrega vamos a ver como acceder al servicio de geoposicionamiento de Google Geocoding.

Tal y como indica en las especificaciones de Geocoding, se puede acceder de dos formas diferentes. Una usando XML y otra usando JSON.

La primera seria invocando la dirección directamente a la URL http://maps.google.com/maps/api/geocode/xml?address=Puerta+del+sol,1+Madrid+Spain&region=sp&sensor=false.
En este caso, nos devuelve la lista de posibles direcciones, junto a cada una de sus posiciones geográficas.

<GeocodeResponse>
  <status>OK</status>
  <result>
    <type>street_address</type>
    <formatted_address>Callede Peña del Sol, 1, 28034 Madrid, España</formatted_address>
    <address_component>
      <long_name>1</long_name>
      <short_name>1</short_name>
      <type>street_number</type>
    </address_component>
    <address_component>
      <long_name>Calle dePeña del Sol</long_name>
      <short_name>Calle dePeña del Sol</short_name>
      <type>route</type>
    </address_component>
    <address_component>
      <long_name>Madrid</long_name>
      <short_name>Madrid</short_name>
      <type>locality</type>
      <type>political</type>
    </address_component>
    <address_component>
      <long_name>Madrid</long_name>
      <short_name>M</short_name>
      <type>administrative_area_level_2</type>
      <type>political</type>
    </address_component>
    <address_component>
      <long_name>Comunidadde Madrid</long_name>
      <short_name>Comunidadde Madrid</short_name>
      <type>administrative_area_level_1</type>
      <type>political</type>
    </address_component>
    <address_component>
      <long_name>España</long_name>
      <short_name>ES</short_name>
      <type>country</type>
      <type>political</type>
    </address_component>
    <address_component>
      <long_name>28034</long_name>
      <short_name>28034</short_name>
      <type>postal_code</type>
    </address_component>
    <geometry>
      <location>
        <lat>40.4884395</lat>
        <lng>-3.7027410</lng>
      </location>
      <location_type>RANGE_INTERPOLATED</location_type>
      <viewport>
        <southwest>
          <lat>40.4874340</lat>
          <lng>-3.7043715</lng>
        </southwest>
        <northeast>
          <lat>40.4901319</lat>
          <lng>-3.7016736</lng>
        </northeast>
      </viewport>
      <bounds>
        <southwest>
          <lat>40.4883964</lat>
          <lng>-3.7034958</lng>
        </southwest>
        <northeast>
          <lat>40.4891695</lat>
          <lng>-3.7025493</lng>
        </northeast>
      </bounds>
    </geometry>
    <partial_match>true</partial_match>
  </result>
</GeocodeResponse>


Menudo chorizo!!

Pero, como podemos usar la opción de JSON, vamos a creare un WCF para recuperar este resultado.
Así, que lo primero que necesitamos crear es un DataContract para almacenar los resultados.

Si ejecutamos la sentencia anterior, sustituyendo XML por JSON, te puedes hacer una idea de como tiene que ser nuestro interface.


    [DataContract]
    public class GeoResponse
    {
        [DataMember(Name= "status")]
        public string Status { get; set; }
        [DataMember(Name= "results")]
        public CResult[] Results { get;set; }

        [DataContract]
        public class CResult
        {

            [DataMember(Name= "formatted_address")]
            publicstring formatted_address { get; set; }
            [DataMember(Name= "address_components")]
            publicGeocodeAddressComponent[] AddressComponents{ get; set; }

            [DataContract]
            publicclass GeocodeAddressComponent
            {
                [DataMember(Name= "long_name")]
                publicstring LongName { get;set; }
                [DataMember(Name= "short_name")]
                publicstring ShortName { get;set; }
                [DataMember(Name= "types")]
                publicstring[] Type { get;set; }
            }

            [DataMember(Name= "geometry")]
            publicCGeometry Geometry { get; set; }

            [DataContract]
            publicclass CGeometry
            {
                [DataMember(Name= "location")]
                publicCLocation Location { get; set; }

                [DataContract]
                publicclass CLocation
                {
                    [DataMember(Name= "lat")]
                    publicdouble Latitude { get;set; }
                    [DataMember(Name= "lng")]
                    publicdouble Longitude { get;set; }

                }
            }
        }
    }

Ahora, definimos la función que usaremos para llamar al Geocoding.

        [OperationContract]
        GeoResponseCallGeoWS(string address);

Ahora, a crear la clase que implementa este interface.

    public class Geocoding : IGeocoding
    {

        public GeoResponse CallGeoWS(stringaddress)
        {
            {
                stringurl = string.Format(
                        "http://maps.google.com/maps/api/geocode/json?address={0}&region=sp&sensor=false",
                        HttpUtility.UrlEncode(address)
                        );
                varrequest = (HttpWebRequest)HttpWebRequest.Create(url);
                request.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip,deflate");
                request.AutomaticDecompression= DecompressionMethods.GZip | DecompressionMethods.Deflate;
                DataContractJsonSerializerserializer = new DataContractJsonSerializer(typeof(GeoResponse));
                varres = (GeoResponse)serializer.ReadObject(request.GetResponse().GetResponseStream());
                return res;
            }

        }
    }

Como veréis, la URL usada es la de Geocode, este nos devolverá el bloque en ZIP y lo descomprimimos automáticamente, a la par que hacemos la deseralización del resultado usando el contract que hemos creado antes.

Como ves, es muy sencillo.

Solo a tener en cuenta una cosa.. La librería de JSON la puedes encontrar en C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0\System.Runtime.Serialization.dll 

Bueno... y después de todo esto, ¿Qué se puede hacer

Pues vamos a usarlo para mostrar información de direcciones y mostrarlo en un mapa de Google Maps.

En este caso, vamos a utilizar la opción de mapas staticos de Google.

http://maps.google.com/maps/api/staticmap?center=latitud,longitud

Geocoding.Geocodinggc = new Geocoding.Geocoding();
GeoResponse gr;

String address = "Paseodel Prado,1,Madrid,Spain";

GeoResponse geocodingResponse = gc.CallGeoWS(address);

Nos devuelve un objeto del tipo GeoResponse, que vamos a recorrer para montar un ListView.

listViewResult.Items.Clear();

foreach(GeoResponse.CResultresult in _geocodingResponse.Results)
{
ListViewItem lv = new ListViewItem(result.formatted_address,0);
               lv.SubItems.Add(Coordenates_ToString(Functions.Convert2DegressMinutesSeconds(result.Geometry.Location.Longitude,true)));
               lv.SubItems.Add(Coordenates_ToString(Functions.Convert2DegressMinutesSeconds(result.Geometry.Location.Latitude)));
      
listViewResult.Items.Add(lv);
}
Como habrás notado, estoy usando la función de conversión de Grados Minutos y segundos que se ha comentado anteriormente, para mostrar la posición geográfica en unidades de GPS.

La función Coordenates_ToString es para formatear nuestras coordenadas.
privateString Coordenates_ToString(Functions.Coordenatescoordenates)
{
    return(coordenates.Geo + " " +coordenates.Degress.ToString() + "º "+
            coordenates.Minutes.ToString() + "' " +
            coordenates.Seconds.ToString() + "'' ");
}

Si quieres ver todo esto en funcionamiento, descárgate el código y el TestHarness para probarlo.



Comentarios

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...

[.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 m...