2: google.maps.ClientGeocoder : latitude et longitude d'un point à partir de son adresse

le - Lien permanent 34 commentaires

L’article 1: Afficher une carte avec Google Maps nous a permis de voir comment afficher une carte en utilisant l’API Google Maps.

Mais l’exemple utilisé supposait que nous connaissions la latitude et la longitude du point sur lequel nous souhaitions centrer notre carte.

En réalité, en particulier lorsque l’on interagit avec un utilisateur, il est plus fréquent de connaître l’adresse d’un lieu, plutôt que ses coordonnées géographiques !
Par exemple, il est plus facile de se souvenir de “Place Bellecour, Lyon, France”, que de “(45.756788, 4.831515)”.

Heureusement, Google Maps fourni un service, le Geocoder, permettant d’obtenir les coordonnées géographiques d’un point à partir de son adresse.
La documentation de l’API de Geocoding est accessible sur le site de google.

Attention : Pour cet article, je présuppose que vous avez lu et compris la première partie : Afficher une carte avec Google Maps, et ne reviendrai pas sur les concepts qui y sont déjà présentés.


Afficher la carte en fonction d’une adresse

En première partie de cette série d’articles sur Google Maps, nous avons centré la carte sur la Place Bellecour, dont nous connaissions la latitude et la longitude :

  • Latitude : 45.756788
  • Longitude : 4.831515

Cela dit, ce n’est pas très “User Friendly“ !

Google Maps fournit un service permettant de “traduire” une adresse en coordonnées géographiques.
Ce service est nommé “Geocoder”.

Le principe de base est simple : vous lui fournissez une adresse en entrée, et il retourne la couple latitude/longitude correspondant.

Pour utiliser ce service, commencez- par instancier la classe google.maps.ClientGeocoder, et utilisez la méthode getLatLng.
Cette méthode réalise un appel en arrière-plan vers les serveurs Google, et appelle, une fois les coordonnées reçues, une méthode dont la référence lui a été passée en second paramètre. Celle-ci reçoit en argument le couple de coordonnées.

Par exemple, si la variable adresse contient l’adresse dont on veut charger les coordonnées :

var geocoder = new google.maps.ClientGeocoder();
geocoder.getLatLng(adresse, function (coord) {
        // Et centrage de la map sur les coordonnées renvoyées par Google :
        map.setCenter(coord, 15);
    });

Notre fonction appelée au chargement de la page peut donc être ré-écrite comme ceci :

var initMap = function ()
{
    var map = new google.maps.Map2(document.getElementById('map'));
    
    var adresse = 'place bellecour, lyon, france';
    
    // Recherche des coordonnées d'un point dont on connait l'adresse :
    var geocoder = new google.maps.ClientGeocoder();
    geocoder.getLatLng(adresse, function (coord) {
            // Et centrage de la map sur les coordonnées renvoyées par Google :
            map.setCenter(coord, 15);
        });
    
}; // initMap

Et voici le résultat :

Recherche sur 'Place Bellecour, Lyon, France' en utilisant le Geocoder

Autrement dit, nous obtenons la même chose que ce que nous voyions au cours de l’article précédent, lorsque nous affichions la carte directement en fonction de la latitude et de la longitude du point nous intéressant.


Soyez précis dans les adresses que vous utilisez

Google Maps est un service fonctionnant à l’échelle du monde entier.
Dans le monde, il existe probablement plusieurs localisations portant le nom de celle qui vous intéresse !

Le Geocoder de Google Maps fait de son mieux : si vous lui passez une adresse qui correspond à plusieurs localisations, il aura tendance à renvoyer les coordonnées de celle qu’il considère comme étant “la meilleure”.

Typiquement, cela peut signifier que si vous saisissez un nom correspondant à plusieurs villes, il pourrait avoir tendance à renvoyer les coordonnées de la plus grande - ou de la plus peuplée - ou de la plus importante géo-politiquement parlant - ou …

Pour illustrer mes propos, voici un exemple :

Vous cherchez à afficher une carte centrée sur une ville nommée “Vienne”.
Cette ville se trouve en Isère (département 38), en France.
Il existe plusieurs villes nommées “Vienne”.


Vienne, capitale de l’Autriche

Pour commencer, lançons une recherche en appelant le Geocoder en ne lui passant que “Vienne” comme adresse.

Voici le résultat obtenu :

Résultat de la recherche de 'Vienne' avec le Geocoder

Bingo, la capitale de l’Autriche…
Une grande ville nommée “Vienne”, importante d’un point de vue géo-politique, fort peuplée (1.6 million d’habitants, si j’en crois la page que Wikipedia consacre à Vienne.)

Mais pas la “Vienne” que nous recherchions…


Vienne, un département

Seconde tentative, précisons que nous cherchons une localisation en France, en appelant le Geocoder sur “Vienne, France”.

Voici le résultat obtenu :

Résultat de la recherche de 'Vienne, France' avec le Geocoder

Cette fois, le service Google Maps nous renvoi vers le département de la Vienne.

Géo-politiquement parlant, ce département est plus important que la ville que nous cherchions ; sa superficie est plus grande ; il est plus peuplé ; et il est probablement plus connu…

Mais ce n’est pas la ville qui nous intéressait !


Vienne, une ville en Isère

Pour notre troisième essai, soyons encore plus précis : lançons une recherche sur “38, Vienne, France”.
(Pour rappel, la ville que nous cherchons est en Isère, le département 38)

Et voici le résultat :

Résultat de la recherche de '38, Vienne, France' avec le Geocoder

Cette fois-ci, le Geocoder nous a bien renvoyé le résultat attendu.


Enseignements à tirer de cet exemple

Quelle était le but de cet exemple ?
Vous montrer que :

  • Le service de geocoding ne fait pas toujours ce que vous souhaiteriez
    • Il peut donc être judicieux de faire valider par l’utilisateur ce que le GeoCoder a renvoyé ; typiquement, si un utilisateur saisit son adresse, et que vous voulez enregistrer les coordonnées correspondantes en Base de Données, pourquoi ne pas afficher une carte à l’utilisateur, lui demandant si la localisation proposée sur la carte est bien celle souhaitée - et lui demandant de préciser son adresse, dans le cas contraire
  • Plus vous êtes précis, meilleures seront les chances que le service de geocoding trouve la “bonne localisation”
    • Indiquez les libellés que vous connaissez
    • Si vous savez à quel pays se rapporte l’adresse, précisez le
    • Si vous pouvez fournir une indication supplémentaire - un code postal, par exemple - faites le !


Fournir quelques indications supplémentaires au GeoCoder

Pour améliorer vos chances d’obtenir la “bonne” adresse, vous pouvez passer quelques indications au service de Geocoding.

setBaseCountryCode

Pour commencer, vous pouvez indiquer au service de Geocoding que vous préférez recevoir des résultats se trouvant dans un pays donné.

Par exemple :

geocoder.setBaseCountryCode('fr');

Dans le cas où votre application n’est pas internationalisée, cela augmente les chances de renvoyer des résultats correspondant à ce que l’utilisateur souhaitait.


setViewport

L’API du GeoCoder permet d’aller plus loin que cela : il est possible d’indiquer au service que l’on souhaite qu’il accorde une priorité plus élevée aux localisation se trouvant dans une zone délimitée par deux points.

Prenons par exemple le cas d’une ville nommée Beaurepaire : il en existe quatre en France.
Les deux qui m’intéressent sont :

Par défaut, lorsque l’on effectue une requête sur “Beaurepaire, France” vers le service de Geocoding, sans lui donner plus de précision, celui-ci retourne :

Résultat de la recherche de 'Beaurepaire, France', sans préciser de Viewport

Ce qui correspond à Beaurepaire en Isère.

