domingo, 28 de abril de 2013

API Google Maps y Visual Basic.NET. Parte V. Elevación de una localización.

Retomando un poco el API de Google Maps, y después de haber visto cómo obtener la latitud y longitud a partir de una determinada dirección (codificación geográfica), o cómo mostrar una localización en un mapa (I y II), el siguiente paso es, utilizando lo anterior, obtener la altitud de un punto en concreto.
El primer paso para obtener la altitud de un lugar es determinar de qué lugar queremos obtenerla. En este caso, para poder obtener la altitud de un punto en concreto debe saberse su latitud y longitud, por lo que vamos a aprovechar la entrada en la que explicábamos cómo determinar la latitud/longitud un lugar, a partir de su dirección (lo que se llama codificación geográfica).
Lo primero que vamos a explicar es la solicitud HTTP que tenemos que crear y nada mejor que ver un ejemplo:
http://maps.googleapis.com/maps/api/elevation/xml?locations=40.4167522,-3.7033701&sensor=false
Como se puede observar, hay pocos parámetros que incluir. A continuación los enumeramos:

PARÁMETROS

  • Locations (obligatorio): se trata de la posición del lugar del que queremos obtener la altitud. Esa localización se debe definir mediante la latitud y la longitud. Ésta se define separada por comas, siendo el primer puesto para la latitud y el segundo para la longitud. Por ejemplo, vamos a definir este parámetro para una latitud dada de 40.416752 y una longitud de -3.7033701, y quedaría de la siguiente forma (sin las comillas), "locations=40.4167522,-3.7033701". También se puede incluir más de una única posición, separándolas por una barra vertical, y quedaría así (sin las comillas), "locations=40.4167522,-3.7033701|42.5499958,-6.5982590".
  • Sensor (obligatorio): determina si la petición procede de un dispositivo con sensor (por ejemplo un receptor GNSS (GPS) de un teléfono móvil). Se puede seleccionar entre true o false. Un ejemplo sería, "sensor=false".

Como hemos visto, se debe incluir primeramente "http://maps.googleapis.com/maps/api/elevation/xml?" y a esto se le añaden los dos parámetros explicados, separados por el símbolo "&".
Una vez realizado esto, si hacemos clic en el enlace de la petición, veremos un archivo XML que nos muestra la información.
Entre la información devuelva se encuentra el status de la petición, es decir, si ha habido algún fallo o todo es correcto, la localización que le hemos enviado y por último, y más interesante, la altitud del punto y la resolución de esa altitud. La resolución indica la distancia máxima (en metros) entre los puntos de datos desde los que se interpoló la elevación.

Resultado de la petición

Una vez que se sabe la teoría, ahora tenemos que implementarlo. Para ello lo que tenemos que hacer primeramente, es crear la petición HTTP y una vez creada, debemos obtener los resultados (en este caso altitud y resolución). Lo primero que se va a mostrar es la función que construye la URL, hace la petición y devuelve los datos con la altitud y resolución. A esta función la vamos a llamar Altitud, y recibirá dos parámetros, uno la latitud y otra la longitud (el parámetro sensor lo vamos a poner como opcional). Antes que nada hay que hacer los Imports al principio del formulario:

Imports System.IO
Imports System.Xml.XPath
El código de la función sería el siguiente.
 Private Function Elevación(ByVal latitud As Decimal, ByVal longitud As Decimal, Optional ByVal Sensor As Boolean = False) As ArrayList

        'Creamos la url con los datos
        Dim url = "http://maps.googleapis.com/maps/api/elevation/xml?locations=" & latitud & "," & longitud & "&sensor=" & Sensor.ToString.ToLower

        'Creamos un arraylist con la elevación
        Dim elevaciones As New ArrayList()

        'Creamos una petición http y asignamos un tiempo máximo de espera de 3000 milisegundos
        Dim req As System.Net.HttpWebRequest = DirectCast(System.Net.WebRequest.Create(url), System.Net.HttpWebRequest)
        req.Timeout = 3000

        Try
            'Preparamos el archivo xml
            Dim res As System.Net.WebResponse = req.GetResponse()
            Dim responseStream As Stream = res.GetResponseStream()
            Dim NodeIter As XPathNodeIterator
            Dim docNav As New XPathDocument(responseStream)
            Dim nav = docNav.CreateNavigator

            'Variables que contendrán la elevación y resolución obtenida del XML
            Dim Exelevacion, Exresolucion As String

            'Creamos los paths
            Exelevacion = "ElevationResponse/result/elevation"
            Exresolucion = "ElevationResponse/result/resolution"


            'Recorremos el xml
            NodeIter = nav.Select(Exelevacion)
            While (NodeIter.MoveNext())
                elevaciones.Add(NodeIter.Current.Value)
            End While

            NodeIter = nav.Select(Exresolucion)
            While (NodeIter.MoveNext())
                elevaciones.Add(NodeIter.Current.Value)
            End While

            'cerramos el response
            responseStream.Close()

        Catch ex As Exception
            'Si algo ha pasado
            elevaciones.Clear()
            elevaciones.Add("Algo ha ocurrido")
        End Try

        'Devolvemos una arraylist que contendrá en primera posición
        'la elevación y en segundo posición la resolución
        Return elevaciones

    End Function
Como se puede observar el proceso es muy sencillo, ahora sólo queda hacer el formulario para que el usuario pueda introducir la latitud y longitud y le sea devuelva la altitud y resolución. En este formulario vamos a tener dos Textbox para escribir la latitud y la longitud (txtlatitud, txtlongitud) y otros dos donde se incluirá la elevación y resolución de la petición (txtaltitud, txtresolucion). El formulario sería así:

Formulario petición altitud

Ahora vamos a incluir en el evento Mouse_click del botón, una comprobación de que los datos introducidos son correctos y la petición a la función pasándole la latitud/longitud. Una vez devuelta, se rellenarán los textbox con la información correspondiente.

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

        'Comprobamos que sean valores numéricos
        If IsNumeric(txtlatitud.Text) And IsNumeric(txtlongitud.Text) Then
            'Creamos un arraylist y hacemos la petición
            Dim listaConDatos As ArrayList = New ArrayList(Elevación(CDec(txtlatitud.Text), CDec(txtlongitud.Text)))
            'Comprobamos que nos devuelve dos datos (uno elevación y otro resolución)
            If listaConDatos.Count = 2 Then
                txtaltitud.Text = listaConDatos(0) & " metros"
                txtresolucion.Text = listaConDatos(1) & " metros"
            Else 'En caso de no devolver dos datos
                txtaltitud.Text = "Datos no encontrados"
                txtresolucion.Text = "Datos no encontrados"
            End If
        End If

    End Sub

Todo el proceso es muy sencillo y los resultados son devueltos rápidamente. También se podría incluir la función de codificación geográfica explicada en anteriores artículos, y el proceso sería; localización (dirección postal) --> latitud/longitud --> elevación.
Podéis descargar el código fuente aquí:

Más info: https://developers.google.com/maps/documentation/elevation/?hl=es

1 comentario:

  1. gracias por el aporte de verdad me a servido de mucho pero mi pregunta es que sabe que estuve probando con diferentes coordenadas y cuando coloco cordenadas con decimales como 10.065065 -69.339178 me arroja como resultado datos no encontrados. y de verdad lo estoy revisando y no encuentro la solucion

    ResponderEliminar