Postcode omzetten in geo-coördinaten met Google Maps API

Hoe kun je het opzoeken van de longitude, latitude van een postcode automatiseren en gebruiken in je PHP-code? Door gebruik te maken van Google Maps.

Met de hand: http://maps.google.com/maps/geo?q=adres&output=xml
Bij adres kun je adresgegevens in verschillende soorten opgegeven:
Amsterdam
5026 RM, Tilburg
Saal van Zwanenbergweg 11, Tilburg, Nederland
New York
Bijvoorbeeld: http://maps.google.com/maps/geo?q=5026 RM, Tilburg&output=xml

Het adres kan een postcode zijn, maar ook een straatnaam met nummer, plaats en land. Zorg wel dat het een unieke en eenduidige combinatie is. Hoe meer informatie, hoe nauwkeuriger de coördinaten.

Er komt een XML-uitvoer terug met alle gegevens. Je kunt de resultaten hiervan onder andere gebruiken om adressen te vinden binnen een straal van een opgegeven adres. Deze procedure is in PHP goed te automatiseren.

<?php
  // Juli 2010, Rian Rietveld, RRWD web development
  // Input: in te voeren adres, als get/post-variable in te voeren
  $adres = urlencode("5026 RM, Nederland");

  // Aanroep functie
  $coordinates = IncludeURL($adres);

  // Output: de coordinaten longitude, latitude, altitude, voor verwerking in de rest van de code
  echo "coordinates zijn: $coordinates";


  function IncludeURL($adres, $timeout=10) {
 // Roep Google Maps aan met het adres en de soort output
    $url = "http://maps.google.com/maps/geo?q=".$adres."&output=xml";

 // defineer een header
    $parts = parse_url($url);
    $host = $parts['host'];
    $path = $parts['path'];
    $query = $parts['query'];
    $header = "GET $path"."?"."$query HTTP/1.0\r\n";
    $header .= "Host: $host\r\n";
    $header .= "User-Agent: {$_SERVER['SERVER_NAME']}{$_SERVER['REQUEST_URI']} - RRWD\r\n\r\n";

 // open socket naar Google en lees output in
    if (gethostbyname($host) != $host) {
      $socket = @fsockopen($host, 80, $errno, $errstr, $timeout);
      if ($socket) {
        fwrite($socket, $header);
        unset($http_response);
        while (!feof($socket)) {
          $http_response .= fread($socket, 256);
        }
        fclose($socket);
        if (strpos($http_response, "200 OK")) {
        // mik de header weer weg
          $pos1 = stripos($http_response, "<?xml");
          $http_response = substr("$http_response",$pos1);
        // lees de xml in en pik de coordinates eruit
          $xml = new SimpleXMLElement($http_response);
          return $xml->Response->Placemark->Point->coordinates;
        }
      }
    }
  }

?>

In veel voorbeelden wordt het uitlezen van de output gedaan via de functie file_get_contents($url). Deze functie wordt echter niet door alle providers toegestaan om veiligheidsredenen. Maar zoals hierboven beschreven werkt het altijd vanaf PHP 5.2

Tip: Soms kloppen de coördinaten die Google teruggeeft niet helemaal. Voor de exacte coördinaten type je het adres in bij maps.google.nl en klik je rechts met de muis op precies de juiste plek. Er komt een keuze menu, kies: routebeschrijving vanaf dit punt. Rechts op het scherm komen dan de exacte coördinaten van het betreffende punt onder de routebeschrijving te staan (A).

Je kunt de postcode-coördinaten combinatie ook verkrijgen via het 6pp-project van Kees van den Broek. Je kunt op deze site ook een SQL-bestand downloaden met adresgegevens en coördinaten in Nederland. Deze database wordt door vrijwilligers bijgehouden.

Bronnen

Advertisements

Author: Rian Rietveld

WordPress Engineer focussing on accessibility