Maintenant, considérons que l’utilisateur de notre application souhaite effectuer une recherche sur l’Ouest de la France (que ce soit parce qu’il habite dans la région, parce qu’il recherche une destination de vacances, … tout dépendra de votre application) : la ville retournée par défaut ne lui conviendra certainement pas.

Le service de GeoCoding permet de définir une zone rectangulaire, délimitée par deux couples de coordonnées :

  • Point constituant la limite sud-ouest de la zone,
  • et coordonnées du nord-est de la zone.

Par exemple, pour délimiter une zone dans l’Ouest de la France :

var pointSW = new GLatLng(44, -3);
var pointNE = new GLatLng(48, 2);
geocoder.setViewport(new GLatLngBounds(pointSW, pointNE));

Dans sa recherche de coordonnées, le Geocoder aura tendance à privilégier les points situés dans cette zone.
Si nous relançons notre recherche sur “Beaurepaire, France”, en utilisant la fonction setViewport comme présenté au-dessus, nous obtenons à présent :

Résultat de la recherche de 'Beaurepaire, France', en précisant un Viewport dans l'Ouest de la France

Cette fois-ci, c’est Beaurepaire en Vendée qui a été renvoyé par le service de Geocoding.

Pour plus de clarté, j’ai ajouté l’affichage de la zone définie via setViewport, à l’aide du code suivant :

var cadre = new GPolyline([
                new GLatLng(pointNE.lat(), pointSW.lng()),
                new GLatLng(pointNE.lat(), pointNE.lng()),
                new GLatLng(pointSW.lat(), pointNE.lng()),
                new GLatLng(pointSW.lat(), pointSW.lng()),
                new GLatLng(pointNE.lat(), pointSW.lng())
            ], "#000000", 3);
map.addOverlay(cadre);

Un point important est à noter : préciser un viewport est une indication seulement !
Autrement dit, le Geocoder est susceptible de ne pas suivre votre indication, et de retourner des coordonnées extérieures à la zone définie !
Sur l’exemple de Vienne, par exemple, ça ne fonctionnait pas : je me retrouvais toujours en Autriche… (Ce qui explique que, pour cette partie, j’ai utilisé une autre ville en exemple ^^)


Obtenir plusieurs localisations pour une adresse

Le service de GeoCoding permet d’aller plus loin : jusqu’à présent, nous l’avons utilisé pour obtenir une couple de coordonnées pour une adresse… Mais, pour une adresse donnée, il peut renvoyer plusieurs couples de coordonnées, correspondant toutes plus ou moins à la saisie.

Je m’explique : plus haut, nous avons travaillé avec l’exemple de “Beaurepaire, France”, et nous avons constaté qu’il existait plusieurs “Beaurepaire” en France.
Mais la méthode getLatLng du Geocoder ne nous renvoyait toujours qu’une seule localisation : celle qui était considéré comme “la meilleure” par le service ; pas forcément celle que vous, ou votre utilisateur, considéreriez comme “la meilleure” !

Cette solution n’est pas forcément la plus adaptée au contexte de votre application : vous pourriez demander à l’utilisateur, parmi la liste des villes répondant à sa saisie, laquelle est celle qui l’intéresse réellement…

Pour répondre à ce besoin, le service de Geocoding fourni une autre méthode : getLocations.
Elle fonctionne de la même manière que getLatLng, mais renvoie des données pour une ou plusieurs localisations.

Par exemple, en l’appelant sur “Beaurepaire, France”, la fonction de callback passée en second paramètre recevra non pas un simple couple de coordonnées, mais un objet de la forme suivante :

{
   "name":"beaurepaire, france",
   "Status":{
      "code":200,
      "request":"geocode"
   },
   "Placemark":[
      {
         "id":"p1",
         "address":"Beaurepaire, France",
         "AddressDetails":{
            "Country":{
               "CountryNameCode":"FR",
               "AdministrativeArea":{
                  "AdministrativeAreaName":"Rhône-Alpes",
                  "SubAdministrativeArea":{
                     "SubAdministrativeAreaName":"Isère",
                     "Locality":{
                        "LocalityName":"Beaurepaire"
                     }
                  }
               }
            },
            "Accuracy":4
         },
         "Point":{
            "coordinates":[
               5.05504,
               45.338439,
               0
            ]
         }
      },
      {
         "id":"p2",
         "address":"Beaurepaire, France",
         "AddressDetails":{
            "Country":{
               "CountryNameCode":"FR",
               "AdministrativeArea":{
                  "AdministrativeAreaName":"Pays de la Loire",
                  "SubAdministrativeArea":{
                     "SubAdministrativeAreaName":"Vendée",
                     "Locality":{
                        "LocalityName":"Beaurepaire"
                     }
                  }
               }
            },
            "Accuracy":4
         },
         "Point":{
            "coordinates":[
               -1.087891,
               46.910971,
               0
            ]
         }
      },
      {
         "id":"p3",
         "address":"Beaurepaire-en-Bresse, France",
         "AddressDetails":{
            "Country":{
               "CountryNameCode":"FR",
               "AdministrativeArea":{
                  "AdministrativeAreaName":"Bourgogne",
                  "SubAdministrativeArea":{
                     "SubAdministrativeAreaName":"Saône-et-Loire",
                     "Locality":{
                        "LocalityName":"Beaurepaire-en-Bresse"
                     }
                  }
               }
            },
            "Accuracy":4
         },
         "Point":{
            "coordinates":[
               5.386905,
               46.667817,
               0
            ]
         }
      },
      {
         "id":"p4",
         "address":"Beaurepaire, France",
         "AddressDetails":{
            "Country":{
               "CountryNameCode":"FR",
               "AdministrativeArea":{
                  "AdministrativeAreaName":"Picardie",
                  "SubAdministrativeArea":{
                     "SubAdministrativeAreaName":"Oise",
                     "Locality":{
                        "LocalityName":"Beaurepaire"
                     }
                  }
               }
            },
            "Accuracy":4
         },
         "Point":{
            "coordinates":[
               2.57048,
               49.293437,
               0
            ]
         }
      },
      {
         "id":"p5",
         "address":"Beaurepaire, France",
         "AddressDetails":{
            "Country":{
               "CountryNameCode":"FR",
               "AdministrativeArea":{
                  "AdministrativeAreaName":"Haute-Normandie",
                  "SubAdministrativeArea":{
                     "SubAdministrativeAreaName":"Seine-Maritime",
                     "Locality":{
                        "LocalityName":"Beaurepaire"
                     }
                  }
               }
            },
            "Accuracy":4
         },
         "Point":{
            "coordinates":[
               0.220527,
               49.665643,
               0
            ]
         }
      },
      {
         "id":"p6",
         "address":"Beaurepaire-sur-Sambre, France",
         "AddressDetails":{
            "Country":{
               "CountryNameCode":"FR",
               "AdministrativeArea":{
                  "AdministrativeAreaName":"Nord-Pas-de-Calais",
                  "SubAdministrativeArea":{
                     "SubAdministrativeAreaName":"Nord",
                     "Locality":{
                        "LocalityName":"Beaurepaire-sur-Sambre"
                     }
                  }
               }
            },
            "Accuracy":4
         },
         "Point":{
            "coordinates":[
               3.793896,
               50.062004,
               0
            ]
         }
      },
      {
         "id":"p7",
         "address":"Beaurepaire, Champrond-en-Gâtine, France",
         "AddressDetails":{
            "Country":{
               "CountryNameCode":"FR",
               "AdministrativeArea":{
                  "AdministrativeAreaName":"Centre",
                  "SubAdministrativeArea":{
                     "SubAdministrativeAreaName":"Eure-et-Loir",
                     "Locality":{
                        "LocalityName":"Champrond-en-Gâtine",
                        "DependentLocality":{
                           "DependentLocalityName":"Beaurepaire"
                        }
                     }
                  }
               }
            },
            "Accuracy":4
         },
         "Point":{
            "coordinates":[
               1.087505,
               48.389163,
               0
            ]
         }
      },
      {
         "id":"p8",
         "address":"Beaurepaire, Laigny, France",
         "AddressDetails":{
            "Country":{
               "CountryNameCode":"FR",
               "AdministrativeArea":{
                  "AdministrativeAreaName":"Picardie",
                  "SubAdministrativeArea":{
                     "SubAdministrativeAreaName":"Aisne",
                     "Locality":{
                        "LocalityName":"Laigny",
                        "DependentLocality":{
                           "DependentLocalityName":"Beaurepaire"
                        }
                     }
                  }
               }
            },
            "Accuracy":4
         },
         "Point":{
            "coordinates":[
               3.86494,
               49.85891,
               0
            ]
         }
      },
      {
         "id":"p9",
         "address":"Beaurepaire, Doullens, France",
         "AddressDetails":{
            "Country":{
               "CountryNameCode":"FR",
               "AdministrativeArea":{
                  "AdministrativeAreaName":"Picardie",
                  "SubAdministrativeArea":{
                     "SubAdministrativeAreaName":"Somme",
                     "Locality":{
                        "LocalityName":"Doullens",
                        "DependentLocality":{
                           "DependentLocalityName":"Beaurepaire"
                        }
                     }
                  }
               }
            },
            "Accuracy":4
         },
         "Point":{
            "coordinates":[
               2.395936,
               50.16396,
               0
            ]
         }
      },
      {
         "id":"p10",
         "address":"Beaurepaire, Chauffayer, France",
         "AddressDetails":{
            "Country":{
               "CountryNameCode":"FR",
               "AdministrativeArea":{
                  "AdministrativeAreaName":"Provence-Alpes-Côte d'Azur",
                  "SubAdministrativeArea":{
                     "SubAdministrativeAreaName":"Hautes-Alpes",
                     "Locality":{
                        "LocalityName":"Chauffayer",
                        "DependentLocality":{
                           "DependentLocalityName":"Beaurepaire"
                        }
                     }
                  }
               }
            },
            "Accuracy":4
         },
         "Point":{
            "coordinates":[
               6.02335,
               44.739799,
               0
            ]
         }
      }
   ]
}

