-
Notifications
You must be signed in to change notification settings - Fork 10
Serving Custom Tiles using Martin
Martin can basically serve tiles using 2 different ways: Views and Functions
The most simple way is to just create a view of the necessary data you want to serve and specify this view in your config.yaml file.
Example: peak view:
CREATE VIEW peaks AS
SELECT planet_osm_point.name,
planet_osm_point.tags->'ele'::text AS ele,
planet_osm_point.way -- necessary field for coordinates
FROM planet_osm_point
WHERE planet_osm_point."natural" = 'peak'::text;
peak config:
postgres:
...
tables:
peaks:
schema: public
table: peaks
srid: 3857
geometry_column: way
geometry_type: POINT
properties:
name: text
ele: int
...
Although this option can be used to provide the data very fast with limited configurations needed, it also doesn't give you too many options in tuning how much is served at which zoom levels.
The alternative to views are functions as tile sources (https://maplibre.org/martin/sources-pg-functions.html)
In Postgres you can specify functions that are to be executed. In those functions more freedom is given in how detailed you want to configure your query. Martin requires the function to have 3 integer parameters (z,x,y values for the tile you are currently requesting) and a bytea as a return type. The bytea is written by the ST_AsMVT function that is available in postgres/postgis. Additionally it is also possible to specify a fourth parameter where you can pass through additional values to your function.
Example: peak function:
CREATE OR REPLACE
FUNCTION peak_tile(z integer, x integer, y integer)
RETURNS bytea AS $$
DECLARE
mvt bytea;
BEGIN
-- NOTE it is possible to add if branches here for better individual configurations
SELECT INTO mvt ST_AsMVT(tile, 'peak_tile', 4096, 'geom', 'id') FROM (
SELECT
id, name, long, lat,
ele,
-- transform the point into the current vector tile -> x/y points lie within (0,4096)
-- this is necessary for vector tiles on a flat map like leaflet
ST_AsMVTGeom(
ST_Transform(way, 3857),
ST_TileEnvelope(z,x,y),
4096, 64, true
) as geom
FROM peaks
-- only select points where the current position and current tile bbox overlap
WHERE ST_TRANSFORM(way,4674) && ST_Transform(ST_TileEnvelope(z,x,y), 4674)
ORDER BY ele DESC
-- possible to use z parameter here to to differentiate how much is returned per zoom level
LIMIT 1
) as tile;
RETURN mvt;
END
$$ LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE;
peak config:
postgres:
...
functions:
peak_tile:
schema: public
function: peak_tile
minzoom: 7
properties:
name: text
long: double
lat: double
ele: int
...