Thursday, April 8, 2010

Tile overlays with Google Maps API v3 and GeoServer

I was introduced to the Google Maps v3 API last May at Google I/O. And I am sadly just getting around to doing something with it beyond the "hello world" example given on their website.

My plan is to serve image overlay tiles from a geoserver backed by a postgresql database with postGIS. Last week I installed postGIS and setup a new database with the postGIS functions. I created a table to import a shapefile w/ supporting files. (I should post some howto details on all that...)

So to get a basic v3 maps running with image tile overlays, the key docs are at:

You can follow the example there first, and get a tiled image overlay working, showing a traffic overlay from google's server. The "tile server" URL format is formed by a function, e.g.
1: function(coord, zoom) {
2:   return "" +
3:     "zoom=" + zoom + "&x=" + coord.x +
4:     "&y=" + coord.y + "&client=google";
5: }

Now, back to the GeoServer side of things.  The key thing I needed to know was what the format of the URL should be to get a raster tile image out of the GeoWebCache. The GeoWebCache docs show the following, which is aimed at v2 google maps API.  (From

To be sure, when I installed GeoServer 2.0.1, I was under the impression that it included GeoWebCache. I could confirm when I browse to the following URL and see a GeoWebCache page.

In this screen shot you can see my indiana counties shapefile that I had imported into a postGIS table. The "spelling" of that data layer will be used in the URL that follows.

So, given the GeoWebCache docs above, and the fact that I had a different base URL, I construed that the proper URL to fetch a google maps tile would perhaps be:

Putting this URL into my web browser, I was served a single 256x256 PNG tile as desired. Success.

So below is my example of hooking up v3 google maps API to GeoWebCache tile server. This presumes you have a corresponding div tag in your html file, e.g.,

1: <div id="map_canvas" style="border: 1px #333 solid; height: 375px; width: 500px;"></div>

And the code:

1: function initialize() {
2:   var latlng = new google.maps.LatLng(39.8895, -86.1575); // Indiana
3:   var myOptions = {
4:     zoom: 6,
5:     center: latlng,
6:     mapTypeId: google.maps.MapTypeId.ROADMAP
7:   };
8:   var indianaCountiesOptions = {
9:     getTileUrl: function(coord, zoom) {
10:       return "http://myserver:8080/geoserver/gwc/service/gmaps?layers=indiana:indiana_counties&" +
11:        "zoom=" + zoom + "&x=" + coord.x + "&y=" + coord.y + "&format=image/png";
12:     },
13:     tileSize: new google.maps.Size(256, 256),
14:     isPng: true,
15:     opacity: 0.25
16:   };
18:   var customMapType = new google.maps.ImageMapType(indianaCountiesOptions);
19:   var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
20:   map.overlayMapTypes.insertAt(0, customMapType);
21: }