Comme points intéressants, on peut noter :

  • Une propriété “Status” indiquant si la requête a réussi,
  • Une propriété “Placemark”, contenant une liste de localisations correspondant à la saisie,
  • avec, pour chaque Placemark :
    • L’adresse : “address”,
    • Les composantes de l’adresse : “AdressDetails” (département, région, …)
    • Les coordonnées correspondantes : propriété “Point.coordinates”

Un exemple d’utilisation de cette fonctionnalité pourrait être :

geocoder.getLocations(adresse, function (coordonnees) {
        var nbrPlacemarks = coordonnees.Placemark.length;
        var iPlacemark;
        var placemark;
        for (iPlacemark=0 ; iPlacemark<nbrPlacemarks ; iPlacemark++)
        {
            placemark = coordonnees.Placemark[iPlacemark];
            createMarkerOnPlacemark(map, placemark);
        }
    });

Cette portion de code fait appel au service de Geocoding, et, pour chaque localisation possible retournée, appelle la méthode suivante :

var createMarkerOnPlacemark = function (map, placemark)
{
    var coord = placemark.Point.coordinates;
    var marker = new GMarker(new GLatLng(coord[1], coord[0]));
    GEvent.addListener(marker, "click", function() {
        var html = placemark.address;
        html += '<br />';
        html += '( ' + placemark.Point.coordinates[1] + ' ; ' 
                + placemark.Point.coordinates[0] + ' )';
        html += '<p>';
        if (placemark.AddressDetails.Country.AdministrativeArea)
        {
            var administrativeArea = placemark.AddressDetails.Country.AdministrativeArea;
            html += administrativeArea.AdministrativeAreaName;
            if (administrativeArea.SubAdministrativeArea)
            {
                var subAdministrativeArea = administrativeArea.SubAdministrativeArea;
                html += '<br />';
                html += subAdministrativeArea.SubAdministrativeAreaName;
                if (subAdministrativeArea.Locality)
                {
                    var locality = subAdministrativeArea.Locality;
                    html += '<br />';
                    html += locality.LocalityName;
                    if (locality.DependentLocality)
                    {
                        html += '<br />';
                        html += locality.DependentLocality.DependentLocalityName;
                    }
                }
            }
        }
        html += '</p>';
        marker.openInfoWindowHtml(html);
    }); // addListener
    map.addOverlay(marker);
}; // createMarkerOnPlacemark

Cette méthode place un marqueur sur la carte, à l’emplacement de la localisation proposée par le Geocoder, et défini un gestionnaire d’événement associé au clic sur ledit marqueur : un clic sur celui-ci provoquera l’ouverture d’une fenêtre d’information, contenant quelques données sur la localisation en question.
(Nous verrons plus loin, dans un autre article, comment utiliser les marqueurs et les fenêtres d’information)

Et voici le résultat, pour une recherche sur “Beaurepaire, France” :

recherche-geocoder-getLocations-beaurepaire.png

La même chose, après avoir cliqué sur un marqueur :

recherche-geocoder-getLocations-beaurepaire-window1.png

Et sur un autre marqueur :

recherche-geocoder-getLocations-beaurepaire-window2.png

Et pour finir, par curiosité, voici ce qu’il se passe si nous indiquons au service de Geocoding, via la méthode setViexport présentée plus haut, que nous voulons qu’il accorde une priorité plus élevée à une zone dans l’Ouest de la France :

recherche-geocoder-getLocations-beaurepaire-setViewport.png

On constate que certains points en dehors du viewport demandé ont disparu… Mais on a la preuve qu’utiliser la méthode setViewport revient à donner une indication, et seulement une indication, au service de Geocoding.


Utiliser le Geocoder côté serveur, via une requête HTTP

Jusqu’à présent, nous avons vu comment utiliser le Geocoder côté client, en Javascript.
Mais il est aussi possible de l’utiliser côté serveur, dans le langage que vous utilisez pour le reste de votre application.

Le principe est simple :

  • Vous émettez une requête HTTP vers http://maps.google.com/maps/geo? en passant en paramètre
    • votre clef d’API
    • le format de données attendu en retour
      • json
      • xml / kml
      • csv
    • l’adresse que vous voulez localiser

Et le Geocoder vous renvoi la liste des localisations correspondantes, exactement comme vu juste au-dessus.

Par exemple, en PHP, en utilisant l’extension curl, vous écririez :

$localisation = "Place Bellecour, Lyon, France";
//$localisation = "Beaurepaire, France";

$localisationUrl = urlencode($localisation);
$outputMode = 'xml';    // csv / xml / kml / json
$apiKey = '...';  // TODO placer ici votre clef d'API
$urlGeocoder = 'http://maps.google.com/maps/geo?key=' . $apiKey . '&output=' . $outputMode . '&q=' . $localisationUrl;

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $urlGeocoder);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla 5/0'); // Pour avoir de l'UTF-8 en sortie...
$resultGeocoder = curl_exec($ch);
$httpStatus = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

Si le format demandé en sortie est ‘csv’, vous obtiendrez en réponse une chaîne composée de quatre champs, séparés par des virgules :

  • code de statut,
  • précision,
  • latitude,
  • et longitude

Si le format demandé est ‘xml’ ou ‘kml’, vous obtiendrez une réponse au format XML, contenant toutes les informations que nous avons déjà eu à disposition lorsque nous avons utilisé getLocations côté client.

