Servei de càlcul de rutes

Servei Web que retorna la ruta òptima entre dues coordenades en format KML. El servei permet especificar a més el tipus de via que volem emprar: vehcle, bicicleta o ambdós. Aquest servei utilitza la xarxa viàra d'OpenStreetMap i serveis d'enrutament (PgRouting - Postgis) instal·lats als nosrtes servidors, i ha estat possible gràcies a l'especial dedicació dels alumnes en pràctiques de l'IES Ramis que han col·laborat amb SILME.

En aquesta guia es mostrarà com utilitzar el servei web de la IDE menorca per implementar una ruta en un mapa de tres maneres possibles: amb OpenLayers, amb Leaflet.js i amb Google Maps API v3.

1.- Sol·licitud de càlcul de rutes

Una sol·licitud de càlcul de rutes és URL HTTP amb el següent format:
 

http://ide.cime.es/menorcarouting/ruta.aspx


Paràmetres obligatoris

  • coord1: Parell de coordenades que indiquen la longitud i latitud de la posició inicial. Els valors corresponents a la longitud i la latitud van separats per comes (","). El sistema de coordenades emprat és l'EPSG:4326 - WSG84, el més habitual en dispositius mòbils, Google Maps, etc.
  • coord2: Parell de coordenades que indiquen la longitud i latitud de la posició final. Els valors corresponents a la longitud i la latitud van separats per comes (","). El sistema de coordenades emprat és l'EPSG:4326 - WSG84, el més habitual en dispositius mòbils, Google Maps, etc.
  • typeRoute: Paràmetre que indica el tipus de via que volem emprar. Els possibles valors són: car, bike o everything.


Un exemple de crida al servei seria el següent:
http://ide.cime.es/menorcarouting/ruta.aspx?coord1=3.994249,40.0444087&coord2=4.009831916187729,39.97307093003211&typeRoute=car
On estem demanant la ruta òptima en cotxe entre el punt 1 (longitud: 3.994249, latitud: 40.0444087) i el punt 2 (longitud: 4.009831916187729, latitud: 39.97307093003211).
 

2.- Resposta a les sol·licituts de càlcul de rutes

La resposta és una cadena en format KML que podem emprar directament amb Google Earth, OpenLayers, Leaflet o l'API de Google Maps:

 
Dins les dades de retorn (tag "extendeddata") podrem trobar la distància total del track. Podeu trobar més informació sobre el format KML en aquest enllaç.
 
 

3.- Implementació de rutes amb Openlayers

El primer pas serà descarregar les llibreries de Openlayers i importar-les:

 

<script src="OpenLayers-2.11/ArcGISCache.js" type="text/javascript" ></script>
<script src="OpenLayers-2.11/proj4js-combined.js" type="text/javascript"></script>

 

A continuació podem carregar una capa base per el mapa a partir dels serveis WMS que ofereix la IDE menorca.

 

			//Capes WMS Base
			var layerRef = new OpenLayers.Layer.WMS(
				"Base referència WMS",
				"http://ide.cime.es/menorca/wms/base_referencia", 
				{layers: 
					[
						'ombres',
						'RE007RUS_municipis',
						'RE007RUS_entitatsurbanes',
						'OR007POR_limpn',
						'RE007RUS_equipaments',
						'RE007RUS_edificis25000',
						'RE007RUS_edificis10000',
						'RE007RUS_edificis5000',
						'RE007RUS_piscines',
						'RE007RUS_piscines_s2',
						'RE007RUS_torrents',
						'RE007RUS_zoneshumides',
						'RE007RUS_parets5000',
						'RE007RUS_parets25000',
						'RE007RUS_corvesnivell',
						'RE007RUS_xarxaviaria',
						'RE007RUS_xarxaviaria_s2',
						'RE007URB_carrer',
						'RE007URB_zverda',
						'RE007URB_vorera',
						'RE007URB_torrent',
						'RE007URB_places',
						'RE007URB_parking',
						'RE007URB_constru',
						'RE007URB_piscina',
						'RE007URB_eixcarrer',
						'RE007URB_portals',
						'RE007URB_arbres',
						'RE007URB_jardins',
						'RE007RUS_llocs',
						'RE007RUS_lterme',
						'RE007TOP_topo05',
						'RE007TOP_topo10',
						'RE007TOP_topo25',
						'RE007TOP_topo50',
						'RE007TOP_top100',
						'RE007RUS_costal',
						'RE007TOP_top200',
					],
					transparent: 'TRUE'
				},
				{isBaseLayer: true, visibility: true}
			);					
			
			//opcions de visualització
			var options = {

				//Sistema de Referència
				projection: new OpenLayers.Projection('EPSG:25831'),
				displayProjection: new OpenLayers.Projection('EPSG:25831'),
				
				//Unitats
				units: 'm',
				
				//Dimensions
				maxExtent: new OpenLayers.Bounds(567000, 4406000, 614000, 4439000),
				maxResolution: 'auto'
			}

			 
			//Creem l'objecte "map", hi afegim les capes i el centrem
			map = new OpenLayers.Map('map',options);
			map.addLayers([layerRef]);
			map.setCenter(new OpenLayers.LonLat(4.10,39.95), 0);
			
			//Controls
			map.addControl(new OpenLayers.Control.LayerSwitcher()); 
			map.addControl(new OpenLayers.Control.ScaleLine({maxWidth:200})); 
			map.addControl(new OpenLayers.Control.MousePosition()); 

 

