MSDN España

Noticias, avisos, reflexiones... del equipo que hay detrás de MSDN en España... también tendremos alguna que otra firma invitada :)

Windows Phone Tips&Tricks. Cómo pintar una ruta entre dos puntos en un mapa

Windows Phone Tips & Tricks. Cómo pintar la ruta entre dos puntos en un mapa

[Nota: Este artículo pertenece a la serie de Windows Phone Tips & Tricks de MSDN España]

Una de las posibilidades que nos ofrece la API de los nuevos mapas de Windows Phone 8 es la de calcular una ruta entre dos puntos (en este caso lo haremos entre la posición actual y el resultado de una búsqueda)
y pintarla sobre nuestro mapa. Para ello, he creado una aplicación de ejemplo en la que tenemos el mapa, un botón para obtener nuestra posición actual y otro botón para calcular la ruta entre esta posición y la buscada y pintarla sobre el mapa:

 

En mi clase tengo definida una lista de coordenadas, a la que primero añadiremos las coordenadas de nuestra posición actual y luego las coordenadas del destino. Para ello, empezamos por obtener y guardar las coordenadas de nuestra posición actual. En este otro Tip&Trick se explica como conseguirlo, pero dejo el código para recordarlo:

        private List<GeoCoordinate> coordinates = new List<GeoCoordinate>();

        private async void GetCurrentPosition()
        {
            Geolocator geolocator = new Geolocator();
            Geoposition currentPosition = null;
            try
            {
                // Obtener posición actual
                currentPosition = await geolocator.GetGeopositionAsync();
                // Guardamos el valor de las coordenadas de la posición
                // actual en nuestra lista
                coordinates.Add(new GeoCoordinate
                                 (currentPosition.Coordinate.Latitude,
                                 currentPosition.Coordinate.Longitude));
                // Centramos el mapa en la posición actual
                this.Mapa.Center = coordinates.LastOrDefault();
                this.Mapa.ZoomLevel = 10;
            }
            catch (UnauthorizedAccessException)
            {
                // Localización desactivada en las características del teléfono
                // o capacidad no incluida en el manifiesto
                MessageBox.Show("No tienes los permisos adecuados para utilizar esta funcionalidad");

                // En caso de no tener habilitada la característica de localización en el teléfono
                // podríamos lanzar el menú de configuración para activarla
                // Launcher.LaunchUriAsync(new Uri("ms-settings-location:"));
            }
            catch (Exception ex)
            {
                // Ocurre algún otro error
                MessageBox.Show(ex.Message);
            }
        }

Tras ejecutar este código en la aplicación podemos ver lo siguiente (el mapa centrado en la posición actual y con mayor nivel de zoom):

 El siguiente paso es realizar la búsqueda del destino deseado, guardar sus coordenadas y pintar la ruta entre nuestra posición actual y el destino deseado. En este caso la ruta será Redmond-Los Ángeles, por lo que el término a buscar en nuestra GeocodeQuery será “Los Angeles, CA”:

        private void SearchForDestiny()
        {
            try
            {
                GeocodeQuery geocodeQuery = new GeocodeQuery();
                // Realizamos la búsqueda de las coordenadas del destino deseado
                geocodeQuery.SearchTerm = "Los Angeles, CA";
                // Establecemos las coordenadas para centrar el mapa (posición actual)
                geocodeQuery.GeoCoordinate = new GeoCoordinate
                                             (this.coordinates.LastOrDefault().Latitude,
                                              this.coordinates.LastOrDefault().Longitude);
                // Nos suscribimos al evento de finalización de esta búsqueda
                // y la lanzamos para tratar los datos
                geocodeQuery.QueryCompleted += geocodeQuery_QueryCompleted;
                geocodeQuery.QueryAsync();
                this.Mapa.ZoomLevel = 5;
            }
            catch (UnauthorizedAccessException)
            {
                // Localización desactivada en las características del teléfono
                // o capacidad no incluida en el manifiesto
                MessageBox.Show("No tienes los permisos adecuados para utilizar esta funcionalidad");

                // En caso de no tener habilitada la característica de localización en el teléfono
                // podríamos lanzar el menú de configuración para activarla
                // Launcher.LaunchUriAsync(new Uri("ms-settings-location:"));
            }
            catch (Exception ex)
            {
                // Ocurre algún otro error
                MessageBox.Show(ex.Message);
            }
        }

Al terminar la búsqueda del destino deseado, debemos procesar los datos del resultado encontrado en geocodeQuery_QueryCompleted, el controlador encargado de recoger las coordenadas del destino establecido, guardarlas en nuestra lista y lanzar la búsqueda de la ruta entre los dos puntos:

        void geocodeQuery_QueryCompleted(object sender,
            QueryCompletedEventArgs<IList<MapLocation>> e)
        {
            if (e.Error == null)
            {
                // Añadimos las coordenadas del resultado de
                // la búsqueda a nuestra lista de coordenadas
                coordinates.Add(e.Result[0].GeoCoordinate);

                RouteQuery routeQuery = new RouteQuery();
                // Establecemos los puntos de nuestra ruta (posición actual y destino)
                routeQuery.Waypoints = coordinates;
                // Nos suscribimos al evento de finalización de búsqueda de ruta y la lanzamos
                routeQuery.QueryCompleted += routeQuery_QueryCompleted;
                routeQuery.QueryAsync();
                (sender as GeocodeQuery).Dispose();
            }
        } 

Para terminar, al finalizar la búsqueda de una ruta entre los dos puntos establecidos, debemos controlar los resultados de esta búsqueda y su visualización en routeQuery_QueryCompleted:

        void routeQuery_QueryCompleted(object sender,
                    QueryCompletedEventArgs<Route> e)
        {
            if (e.Error == null)
            {
                Route MyRoute = e.Result;
                MapRoute mapRoute = new MapRoute(MyRoute);
                // Pintamos la ruta resultante en nuestro mapa
                this.Mapa.AddRoute(mapRoute);
                (sender as RouteQuery).Dispose();
            }
        }

 

Y esto sería lo que veríamos en la aplicación al ejecutar ambas búsquedas:

A partir de la ruta podemos obtener también la distancia total (LenghtInMeters), el tiempo necesario para recorrerla (EstimatedDuration), las indicaciones para seguir esa ruta (lista de Maneuvers en cada paso (Leg) de la ruta), etc.

 

Un saludo,

Gorka Madariaga (@Gk_8)

Blog: formulario de comentarios de publicación (CAPTCHA)