User:Amake/gmcoords.php

From Wikipedia, the free encyclopedia

gmcoords.php is a PHP script that fetches coordinates from Google Maps and formats them for inclusion on Wikipedia articles. It is meant to be run locally from the command line. A variant of this script is used by my bot JMuniBot to semi-automatically tag Japanese municipality articles with geodata.

[edit] Notes

  • Usage: gmcoords.php [d|dm|dms] query
  • The first argument is the desired accuracy: degrees, minutes, seconds
  • On Mac OS X and Linux systems, it puts the resulting string in your clipboard for easy pasting, assuming you have pbcopy (part of the OS X developer tools) or xclip installed. Otherwise it goes to stdout.
  • If you'd like to try it out
    1. copy and paste the code below into a text file on your machine,
    2. make the file executable (chmod u+x gmcoords.php)
    3. run the file from the command line as suggested above.
  • However, it won't work as-is; you must get your own Google Maps API key at http://www.google.com/apis/maps/signup.html and insert it for the value of the $key variable.
  • You also need the cURL module for PHP. This may already be supplied with your PHP package.
  • The default case assumes the following:
    • The query is for a town, city, or village
    • The town, city, or village is in Japan
    • The appropriate precision for these cases is degrees+minutes

[edit] Example usage

user@mybox:~$ ./gmcoords.php 由仁町役場

Querying google for 由仁町役場 ... done
Copying to X11 pasteboard: {{coor title dm|43|0|N|141|47|E|region:JP_type:city}}

I typically query for city halls (市役所) or town/village offices (町役場 or 村役場). Google usually has coordinates for these, except in the cases of (relatively) recently merged or renamed towns. In those cases I query the address listed on the ja: page; if that still doesn't work, I figure out which of the merged towns' offices became the new town office, and query that one.

[edit] Code

#!/usr/bin/php -f

<?php

$usage = "Usage: $argv[0] [d|dm|dms] query\n";
$debug = true;

$key = 'GOOGLE MAPS API KEY GOES HERE';

// Handle arguments
if (count($argv) == 3) {
        $accuracy = $argv[1];
        switch ($accuracy) {
                case 'd':
                case 'dm':
                case 'dms':     break;
                default:        die($usage);
        }
        $query = $argv[2];
} elseif (count($argv) == 2) {
        $query = $argv[1];
        // Default to degrees+minutes
        $accuracy = 'dm';
} else {
        die($usage);
}

// Perform query (requires cURL module for PHP)
$query = str_replace(' ', '+', $query);
$ch = curl_init("http://maps.google.com/maps/geo?q=$query&output=csv&key=$key");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
echo 'Querying google for ' . $query . ' ... ';
$reply = curl_exec($ch);
echo "done\n";

if ($debug) echo "Google returned: $reply\n";

$coords = explode(',', $reply);

// Handle errors from Google
switch ($coords[0]) {
        case 602:       die("Query not found\n");
        case 610:       die("Bad API key.  Get one at http://www.google.com/apis/maps/signup.html\n");
}

// Google returns (blah),(blah),(N coord),(E coord) so remove first 2 items
array_shift($coords);
array_shift($coords);

// Convert decimal coords to dms
switch ($accuracy) {
        case 'd':       for ($i = 0; $i < 2; $i++) {
                                $degrees[$i] = round($coords[$i]);
                        }
                        $wiki = "{{coor title d|$degrees[0]|N|$degrees[1]|E|region:JP_type:city}}";
                        break;
        case 'dm':      for ($i = 0; $i < 2; $i++) {
                                $degrees[$i] = (int) $coords[$i];
                                // regular modulus (%) only works on ints
                                $decimal1 = fmod($coords[$i], 1);
                                $minutes[$i] = round($decimal1 * 60);
                                if ($minutes[$i] == 60) {
                                        $minutes[$i] = '0';
                                        $degrees[$i]++;
                                }
                        }
                        $wiki = "{{coor title dm|$degrees[0]|$minutes[0]|N|$degrees[1]|$minutes[1]|E|region:JP_type:city}}";
                        break;
        case 'dms':     for ($i = 0; $i < 2; $i++) {
                                $degrees[$i] = (int) $coords[$i];
                                $decimal1 = fmod($coords[$i], 1);
                                $minutes[$i] = (int) ($decimal1 * 60);
                                $decimal2 = fmod($decimal1 * 60, 1);
                                $seconds[$i] = round($decimal2 * 60);
                                if ($seconds[$i] == 60) {
                                        $seconds[$i] = '0';
                                        $minutes[$i]++;
                                }
                                if ($minutes[$i] == 60) {
                                        $minutes[$i] = '0';
                                        $degrees[$i]++;
                                }
                        }
                        $wiki = "{{coor title dms|$degrees[0]|$minutes[0]|$seconds[0]|N|$degrees[1]|$minutes[1]|$seconds[1]|E|region:JP_type:city}}";
                        break;
        default:        die("Unknown error\n");
}

// Copy to pasteboard if available
if (exec("which xclip")) {
        echo "Copying to X11 pasteboard: $wiki\n";
        exec("echo -n \"$wiki\" | xclip -selection clipboard");
} elseif (exec("which pbcopy")) {
        echo "Copying to OS X pasteboard: $wiki\n";
        exec("echo -n \"$wiki\" | pbcopy");
} else {
        echo $wiki . "\n";
}

?>