11 thoughts on “Postcode omzetten in geo-coördinaten met Google Maps API”

  1. Is het ook mogelijk om met het script gewoon een routeplanner te maken? ik wil namelijk zoiets op een site van me zetten waarmee mensen gewoon twee adressen op kunnen geven en dan op plan route kunnen drukken.

    Like

  2. Ik wil de afstand tussen postcodes weten via google maps. Het liefste nog gesplitst tussen aantal km snelweg en aantal km niet snelweg. Is dit mogelijk te berekenen met dit script?

    Like

  3. Iemand een idee waarom ik deze melding krijg?? Notice: Undefined variable: http_response in D:\websites\thuisfeesten\test.php on line 40. Lijn 40 is in dit geval: $http_response .= fread($socket, 256);. Alvast Bedankt

    Like

  4. Bedankt voor het delen van dit nuttige script!

    De API van Google lijkt veranderd te zijn, de request moet anders geformateerd worden en de indeling van de XML lijkt anders te zijn. Ik heb de code als volgt aangepast:

    <?php
    // Juli 2010, Rian Rietveld, RRWD web development
    // Input: in te voeren adres, als get/post-variable in te voeren
    $adres = urlencode("2321EC");

    // Aanroep functie
    $coordinates = IncludeURL($adres);

    // Output: de coordinaten longitude, latitude, altitude, voor verwerking in de rest van de code
    echo "\ncoordinaten zijn: $coordinates \n";

    function IncludeURL($adres, $timeout=10) {
    // Roep Google Maps aan met het adres en de soort output

    // Oud
    $url = "http://maps.google.com/maps/geo?q=&quot;.$adres."&output=xml"; // Defineer een header

    // Nieuw
    $url = "http://maps.google.com/maps/api/geocode/xml?address=&quot;.$adres."&sensor=false";

    $parts = parse_url($url);
    $host = $parts['host'];
    $path = $parts['path'];
    $query = $parts['query'];
    $header = "GET $path"."?"."$query HTTP/1.0\r\n";
    $header .= "Host: $host\r\n";
    $header .= "User-Agent: {$_SERVER['SERVER_NAME']}{$_SERVER['REQUEST_URI']} – RRWD\r\n\r\n";

    // open socket naar Google en lees output in
    if (gethostbyname($host) != $host) {
    $socket = @fsockopen($host, 80, $errno, $errstr, $timeout);
    if ($socket) {
    fwrite($socket, $header);
    unset($http_response);
    while (!feof($socket)) {
    $http_response .= fread($socket, 256);
    }
    fclose($socket);
    if (strpos($http_response, "200 OK")) {

    // mik de header weer weg
    $pos1 = stripos($http_response, "result->geometry->location->lat . ” , “. $xml->result->geometry->location->lng;
    }
    }
    }
    }

    ?>

    Like

  5. Hoi Maarten,

    Leuk script, maar zit vol fouten. Misschien volgende keer even runnen voordat je publisht?
    Je XML-toevoegingen waren wel zinvol, want daardoor werkt onderstaand script wel, en deze heeft ondersteuning voor postcodes met alleen 4 cijfers en volledige postcodes (1234AA). In geval van alleen 4 cijfers wordt gekeken of het een prefix is van een bestaande postcode (om locaties van andere landen uit te sluiten).

    De output is postcode (volledige vorm uit XML = met spatie), plaats, gemeente, provincie, land en coördinaten, gesplitst door een |-teken (kun je makkelijk aanpassen, was nodig voor ons database).
    Ik heb deze code gebruikt op ons klantendatabase, zodat ik nu hun coördinaten heb. Ideaal voor GIS-analyse.

    Je kunt hem hier testen: http://phpfiddle.org/.

    <?php

    $postcode = urlencode("9202");
    $coordinates = IncludeURL($postcode);
    echo "$coordinates\n\n";

    function IncludeURL($postcode, $timeout = 10) {
    // Roep Google Maps aan met het adres en de soort output
    $url = "http://maps.google.com/maps/api/geocode/xml?address=&quot; . $postcode . "&sensor=false";

    $parts = parse_url($url);
    $host = $parts['host'];
    $path = $parts['path'];
    $qry = $parts['query'];
    $header = "GET $path"."?"."$qry HTTP/1.0\r\n";
    $header .= "Host: $host\r\n";
    $header .= "User-Agent: {$_SERVER['SERVER_NAME']}{$_SERVER['REQUEST_URI']} – RRWD\r\n\r\n";

    if (gethostbyname($host) != $host) {
    $socket = @fsockopen($host, 80, $errno, $errstr, $timeout);
    if ($socket) {
    fwrite($socket, $header);
    //unset($http_response);
    $http_response = '';
    while (!feof($socket)) {
    $http_response .= fread($socket, 256);
    }
    fclose($socket);
    if (strpos($http_response, "200 OK")) {
    // mik de header weer weg
    $pos1 = stripos($http_response, "status == ‘OK’) {
    if (strlen($postcode) == 4) {
    // dus 9202 i.p.v. 9202NB
    for ($x = 0; $x result[$x]->type == ‘postal_code_prefix’) {
    $postcode = $xml->result[$x]->address_component[0]->long_name;
    $plaats = $xml->result[$x]->address_component[1]->long_name;
    $gemeente = $xml->result[$x]->address_component[2]->long_name;
    $provincie = $xml->result[$x]->address_component[3]->long_name;
    $land = $xml->result[$x]->address_component[4]->long_name;
    $latitude = $xml->result[$x]->geometry->location->lat;
    $longitude = $xml->result[$x]->geometry->location->lng;
    return $postcode . ‘|’
    . $plaats . ‘|’
    . $gemeente . ‘|’
    . $provincie . ‘|’
    . $land . ‘|’
    . $latitude . ‘|’
    . $longitude;
    }
    }
    return ‘(postcode bestaat niet)’;
    } else {
    // postcdoe met 6 karakters zoals 9202NB
    $postcode = $xml->result[0]->address_component[0]->long_name;
    $plaats = $xml->result[0]->address_component[1]->long_name;
    $gemeente = $xml->result[0]->address_component[2]->long_name;
    $provincie = $xml->result[0]->address_component[3]->long_name;
    $land = $xml->result[0]->address_component[4]->long_name;
    $latitude = $xml->result[0]->geometry->location->lat;
    $longitude = $xml->result[0]->geometry->location->lng;
    return $postcode . ‘|’
    . $plaats . ‘|’
    . $gemeente . ‘|’
    . $provincie . ‘|’
    . $land . ‘|’
    . $latitude . ‘|’
    . $longitude;
    }
    } else {
    return ‘(postcode bestaat niet)’;
    }
    }
    }
    }
    return ‘(geen reactie van Maps)’;
    }

    ?>

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s