Web and mobile applications account for most of the maps usage today. We recently read that about 54% of smartphone users have Google Maps running on their phone making it the most popular application in the market. In the recent years, the technology behind web maps have improved considerably, owing to the incredibly fast and intuitive experience that we enjoy today. What we see, drag, scroll, touch, pinch and poke today is a set of map tiles.
The OpenStreetMap Wiki defines map tiles this way –
square bitmap graphics displayed in a grid arrangement to show a map
The fine folks at MapBox defined it this way –
tiles are typically 256×256 pixels and are placed side-by-side in order to create the illusion of a very large seamless image.
This technique of preparing and serving maps changed the way they are consumed drastically. Earlier, loading the map in a browser would take up so much memory that it was practically impossible to browse the map easily. Tiles make sure that only the required (usually the area which is currently viewed) have to be displayed on the browser, reducing the memory footprint. Even though Google got the usage of tiling right, they did not invent it. Web Map Service which came out in 1999 as an OGC standard set the web mapping revolution to a new level. WMS was slow for a lot of neogeographers. This frustration lead Anselm Hook to explore the idea of tiling the map for better performance.
Let’s take another step forward and see how the tiles work and how they are generated.
When we view a map on the browser, there’s an immensely powerful feature – zoom. The world map at the least zoom level (level 0) is usually four square images which forms a grid of tiles. Every location on the earth is represented by a tuple with two elements – [latitude, longitude]. This, on your screen, translates to [x, y] which is the pixel coordinates. Zoom levels are incorporated to this data structure by adding one more element to the tuple – [latitude, longitude, zoom]. For instance, [12.9719, 77.5938, 12] is Bangalore at zoom level 12 and [12.9719, 77.5938, 15] is Bangalore at zoom level 15.
The geographic data in databases or shapefiles are rendered into the tiles through a process which involves several stages. We will quickly run through the most important and commonly used pipeline using a stack of open source softwares.
Mapnik is the de facto open source rendering library written in C++ that is used by large geographic data projects like OpenStreetMap to tiny map studios. Mapnik accepts a wide variety of input data – PostgreSQL databases, Shapefiles, GeoTIFF, and renders the data into set of map tiles depending on the style that you have developed. The styles are XML files which explain what Mapnik should do for each of the geographic feature (read tags) that it finds in the data source.
<Style name="highways"> <Rule> <Filter>[highway] <> ''</Filter> <LineSymbolizer> <CssParameter name="stroke">#808080</CssParameter> <CssParameter name="stroke-width">2</CssParameter> <CssParameter name="stroke-linejoin">round</CssParameter> <CssParameter name="stroke-linecap">round</CssParameter> </LineSymbolizer> </Rule> <Rule> <Filter>[highway] <> ''</Filter> <TextSymbolizer name="name" fontset_name="book-fonts" size="9" fill="#000" halo_radius="1" placement="line" /> </Rule> </Style>
The above XML is one of the many style tags used by OpenStreetMap to render the tiles using Mapnik. This style tag refers to the highways that you see on the map. A style tag comprises of several Rules. A common technique is to apply CSS to the features that satisfy a rule and Mapnik will pick it up.
The tiles rendered by Mapnik are then served from what is called a Tile Server. The commonly used tools for a server is Apache with the mod_tile extension. I like the Python based server called TileStache. It’s fast and easy to setup. When the browser requests for a map tile, the server checks if the tile has been already rendered, if yes it is send to the browser. Otherwise, it is send to Mapnik for rendering.
We will discuss more about the configuration and best practices of setting up a rendering stack eventually in another blog post.