A key task when designing our map technology stack was to be able to render a lot of location places while maintaining acceptable response times and keeping a smooth navigation. This is a big challenge as you have to manage all parts of the stack, from the geographic data storage to the client side rendering.
Woosmap allows you to display hundreds of thousands locations whatever the browsing interface, mobile or not. To address this issue, we have integrated a map “multi-scale” rendering technology based on the tiling method.
The purpose of this article is to build a definition and explain what we’ve implemented to deal with large amount of locations while still offering a good user experience.
The tiling consists in cutting “large” geographic datasets in many rectangles which could then reassembled on demand on the client side. Nowadays, this method is used in many web-mapping applications, from Google Maps to Mapbox. Below is a basic schema of a raster tile - an image tile.
For this specific tile, the image is pre-built on the server so there is never any wait-time for the tile to be rendered - it is simply sent immediately to the client.
There is a need for tiling when the size of a vector or a raster layer is decreasing the performances of the navigation in the map: loading time too important and navigation not smooth. Basically, this technology allows faster navigation and a generally more positive experience when searching the information you want on a map. We could find a lot of arguments in favour of implementing tiles.
Originally, when we talk about Tiled Maps, we refer primarily to images - rasterized tiles - pre-built on the server. In the past several years, a new data storage format called “vector tiles” has gained popularity. Below is a brief introduction to both of these tiling methods.
A Raster image is made of pixels, each of a different color, arranged to display an image. Raster tiles are simply image tiles representing the map data. Most of the web mapping technologies are raster based. Those maps consist of many map tiles ordered in pyramidal scheme. Such tiles are being loaded in maps quite fast and that is because they are most of the time already rendered on servers.
Much like raster tiles, vector tiles are simply vector representations of geographic data whereby vector features are clipped to the boundary of each tile. They are the vector data equivalent of image tiles for web mapping, applying the strengths of tiling – developed for caching, scaling and serving map imagery rapidly – to vector data.
The idea behind vector tiles is that it is more efficient to keep data styling separate from the data coordinates and attributes. The client can use a predefined set of styling rules to draw tiles of raw vector coordinates and attribute data sent by the server. This allows the restyling of data on the fly, which is another serious limitation of rasterized tiles. Vector tiles have several advantages over fully rendered image tiles:
All the measures taken was carried out by opening the map for each zoom level (no zoom-in) with the following requirements:
The following diagram shows the agregated tiles sizes of vector vs raster map. As the vector data encapsulates attribute information, required for styling for example, that the raster doesn’t, this chart should therefore be taken with precaution (regarding your data attributes).
As you can see, the vector tiles load size is approximately 40x bigger for the top level scale! But there is a convergence zoom level, the breakpoint, where the raster tiles become heavier to load than vector.
In our case, we are using the Google Maps DataLayer to display the vector tiles. As demonstrated in this diagram, performance degrades as markers are added. To process over 1000 markers from vector tiles make the web map unusable.
Considering the above and that we decided not to use Web GL due to browser compatibility criteria, we have developed an hybrid tiling technology that combines the two approaches, raster and vector ;-). The idea behind this is to get the most out of both worlds and to better meet the needs of users of our product.
We’ve implemented a combination of raster tiles for the top level scales, and vector tiles at the bottom level scales. This way, we benefit from having a fast web map at every scale while preserving a smooth navigation and a clear rendering for higher client resolution.
To switch from one to the other, we define a zoom level breakpoint. As the tiled vector is rendered on the client, it’s quite easy to offer a good user experience but for the top level, the raster rendering, that is “une autre paire de manches”, as the French expression goes!
To offer a fast web mapping experience you should pay attention to the essential interactive aspect. On a typical map you can have thousands of features which all need to be usable on a variety of devices. The UTFGrid specification defines a way to transport interactive data to a map interface, like a tooltip, so that it loads progressively and performs well across legacy browsers and modern mobile devices.
On the following jsFiddle Sample, you can get information (
id on hover,
name on click) on each dots despite the use of raster images. The production of these features was made possible thanks to the support of UTF Grid tiles.
This technology has been developed by Mapbox and is open sourced. You can read the specification on their github. They offer nice interactive demos to understand well the concept: VisibleMap Demo and Poisoned Places Map.
We’ve implemented an architecture based on open standards, like Mapnik and UTF Grid, and proprietary Woosmap components. Below is the corresponding schema of our tiling architecture.
TiledView class enables the use of the raster tiles (see official doc). Our WebApp natively supports the hybrid tiling system.
A tile cache is a server that sits between the browser and the map server. It checks to see if a requested map tile is already hanging around in a cache somewhere, where it can be served up quickly to short-circuit the call to the map server. If the map tile has not been generated, the tile cache gets it from the map server and saves it to speed up subsequent requests. In our configuration, we’re using a Content Delivery Network as it allows us to manage tile cache as well as other traffic to end users. The principle of a CDN is quite simple: dispersing all of your static content across multiple servers geographically closer to your users will make your web pages load much faster.
We’re caching the tiles only on-demand, not for pre-seeding, to keep data the most up-to-date as possible. However, our CDN instructs a visitor’s browser to cache files for two hours to prevent heavy loads due to concurrent users. During this period, the browser loads the files from its local cache, speeding up page loads.
Basically, the map server brick takes geospatial data as input and renders graphical output. In our case, it spits out a series of map tiles, which are uniformly sized graphic (raster) and JSON (vector) files that are served to and assembled in the browser as the displayed map.
For the Raster tiling, we’ve implemented Mapnik using the python bindings (Mapnik is orignially written in
C++). It’s an open source toolkit for developing mapping applications that renders beautifully, has a developer-friendly interface and offers strong performance. Furthermore, the toolkit is aimed primarily at web-based development and there is a large developers community around this map server.
For the vector tiles, we could use Mapnik as it supports natively this feature (See this implementation of Mapbox Vector Tile specification for Mapnik), but our data is lightweight (it supports only point geometry) and we don’t need all the complexity of this spec. That’s why we developed our own custom vector tiler server. For now, we’re not using a data encoding to transport the vector data from map server through to the client. This could be a great improvement so we are looking seriously on implementing the Google Porotobuf data interchange format.
All the geographic dataset we manage is stored using a spatial database which provides a geometry type and functions that operate on it. This gives us the ability to make SQL queries that include spatial predicates like “within two miles of this latitude and longitude”, that is especially interesting for our needs to bring our users to the displayed places.
Our platform is able to dynamically serve a lot of concurrent users displaying huge geographic data. The development of an hybrid tiling strategy and the use of a content delivery network make us comfortable to support heavy loads.
We are continuously working to improve the user experience and need to explore certain topics in greater detail. For instance, the Google ProtoBuf data interchange format could be adapted to our homemade tiler to increase the performance. Also, the use of a WebGL technology, like the CanvasLayer Utility for Google Maps, on the client side would be a great improvement for a smoother navigation.
If you have any questions about the content or the process described, please don’t hesitate to reach out to me through the contact page.
If you want to go further
Woosmap offers an easy embeddable Store Locator Widget. Our aim is to help you to integrate a powerf [...]
The Google Places API is a service that returns places predictions using HTTP requests. The service [...]
Google Maps and Woosmap Platform APIs and SDKs require you to send an API key with all calls. API ke [...]