Friday, April 21, 2006

Hacking Google Maps Geocoding

Geocoding - the process of converting a street address to longitude/latitude. Necessary because the Google Maps API expects longitude/latitude numbers based on the WGS 84. And in order for your points to resolve correctly on the map you are using (Google/Navteq in my case), you would hope to have geocoding from that same source. And as we know Google does not offer this service.

I'm sure Navteq is holding Google to some agreement not to provide this service with their APIs. Think of it. Navteq's business is providing this data. They spend lots money with their high-tech cruiser vans traveling every road to collect the data. They charge Google big bucks for it. They don't want Google giving it away for free.

So what are your options since Google offers no geocoding service?

US Census TIGER data

You can use the geocoder.us free web service that has loaded this data for the US. I loaded the data for my county into MySQL. Hey, it's for a database course, right? So why not load the data and play with it. But what I found was the data showed a number of inaccuracies and there was quite a bit of missing data. It didn't map well onto Google.

Yahoo! Maps REST API

Yahoo! offers a REST API for gecoding. It's easy to use and open. My friend that works at Yahoo! was eager for me to use it. :) But similar problem. It works best when placing points on a Yahoo! map, not a Google Map. The points end up being off just enough.

Hack Google

Not a good idea for a commercial app (I'm sure Google might complain), but for my grad school project, I thought it might be worth exploring. And sure enough there is various scripts out there on doing just that. If you call a url like http://maps.google.com/maps?q=[your address here]&output=js (note the output=js at the end), Google returns a Javascript function with the longitude/latitude that you are looking for inside. However, just to prove that this is not an ideal solution, Google has changed the format of this output so that any of the previous hacks would no longer work. It's not a public API afterall! :) My script is shown below.




<html>
<head>
    <title>Google Geocode</title>
</head>

<body>
<h2>Google Geocode</h2>
<form name="mainform" action="">" method="GET">
    <b>Address:</b> <input type="text" size="40" name="address" value="">">
    <input type="submit" name="geo" value="Google Geocode">
</form>

<hr />
<b>Geo-location:</b>
<ul>
<?php
if (array_key_exists('geo', $_REQUEST)) {
    $result = get_long_lat($_REQUEST['address']);
    print_r("<li>Longitude: ".$result["longitude"]);
    print_r("<li>Latitude: ".$result["latitude"]);
}
?>
</ul>
</body>
</html>

<?php

function get_long_lat($q) {
  $q = urlencode($q);
  $gm = fopen('http://maps.google.com/maps?q=' . str_replace('','+',$q) . '&output=js','r');
  $tmp = stream_get_contents($gm);
  fclose($gm);
  $x = preg_replace('/.*\{center: \{lat: ([^,]*),lng: ([^}]*).*/', "|$1|$2|", trim($tmp));
  list($dmy,$lat_value, $lng_value) = explode("|",$x );
  return(array('longitude'=>$lng_value, 'latitude'=>$lat_value));

}
?>


My Superior trails map project includes an address field that uses this code to geocode the provided address and insert a marker on the map.

Thanks to Dan Moore for his insights and feedback on geocoding options.

1 comment:

jvaleski said...

Here's another cut at using Google as a geocoder; not sure if it still works. As Greg pointed out, it's not a public API so it's subject to breaking :-). Furthermore, I think Google now does provide a geocoder anyway :-).

http://valeski.org/code/googleGetCoordinates.txt