D'aquesta manera hem creat un mapa i li hem posat com a capa, la base de referència de la IDE menorca. A més a més, hem configurat unes poques opcions bàsiques. El següent pas serà afegir una capa vector buida per després poder-li assignar el vector de la ruta.

 

			/* Creem el vector */
			vector_ruta = new OpenLayers.Layer.Vector(
				"Routing",
				{
					styleMap: new OpenLayers.StyleMap({
						"default": {
							labelYOffset: 25,
							label: "",
							strokeWidth: 4,
							strokeColor: "#ff0000"
						}
					})
				}
			);
			
			/* Afegim el vector al mapa */
			map.addLayer(vector_ruta);

 

Com podem veure, en la creacío de la capa podem modificar algunes propietats bàsiques com el color, el gruix, etc. Ara cal afegir a aquesta capa el vector amb la ruta que desitjem. Això ho farem mitjançant el servei web de càlcul de rutes de la IDE de Menorca, és a dir, enviarem una petició de les coordenades inicials i finals, així com el tipus de ruta a emprar. El KML que ens retorni, l'aprofitarem per a construir un element de la capa vector_ruta:

 

			var url = "http://ide.cime.es/menorcarouting/ruta.aspx?coord1=3.994249,40.0444087&coord2=4.009831916187729,39.97307093003211&typeRoute=car";
			
			var oReq = new XMLHttpRequest();
			
			oReq.open("get", url, true);
			oReq.send();
			
			oReq.onload = function() {
			
			vector_ruta.destroyFeatures();
			
			var format = new OpenLayers.Format.KML({
				'internalProjection': map.baseLayer.projection,
				'externalProjection': new OpenLayers.Projection("EPSG:4326")
				});
				
			var feature = format.read(this.responseText);
			vector_ruta.addFeatures(feature);
			}

 

I aquí, el resultat:

 


 

El problema en Javascript del Cross-Domain-Call:

 

Sovint ens trobem que volem cridar mitjançant AJAX una url que cau fora del nostre domini. Aleshores, el nostre codi es queixa perquè no pot fer crides a arxius ubicats fora del domini on tenmim la nostra pàgina web. És el que es coneix CROSS-DOMAIN CALL.

 

Què és una Cross Domain Call ?

 

