t-rex-tileserver / t-rex

t-rex is a vector tile server specialized on publishing MVT tiles from your own data
https://t-rex.tileserver.ch/
MIT License
556 stars 69 forks source link

Pixel size for sampling tolerance in WGS84 #285

Open ChristianBeilschmidt opened 2 years ago

ChristianBeilschmidt commented 2 years ago

I'm using T-Rex to generate WGS84 vector tiles for Natural Earth Data. For this, I import the geopackage into PostGIS and then use this as a datasource for T-Rex.

One layer is specified like this:

[[tileset.layer]]
name = "boundary_lines_land"
geometry_field = "geom"
geometry_type = "MULTILINESTRING"
fid_field = "fid"
srid = 4326
buffer_size = 0
simplify = true
make_valid = true

[[tileset.layer.query]]
minzoom = 0
maxzoom = 2
sql = """SELECT geom, fid, featurecla, name, min_zoom FROM ne_110m_admin_0_boundary_lines_land WHERE min_zoom::integer <= !zoom! AND geom && !bbox!"""

[[tileset.layer.query]]
minzoom = 3
maxzoom = 4
sql = """SELECT geom, fid, featurecla, name, min_zoom FROM ne_50m_admin_0_boundary_lines_land WHERE min_zoom::integer <= !zoom! AND geom && !bbox!"""

[[tileset.layer.query]]
minzoom = 5
maxzoom = 10
sql = """SELECT geom, fid, featurecla, name, min_zoom FROM ne_10m_admin_0_boundary_lines_land WHERE min_zoom::integer <= !zoom! AND geom && !bbox!"""

It seems to work in general :tada: but unfortunately every line gets simplified to having only ~3 nodes.

grafik

Then I found the tolerance parameter, which is per default !pixel_width! / 2. However, there was no difference when I changed the 2 to 4, 16 or 100 – which appeared very strange.

I look into the codebase about the database queries and the string replacement seems to be working just fine, so this left me to question what pixel_width is. In more detail, I found the following code:

https://github.com/t-rex-tileserver/t-rex/blob/f2433f648eee4d793e076e1a7570ba7666b4b232/tile-grid/src/grid.rs#L185-L193

So pixel width has something to do with 256-pixel tile width in meters for Web Mercator.

Then, I tried to divide the pixel width with the fixed value that was multiplied to our degree values. This leads to the following setting:

tolerance = "!pixel_width! / 3507975.35 / 2"

And this seems to solve the simplification problem to reasonable country borders.

grafik

So I guess either there should either be different defaults for different projections for tolerance or the pixel size for degrees is debatable.

pka commented 2 years ago

Thanks for your investigations. Seems clear that the current tolerance default doesn't make sense for geographic coordinates. Thanks for documenting a tolerance configuration,which works better!