Tutoriel : GIS et la mobilité

Ce tutoriel explique comment intégrer la position (latitude et longitude) de l’internaute utilisant un terminal mobile dans une carte GIS. Il donne un exemple d’exploitation de cette position au travers de l’affichage des x points les plus proches.

Mobilité et respect de la vie privée

Les informations de localisation de l’internaute présentent un caractère sensible au regard des libertés individuelles (voir en France à ce sujet le site de la Commission Nationale Informatique et Libertés).

Dans ce tutoriel, l’internaute choisit de partager ses informations de localisation et ces informations ne sont pas enregistrées en base de données, afin de prendre en compte ce caractère sensible. Par conséquent, nous déclinons toute responsabilité dans l’exploitation frauduleuse qui pourrait être faite des techniques présentées.

Problématique

Par défaut, GIS 4 permet d’afficher sur une carte :

  • Soit des points liés, c’est à dire enregistrés en base ;
  • Soit un point libre, c’est à dire un point dont les coordonnées (latitude et longitude) ne sont pas enregistrées en base, mais écrites dans le squelette qui contient la carte GIS.

L’introduction de la gestion de la mobilité dans GIS soulève les deux questions suivantes :

  • Comment faire pour définir les coordonnées du point libre de manière dynamique, c’est à dire non pas en dur dans le squelette, mais en fonction de la localisation de l’internaute ?
  • Comment faire pour afficher simultanément un point libre et des points liés, si nous souhaitons utiliser la géolocalisation pour sélectionner des points liés proches de l’internaute géré comme un point libre ?

Nous allons dans ce tutoriel apporter une réponse à chacune de ces questions.

La première partie de ce tutoriel explique comment récupérer la position courante de l’internaute (latitude et longitude), en utilisant dans du code Javascript des fonctions de l’interface de programmation HTML5 de géolocalisation. Une fois récupérées, cette latitude et cette longitude sont transmises à une carte GIS via l’URL d’appel de la page SPIP qui contient cette carte. Dans cette carte GIS, la latitude et la longitude transmises sont exploitées comme coordonnées de l’objet point_libre de GIS.

La seconde partie de ce tutoriel décrit une boucle permettant d’afficher dans une carte GIS un point libre et les x points liés situés dans un cercle de rayon donné ayant ce point libre comme centre.

Enfin, dans la troisième et dernière partie, nous associons les techniques présentées dans les deux premières parties, pour afficher dans une carte GIS un point libre et mobile, ainsi que les x points liés situés dans un cercle de rayon donné ayant ce point libre comme centre. Un exemple du résultat obtenu est visible sur cette page consacrée à la Petite Ceinture ferroviaire de Paris.

Le modèle géolocalisation

L’objectif est de permettre de géolocaliser l’internaute qui accède à la page depuis un terminal mobile.

La géolocalisation est calculée par le navigateur Web grâce aux informations fournies par les réseaux de communication sans fil (comme la téléphonie mobile et le wifi), ou par le système GPS. La précision du calcul de la localisation dépend donc du navigateur, du terminal et du mécanisme utilisés.

Des fonctions de l’interface de programmation HTML5 de géolocalisation, utilisables en Javascript, permettent de récupérer cette position (latitude et longitude).

Nous utilisons ces fonctions en demandant à l’utilisateur de cliquer sur un bouton Rechercher ma position : le clique sur ce bouton, grâce à l’évènement Javascript onclick, appelle une fonction qui calcule la position de l’utilisateur puis transmet cette position à une seconde page.

Cette page peut alors afficher dans une carte GIS la position de l’utilisateur au moyen de l’objet point_libre dont les coordonnées sont celles reçues depuis la première page.

Pour implanter ce scénario, nous avons créé le modèle géolocalisation décrit dans le fichier :
squelettes/modeles/géolocalisation.html

Ce modèle admet deux paramètres :

  • gPage qui décrit le type de la page appelée (article, rubrique, etc.),
  • gIdentifiant qui décrit l’identifiant de l’objet SPIP appelé.

L’objectif de cette approche est de rendre générique l’appel de pages gérant différentes catégories d’objets SPIP.

Par exemple, pour que la position de l’internaute soit transmise à l’article numéro 234, il faut utiliser le modèle géolocalisation de la manière suivante :
<geolocalisation|gPage=article|gIdentifiant=234>

