8. Script PHP coté serveur

Nous utiliserons un script PHP pour exécuter les requêtes de routafe et renverons le résultat au client web.

Les étapes suivantes sont nécessaires :

  • Retrouver les coordonnées du point de départ et de celui d’arrivée.
  • Trouver l’arrête la plus proche d’un point de départ ou d’arrivée.
  • Prendre soit le noeud de début ou de fin de l’arrête (for Dijkstra/ A-Star) ou l’arrête elle-même (Shooting-Star) comme début ou fin du parcours.
  • Exécuter les requête de recherche de plus court chemin.
  • Retourner le résultat de la requête en XML ou mieux encore en GeoJSON au client web.

Note

Pour conserver cet exemple aussi simple que possiblle et de mettre en évidence les requête de routafe, ce script PHP ne valide pas les paramètres des requêtes et ne prend pas en compte les problèmes de sécurités de PHP.

Commençons avec quelque modèles PHP et plaçon ces fichiers dans un répertoire accessible par le serveur Apache :

<?php

   // Paramétrage de la connexion à la base de données
   define("PG_DB"  , "routing");
   define("PG_HOST", "localhost"); 
   define("PG_USER", "postgres");
   define("PG_PORT", "5432"); 
   define("TABLE",   "ways");

   // Récupérer le point de départ
   $start = split(' ',$_REQUEST['startpoint']);
   $startPoint = array($start[0], $start[1]);

   // Récupérer le point d'arrivée
   $end = split(' ',$_REQUEST['finalpoint']);
   $endPoint = array($end[0], $end[1]);
   
?>

8.1. L’arrête la plus proche

Habituellement les points de départ et d’arrivée, qui sont récupérer depuis le client, n’est pas le point de départ ou d’arrivée d’un tronçon. Il est plus simple de retrouver l’arrête la plus proche que le sommet le plus proche, parce que l’algorithme “Shooting-Star” est basé sur les arrêtes. Pour les algorithmes basés sur les sommets (Dijkstra, A-Étoile) nous pouvons choisir le opint de départ ou d’arrivée de l’arrête sélectionnée.

<?php

   // Trouver le tronçon le plus proche
   $startEdge = findNearestEdge($startPoint);
   $endEdge   = findNearestEdge($endPoint);

   // FONCTION findNearestEdge
   function findNearestEdge($lonlat) {

      // Connexion à la base de données
      $con = pg_connect("dbname=".PG_DB." host=".PG_HOST." user=".PG_USER);

      $sql = "SELECT gid, source, target, the_geom, 
		          distance(the_geom, GeometryFromText(
	                   'POINT(".$lonlat[0]." ".$lonlat[1].")', 4326)) AS dist 
	             FROM ".TABLE."  
	             WHERE the_geom && setsrid(
	                   'BOX3D(".($lonlat[0]-0.1)." 
	                          ".($lonlat[1]-0.1).", 
	                          ".($lonlat[0]+0.1)." 
	                          ".($lonlat[1]+0.1).")'::box3d, 4326) 
	             ORDER BY dist LIMIT 1";

      $query = pg_query($con,$sql);  

      $edge['gid']      = pg_fetch_result($query, 0, 0);  
      $edge['source']   = pg_fetch_result($query, 0, 1);  
      $edge['target']   = pg_fetch_result($query, 0, 2);  
      $edge['the_geom'] = pg_fetch_result($query, 0, 3);  

      // Fermer la connexion
      pg_close($con);

      return $edge;
   }
   
?>

8.2. Requête de routage

<?php

   // Choisir un algorithme de parcours
   switch($_REQUEST['method']) {

      case 'SPD' : // Shortest Path Dijkstra 

        $sql = "SELECT rt.gid, ST_AsGeoJSON(rt.the_geom) AS geojson, 
	                 length(rt.the_geom) AS length, ".TABLE.".gid 
	              FROM ".TABLE.", 
	                  (SELECT gid, the_geom 
	                      FROM dijkstra_sp_delta(
	                          '".TABLE."',
	                          ".$startEdge['source'].",
	                          ".$endEdge['target'].",
	                          0.1)
	                   ) as rt 
	              WHERE ".TABLE.".gid=rt.gid;";
        break;
        
      case 'SPA' : // Shortest Path A* 

        $sql = "SELECT rt.gid, ST_AsGeoJSON(rt.the_geom) AS geojson, 
	                   length(rt.the_geom) AS length, ".TABLE.".gid 
	                FROM ".TABLE.", 
	                    (SELECT gid, the_geom 
	                        FROM astar_sp_delta(
	                            '".TABLE."',
	                            ".$startEdge['source'].",
	                            ".$endEdge['target'].",
	                            0.1)
	                     ) as rt 
	                WHERE ".TABLE.".gid=rt.gid;";  
        break;

      case 'SPS' : // Shortest Path Shooting*

        $sql = "SELECT rt.gid, ST_AsGeoJSON(rt.the_geom) AS geojson, 
	                   length(rt.the_geom) AS length, ".TABLE.".gid 
	                FROM ".TABLE.", 
	                    (SELECT gid, the_geom 
	                        FROM shootingstar_sp(
	                            '".TABLE."',
	                            ".$startEdge['gid'].",
	                            ".$endEdge['gid'].",
	                            0.1, 'length', true, true)
	                     ) as rt 
	                WHERE ".TABLE.".gid=rt.gid;";
        break;   

   } // fin switch

   // Connexion à la base de données
   $dbcon = pg_connect("dbname=".PG_DB." host=".PG_HOST." user=".PG_USER);

   // Exécuter une requête
   $query = pg_query($dbcon,$sql); 
   
?>

8.3. Sortie au format GeoJSON

OpenLayers permet l’affichage de lignes en utilisant directement des données au format GeoJSON, donc notre script retourne un objet FeatureCollection au format GeoJSON :

<?php

   // Renvoit un chemin au format GeoJSON
   $geojson = array(
      'type'      => 'FeatureCollection',
      'features'  => array()
   ); 
  
   // Ajouter un tronçon au tableau GeoJSON
   while($edge=pg_fetch_assoc($query)) {  

      $feature = array(
         'type' => 'Feature',
         'geometry' => json_decode($edge['geojson'], true),
         'crs' => array(
            'type' => 'EPSG',
            'properties' => array('code' => '4326')
         ),
         'properties' => array(
            'id' => $edge['id'],
            'length' => $edge['length']
         )
      );
      
      // Ajouter un tableau d'éléments au tableau de collection d'éléments
      array_push($geojson['features'], $feature);
   }

	
   // Fermeture de la connexion
   pg_close($dbcon);

   // Renvoyer le résultat
   header('Content-type: application/json',true);
   echo json_encode($geojson);
   
?>

Table des matières

Sujet précédent

7. Requêtes de routage avancées

Sujet suivant

9. Client en GeoExt

License

Ce travail est distribué sous licence Creative Commons Attribution-Share Alike 3.0 License.

Creative Commons License