Embarcadero MVP.
Analista y Programador de Sistemas Informáticos.
Estudios de Informática (Ingeniería Técnica Superior) en la UPC (Universidad Politécnica de Barcelona).
Llevo utilizando Delphi desde su versión 3. Especialista en diseño de componentes, Bases de Datos, Frameworks de Persistencia, Integración Continua, Desarrollo móvil,…
Anteriormente en el blog he escrito entradas sobre cómo visualizar rutas o tracks en mapas de Google , en diferentes formatos. Al final la idea es la misma en todos los ejemplos; Pintar una sucesión de puntos correspondientes a latitud y longitud sobre un mapa. Nada más. Hemos visto cómo hacerlo con los ficheros KML que utiliza Google o los ficheros GPX (GPS eXchange Format), que están considerados como un estándar en este tipo de representación.
No es mi intención seguir el camino que muchas compañías están tomando de “mudarse” de los mapas de Google a OpenStreetMap, desde que Google anunció que iba a cobrar por utilizar los suyos, sino más bien ampliar las posibilidades de los ejemplos que ya habíamos visto para poder utilizar estos mapas también.
He utilizado el mismo ejemplo que en su día hice para la visualización de tracks en Google Maps; “El Visor KML”. Como ya he dicho, la idea es la misma, pero utilizando diferente proveedor de mapas.
En el caso de Google Maps, para crear el mapa y la polilínea utilizamos las siguientes clases:
map = new GMap2(document.getElementById("map"));
…
var polyline = new GPolyline…
map = new GMap2(document.getElementById("map"));
…
var polyline = new GPolyline…
En el caso de OpenStreetMap utilizamos:
map = new OpenLayers.Map("map_canvas", options…
…
var linear_ring = new OpenLayers.Geometry.LinearRing(points);
polygonFeature = new OpenLayers.Feature.Vector(
new OpenLayers.Geometry.Polygon([linear_ring]), null, style);
map = new OpenLayers.Map ("map_canvas", options…
…
var linear_ring = new OpenLayers.Geometry.LinearRing(points);
polygonFeature = new OpenLayers.Feature.Vector(
new OpenLayers.Geometry.Polygon([linear_ring]), null, style);
Siguiendo con la misma idea su miramos como proveedor Bing Maps (Microsoft) o los mapas de Yahoo, el sistema es fácilmente “portable” a estos. Si buscamos un poco en la API para Bing, vemos que para crear el mapa y la polilínea podemos utilizar:
map = new MM.Map(document.getElementById("myMap"), options…
var polyline = new MM.Polyline([…
map = new MM.Map(document.getElementById("myMap"), options…
var polyline = new MM.Polyline([…
Y en el caso de Yahoo Maps utilizaríamos:
var map = new YMap(document.getElementById('map'));
polylinePoints =[];
map.addOverlay(new YPolyline(polylinePoints, options…
var map = new YMap(document.getElementById('map'));
polylinePoints = [];
map.addOverlay(new YPolyline(polylinePoints, options…
Modificando el ejemplo antes comentado, he añadido a los mapas de Google Maps, los mapas de OPenStreetMap y los de Bing Maps. Si alguien se anima a completarlo con los de Yahoo Maps (ya he parado aquí) os lo dejo como “ejercicio” y espero que lo compartáis aquí.
Os dejo unas imágenes del resultado.
Los diferentes mapas se encuentran en un fichero de recursos.
NOTA: Es posible que debido a los cambios de licencias de Google y del resto de proveedores, no se pueda ejecutar el proyecto de ejemplo correctamente sin algunos cambios respecto a las API, pero el código sigue siendo válido y orientativo para el que tenga que trabajar con estos temas.
Embarcadero MVP.
Analista y Programador de Sistemas Informáticos.
Estudios de Informática (Ingeniería Técnica Superior) en la UPC (Universidad Politécnica de Barcelona).
Llevo utilizando Delphi desde su versión 3. Especialista en diseño de componentes, Bases de Datos, Frameworks de Persistencia, Integración Continua, Desarrollo móvil,…
Hoy me ha llegado la invitación a probar Google Wave.
Estoy revisando por encima y por ahora no tengo mucho tiempo; De todas formas lo primero que he visto es que tengo algunas invitaciones para compartir (creo que en este momento quedan 7).
Si alguno de los que asíduamente leéis este blog necesitáis o queréis alguna, pues basta con pedirla, que para eso es esta entrada.
Embarcadero MVP.
Analista y Programador de Sistemas Informáticos.
Estudios de Informática (Ingeniería Técnica Superior) en la UPC (Universidad Politécnica de Barcelona).
Llevo utilizando Delphi desde su versión 3. Especialista en diseño de componentes, Bases de Datos, Frameworks de Persistencia, Integración Continua, Desarrollo móvil,…
En la última entrada acerca de la API de Google Maps, vimos cómo mostrar un Mapa utilizando la API en un programa Delphi, cómo centrarlo en una posición predefinida y utilizando un Zoom predeterminado.
Además como seleccionar entre los diferentes controles que podemos añadir al mapa (Zoom, Vista general, tipo de mapa…).
También cómo colocar una marca en una ubicación y cómo generar una ventana con información asociada a esa marca (NOTA1).
Una vez visto cómo mostrar el mapa, lo que nos queda es ver cómo podemos, desde nuestro programa Delphi, interactuar con él; Es decir, que el usuario pueda modificar determinadas características del mapa que tiene en pantalla, y nosotros podamos recuperar esos cambios, para utilizarlos en nuestro programa.
Vamos a continuar con el ejemplo visto en las entradas anteriores; Mostraremos al usuario un Mapa ubicado en una determinada posición. El usuario debe poder «reubicar» la vista del mapa y modificar el Zoom con que está visualizando el mapa, y esos son los valores que obtendremos para posteriormente almacenarlos y actualizarlos en nuestro programa.
Coordenada de Longitud
Coordenada de Latitud
Zoom actual del mapa
La forma de conseguirlo, es añadir a la página web el código necesario para capturar eventos que se produzcan en el mapa. Incluiremos controles de edición, donde se almacenan la longitud/latuitud y Zoom, que después recuperaremos desde el programa Delphi.
GEvent.addListener(map, "click", function (overlay,point)
GEvent.addListener(map, "zoomend", function (oldLevel, newLevel)
GEvent.addListener(map, "mousemove", function(latlng)
Aunque uno no esté muy familiarizado con el tema (yo mismo no lo estoy mucho ;-D ), no hacen falta muchas explicaciones para comprender los eventos; «Capturaremos» en OnClick, OnZoomEnd y OnMouseMove sobre el mapa. Aquí se puede acceder a la lista de eventos, métodos y propiedades de la clase Gmap.
En el caso del evento OnClick, por ejemplo, utilizaremos un código como este:
GEvent.addListener(map, "click", function (overlay,point){
if (point){
document.posicion.x.value=point.x
document.posicion.y.value=point.y
document.posicion.z.value=map.getZoom()
TipoMapa = map.getCurrentMapType().getName()
document.posicion.t.value=TipoMapa
}
Obtenemos información del punto actual (utilizando un parámetro) y el Zoom actual y el tipo de Mapa utilizando métodos de la clase GMap. Todos ellos se almacenan (como hemos comentado antes) en componentes de tipo Text, que nos sirven como «paso intermedio» para luego capturar esos valores de la página Web desde nuestro programa.
Como resultado final, os dejo el ejemplo que se adjunta con esta entrada. En él he incluído/integrado la parte de Geocodificación (visto en las entradas I y II), y el código y modificaciones necesarias para recuperar posición, Zoom y tipo de Mapa (este incluído a última hora) que el usuario selecciona en un Mapa.
La información de los lugares puede ser guardada y recuperada de un fichero de texto; La estructura es bastante simple y no hace falta mayor explicación. Se almacena en el mismo directorio de la aplicación y recibe el nombre de «Lugares.txt».
La información que podemos capturar del Mapa (utilizando la clase GMap) y de otros elementos que estén incluíds en el mapa (imágenes, líneas, marcas,…) es muy extensa y está detallada en las referencias de la API de Google Maps.
Personalmente, creo que las posibilidades de ampliación son muy grandes y bastantes más sencillas de lo que a priori puede parecer.
Espero que estas entradas hayan sido de utilidad. Como siempre cualquier comentario, corrección, sugerencia,… es bienvenida. ;-D
Un saludo.
ACTUALIZACIÓN (10 Febrero 2012): Dado el cambio de política de Google, ahora es necesario (obligatorio) colocar la key que se proporciona desde Google para poder utilizar la API. Es necesario modificar el fichero _mapa.txt del recurso y recompilarlo utilizando RC.CMD.
Embarcadero MVP.
Analista y Programador de Sistemas Informáticos.
Estudios de Informática (Ingeniería Técnica Superior) en la UPC (Universidad Politécnica de Barcelona).
Llevo utilizando Delphi desde su versión 3. Especialista en diseño de componentes, Bases de Datos, Frameworks de Persistencia, Integración Continua, Desarrollo móvil,…
Si habéis revisado el ejemplo sencillo que vimos en la primera entrada, os habréis fijado que hay un parámetro al final de la dirección del que no hemos hablado. Se trata del formato de salida para los datos. Los formatos que acepta el API de Google Maps son los siguientes:
XML: Formato extendido en XML/KLM.
KLM: Formato extendido en KL; Se diferencia del anterior en los tipos MIME.
JSON: La salida de este formato se guarda en formato de objeto JSON (Javascript Object Notation).
CSV: Formato comprimido separado por comas (el que se utilizó en el ejemplo).
Para utilizar un formato diferente, basta con añadir al final de la línea de petición el formato deseado:
Retomando el tema inicial, vamos a utilizar uno de los formatos extendidos para obtener más información de una dirección dada, además de las coordenadas de Latitud y Longitud.
Si realizamos una petición HTTP utilizando el formato json obtenemos una respuesta como esta por parte del servidor:
Utilizando un sencillo «parser» con este resultado podemos extraer la información para poder utilizarla en nuestros programas.
El ejempo que se ve en la imagen puede descargarse desde aquí.
He creado además una clase derivada de TThread que permite acceder a la imagen. Me ha parecido que en futuros usos me va a ser más útil así, aunque realmente todavía no la he probado en un entorno «multithread».
Y aun podemos extraer más, ya que si la dirección es ambigua (pero correcta), google puede devolver más de un resultado. De esta forma, con una dirección tipo:
Obtendremos por parte de Google la lista de direcciones correcta que pueden corresponder a esta calle. Cada una de ellas presenta la estructura mostrada anteriormente variando el identificador (id):
"Placemark": [ {
"id": "p1",
...
"id": "p2",
...
"Placemark": [ {
"id": "p1",
...
"id": "p2",
...
Sucesivamente para las distintas direcciones correctas y posibles para esa combinación: Alava, Burgos, Ciudad Real, Cuenca,…
A partir de aquí, no costaría mucho para modificar el ejemplo anterior de forma que se puedan extraer y mostrar los datos, no sólo de la primera dirección, sino de todas las devueltas en la petición.
Hasta aquí estos dos artículos (I y II), que sirven a modo de introducción y prefacio del próximo que estoy preparando.
Está claro, que la idea final y el objetivo que persigo es poder integrar en un programa Delphi las características de Google Maps. El problema actual es, que en nuestras Base de Datos/programas normalmente no tenemos codificadas nuestras direcciones con Latitud/Longitud, así aque para llegar a nueastro objetivo antes tenemos que conseguir estos dos parámetros. Ahí es donde nos és útil el concepto de «Codificación geográfica».
Una vez que tenemos Latitud y Longitud para nuestra dirección, ya podemos avanzar un paso más…
Embarcadero MVP.
Analista y Programador de Sistemas Informáticos.
Estudios de Informática (Ingeniería Técnica Superior) en la UPC (Universidad Politécnica de Barcelona).
Llevo utilizando Delphi desde su versión 3. Especialista en diseño de componentes, Bases de Datos, Frameworks de Persistencia, Integración Continua, Desarrollo móvil,…