Même chose si le format demandé est ‘json’, sauf que, cette fois-ci, les données seront regroupées au sein d’une chaîne de caractères en notation littérale d’objet Javascript.

Selon la situation, vous utiliserez quelque chose ressemblant à l’une des trois possibilités offertes par le code suivant :

if ($httpStatus === 200)
{
    if ($outputMode === 'csv')
    {
        list($status, $accuracy, $latitude, $longitude) = explode(',', $resultGeocoder);
        if ($status === '200')
        {
            echo "Latitude : $latitude\n";
            echo "Longitude : $longitude\n";
            echo "Précision : $accuracy\n";
        }
    } // csv
    else if ($outputMode === 'xml' || $outputMode === 'kml')
    {
        $xml = new SimpleXMLElement($resultGeocoder);
        //var_dump($xml);
        if ((string)$xml->Response->Status->code === '200')
        {
            foreach ($xml->Response->Placemark as $placemark)
            {
                echo "Adresse : {$placemark->address}\n";
                $coordonnees = explode(',', $placemark->Point->coordinates);
                echo "Latitude : {$coordonnees[1]}\n";
                echo "Longitude : {$coordonnees[0]}\n";
                echo "Précision : {$placemark->AddressDetails['Accuracy']}\n";
            }
        }
    } // xml / kml
    else if ($outputMode === 'json')
    {
        if (function_exists('json_decode'))
        { // La fonction json_decode n'est présente que depuis PHP 5.2
            $data = json_decode($resultGeocoder);
            //var_dump($data);
            if ($data->Status->code === 200)
            {
                foreach ($data->Placemark as $placemark)
                {
                    echo "Adresse : {$placemark->address}\n";
                    echo "Latitude : {$placemark->Point->coordinates[1]}\n";
                    echo "Longitude : {$placemark->Point->coordinates[0]}\n";
                    echo "Précision : {$placemark->AddressDetails->Accuracy}\n";
                }
            }
        }
    } // json
} // HTTP 200

La version ‘csv’ est très simple, du fait que le Geocoder ne renvoit, dans ce mode, que des données minimalistes.
Les version ‘xml’ et ‘json’ sont plus riches, et permettent d’obtenir plus de données - le choix entre l’une ou l’autre vous renvient, puisqu’elles présentent les mêmes fonctionnalités.


Quelques remarques

Pour terminer cet articles, j’aimerais juste ajouter une ou deux remarques.

Le service de Geocoding n’a pas toujours raison

Tout d’abord, pensez à vos utilisateurs : c’est pour eux que vous écrivez votre application, et, eux seuls peuvent dire si une localisation est correcte ou non.

Autrement dit, ne tenez pas pour vérité les données renvoyées par le service de Geocoding : il renvoi ce qu’il considère comme juste ; pas nécessairement ce qui l’est pour vos utilisateurs.

Vous devriez donc toujours offrir à vos utilisateur la possibilité de valider ou corriger les coordonnées correspondant à leur saisie, avant de les enregistrer et d’en tenir compte pour la suite de vos traitements.


N’effectuez pas plus de requêtes que nécessaire

Obtenir les coordonnées correspondant à une adresse revient à effectuer une requête HTTP. Cela prend du temps.

Autant que possible, donc, n’abusez pas de cette fonctionnalité : si vous en avez la possibilité, effectuez la requête auprès du service de geocoding une et une seule fois, et stockez les coordonnées en plus de l’adresse, de manière à accélérer l’affichage.

Ceci est d’autant plus important que le service de Geocoding ne vous permet pas d’effectuer un nombre illimité de requêtes.


Le prochain article nous permettra de voir quels sont les différents types de carte que Google-maps nous permet d’afficher, ainsi que les principaux contrôles que nous pouvons leur ajouter.


Navigation :

MAJ le 02/03/2008 : Ajout de la partie Navigation + Lien vers la partie 3.
MAJ le 16/04/2008 : Mise à jour de la partie Navigation : ajout du lien vers la partie 4.


Vous avez apprécié cet article ? Faites le savoir !

Commentaires

1. Par bertelle nicolas le 2008-02-10 16:12
bertelle nicolas

Bonjour

Vous pouvez visiter pour plus d'informations sur l'utilisation des GoogleMaps.

Amicalement

2. Par Tatane le 2008-08-28 16:53
Tatane

Salut,

article très complet et très clair, félicitations !
Je me posais la question pour une appli que je réalise actuellement s'il était possible de récupérer ville, region, dept et pays à partir d'une requête de géolocalisation mais en partant des coordonnées gps (lat, lng) ?

Grosso modo j'aimerai récupérai le nom de la ville la plus proche d'un point ajouté sur une carte pour pouvoir alimenter une base de données (ville, département, région, pays), en fait j'ai déjà cette base rempli avec tt ce qui concerne la France mais mon appli ne sera pas limité à ce pays.
Donc j'aimerai remplir ma base au fur et à mesure des points ajoutés via mes utilisateurs ...

si tu as une piste ou la connaissance d'un autre service de geolocalisation autre que google qui me permettrait de faire cette opération inverse je t'en remercie par avance ... :-)

Tatane

3. Par Pascal MARTIN le 2008-08-28 21:20
Pascal MARTIN
Bonsoir,

Merci :-)

Au risque de te décevoir, je ne me rappelle pas être jamais tombé sur cette fonctionnalité ; de manière générale, c'est plus souvent l'inverse que l'on rencontre : l'utilisateur saisi son adresse, on lui affiche la carte (via un coup de GeoCoding), et il peut affiner en plaçant un marqueur à l'endroit précis qu'il l'intéresse.
Alors que là, l'inverse... Je n'ai pas souvenir que l'API Google Maps fournisse cette fonctionnalité, en tout cas :-(

Pourtant, j'imagine que Google a ce qu'il faut pour fournir cette fonctionnalité : elle semble inclue à la nouvelle version de Gears.
Cf : http://code.google.com/apis/gears/api_geolocation.html#address
Je n'ai eu le temps de tester à fond, mais à première vue, c'est pas si mal ; avec la portion de code suivante, il me sort que je suis à Lyon - ce qui est correct (il se trompe sur l'arrondissement, par contre ^^ ) :
var geo = google.gears.factory.create('beta.geolocation');
function updatePosition(position) {
    console.log(position);
}
function handleError(positionError) {
    alert('Attempt to get location failed: ' + positionError.message);
}
geo.getCurrentPosition(updatePosition, handleError, {
    enableHighAccuracy: true,
    gearsRequestAddress: true,
    gearsAddressLanguage: 'fr-FR'
});
Ce qui donne dans firebug, une fois déplié :
Plutôt intéressant, non ?
Mais, comme je disais plus haut, ça passe par Gears... Avec la multitude de contraintes que cela implique... Contraintes qui font que ça ne répond pas à ton besoin de site "grand public".

Avec un peu de chance, qui sait, on retrouvera peut-être bientôt cette fonctionnalité dans l'API Maps !
(ou alors, elle y est déjà, et je ne l'ai pas vu en survolant la doc ^^ )

N'hésitez pas à re-poster pour nous tenir au courant du résultat de vos recherches : ça en intéresse sûrement d'autres !
(dont moi un jour futur, j'imagine ;-) )
4. Par Tatane le 2008-08-29 09:27
Tatane

ok merci bcp pour la réponse, effectivement dans ce sens là c'est rare comme requete ...
j'ai lu un de tes articles sur google gear et effectivement ça risque de ne pas être enviseagable pour mon site ...

bah je trouverai bien une solution, pour le moment j'ai pris le pb à l'envers et je cherche des bases de données ou listing d'au moins pays/regions/dept, y'a qqs ressources intéressantes genre çà : http://164.214.2.53/gns/html/cntry_...

à suivre ...

merci pour le coup de pouce ;)

5. Par Pascal MARTIN le 2008-08-29 21:33
Pascal MARTIN
Pas de problème :-)
Bonne continuation !

Et merci pour le lien ; j'ai bookmarqué, ça peut toujours servir ^^
6. Par Phil le 2008-09-23 18:01
Phil

Quoi qu'il en soit, j'ai testé l'API de Google Maps et il y a de gros soucis pour récupérer des données via XML car tantôt on a le tag SubAdministrativeArea tantôt le tag DependentLocality (cas d'une adresse belge), bref je n'ose imaginer aux autres cas de figure où c'est encore autre chose que ces deux termes...