Le script Javascript décrit dans le fichier géolocalisation.html utilise les paramètres gPage et gIdentifiant pour générer une URL de type « page » qui sert à appeler la page cible. Dans notre exemple, l’URL générée est :
www.monsite.fr/?page=article&id=234

Dans le squelette de la page cible, il faut prévoir d’assigner la valeur de id au critère de boucle utilisé au moyen de la balise #ENV. Par exemple :

  • {id_article=#ENV{id}} pour une boucle ARTICLES
  • {id_rubrique=#ENV{id}} pour une boucle RUBRIQUES

Voici le code complet du modèle géolocalisation.html :

<script type="text/javascript">//<![CDATA[
var url_dest="";
var identifiant="";

function post(path, params, method) {
    method = method || "post"; // Set method to post by default if not specified.

    // The rest of this code assumes you are not using a library.
    // It can be made less wordy if you use one.
    var form = document.createElement("form");
    form.setAttribute("method", method);
    form.setAttribute("action", path);

    for(var key in params) {
        if(params.hasOwnProperty(key)) {
            var hiddenField = document.createElement("input");
            hiddenField.setAttribute("type", "hidden");
            hiddenField.setAttribute("name", key);
            hiddenField.setAttribute("value", params[key]);

            form.appendChild(hiddenField);
         }
    }

    document.body.appendChild(form);
    form.submit();
}

function maPosition(position) {
	// Envoi de la latitude et de la longitude recuperees vers le serveur Web (on est dans le navigateur)
	post('./?page='+url_dest+'&id='+identifiant+'&gLatitude=' + position.coords.latitude + '&gLongitude=' + position.coords.longitude);
}

// Fonction de callback en cas d'erreur
function erreurPosition(error) {
    var info = "Erreur lors de la geolocalisation : ";
    switch(error.code) {
    case error.TIMEOUT:
    	info += "Timeout !";
    break;
    case error.PERMISSION_DENIED:
    info += "Vous n'avez pas donne la permission";
    break;
    case error.POSITION_UNAVAILABLE:
    	info += "La position n'a pu etre determinee";
    break;
    case error.UNKNOWN_ERROR:
    	info += "Erreur inconnue";
    break;
   }
   alert(info);
}

function geolocalisation(gPage, gIdentifiant){  url_dest=gPage;  identifiant=gIdentifiant;  
  if(navigator.geolocation) {
      navigator.geolocation.getCurrentPosition(maPosition, erreurPosition,{maximumAge:600000});
  }
  else alert("La geolocalisation n'est pas supportee par votre navigateur. Verifier sa configuration");
  return true;
}

//]]>
</script>


<div id='infoposition'>
<form name="formGeoCeinture">
<input type='button' onclick='geolocalisation("#ENV{gPage}", "#ENV{gIdentifiant}")' value="Rechercher ma position">
</form>
</div>

Pour résumer, en cas de succès de la lecture de la position au moyen de la méthode getCurrentPosition, la fonction maPosition est appelée. Cette fonction insère dans l’URL de la page appelée les variables gLatitude et gLongitude qui contiennent respectivement la latitude et la longitude calculées par la méthode getCurrentPosition.
Dans notre exemple, l’URL générée est :

www.monsite.fr/?page=article
&id=234&gLatitude=48.85&gLongitude=2.39

En cas d’erreur de lecture de la position, la fonction erreurPosition, qui affiche la cause de l’erreur dans une boîte de dialogue, est appelée.

Le détail de l’utilisation de l’API de gélocalisation HTML 5 en Javascript est décrit par exemple sur le site Alsacréations dont nous avons repris une partie du code.

Dans la page appelée

Il suffit, pour définir les coordonnées du point libre, de récupérer les valeurs de gLatitude et gLongitude depuis l’URL générée par le code Javascript au moyen de la balise #ENV comme dans cet exemple :

[(#INCLURE{fond=modeles/carte_gis, lat=#ENV{gLatitude}, lon=#ENV{gLongitude}, objets=point_libre, titre=Visiteur, description=Vous êtes ici, icone=marker-icon-red.png})]

Et le tour est joué.

L’objet articles_distance_from

Nous souhaitons d’afficher dans une carte GIS un point libre et les articles associés aux x points liés les plus proches de ce point libre. Commençons par faire l’inventaire des fonctionnalités disponibles dans GIS 4 :

  • L’option point_libre permet de passer à une carte GIS la position (latitude et longitude) d’un point non enregistré en base et de centrer la carte sur la position de ce point. Mais seul le point libre est affiché ;
  • Le paramètre localize_visitor/localiser_visiteur permet de centrer la carte sur la position (latitude, longitude) de l’internaute en utilisant l’API de géolocalisation HTML5 ;
  • Le critère distancefrom permet d’afficher les points situés à une distance maximale d’un point de référence dont on fournit la position (latitude et longitude). Mais ce point de référence n’est pas affiché ;
  • Enfin, le paramètre limit permet de sélectionner le nombre maximum de points à afficher.

En conclusion, GIS 4 offre les fonctionnalités de base à combiner pour afficher simultanément un point libre et les x points les plus proches de lui. Nous allons voir à présent comment réaliser cette combinaison.

L’affichage d’un point libre est décrit dans le fichier :
gis/json/gis_point_libre.html

L’affichage des articles associés à des points liés est décrit dans le fichier :
gis/json/gis_articles.html

Par conséquent, nous allons fusionner ces deux descriptions dans un nouveau fichier que nous appelons :
squelettes/json/gis_articles_distance_from.html

Ce nouveau fichier permet l’affichage simultané d’un point libre et des articles associés aux x points liés les plus proches.

Le contenu du fichier squelettes/json/gis_articles_distance_from.html comprend deux parties :

  • La première partie décrit la liste des articles associés aux points liés sélectionnés ;
  • La second partie décrit le point libre.

Pour afficher dans ce nouveau fichier les points liés les plus proches du point libre, nous utilisons le critère distancefrom< pour les sélectionner.

Nous utilisons le paramètre limit=x pour limiter la sélection aux x points liés les plus proches.

Enfin, nous utilisons le critère par distance pour afficher les points liés sélectionnés par distance croissante par rapport au point libre.

Le code est le suivant :

<BOUCLE_art(ARTICLES){gis}{par distance}{distancefrom #ARRAY{lat,#ENV{glat},lon,#ENV{glon}}, <=, #ENV{distance}}{id_article ?}{id_rubrique ?}{id_secteur ?}{id_mot ?}{id_groupe ?}{id_auteur ?}{recherche ?}{0, #ENV{limit}}{","}>
	{"type": "Feature",
	"geometry": {"type": "Point", "coordinates": [#LON, #LAT]},
	"id":"#ID_GIS",
	"properties": {
		"title":[(#TITRE_GIS*|sinon{#TITRE*}|extraire_multi|supprimer_numero|json_encode)],
		"description":[(#DESCRIPTIF_GIS|sinon{#DESCRIPTIF}|json_encode)][
		(#LOGO_GIS|gis_icon_properties)]
	}
	}
</BOUCLE_art>
	,{
	"type": "Feature",
	"geometry": {"type": "Point", "coordinates": [[(#ENV{glon})], [(#ENV{glat})]]},
	"id":"1",
	"properties": {
		"title":[(#ENV{titre}|?{#ENV{titre},"<p>Visiteur/Visitor</p>"}|json_encode)],
		"description":[(#ENV{description}|?{#ENV{description}|wrap{<p>},"Vous êtes ici/You are here"}|json_encode)][
		(#CHEMIN{squelettes/images/marker-icon-red.png}|sinon{#CHEMIN{#ENV*{icone,0}}}|gis_icon_properties)]
		}
	}

Ce fichier squelettes/json/gis_articles_distance_from.html décrit l’objet articles_distance_from, qui est utilisable avec le modèle carte_gis.

Par exemple :

[(#INCLURE{fond=modeles/carte_gis, glat=48.887167, glon=2.301005, objets=articles_distance_from, distance=1000, limit=3, titre=Visiteur, description=Vous êtes ici, icone=marker-icon-red.png})]

La position du point libre est décrite au moyen des paramètres glat et glon que nous introduisons.
Le paramètre distance que nous introduisons également permet de définir la distance maximale en kilomètres des points liés recherchés par rapport au point libre.

Pour être utilisables, ces paramètres,doivent être ajoutés dans config/mes_options.php à la liste des paramètres utilisables lors de l’appel au modèle carte_gis :

$GLOBALS['spip_pipeline']['gis_modele_parametres_autorises'] .= "|geolocalisation";
    function geolocalisation($flux) {
   $flux[] = 'glat';
   $flux[] = 'glon';
   $flux[] = 'distance';
   return $flux;
   }

Les paramètres titre, description et icône sont les mêmes que ceux définis pour l’objet point_libre.

Le point libre est représenté par un marqueur de couleur rouge tandis que les points liés les plus proches sont indiqués par des marqueurs de couleur bleue.

Un exemple d’application

Exemple d’utilisation de la géolocalisation d’un internaute mobile sous GIS
L’internaute apparaît en rouge, tandis que les trois gares de la Petite Ceinture de Paris les plus proches de sa position apparaissent en bleu.
Bruno Bretelle - Petite Ceinture Info (www.petiteceinture-info.fr)

Dans l’exemple précédent, les valeurs respectives de glat et glon sont définies de manière statique.

Or nous avons vu dans la première partie de ce tutoriel que nous pouvons définir les valeurs respectives de glat et glon au moyen de la balise #ENV, à partir de l’URL d’appel de la page qui contient la carte GIS, comme dans cet exemple :

[(#INCLURE{fond=modeles/carte_gis, glat=#ENV{gLatitude}, glon=#ENV{gLongitude}, objets=articles_distance_from, distance=1000, limit=3, titre=Visiteur, description=Vous êtes ici, icone=marker-icon-red.png})]

Les variables d’environnement sont passées dans l’URL sous la forme :
?gLatitude=<valeur>&gLongitude=<valeur>
où les valeurs de ces deux variables sont mises à jour à partir de la localisation d’un terminal mobile.

Voici un exemple de boucle SPIP qui intègre cette utilisation du modèle carte_gis :

<BOUCLE_contenu_article(ARTICLES){id_article=#ENV{id}}>
<B_articles>
	<ul>
	<BOUCLE_articles_points(ARTICLES){gis}{0,3}{par distance}{distancefrom #ARRAY{lat,#ENV{gLatitude},lon,#ENV{gLongitude}}, <=, 1000}>	
		<li><a href="#map1" onclick="javascript:gis_focus_marker(#ID_GIS,1);">#TITRE / Distance à vol d'oiseau : [(#DISTANCE|couper{6})] km</a></li>
	</BOUCLE_articles_points>
	</ul>
	<br/>
	[(#INCLURE{fond=modeles/carte_gis, glat=#ENV{gLatitude}, glon=#ENV{gLongitude}, objets=articles_distance_from, distance=1000, limit=3, centrer_auto=oui, scale=oui, fullscreen=oui,ajax})]
	<br/>
	<br/>		
</B_articles>
	<h3 class="spip">Pas de site présent à moins de 1000 kilomètres de votre localisation</h3>
<//B_articles>

</BOUCLE_contenu_article>

La boucle contenu_article affiche au-dessus de la carte GIS la liste des points les plus proches sous forme de liens. En cliquant sur l’un de ces liens, le point correspondant est localisé sur la carte. Nous utilisons pour cela le code donné dans le paragraphe « Appeler un point géolocalisé à partir d’un squelette » de la page « Astuces GIS » du Wiki de SPIP-contrib.

Les même critères de sélection et d’affichage des points sont utilisés pour l’affichage de ces liens que ceux utilisés dans le fichier squelettes/json/gis_articles_distance_from.html pour afficher les points sur la carte.

Utilisation avec ZPIP v1
Si vous utilisez ZPIP v1, placez le squelette précédent dans un fichier nommé par exemple geo_articles_proches.html dans le sous-répertoire contenu de ZPIP. Dans le répertoire racine de ZPIP, n’oubliez pas de créer un autre fichier nommé geo_articles_proches.html et contenant le code suivant :

<BOUCLE_principale_article(ARTICLES){id_article=#ENV{id}}>
<INCLURE{fond=structure}{env}{id_rubrique=#ENV{id_rubrique,#ID_RUBRIQUE}}{id_secteur=#ID_SECTEUR}{type=geo_articles_proches}{composition=#COMPOSITION} />
</BOUCLE_principale_article>

Conclusion

Nous avons montré comment il est possible de sélectionner les points liés affichés dans une carte GIS en fonction de la position courante d’un internaute mobile. D’autres pistes restent sans doute à explorer. Nous pouvons citer à titre d’exemple l’utilisation de la méthode watchPosition de l’API de géolocalisation HTML 5, qui permet un suivi continu de la position de l’internaute, au lieu de la méthode getCurrentPosition qui offre un calcul ponctuel de cette position.

Un autre point à étudier est l’utilisation d’Ajax afin d’optimiser l’affichage des cartes GIS utilisées dans ce contexte de mobilité.

Autre piste de développement : stocker en base de données les géolocalisations calculées, afin de déterminer où se trouvent les internautes (tout en respectant la vie privée bien entendu).

À votre tour de jouer !

Discussion

3 discussions

  • Bonjour, très intéressant...
    je souhaite pouvoir choisir le fond de carte, et proposer une geolocalisation sur ma framacarte.
    Ce choix est-il possible ?
    merci

    Répondre à ce message

  • 1

    Bonsoir, je n’arrive pas à comprendre comment intégrer le bouton « Rechercher ma position »
    -  j’ai bien mis le fichier géolocalisation . html dans le dossier modeles de mon dossier squelette avec le script.

    dans le squelette de la page geo_articles_proches_mots.html je met ce code/boucle :
    <INCLURE{fond=modeles/geolocalisation,gPage=geo_articles_proches_mots,gIdentifiant=3,env,ajax} />

    quand je clique, il me trouve bien ma position, puis le texte indique la distance du point, la carte, mais celle-ci est globale et surtout sans point...

    là je suis perdu !
    car sinon je sais pas ou mettre la balise : <geolocalisation|gPage=article|gIdentifiant=234> dans un article, cela ne fonctionne pas.

    si quelqu’un à une piste.
    Merci
    Claude

    • Bonjour,

      Le modèle géolocalisation calcule les coordonnées de l’utilisateurs et les envoie à la page spécifiée par l’inclusion de <geolocalisation|gPage=article|gIdentifiant=234> dans le corps d’un article.

      Ici, la page est de type article et l’article porte le numéro 234.

      Par conséquent, pour la seconde question concernant l’usage de <geolocalisation|gPage=article|gIdentifiant=234> dans le corps d’un article : votre site dispose-t’il d’un article dont le numéro est 234 ? Si ce n’est pas le cas, essayez avec un article publié sur votre site.

      Pour la première question, je vous suggère de faire déjà les tests sans utiliser Ajax et en reprenant l’exemple indiqué dans le paragraphe « Un exemple d’application ». Je n’ai pas testé cette méthode avec Ajax. Aussi j’ai tendance à dire que l’adaptation de ce tutoriel à Ajax est un travail en cours. ;-)

      Bien cordialement,
      Bruno.

    Répondre à ce message

  • Ah super, ça fait un bon exemple du critère « distancefrom » que j’avais ajouté. Merci ! :)

    Répondre à ce message

Ajouter un commentaire

Avant de faire part d’un problème sur un plugin X, merci de lire ce qui suit :

  • Désactiver tous les plugins que vous ne voulez pas tester afin de vous assurer que le bug vient bien du plugin X. Cela vous évitera d’écrire sur le forum d’une contribution qui n’est finalement pas en cause.
  • Cherchez et notez les numéros de version de tout ce qui est en place au moment du test :
    • version de SPIP, en bas de la partie privée
    • version du plugin testé et des éventuels plugins nécessités
    • version de PHP (exec=info en partie privée)
    • version de MySQL / SQLite
  • Si votre problème concerne la partie publique de votre site, donnez une URL où le bug est visible, pour que les gens puissent voir par eux-mêmes.
  • En cas de page blanche, merci d’activer l’affichage des erreurs, et d’indiquer ensuite l’erreur qui apparaît.

Merci d’avance pour les personnes qui vous aideront !

Par ailleurs, n’oubliez pas que les contributeurs et contributrices ont une vie en dehors de SPIP.

Qui êtes-vous ?
[Se connecter]

Pour afficher votre trombine avec votre message, enregistrez-la d’abord sur gravatar.com (gratuit et indolore) et n’oubliez pas d’indiquer votre adresse e-mail ici.

Ajoutez votre commentaire ici

Ce champ accepte les raccourcis SPIP {{gras}} {italique} -*liste [texte->url] <quote> <code> et le code HTML <q> <del> <ins>. Pour créer des paragraphes, laissez simplement des lignes vides.

Ajouter un document

Suivre les commentaires : RSS 2.0 | Atom