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
545 stars 68 forks source link

Polygon Shift: Custom Projection #301

Closed xycarto closed 1 year ago

xycarto commented 1 year ago

Hi T-Rex,

I have a curious issue. I am working with T-Rex (t_rex 0.14.3 (GDAL version 3.0.4)) generating a vector tile cache from a custom projection. The projection has a non-traditional 2x scaling factor. The resolution of the projection look like this:

resolutions = [8960.0,4480.0,2240.0,1120.0,560.0,280.0,140.0,70.0,28.0,14.0,7.0,2.8,1.4,0.7,0.28,0.14,0.07]

Here is the issue, when I run the vector tiling process, everything seems to go well; however, when I load the tile in JS and view the map, the data in the tiles "shifts" to strange places. This only happens at the location where the resolutions do an uncommon jump. In this case, where the resolution goes from 70 to 28 (or zoom 8)

This is an image of the shift (Nothing should be out over the sea):

Screenshot from 2023-03-07 21-48-20

I have a hard time getting this issue to repeat it is mostly seems to happen when I have a base data set with a very large number of vertices.

This is toml config I am using:

datasource = [
    { dbconn = "postgresql://postgres:postgres@localhost/swa", name = "dbconn", default = true },
]

[service.mvt]
viewer = true

[grid.user]
width = 4096
height = 4096
srid = 2193
units = "m"
resolutions = [
    8960.0,
    4480.0,
    2240.0,
    1120.0,
    560.0,
    280.0,
    140.0,
    70.0,
    28.0,
    14.0,
    7.0,
    2.8,
    1.4,
    0.7,
    0.28,
    0.14,
    0.07,
]
origin = "TopLeft"

[grid.user.extent]
minx = -1000000
miny = 3087000
maxx = 3327000
maxy = 10000000

[[tileset]]
name = "s2_and_s1_vectorised"
extent = [
    176.0686,
    -40.4274,
    178.5501,
    -37.5344,
]

[[tileset.layer]]
name = "s2_and_s1_vectorised"
table_name = "s2_and_s1_vectorised"
geometry_field = "geom"
geometry_type = "POLYGON"
srid = 2193
buffer_size = 1
simplify = true
query = [
    { sql = "SELECT * FROM \"s2_and_s1_vectorised\" WHERE geom && !bbox!" },
]

[cache.file]
base = "data/vector-tiles/"

[webserver]
bind = "0.0.0.0"
port = 8080

Few notes

Generating tileset 's2_and_s1_vectorised'...
Level 10: 108 / 108 [====================================================================================================================================================================================]  
free(): invalid pointer
src/vector-tiles.sh: line 36: 27576 Aborted                 (core dumped) t_rex generate --progress true --maxzoom=10 --minzoom=4 --config configs/${base}.toml

If it helps, I am generating the toml automatically using:

import geopandas as gp
import os
import sys
import toml
import tomli_w

# python3 src/build-toml.py data/vector/vt-queue/SA1-flood-data_stats.gpkg

in_file = sys.argv[1]
base = os.path.basename(in_file).split(".")[0].lower()

gp_in_file = gp.read_file(in_file)
gp_wgs = gp_in_file.to_crs(4326)

bound = gp_wgs.total_bounds
extent = [round(float(bound[0]),4), round(float(bound[1]),4), round(float(bound[2]),4), round(float(bound[3]),4)]

poly_type = gp_in_file.geom_type.head(1)[0].upper()
print(poly_type)

toml_template = """
[service.mvt]
viewer = true

[[datasource]]
dbconn = "postgresql://postgres:postgres@localhost/swa"
name = "dbconn"
default = true

[grid.user]
width = 4096
height = 4096
extent = { minx = -1000000, miny = 3087000, maxx = 3327000, maxy = 10000000 }
srid = 2193
units = "m"
resolutions = [8960.0,4480.0,2240.0,1120.0,560.0,280.0,140.0,70.0,28.0,14.0,7.0,2.8,1.4,0.7,0.28,0.14,0.07]
origin = "TopLeft"

[[tileset]]
name = "%s"
extent = %s

[[tileset.layer]]
name = "%s"
table_name = "%s"
geometry_field = "geom"
geometry_type = "%s"
srid = 2193
buffer_size = 1
simplify = true

[[tileset.layer.query]]
sql = 'SELECT * FROM "%s" WHERE geom && !bbox!'

[cache.file]
base = "data/vector-tiles/"

[webserver]
bind = "0.0.0.0"
port = 8080
""" % (base, extent, base, base, poly_type, base)

toml_parse = toml.loads(toml_template)
print(toml.dumps(toml_parse))

with open(f"configs/{base}.toml", mode="wb") as fp:
    tomli_w.dump(toml_parse, fp)
xycarto commented 1 year ago

Resolved by switching tile size to 512, 512

[grid.user]
width = 512
height = 512
srid = 2193
units = "m"
resolutions = [
    8960.0,
    4480.0,
    2240.0,
    1120.0,
    560.0,
    280.0,
    140.0,
    70.0,
    28.0,
    14.0,
    7.0,
    2.8,
    1.4,
    0.7,
    0.28,
    0.14,
    0.07,
]
origin = "TopLeft"

I'd still be curious why it fails on the larger tile size, but I think it is irrelevant at this point.

Happy if this issue is cloed

pka commented 1 year ago

Thanks for the detailed description. The error with a bigger grid tile size sounds like a possible number overflow in the grid calclulation. But the message free(): invalid pointer sounds like an error in an underlying C library. But the PostgreSQL driver is pure Rust, so this is strange. Only way to track that down would be enabling debug logging.