With the release of Version 5 of Google Maps on Android the processing has moved away from web servers and onto mobile devices by becoming a vector application. Up until this release, all versions of Google Maps, on phones or desktops, were based on the client requesting raster tiles from the server whenever you zoomed or panned across the map. This article takes a detailed look at these features from a Digital Cartography perspective. It is also interesting for people who are looking at the benefits of getting devices to do more of the heavy lifting.
Map Tiles are created by a map server which takes the vector data (from databases or GIS files) and draws them to create a map image. Before tiles, map servers used to create a single raster based on the image request size – ie the hole on the page somebody wanted a map to fill. Tiling did two things:
- Created a standard grid for a map projection so that the same image could be requested by different clients
- Allow the browser to grab more smaller images rather than a single big one.
In a typical map window you have 9 tiles for an approximate size at avg 20KB/tile is 180KB.
The size of this data as vector is 260KB as compressed xml. In a raster tiling implementation, you need the vector data stored (in a db or flat files) and also tiles stored or a way to generate the tiles from the vector data. If the tiles are already generated then you can use a standard web server to just send the requested tiles. They are just files. The Google API allows the client browser to work out what tile urls are required for any given location and scale. The web server then does no spatial work, it just sends back images.
Then you zoom in. It occurs all over again. 9 more tiles are requested. Another 180KB. The vector client (Android Google Maps) has no round trip to the server. Just re-render the data based on the new view-port extents as it already has the data. It is possible that rather than re-render you can just scale the vector data already rendered.
To render vector in a browser there are a number of solutions. SVG is one and VML is the way Microsoft Internet explorer works. Projects like OpenLayers extract this browser difference away so as a web developer you can draw vector and Openlayers works out which rendered (SVG or VML) to use.
If we now think about using vector information, rather than raster, what are the differences in the request cycle? The client (Google API or OpenLayers) sends an intelligent request to the server for some vector data. For example, give me all the vector data in this geographic area (extents?). The web server can then grab the vector data from the flat files or database and format it based on the request, using data formats such as KML or GEO-JSON. The responses can be cached so that you don’t have to transform it on the fly everytime. This is a little be more work than serving a static file as it now needs to do a database query or dynamic code request. The requirements for storage is reduced when serving vector data compared to raster images. However, the client has render and style the data sent to it by the server (KML, GEO-JSON, etc).
The client then has to do some heavy lifting as it needs to take the geo-json (kml or ?) and then render it. This rendering will be done on some styles that suit the look and feel.
Updating map data
Now as it happens, map data is not as static as one would think. New houses are built, new roads to these houses are constructed and new highways under, around and through houses are created all the time. In the raster (tile) model of the world, you would update your database or flat file then delete all your existing tiles. Then you would 'seed' the cache either by some server process or letting the poor next user get a slow response while you generate the tile that they requested.
In the vector model, you just start servicing the new data to the next request. It's likely that you would design the vector client so it has some way of checking the 'last updated' date for the area of map data currently being rendered so it could grab the new data.
Why is this interesting. Well, you have moved the very 'expensive' rendering task from your machines to machines not paid for by you. Instead of rendering the lowest common denomitator in styles for tiles you can let each device render what is has the ability to render.
You can now continually update data without having to manage the rendered tile sets.
Labels can be repositioned when the map moves in a client side vector implementation.
Panned slightly and the label has been redrawn on the client in suitable location
The user now gets important information in a more consumable way. If this was tiles, the label would not move. The device is deciding where to label the roads.
Vector labelling doesn't yet have the same level of cartographic control that you do on a server map renderer. Some examples. Curved labels.
Note how the label is perpendicular to the longest line segment of the arc. A sensible first step.
Note the more advanced curved labelling from the server rendered (old style) map tiles
Split labelling You need an algorith to join both parts of a street that is broken by an intersection, effectively joining the roads into a single line. In v5 it's just picking the one that makes the most sense (on screen and not likely to collide with another label)
I believe the Google Maps vector application is requesting vector data in chunks. Possibly the server has millions of files, each one representing a small geographic area. Essentially, you could have a similar directory structure as raster tiles but instead of having images you have chunks of vector data. The client then requests the 'chunks' of vector data and joins roads (and other features) that are actually the same. When panning in the vector google maps you will often see an end of road then moments later the road end will be redrawn with a continuation.
An alternative, could be to have the sets of data set at a particular data size rather than geographic extents. That way, each chunk of data would be the same size and the servers could be optimised to serve that exact size of data. It would require a more sophisticated client to work out which chunk of data to request. A lightweight service on the server could help the client do that if you wanted a mapping between geographic extents and the file size optimised data sets.
If there is interest, next time I’ll show the difference on server load between generating and serving tiles to serving geo-json/kml.
My Ignite talk where I discuss the whole idea of moving more from server centric to device and network aware services. Angus Ignite Talk – Fast train from central