Use Google Maps Tiles with the API

One thing every Maps developer notices eventually, is that the API’s imagery doesn’t exactly match that which is on Google Maps itself.

Check out the two maps of uptown Waterloo, below. The image on the left is a shot of the API, while the one on the right is from Google Maps. Not only is the API getting bizarre anachronistic road names, it’s missing the label on Wilfred Laurier school, and the two maps aren’t even agreeing about the shapes of parks or built-up areas.

api-map-small.png     gmaps-map-small.png

On the Google Maps Newsgroup, developer Bret Taylor provides this explanation:

We are in the process of turning on new map tiles for API sites. The
map tiles are built from Tele Atlas data in the US (the same vector
data used in Google Earth) rather than Navteq data. This should be a
relatively transparent change on your sites, but we are eager to hear
any issues you have with data quality and/or the tiles themselves,
which should be identical in terms of design.

So please do send them your feedback, but this is where it’s at; Maps API developers operating in rural regions are stuck with the bizarre, out-dated TeleAtlas data.

Unless, of course, you make your own tile layer that points directly at the official Google Maps tiles, like this sweet example here. Stay tuned below for some explanation.

Note: This is an unsupported hack. It doesn’t appear to be forbidden in the terms of use, but you’ll need to stay on top of any mashup using this trick—at any moment, Google could start blocking off-site referers on certain imagesets.

Update: The original version of this article had the tiles hard-coded to version 2.21; it’s been updated now to grab a more recent version.

Adding Tilesets

One of my favourite examples in the book is the Blue Marble map that Jeff came up with. The code for that is the genesis of this (much simpler) demo. However, in this version I’m just pointing at Google’s tiles, rather than providing my own. To configure the widget in the top-right corner, I’ve put the following in my init() function:

G_NORMAL_MAP.getName = function() { return 'TeleAtlas'; }
map.addMapType(G_NORMAL_MAP);
map.addMapType(getNavTeq());

map.removeMapType(G_HYBRID_MAP);
map.removeMapType(G_SATELLITE_MAP);
map.addControl(new GMapTypeControl());

The first line overrides the normal map’s getName function so that it identifies itself as TeleAtlas, rather than simply Map. The following two lines add the normal and NAVTEQ tilesets to the map. The getNavTeq function returns a GMapType object; we’ll have a look at this function in a moment.

The last three lines remove the hybrid and satellite views (enabled by default, but they don’t really interest us), and then add the actual control that places the little buttons in the top-right corner.

Creating Tilesets

The real meat of this demo is in the getNavTeq function, of course, since this is what actually sets up the new maptype . This actually takes place in three steps: setting up the copyrights, setting up the tileset, and setting up the map type.

Copyrights. It may seem mundane, but acknowledging a data source is an important part of a project like this. We’re just putting one big copyright in; it covers the whole world:

copyrights = new GCopyrightCollection('Map data');

copyrights.addCopyright(new GCopyright(
    'gmaps-navteq',
    new GLatLngBounds(new GLatLng(-90,-180), new GLatLng(90,180)),
    0,
    '©2006 NAVTEQ'
));

The documentation for GCopyright makes it pretty clear how this works; we just give it an identifier, a rectangular boundary, a minimum zoom level, and a text string.

The Tileset. This is almost identical to what I’ve showed previously in the demo of rendering shapefiles, except this time, I’ve pointed the target URL back at Google’s server, and I’ve observed their convention of rotating the mt# server value:

var tileset = new GTileLayer(copyrights, 0, 14);
tileset.getTileUrl = function(tile, zoom){
    tileServer++;
    if (tileServer > 3) tileServer = 0;
    return 'http://mt' + tileServer + '.google.com/mt?n=404&v=w' + tileVersion + '&x=' + tile.x + '&y=' + tile.y + '&zoom=' + (17 - zoom) + '';
};
tileset.isPng = function() { return false; }
tileset.getOpacity = function() { return 1.0; }

The real key to pick up on here is, even though the API has switched over, NAVTEQ tiles are still labelled using the old negative-is-higher zoom convention. That’s what the mysterious 17 - zoom stuff is all about.

The Map Type. Setting up a GMapType object is actually really simple; it’s just a matter of passing several parameters to the class’s constructor:

var maptype = new GMapType(
    [tileset],
    new GMercatorProjection(14),
    'NAVTEQ',
    {
shortName:'NT',
        tileSize:256,
        maxResolution:14,
        minResolution:0
    }
);

The scariest thing here is the [tileset] bit. There’s actually nothing magical at all about the square brackets—they’re just marking off an array. It’s an array because a given GMapType may contain multiple layers, like Google’s own hybrid map, which has the standard satellite photography beneath a special translucent road set.

Remarks

As in the note above, use this trick with caution. If you’re making a local mashup in an area favoured by one or the other of the sources, the worst you can do is pick the one that’s more appropriate. But just be aware that all the data is certainly subject to extensive licensing agreements between both NAVTEQ, TeleAtlas, and Google, and using this method may be pushing the line on those. If you get a nastygram from the Google lawyers, just switch it back.

Update: It seems clear from threads like these that people believe users of the free API are to show TeleAtlas tiles only. Can anyone find a confirmation of this?

The Files Involved


4 Responses to “Use Google Maps Tiles with the API”  

  1. 1 Berry Ratliff

    I have added a few others

    http://www.provide.net/~bratliff/compare.htm

    Conceivably, you could use Google’s API to display Virtual Earth’s and/or Yahoo’s tiles but you would have a lot of people upset with you.

    The file

    http://www.provide.net/~bratliff/register.js

    contains routines to generate the the various tile URLs.

  2. 2 Mike

    Wow, consider me one-upped. Thanks for the link, Berry; looks like a terrific resource for comparing the different datasets.

    For those of you who were interested in the source code, I apologize for the broken links which are now corrected.

  3. 3 Berry Ratliff

    I am planning to offer a light weight pop-up facility to run in another window / frame / iframe.

    I have a flyover demo running at:

    http://www.provide.net/~bratliff/flyover.htm

    The Terra Server aerials for Pebble Beach are pretty ugly but perfectly legal. Hint - use the menu to switch to one of the other providers.

  4. 4 SurferDude

    Looks like the Navteq tiles no longer work :(


Buy Our Books!

(Here's Why) PHP book Rails book DOM book mashups book