XYZ: Dynamic vector tiles created on the fly, cached and updated directly in PostGIS.
tl, dr; Here is a demo showing dynamic cached vector tiles in action.
edit: There is now a follow up article which highlights geometry edits on cached MVT layer with OpenLayers 5.
Mapbox Vector Tiles
Talking Vector Tiles, I refer to the Mapbox Vector Tiles (MVT) specification. The methods outlined in this article would not be possible without the heavy lifting of the Mapbox engineers at large. I won’t get into the details of the specification here or discuss why you should be using MVT in web maps.
I am taking a chance here and guess you already know a great deal about vector tiles and perhaps already use them. Otherwise here is a good primer written by Giovanni Allegri. You should read this article even if you think you are already clued up on all things MVT.
At GEOLYTIX we have been working for some time on an open source solution to bring spatial data and analytics to the cloud. This solution being XYZ, a framework to build applications which prominently feature a map control. The release candidate is currently tested and I intend to write more on this topic and provide a step-by-step workshop soon.
XYZ is meant to run as a cloud function which serves vector tiles to a map renderer. The tiles should be cached in a separate PostGIS table when generated from a data source and served directly from the tile cache when possible.
If MVT in tile_cache > Return MVT;
The tile cache table must have indexes to provide fast access to cached tiles and remove tiles which are no longer valid. A primary key on the z, x, y index fields allow selection of tiles from a tiled web map request.
A spatial index on the tile’s geometry (Polygon, 3857) allows to select and remove tiles which intersect with updated features in the data source.
The full schema of the tile cache for the Natural Earth data source is shown in this gist:
The XYZ framework will automatically generate the tile cache if required.
If not MVT in tile_cache > Create MVT;
If a tile is not found in the cache it must be generated and stored for subsequent requests.
The tile’s bounding box geometry can be defined by using Mapbox’ TileBBox function. The TileBBox function turns slippy map tile names into projected Web Mercator bounds. The bounding box geometry is used to select intersecting geometries in a PostGIS table which has an indexed geometry (SRID 3857) field. The id and other properties which should be assigned to features represented in the tile are selected within the tile subquery. From this subquery the tile can be returned to the client as well as inserted into the cache table. The primary key will prevent tiles to be duplicated.
This gist shows the structure of a sample query used for the Natural Earth Countries layer.
A cached tile must be retired once the geometry or properties of a feature represented in this tile changes.
Within the XYZ framework we use a simple query to find all tiles in the cache which intersect the old as well as the new feature geometry if the geometry changes.
It’s best explained when displaying the bounding boxes of cached tiles as a MVT layer themselves.
Changing the theme to display population figures divided by area I first select México. I then up it’s population by ~100 million. No bad hombres; I promise.
Confirming POTUS’ worst nightmare we see that the themed layer has updated accordingly.
Toggling the tiles meta layer we see that previously cached tiles were removed during the property update.
Please have a play yourselves with our hosted demo:
As mentioned earlier, this demo is built from our first release candidate which we are currently testing. If you see something, say something. Any comments and bug reports are more than welcome. Fancy to fork the XYZ repo? Please wait until we sign off the V1 release in the next couple of days or so.
Finally a word of thanks to GEOLYTIX who are hugely committed to open source and funded the XYZ development over the last few years. A special thanks to my colleague Agata who has done most of the groundwork for the vector tile generation and to Rob who joined our team recently and is now in charge of testing and pushing the V1 release out. Thereafter we plan to run some benchmarks and look to further improve the process’ performance.
Please see me at a future FOSS4G conference or get in contact via mail / twitter if you would like to become involved with the XYZ project.