|
Home Hacks Interesting Links Local Links Photography Parks Cooking |
Generating maps from Google MapsA lot of this information is outdated; jump to the update for more updated information. Google Maps is a great mapping resource. It raises the bar for other mapping services like Yahoo Maps and MapQuest. This page describes a little hack I did to generate maps from the Google Map server, for use in other applications. Disclaimer: this information is meant for personal use only; please don't misuse it. Even though Google Maps lets you print out maps, this leaves something to be desired. For one, I'd like to be able to annotate my maps and do something more with them. In addition, I might want to print out a larger version of the map, without the stuff Google puts on their print version of the page. Others have described the inner workings of Google Maps, so I'll skip that portion. What I found appealing was that Google had generated all the maps statically; the viewport (map you're looking at) is tiled with prefabbed 128x128 pixel GIF images. Since these image tiles are pre-generated, I didn't think it would be too much strain on Google's servers to download a set of these for the required coordinates.
The viewable map is made up of 128x128pixel GIF images like this
The "center" of the Google Map is a point in Kansas. It is somewhere in the region of Waconda Lake, near Glen Elder State Park and Reservation. From looking at the JavaScript code in GoogleMaps, its Lat/Long coordinate are (39.5N , 98.35W). Google allocates 2(17 - zoom) pixels per degree of lattitude; and 2(17 - zoom) * 0.77162458338772 pixels per degree of longitude (the earth bulges at the middle). (Initially I had used line fitting to figure out this stuff, but a well-timed look at the JS code saved me the math gymnastics. UTSL!). To get the tile number, divide this pixel value by tile size (128), and you have the (x,y) coordinates for the tile. An example: Buffalo, NY has the coordinates (42.88980N , 78.85968W). To get the tile for this Lat/Long pair, we do the following (using zoom=0):
Given this, what can be done with these tiled images?
First, I wrote a little Perl script that uses LWP::Simple to fetch the corresponding tile images, and inserts them into a bigger image using Image::Magick's Composite function. Here's a snippet of the code: (because I don't want to be the posterboy for some DMCA-inspired attention, I won't be releasing it)
my $url = 'http://mt.google.com/mt?v=.1&zoom=' . $zoom . '&' ;
my $image = Image::Magick->new(size=> int($width*$tilex) . 'x' . int($height*$tilex));
$image->Read('gradient:white-white');
...in the loop...
my $gif = get($url . 'y=' . $y . '&x=' . $x);
my $tile = Image::Magick->new(magick => 'gif');
$tile->BlobToImage( $gif );
$image->Composite( image => $tile, y => int($i*$tilex) , x => int($j*$tilex) , compose=>'over')
Next, using a simple text-based language and Image::Magick's annotation features, we can place arbitrary graphics and text on these maps. And finally: since the SVG standard allows embedding images (including URLs) into SVG documents, it is possible to generate SVG docs that link to GoogleMaps' images directly, overlaid by vector graphics which can be used to mark routes, interesting waypoints, etc. This is left as an exercise for the reader ;-) (Note: both sodipodi and inkscape, the two popular SVG editors for Linux, do not as yet support external links to images). One thing that has been bothering me is why the tile coordinates can't be calculated exactly from the Lat/Long, and if there's a way to do that short of hitting Google's site repeatedly. I know, the Earth isn't flat. If you have any comments/questions, please let me know. I'll be happy to answer them. Overall, this has been a fun exercise. I started this exploration so I could print out larger maps and annotate them for use in hiking. Thanks to Google, now I can get lost in the wilderness with ease. :-) 09/16/2006 Update: It's been a while since I updated this page. I have received a steady stream of questions from people for generating their own maps from the Google tiles. While Google Maps does allow one to print, sometimes it is necessary to make your own map.
Google has changed how it lays out tiles. They are no longer using the quad-tree representation
outlined above; they have given up on that and are now using a simple planar coordinate
system. Consider, for example, the town of Plymouth, MA. If you zoom out enough and look at the media, the town's tiles at
zoom level 6 (where 0 is the highest magnification) are at Now, if you wanted to zoom in one level in, each these tiles would each yield 4 (2x2) tiles at the next higher zoom level. So, you would get:
Keep doing this, and at the highest zoom level (0) you'll have a 128x64 grid of images, going from (X=39744) through (X=39871), and from (Y=48640) through (Y=48703). |
|