Skip to content

Concept

Katatunga edited this page Jul 6, 2020 · 5 revisions

Motivation

The project came to life within the OpenHistoricalDataMap project which aims to provide a website that displays maps from current time as well as historic maps.

We wanted to use Mapnik to render these maps. We also wanted to use the existing styles, so we wouldn't have to create them.

Map data should only be rendered if it is valid on a given date. The project should be able to change this date dynamically. Because the default Mapnik has no concept of time, we couldn't use it for this project without making changes.

To ensure simple usage and easy reproducability we wanted to change as little as possible about Mapnik and it's stylesheets.

Idea

The database used by OpenHistoricalDataMap (OHDM-Converter) has a concept of time. Every object (row) in it is valid only in a finite time frame (columns: valid_since, valid_until).

If we could control every database query made while rendering, we could provide Mapnik with only the data valid on a given date.

Therefore, the basic algorithm should look like this:

  1. Take a parameter (the given date)
  2. Alter the database queries to respect this parameter
  3. Ask Mapnik to start rendering using the altered queries
  4. Save the resulting tiles into a directory which includes this parameter

psr_concept

Project

Because we couldn't setup the current version of Mapnik (Python-Bindings wouldn't work), we used Mapnik 2 and it's according stylesheets.

For the purpose of creating a simple proof of concept, we didn't want to worry about caching or the general use of tileservers. Generate_tiles.py, which is used for prerendering, was a fitting base script.

1. Take a parameter (the given date)

As generate_tiles.py did not accept parameters, we had to modify it, but conserved the original script fully, only commenting out the executive part.

We built our script around it to accept parameters both from CLI as well as from listening to a given port, but did not touch any of it's rendering procedures.

2. Alter database queries

Select-Statements in stylesheets

In the stylesheets, every occurence of a Select-Statement adds a prefix to the queried table:

Default: 
- prefix = "planet_osm"
- tables = "_point, _line, _polygon"
- result = "planet_osm_point, planet_osm_line, planet_osm_polygon"

The prefix definition is centralized, so altering only this definition would result in the change of every Select-Statement. Hence, we can freely choose the prefix of every queried table.

Preselect valid data

Since the database has a concept of time, it is possible to easily create views which only contain data valid on a given date.

CREATE OR REPLACE VIEW [viewname] AS (SELECT * FROM planet_osm_point WHERE [date] BETWEEN valid_since AND valid_until);

3. Ask Mapnik to start rendering using the altered queries

Now we just need to match the prefix (in the stylesheets) to the viewname, causing Mapnik to use only the preselected data. We then used the original rendering process of generate_tiles.py.

4. Save the resulting tiles into a directory which includes this parameter

Generate_tiles.py itself saved tiles to a given (hardcoded) directory DIR as follows:

DIR / ZOOM / X / Y.png

We just added the DATE (parameter) before ZOOM to differentiate between tilesets rendered for different time frames.

DIR / DATE / ZOOM / X / Y.png

Conclusion

As already stated, this is a simple proof of concept. A lot of time went into identifying parts of OpenStreetMap easily usable for our cause. Therefore, the project itself can only be used for prerendering and cannot serve tiles to an online service.

But as long as you can control every database query of the rendering process with some variable, you can apply this concept to more complicated scenarios. The next step would be serving tiles instead of saving them into a file system.