Skip to content

[OpenLayers] Afficher un itinéraire calculé avec l’API Google Maps

Quand on est un peu familier avec les API de Google, afficher un itinéraire Google Maps dans une carte Google Maps est un jeu d’enfant car tout est déjà prévu pour vous rendre accro aux produits Google faciliter la tâche ! Voici un petit tuto pour afficher facilement, dans une carte OpenLayers, un itinéraire calculé par Google Maps !

1) Récupérer l’itinéraire en PHP ou en JS

En JS, il faut commencer par appeler l’API Google Maps. Pour ce faire, il vous faudra une clef d’API légalement obtenue (délivrée sur simple demande). La subtilité, ici, est d’appeler une librairie complémentaire (« geometry »), mais nous en reparlerons plus tard…

<script src="https://maps.googleapis.com/maps/api/js?key=pL34s3_g3t_y0uR_0wN_k3y&libraries=geometry&sensor=false"></script>

Ensuite, il faut demander gentiment à Google de calculer notre itinéraire :

var adresse_depart = 'paris';
var adresse_arrivee = 'poitiers';
var encoded_polyline;
var directionsService = new google.maps.DirectionsService();
directionsService.route({origin:adresse_depart, destination:adresse_arrivee, travelMode:google.maps.TravelMode.DRIVING},function(result, status){
    if(status == google.maps.DirectionsStatus.OK)
    {
        encoded_polyline = result['routes'][0]['overview_polyline']['points'];
    }
});

En PHP, il suffit d’appeler une URL avec les bons paramètres qui vont bien et, hop, on a bel objet JSON prêt à être utilisé. Parmi toutes les informations contenues par ce JSON, on ne va s’intéresser qu’à une seule donnée :

$origine = 'paris';
$destination = 'poitiers';
$appel_api = file_get_contents('http://maps.googleapis.com/maps/api/directions/json?origin='.$origine.'&destination='.$destination.'&sensor=false');
$itineraire = json_decode($appel_api);
$encoded_polyline = $itineraire->routes[0]->overview_polyline->points

Donc, ce qui nous intéresse ici, c’est le contenu de la dernière variable (que nous avons appelé « encoded_polyline »), à savoir une chaîne de caractères un peu bizarre :

aph{GepaAnKcSlAqQuOoc@eYrCaZ|TyLvf@uJfZ_[fDoX}S}\y[wfAee@}OeAcGiAjB_HnCfh@o@ ...

Mais cette chose immonde au premier abord est en fait une « overview_polyline », c’est à dire le résumé (encodé) de la géométrie de votre itinéraire – des points qui la composent, pour être plus précis !

Toute la (faible) complexité de notre mission réside donc dans le décodage de cette chaîne de caractère. Et, là encore, c’est Google qui va le faire le boulot !

2) Préparons la carte OpenLayers

Un peu de JS pour avoir une carte OpenLayers à disposition…

var cartographie;
var epsg_4326 = new OpenLayers.Projection("EPSG:4326");
var epsg_3857 = new OpenLayers.Projection("EPSG:3857");
cartographie = new OpenLayers.Map('carte');

// Couche "OSM"
var couche_osm = new OpenLayers.Layer.OSM('OpenStreetMap');
cartographie.addLayer(couche_osm);
cartographie.setCenter(new OpenLayers.LonLat(2, 48).transform(epsg_4326, epsg_3857), 7);

// Couche "Itinéraires"
var couche_itineraires = new OpenLayers.Layer.Vector('Itinéraires',{styleMap:new OpenLayers.StyleMap({'default':new OpenLayers.Style({strokeWidth:2,strokeColor:'red'})})});
cartographie.addLayer(couche_itineraires);

3) Transformation de l’itinéraire Google Maps en ligne classique

Comme prévu, il ne nous reste plus qu’à demander à l’API JS de Google Maps de décoder la chaîne de caractères (notre variable encoded_polyline, souvenez-vous…). Pour cela, il faut appeler cette API, en n’oubliant pas la librairie complémentaire « geometry » (cf. calcul de l’itinéraire en JS au début du tutoriel) !

<script src="https://maps.googleapis.com/maps/api/js?key=pL34s3_g3t_y0uR_0wN_k3y&libraries=geometry&sensor=false"></script>

Ensuite, on fait décoder la chaîne par l’API, qui va nous retourner un tableau de points projetés en WGS84. On va parcourir ce tableau pour reconstruire notre propre tableau de points reprojetés en Google Spherical Mercator (ex-900913, ex-3875 et actuel EPSG:3857) :

var decoded_polyline = google.maps.geometry.encoding.decodePath(encoded_polyline);
var points = new Array();
for(var i in decoded_polyline)
{
    // On récupère les deux coordonnées en WGS84 pour en faire un objet "Point" correctement reprojeté
    var lonlat = new OpenLayers.LonLat(decoded_polyline[i].lng(), decoded_polyline[i].lat()).transform(epsg_4326, epsg_3857);
    var point = new OpenLayers.Geometry.Point(lonlat.lon, lonlat.lat);
    // On ajoute ce point à notre tableau de points
    points.push(point);
}
// On ajoute, à notre couche d'itinéraires, un objet "Ligne" construit à partir du tableau de "Points"
couche_itineraires.addFeatures([new OpenLayers.Feature.Vector(new OpenLayers.Geometry.LineString(points))]);
cartographie.zoomToExtent(couche_itineraires.getDataExtent());

Si vous êtes partis de l’exemple en JS au début du tutoriel, attention à bien mettre ce bloc de code dans le bloc if(), juste derrière l’assignation de la variable « encoded_polyline », car des appels asynchrones compliquent notre affaire…

Et voilà ! C’est déjà fini ! Elle est pas belle la vie ?

Allez, je vous donne un exemple complet (en JS) : copiez le code-source, mais pensez à changer la clef de l’API Google Maps !

ol_itineraire_google_maps

  1. Aissam Permalien

    Bonjour,

    J’ai lu attentivement votre tutoriel, en fait cela fait longtemps que je cherche comment intégrer l’itinéraire calculé par google maps V3 dans une couche d’OpenLayers, mais en vain.

    Donc j’ai essayé votre code, avant de l’intégrer dans mon application, j’ai essayé tout simplement le code de votre exemple sur le lien http://labs.adrienvh.fr/blog/ol_itineraire_google_maps/ par la suite j’ai changé la clé de l’api google maps, mais rien n’est affiché.
    En quoi réside t-il le problème, je serai vraiment reconnaissant !!

    Commentaire déposé le 02/11/2014
  2. Bonjour,

    Je réponds à Mr Aissam pour l’aider à faire fonctionner cette carte.

    Supprimer : encoded_polyline = result[‘routes’][0][‘overview_polyline’][‘points’];

    Et à la place :
    var decoded_polyline = result[‘routes’][0][‘overview_path’];
    var points = new Array();

    Cordialement

    LL

    Commentaire déposé le 01/03/2015

Rédiger votre commentaire

Vous pouvez utiliser un peu d'HTML dans votre commentaire.
Votre adresse e-mail ne sera pas publiée.

S'inscrire au flux RSS des commentaires de ce billet