7. Par Fred le 2008-10-05 10:59
Fred

Bonjour à tous, super tuto, je ne connaissais pas l'aspect serveur de l'api, merci pour le tuyau.
En rapport avec la question de Tatane, je vous conseille de faire un tour sur www.geonames.org qui propose des web services et autres friandises.
Google maps + geonames donne des résultats trés intéressants.
La bonne journée

Fred

8. Par Max le 2008-10-20 12:02
Max

Parfait c'est exactement ce qui me manquais ! clair et efficace, merci bcp !

9. Par Lili le 2008-11-07 11:34
Lili

Salut

C'est super comme aricle. Merci.
J'avais une question : J'ai une liste de points définis par la latitude et longitude comment savoir si tous mes points sont bien localisés dans un département (en d'autres termes comment repérés les points érronés ? )
Existe il une base de données des longitudes latitude min max par département ou quelque chose comme ça ?
Ou peut être une fonction de l'api google maps qui permet d'obtenir cette information (d'où ma question sur ce forum!)
Je ne peux pas verifier ça "manuellement" car j'ai des dizaines de milliers de points par département

10. Par Pascal MARTIN le 2008-11-07 21:34
Pascal MARTIN

Bonsoir,

Le plus simple que j'ai vu mis en place pour ce genre de cas (mais pas forcément le plus efficace ni le plus exact, c'est l'inconvénient de la simplicité) était au niveau de la vérification de validité de couples latitude/longitude pour des communes que je savais être dans un département, mais dont je n'étais pas sûr des latitudes et longitudes que j'avais à ma disposition, en particulier à cause de communes de même nom :

  • Calculer les coordonnées du "centre" du département, en faisant la moyenne des coordonnées de chacune des communes en faisant parti
  • Ensuite, pour chaque commune que l'on sait être dans le département, calculer sa distance par rapport au "centre" du département (en multipliant latitude et longitude par les coefficients qui vont bien et que je n'ai plus en tête, on a un résultat approximatif, mais pas trop mauvais dans l'ensemble)
  • Si cette distance est supérieure à une marge qu'on se fixe (du genre 50 km), c'est "étrange"

Mais cette méthode colle pour le cas où on sait que les communes sont dans un département, et où la question qui se pose est celle de l'exactitude des coordonnées que l'on a en base...

Après, je pense que cette méthode peut déjà vous permettre de dégrossir le travail : si vous avez un point situé à 300 km du centre de votre département, c'est fort probablement qu'il n'en fait pas parti ; même chose pour 100 km, d'ailleurs...

Mais le résultat sera approximatif... Ce qui signifie que si vous ne voulez pas avoir trop de faux positifs, il vous faudra garder un rayon de département suffisamment grand... Et plus il sera grand, plus vous aurez de faux négatifs... A vous de trouver le juste milieu, donc ^^

Pour une méthode qui ait une exactitude de 100%, je n'ai pas d'idée, désolé.

Note : le coefficient à appliquer n'est pas aussi simple que ça : ça dépend de la position de vos villes sur Terre, pour prendre en compte sa forme et tout ça... => google pour plus d'informations ^^
Vous tomberez par exemple sur http://www.movable-type.co.uk/scripts/latlong.html

Et pour un exemple, voyons voir ce qu'on pourrait avoir en Isère :

select avg(latitude), avg(longitude) from villes where code_departement = '38';

avg(latitude)     avg(longitude)
----------------  ----------------
45.3205410487805  5.49489386866792

=> Le "centre" de l'Isère a pour coordonnées 45.3205410487805 ; 5.49489386866792

Et pour les comparaisons, par exemple :

// Cf http://www.movable-type.co.uk/scripts/latlong.html pour les scripts que j'ai honteusement recopié :
// (exemple d'implémentation en Javascript, ici)

Number.prototype.toRad = function() {  // convert degrees to radians
  return this * Math.PI / 180;
};

var distance = function (lat1, lon1, lat2, lon2) {
    var R = 6371; // km
    var dLat = (lat2-lat1).toRad();
    var dLon = (lon2-lon1).toRad();
    var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
            Math.cos(lat1.toRad()) * Math.cos(lat2.toRad()) *
            Math.sin(dLon/2) * Math.sin(dLon/2);
    var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
    var d = R * c;
    return d;
};

// Distance entre Lyon (qui n'est pas en Isère) et le centre de l'isère :
var dist = distance(45.3205410487805, 5.49489386866792, 45.767299, 4.834328);
console.log(dist);
// => 71.51299641925033
// => ça fait plus de 50 km ; ça semble beaucoup, non ?

// Distance entre Grenoble (qui est en Isère) et le centre de l'isère :
dist = distance(45.3205410487805, 5.49489386866792, 45.197062, 5.710477);
console.log(dist);
// => 21.754213108703517
// => 21 km ? ça semble raisonable, à première vue :-)

OK, ça marche dans ce cas qui va bien ; on peut sans aucun doute trouver des cas trop justes, soit trop loin soit pas assez, qui génèreront des faux positifs ou des faux négatifs (d'autant plus que l'Isère est un peu en longueur)...

Mais ça permet déjà de faire une première passe de "ménage", qui enlèvera avec un peu de chance le plus gros...

Quoi qu'il en soit, bon courage !

11. Par momo72 le 2008-11-19 01:18
momo72

Bonjour,
Je trouve votre tuto très bien et je vous remercies car il est très explicatif. J'ai un pb que je n'arrive pas à résoudre. Il s'agit d'afficher au chargement un très grand nombre d'adresse. J'ai pensé qu'il me fallait convertir toutes ces adresses en coordonnées puis appliquer addGeoPoint, mais je n'arrive pas à trouver comment recuperer précisement la lat et la long (d'une addresse donnée) dans des variables séparement. SVP, pourriez vous m'aider?

12. Par Pascal MARTIN le 2008-11-20 06:44
Pascal MARTIN

Bonjour,

Je ne suis pas certain de comprendre votre question, mais si vous avez un grand nombre de point à afficher, et que, pour chaque point, vous ne connaissez que son adresse, vous allez probablement faire appel au service de GeoCoding un grand nombre de fois... A chaque affichage de page ?

Si oui, votre page va mettre une éternité à s'afficher (et vous vous ferez détester par Google ^^ ) ; à mon avis, il vaudrait mieux stocker, pour chaque point, en plus de son adresse, ses coordonnées (lat/lng), en faisant appel au service de Geocoding une fois pour toutes, à l'enregistrement du point, plutôt qu'à son affichage.

Deux avantages :

  • Si l'ajout d'un point se fait dans un dialogue avec l'utilisateur, vous pouvez lui demander de valider la latitude et la longitude (le service de Geocoding n'étant pas infaillible)
  • Vous ralentirez un brin le processus de création de point, mais vous accélèrerez grandement l'affichage, par la suite -- et un point est certainement affiché plus souvent qu'il n'est modifié.

Quant à obtenir la latitude et la longitude "dans des variables séparées"... J'ai du mal à voir ce que vous voulez dire : pour chaque adresse, il vous faut effectuer un appel au service de Geocoding, en utilisant la classe google.maps.ClientGeocoder et sa méthode getLatLng, la fonction de callback passée en second paramètre recevra alors les informations des coordonnées correspondant à l'adresse recherchée, avec, dans ces informations, la latitude et la longitude ?

13. Par momo72 le 2008-11-28 00:38
momo72

bonjour Pascal,
Je n'ai pu vous répondre depuis la dernière fois car j'ai eu un problème avec ma connexion internet qui vient seulement de se rétablir.
Vous avez tout a fait raison quant à la méthode à employer. Je vais essayer d'être plus précis pour mon problème.
Je voudrais transformer un tableau contenant plusieurs adresses en un tableau contenant les geocoordonnées correspondants. Par exemple, j'ai le tableau addresses qui est de la forme suivante

var addresses = new Array(
new Array("Moscou, Russia", "La place rouge ou le Kremlin <br>Chez Poutine ", true),
new Array("Santiago Chili", " Palais del revolutione <br>Tel 23450987765 ", true)
)

et je voudrais obtenir le tableau geopoints de la forme suivante 

var geopoints = new Array(
new Array(23,54, "La place rouge ou le Kremlin <br>Chez Poutine ", true),
new Array(21,9, " Palais del revolutione <br>Tel 23450987765 <br>", true)
)

et je n'arrive pas à mettre en place un code javascript qui me fait le travail.
Voici ce que j'avais pensé faire: 

function conversion(){
var geopoints = new array;
for (i=0; i< addresses.length;i++){
if (geocoder){
geocoder.getLatLng(addressses[i][0],function(point) {
if (!point){
alert("Location not found:" + adresses[i][0]);
}else {
marker= new GMarker(center);
var tpoint= marker.getPoint();
geopoints[i][0]=tpoint.lat();
geopoints[i][1]=tpoint.lng();
geopoints[i][2]=addresses[i][1];
geopoints[i][3]=addresses[i][2];
}
} )
}
}
return geopoints
}

puis ensuite appeler la fonction conversion:

var geopoints = conversion();

, puis ensuite appliquer la fonction showGeopoints(), mais aucun points ne s'affiche, il n'y a que le map. J'ai vraiment besoin de votre soutient car je dois livrer le client très bientot.Merci d'avance.

14. Par Pascal MARTIN le 2008-11-28 07:50
Pascal MARTIN

Bonjour,

(je fais un peu rapide)

Une chose est à garder à l'esprit quand on utilise le geocoder (je ne sais pas si votre problème vient de là, mais ça se pourrait) : il travaille en asynchrone : vous lancez une requête, mais vous ne savez quand le résultat de cette requête arrivera -- et il n'y a que dans la fonction de callback passée en second paramètre à getLatLng que vous le savez.

Typiquement, le code se trouvant dans le source JS après l'appel à getLatLng sera généralement exécuté avant que les coordonnées n'aient effectivement été obtenues !
Dans votre exemple, ça signifie que au moment où le return geopoints s'exécute, de manière générale, aucune coordonnée n'aura encore été obtenue : les appels seront seulement en train de s'exécuter, en arrière-plan, de manière asynchrone.

En somme, c'est dans la fonction de callback qu'il faudrait manipuler les coordonnées, et non en dehors.

Par exemple, avec quelque chose de ce type :

var init = function ()
{
google.load("maps", "2");
google.setOnLoadCallback(initMap);
}; // init

var adresses = [
["Moscou, Russia", "La place rouge ou le Kremlin
Chez Poutine ", true],
["Santiago Chili", " Palais del revolutione
Tel 23450987765 ", true]
];

var initMap = function ()
{
var map = new google.maps.Map2(document.getElementById('map'));
map.addControl(new GSmallMapControl()); // Contrôle de zoom, déplacement sur la carte
map.setCenter(new google.maps.LatLng(45.756788, 4.831515), 1);

var i;
for (i=0 ; i < adresses.length ; i++) {
var adresse = adresses[i][0];
var geocoder = new google.maps.ClientGeocoder();
geocoder.getLatLng(adresse, function (coord) {
// Fonction appelée quand le geocoder répond
// => C'est le seul endroit où on est certain d'avoir ces coordonnées !
var data = {
lng: coord.x,
lat: coord.y,
adresse: adresse
};
var point = new GPoint(data.lng, data.lat);
var marker = new GMarker(point);
map.addOverlay(marker);
});
}

// Attention : ici, les coordonnées n'ont probablement pas encore
// été obtenues : les appels au géocoder se font de manière asynchrone,
// en arrière-plan, donc

}; // initMap

En espérant que cela vous aide à avancer,

Bon courage !

15. Par lod le 2008-11-28 11:30
lod

J'ai perdu un temps monstre à trouver les coordonnées d'une adresse (latitude/longitude ville)

Je conseille donc ce site à ceux que ça intéresse:
http://www.alsasys.com/web-agency/o...

Amicalement

16. Par momo72 le 2008-11-28 14:25
momo72

Merci Pascal pour tes explications et aussi pour la rapidité de tes réponses, je vais essayer d'exploiter ca tout de suite.
Merci aussi à lod. Je pense que cela me sera aussi très utile.
Amicalement

17. Par Pascal MARTIN le 2008-11-30 22:36
Pascal MARTIN

lod > ça ira plus vite que de pondre un bout de code JS à chaque fois ^^ (et probablement plus vite que de passer par maps.google.com et de récupérer la latitude et la longitude dans le lien qu'on peut obtenir depuis la carte ^^ )

momo72 > pas de problème :-) Bon courage !

18. Par momo72 le 2009-01-12 14:40
momo72

Bonjour,
Je commencerais d'abord par vous souhaiter une bonne et heureuse année 2009, ainsi qu'a tout les internautes qui consulte ce forum.
Je voudrais mettre en place un script qui permet à l'internaute d'avoir l'ensemble des magasins à partir d'une adresse de son choix et dans un rayon de son choix. Je me suis inspiré du tuto qui est à cette adresse:

http://code.google.com/support/bin/...

Il y a donc deux fichiers: l'un connecté à la base de données (phpsqlsearchgen.php) et l'autre connecté à google pour le geacodage (nxgooglemapsapi.php).
J'ai suivi scrupuleusement le tuto mais cela ne fonctionne pas.Après plusieurs tests et contrôles je pense que le pb vient des lignes contenant GDownload() ou parse() du fichier nxgooglemapsapi.php. Voici mes deux fichiers:

nxgooglemapsapi.php
@@<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://
www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">

 <head>
   <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
   <title>Stote Locator</title>
   <script src="[http://maps.google.com/maps?file=api&v=2&key=ABQIAAAASxOW0sFRTtwHqMg4ukQLLhTHs9lI5o6Df0HCZVlYC_EU9t1n4hTvthF3c2nVcAxAbeABdUWC2QR7Zw]"
           type="text/javascript"></script>
   <script type="text/javascript">
   //<![CDATA[
   var map;
   var geocoder;
   function load() {
     if (GBrowserIsCompatible()) {
       geocoder = new GClientGeocoder();
       map = new GMap2(document.getElementById('map'));
       map.addControl(new GSmallMapControl());
       map.addControl(new GMapTypeControl());
       map.setCenter(new GLatLng(25, 1), 2);
     }
   }
  function searchLocations() {
    var address = document.getElementById('addressInput').value;
    geocoder.getLatLng(address, function(latlng) { 
      if (!latlng) {
        alert(address + ' not found');
      } else {
        searchLocationsNear(latlng); 
      }
    });
  }
  function searchLocationsNear(center) {
    var radius = document.getElementById('radiusSelect').value; 
    var searchUrl = 'phpsqlsearchgen.php?lat=' + center.lat() + '&lng=' + center.lng() + '&radius=' + radius;
    __GDownloadUrl(searchUrl, function(data) { 
      var xml = GXml.parse(data);__ ____
      var markers = xml.documentElement.getElementsByTagName('marker');

map.clearOverlays();

      var bounds = new GLatLngBounds();

for (var i = 0; i < markers.length; i++) {

      var name = markers[i].getAttribute('name');

var address = markersi.getAttribute('address');

        var point = new GLatLng(parseFloat(markers[i].getAttribute('lat')),
                                parseFloat(markers[i].getAttribute('lng')));
        var marker = createMarker(point, name, address); 
        map.addOverlay(marker);
        bounds.extend(point);
      }
      map.setCenter(bounds.getCenter(), map.getBoundsZoomLevel(bounds));
    });
  }
   function createMarker(point, name, address) {
     var marker = new GMarker(point);
     var html = '<b>' + name + '</b> <br/>' + address;
     GEvent.addListener(marker, 'click', function() {
       marker.openInfoWindowHtml(html);
     });
     return marker;
   }

   //]]>
 </script>
 </head>
 <body onLoad="load()" onUnload="GUnload()">
   Address: <input type="text" id="addressInput"/> 
   Radius: <select id="radiusSelect">
     <option value="25" selected>25</option>
     <option value="100">100</option>
     <option value="200">200</option>
   </select>
   <input type="button" onClick="searchLocations()" value="Search Locations"/>
   <br/>    
   <br/>

<div style="width:950px; font-family:Arial,
sans-serif; font-size:11px; border:1px solid black">

 <table align="center"> 
   <tbody> 
     <tr>
      <td align="center"> <div id="map" style="overflow: hidden; width:940px; height:500px"></div> </td>
     </tr> 
   </tbody>
 </table>

</div>

 </body>

</html>

@@

et phpsqlsearchgen.php

@@<?php
header("Content-type: text/xml");
require("phpsqlsearch_dbinfo.php");

function parseToXML($htmlStr)
{
$xmlStr=str_replace('<','&lt;',$htmlStr);
$xmlStr=str_replace('>','&gt;',$xmlStr);
$xmlStr=str_replace('"','&quot;',$xmlStr);
$xmlStr=str_replace("'",'&#39;',$xmlStr);
$xmlStr=str_replace("&",'&amp;',$xmlStr);
return $xmlStr;
}

// Get parameters from URL. les variables globales ont été remplies par l'internaute.
$center_lat = $_GET

19. Par momo72 le 2009-01-13 15:07
momo72

Veulliez m'excuser,le deuxième fichier n'était pas complet. Mon application se trouve à l'adresse
http://gbsolutionsinc.net/ProjetMap...
Mon test consiste à rentrer l'adresse
6 allée de Luynes 37000 tours, avec le rayon 25 e je devrais en retour avoir 4 adresses avec marqueurs sur la carte, ce qui n'est pas le cas.
Peut etre pourriez vous me donner un coup de pouce, pour voir ce qui ne vas pas. Je pense que le pb se trouve au niveau de GDownload ou GXml.parse()
Merci d'avance.



phpsqlsearchgen.php

<?php
header("Content-type: text/xml");
require("phpsqlsearch_dbinfo.php");

function parseToXML($htmlStr)
{
$xmlStr=str_replace('<','&lt;',$htmlStr);
$xmlStr=str_replace('>','&gt;',$xmlStr);
$xmlStr=str_replace('"','&quot;',$xmlStr);
$xmlStr=str_replace("'",'&#39;',$xmlStr);
$xmlStr=str_replace("&",'&amp;',$xmlStr);
return $xmlStr;
}

// Get parameters from URL. les variables globales ont été remplies par l'internaute.
$center_lat = $_GET("lat");//j'ai mis des parenthèse car
$center_lng = $_GET("lng");// je n'arrive pas à vous
$radius = $_GET("radius"); // l'envoyer avec les crochets

// Opens a connection to a MySQL server
$connection=mysql_connect ($server, $username, $password);
if (!$connection) {

 die('Not connected : ' . mysql_error());

}

// Set the active MySQL database
$db_selected = mysql_select_db($database, $connection);
if (!$db_selected) {

 die ('Can\'t use db : ' . mysql_error());

}

// Select all the rows in suppliers_details table
$query = sprintf("SELECT suppliers_address , suppliers_latitude , suppliers_longitude , suppliers_city , ( 3959 * acos( cos( radians('%s') ) * cos( radians( suppliers_latitude ) ) * cos( radians( suppliers_longitude ) - radians('%s') ) + sin( radians('%s') ) * sin( radians( suppliers_latitude ) ) ) ) AS distance FROM suppliers_details HAVING distance < '%s' ORDER BY distance LIMIT 0 , 20",

 mysql_real_escape_string($center_lat),
 mysql_real_escape_string($center_lng),
 mysql_real_escape_string($center_lat),
 mysql_real_escape_string($radius));

$result = mysql_query($query);
if (!$result) {

 die('Invalid query: ' . mysql_error());

}

// Start XML file, echo parent node
echo "&lt;markers &gt;\n";

//Iterate through the rows, printing XML nodes for each

while ($row = @mysql_fetch_assoc($result)){

 // ADD TO XML DOCUMENT NODE
 
 echo '&lt;marker ';
echo 'name="' . parseToXML($row['suppliers_city']) . '" ';
echo 'address="' . parseToXML($row['suppliers_address']) . '" ';
 echo 'lat="' . $row['suppliers_latitude'] .'" ';
 echo 'lng="' . $row['suppliers_longitude'] .'" ' ;
echo 'distance="' . $row['distance'] . '" ';
 echo "/&gt; \n";

echo "&lt;/markers&gt; \n";



}

// End XML file



?>

Peut etre pourriez vous me donner un coup de pouce, pour voir ce qui ne vas pas. Je pense que le pb se trouve au niveau de GDownload ou GXml.parse()
Merci d'avance.
Momo

20. Par Tafou le 2009-05-19 18:34
Tafou

Bonjour,

Excellent tuto présentant des fonctionnalités que je ne pensais même pas.
De mon côté, j'ai mis en place sur plusieurs site des Google Maps par contre un problème se pose toujours: certaines adresses ne sont pas trouvées par le geolocaliseur mais trouvé via Google Map.

Avez-vous déjà rencontré ce problème?

Merci.

Note: j'ai déjà vérifié les accents et autres caractères pouvant poser problème.

21. Par Tafou le 2009-05-26 11:32
Tafou

Pour ceux qui passerait par là, le problème venait du fait que j'envoyais trop rapidement les requête à Google. Il est nécessaire d'attendre qq milli-secondes (100ms apparement) entre chaque requête.

22. Par Sinsey le 2009-05-29 09:59
Sinsey

Ah ouais !
Moi dès fois, j'ai des erreurs js aléatoire, du style a is null, peut être du à ça ?
Comment as tu fait pour temporiséer entre chaque ?

23. Par Tafou le 2009-06-03 17:49
Tafou

Sinsey > Voilà ma fonction. Je l'ai trouvé dans la doc de Google et je l'ai un peu arrangé

function getGeocode($adresse){

// Initialize delay in geocode speed
$delay = $lat = $lng = $alt = 0;
$base_url = "http://maps.google.com/maps/geo?out...";

$geocode_pending = true;
while ($geocode_pending) {
$request_url = $base_url . "&q=" . urlencode($adresse);
// Exécution de la requète et récupération du status
$xml = simplexml_load_file($request_url) or die("url not loading");
$status = $xml->Response->Status->code;

if (strcmp($status, "200") == 0) {
// Geocode trouvé
$geocode_pending = false;
$coordinates = $xml->Response->Placemark->Point->coordinates;
$coordinatesSplit = split(",", $coordinates);
// Format: Longitude, Latitude, Altitude
$alt = $coordinatesSplit(crochet ouvrant)2(crochet fermant);
$lat = $coordinatesSplit(crochet ouvrant)1(crochet fermant);
$lng = $coordinatesSplit(crochet ouvrant)0(crochet fermant);
} else if (strcmp($status, "620") == 0) {
// Demande trop rapide, refus de Google
$delay += 100000;
} else {
// Geocode introuveable
$geocode_pending = false;
//echo "Address " . $address . " failed to geocoded. ";
//echo "Received status " . $status . "<br>";
}
usleep($delay);
}

$geocode = array();
$geocode(crochet ouvrant)'latitude'(crochet fermant) = $lat;
$geocode(crochet ouvrant)'longitude'(crochet fermant) = $lng;
$geocode(crochet ouvrant)'altitude'(crochet fermant) = $alt;
$geocode(crochet ouvrant)'status'(crochet fermant) = $status;

return($geocode);
}

NOTE : les crochets ne marchaient pas, j'ai du feinter, à remplacer donc ...

24. Par Cleo le 2009-08-09 13:39
Cleo

merci pour tes explications! ca m'a vraiment beaucoup aidee!
et merci pour ceux qui ont laisser des commentaires instructif!
bonne continuation!
(je vais lire tes autres topic, tu m'inspire!!^^)

25. Par Ben le 2009-09-08 21:20
Ben

Depuis l'autre coté du pont wilson, je te remercie grandement pour ce tuto de qualité qui m'a appris à utiliser l'API google.

A bientôt sur ton blog
A +

26. Par Popote le 2009-09-23 18:18
Popote

salut all
tout d'abord et comme tout les autres un grand merci pour ce tuto acessible et sympa
cependant je n'ai pas trouver tout mon bonheur
je suis a la recherche d'une méthode pour centrer au mieux ma carte avec les coordonnées de plusieurs points
pour un seul point je centre sur ce dernier
mais dans le cas de plusieurs ...comment être sur de centrer sur tout les points ?
mis a part choisir les coordonnées les plus éloignées et les définir comme étant les coordonnées du cadre je ne vois rien d'autre.
merci d'avance si vous avez connaissance d'une fonction permettant de faire un zoom sur plusieurs point
j'espère avoir été assez clair a+

27. Par Sinsey le 2009-10-02 15:57
Sinsey

Tafou >Merci pour la fonction, désolé de ma réponse tardive, mais je n'ai pas été informé de ton post.
En fait, ici tu utilise la méthode XML, moi j'utilise le geocoder en javascript.
Y'a-t-il un équivalent pour le delay. voici ma fonction qui est donc envoyé pour chaque point à placer

geocoder.getLatLng("<?=$nomville.",".$departement?>", function (coord) {<? // Géocodage : Création du point correspondant aux coordonnées nous intéressant?>
alert(coord);
var marker = createMarker(coord,"<?=$labelicon?>"); <? chr(13);// Création d'un marqueur localisé sur ce point?>
map.addOverlay(marker); <? chr(13);// Ajout du marqueur à la carte?>
}); //End geocoder.getLatLng

Et la fonction qui créer le marqueur

@@var createMarker = function (coord, name) {
//Icon

var icon = new GIcon(G_DEFAULT_ICON);
icon.image="http://labs.google.com/ridefinder/i...";
icon.shadow = "http://labs.google.com/ridefinder/i...";
icon.iconSize = new GSize(12, 20);
icon.shadowSize = new GSize(22, 20);

//Marqueur
var marker = new GMarker(coord, icon);
var html = '<b>' + name + '</b>';
GEvent.addListener(marker, 'click',
function() {
marker.openInfoWindowHtml(html);
}
);

return marker;
}

28. Par larde le 2009-12-07 23:06
larde

Utilisation du Geocoder :
vous dites :
Ceci est d'autant plus important que le service de Geocoding ne vous permet pas d'effectuer un nombre illimité de requêtes.

J'ai fait une boucle pour récupérer mes marker et les afficher avec le Géocoder, et effectivement, il semble qu'au bout de quelques markers, il ne trouve pas le suivant.
Il m'a semblé aussi, que si je ne l'utilise pas pendant un certain temp, le même programme affiche bien tous les marker.

Est ce cela la limitation du Géocoder ?
Merci pour une réponse.
Pierre.

29. Par lio le 2010-02-12 11:09
lio

Bonjour,
déjà merci pour le tuto :)
en fait, j'ai le même souci que "Popote".
j'aimerais pouvoir centrer ma carte avec les coordonnées de plusieurs points.
Est-ce que quelqu'un aurait une solution?
Merci d'avance
Lio

30. Par Super NewBe le 2010-05-28 14:09
Super NewBe

Bonjour,

je suis en train de mettre sur pieds un formulaire php qui me retourne un kilométrage de tournée.
Je choisis donc mes différents points et j'envoie une url à Maps qui me sort un nombre de kilomètres (ça, ça marche).

Pour gagner encore du temps lors de la saisie de mes points de largage, je voudrais que le fichier qui va écrire dans ma BDD trouve tout seul les coordonnées de l'adresse.

formulaire:
nom
adresse

posté à ajoutpointdelargage.php

qui doit écrire dans la BDD

nom
adresse
coordonnées

j'ai une clef d'API mais je ne m'en sors pas, je n'ai pas assez de savoir pour mettre ça en place.

Au secours Pascal (-entre lyonnais :)-)

31. Par Super NewBe le 2010-05-31 09:19
Super NewBe

Bonjour,

je suis toujours dans le flou, après avoir passé le we à faire des essais, je n'arrive pas à récupérer les coord pour les poster vers un fichier php qui fera le traitement.

Y a-t-il un chevalier blanc pour venir à mon secours ?

32. Par Super NewBe le 2010-06-07 16:27
Super NewBe

Bonjour,

toujours personne ?
J'ai raté quelquechose...

I'll be back

33. Par slimoss le 2010-09-25 13:00
slimoss

Bonjour,
et bas pascal je te remercie bcp pour ton tuto vraiment j'y ai trouvé ce que je voulais car je me demandais s'il n'existe pas une fonction dans l'api google qui me reflete l'attitude et la longitude d'une adresse entree par un utilisateur dans un editText car j'ai besoin de ces coordonnees retournes par cette fonction pour dessiner mon itineraires entre les deux adresses entrees par l'utilisateurs car c plus pratique pour l'utilisateurs en general de fournir une adresse que des lattitudes et des longitude , et cette fonction est *** GeoCoder***

   Donc merci beaucoup et felicitation
Mais malheureusement j'ai pas trouvé cet api sur android puisque je developpe sur android donc je te demande si tu paux fournir une solution pareille mais cette fois sur android , merciiii d'avance car j'ai vraiment besoin de ton aide pour mon application vraiment si tu m'aides a trouver une solution je t'invite chez moi en tunisie pour manger un couscous tunisien lool ^_^

amicalement
slimoss

34. Par sisi le 2012-04-25 16:23
sisi

bonjour,
est il possible de localiser plusieurs adresses données sur la carte sans donner les coordonnées longitude et latitude juste on introduit un certain nombre d'adresses postale et on les représentes avec plusieurs marqueurs perso
si vous avez une idée cela m'aiderais beaucoup car je bloque dessus depuis un moment
merci a vous

Ce post n'est pas ouvert aux nouveaux commentaires (probablement parce qu'il a été publié il y a longtemps).