És un mecanisme de seguretat de les comunicacions en navegadors actuals. Eviten que un script (XMLHttpRequest d'AJAX) o una aplicació (Flash , Silverlight) d'una pàgina web puguin accedir a un servidor web diferent del que hi resideixen.

 

Per què existeix?

 

Intenten ajudar a evitar dues formes habituals de sabotatge a internet , el Cross Site Request Forgery ( XSRF o session riding ) i el Cross Site Scripting ( XSS ).

 

Com solucionar-lo?

 

Una solució és emprar un Proxy: Fem que l'script o l'aplicació cridin a un servidor intermediari del servei remot que hem posat al nostre servidor web. De tal manera que podem implementar de forma molt senzilla un proxy en PHP (o .NET, etc.) dins nostre domini que rebrà la url externa a sol·licitar i que en retornarà el seu contingut. A continuació es mostra un proxy en PHP molt senzill, anomenat "remoteKML.php" que fa una petició al servei web de càlcul de rutes de la IDE menorca:

 

<?php 
	$file = "http://ide.cime.es/menorcarouting/ruta.aspx?coord1=3.994249,40.0444087&coord2=4.009831916187729,39.97307093003211&typeRoute=car";
	
	header("Content-type: text/javascript");
	
	readfile($file);
?>

 

En aquest arxiu php és on especifiquem les coordenades de l'inici i del final de la ruta i el tipus de transport per la ruta, però les podríem passar com a paràmetres. Així, podríem emprar aquest proxy enlloc de cridar directament el servei web del càlcul de rutes de la IDE menorca:

 

 

	var url = "remoteKML.php";
	
	var oReq = new XMLHttpRequest();
			
	oReq.open("get", url, true);
	oReq.send();
			
	oReq.onload = function() {
			
	vector_ruta.destroyFeatures();
	
	var format = new OpenLayers.Format.KML({
		'internalProjection': map.baseLayer.projection,
		'externalProjection': new OpenLayers.Projection("EPSG:4326")
		});
				
	var feature = format.read(this.responseText);
	vector_ruta.addFeatures(feature);
			}

 

 


4.- Implementació de rutes amb Leaflet

Leaflet és una llibreria Javascript de codi obert àmpliament usada per a construir aplicacions de mapes web. Desenvolupada l'any 2011, suporta la majoria de les plataformes mòbils i d'escriptori, així com HTML5 i CSS3. Juntament amb OpenLayers i l'API de Google Maps, és una de les llibreries JavaScript de mapes més populars i és utilitzat pels principals webs com FourSquare , Pinterest i Flickr.

 

El primer pas per a treballar amb Leaflet serà el d'importar les llibreries de leaflet (i el plugin omnivore) i de mapbox que és la plataforma que utilitzarem per el mapa.

 


<script src='https://api.tiles.mapbox.com/mapbox.js/plugins/leaflet-omnivore/v0.2.0/leaflet-omnivore.min.js'></script>
<script src='https://api.tiles.mapbox.com/mapbox.js/v2.1.9/mapbox.js'></script>

 

A continuació inicialitzarem el mapa, i per fer-ho necessitarem tenir un compte a mapbox.com, per tenir el nostre propi 'token' d'accés.

 

L.mapbox.accessToken = 'pk.eyJ1IjoibXJ2aW5lbnQiLCJhIjoiREhiVG5mVSJ9.HOKjM8fHh1yEMgSneugidA';
var map = L.mapbox.map('map', 'examples.map-i86nkdio');

 

Un cop el mapa està inicialitzat, afagirem la capa de la ruta desitjada.

 

	var runLayer =  omnivore.kml('http://ide.cime.es/menorcarouting/ruta.aspx?coord1=3.994249,40.0444087&coord2=4.009831916187729,39.97307093003211&typeRoute=car')
	.on('ready', function() {
		map.fitBounds(runLayer.getBounds());
	})
	.addTo(map);

 

Com podem observar, es tracta de cridar directament el servei web de càlcul de rutes de la IDE menorca (o bé el proxy corresponent) que hem utilitzat en l'exemple anterior.

 


 

5.- Implementació de rutes amb la API v3 de Google Maps
Finalment explicarem com utilitzar el nostre servei amb la ajuda de la API de Google Maps.

Primer s'inicialitzara una variable per establir les coordenades del nostre mapa i una altra variable per les opcions del mapa.
	var myLatlng = new google.maps.LatLng(40, 4);
	var myOptions = { zoom: 10,
   	 				center: myLatlng,
                    mapTypeId: google.maps.MapTypeId.ROADMAP,
					mapTypeControl: true,
 				    navigationControl: true,
					draggingCursor: 'move'
		            };
Per acabar, declararem el mapa i afagirem la capa amb la funció 'KmlMapParser', que s'ecarrega de agafar el fitxer KML i adaptar-lo com una capa pel mapa.

 

     map = new google.maps.Map(document.getElementById("map"), myOptions);
     xml = new KmlMapParser({ map: map,
     						zoom: 10,
     						kml: 'http://ide.cime.es/menorcarouting/ruta.aspx?coord1=3.994249,40.0444087&coord2=4.009831916187729,39.97307093003211&typeRoute=car',
     						showSidebar: true,
     						showFolders: true,
     						showRootName: false,
     						showSidebarDescriptions: true,
     						showSidebarBubble: false,
     						showMultiPointsAsMarkers: false,
     						allFoldersOpen: true,
     						showImageShadow: false
     						});

 

Un altre cop, utilitzem la crida al servei web de càlcul de rutes (o al mateix fitxer proxy php) que en els dos exemples anteriors. A continuació podem veure el resultat.

 


 

Documents dels exemples

Exemple 1: OpenLayers.
Exemple 2: Leaflet.js.
Exemple 3: Google Maps API v3.
Proxy en PHP.
 

 
 

Desenvolupa:
SILME
Amb la col·laboració de:
Ajuntament de Mao  Ajuntament de Ciutadella  Ajuntament de Alaior  Ajuntament des Castell  Ajuntament de Sant Lluis  Ajuntament des Mercadal  Ajuntament de Ferreries  Ajuntament des Migjorn Gran
En xarxa amb:
IDEIB
 
© Consell Insular de Menorca
Pl. Biosfera, 5 - 07703 MAÓ
+34 971 356 265
cartografia@cime.es
Avís Legal | Accessibilitat | Contacte | XHTML 1.0 | CSS 2.1
CIME