#37: raise the MVT buffer from 64 to 256 to fix the z19 line-layer artifact #59
No reviewers
Labels
No labels
claude-wip
map-report
map:is
map:se
needs-review
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
art/ismap!59
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "night/issue-37-mvt-buffer"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #37
Issue #37 — rendering issue: MVT buffer too small for stroked line layers at z19
What the issue reported
At z17–18 a
coverpolygon near 52.23002/20.91506 (Warsaw) rendered badly; thereporter suspected the MVT buffer was too small. The maintainer later overruled
the fill-only conclusion with screenshots on the issue: line layers at z19
show the classic buffer-cut artifact — road casing missing on one side, and a
road segment ending mid-road with a rounded line-cap — at Powstańców Śląskich
× Czulhowska (Warsaw, PL) and at Hägerstensvägen (Stockholm, SE).
What was wrong
The buffer was 64 units on a 4096-extent tile (= 1/64 of a tile = 4 px at
z19). A road crossing a tile edge gets its tile copy clipped by
ST_AsMVTGeomat the buffer line (x/y = 4160 = 4096+64); MapLibre drawsline-cap: roundat the cut. The road casing is wider than the 4px bleed, sothe cut is visible: casing missing on one side, rounded cap mid-road. At lower
zooms the road width ramp makes the cut less noticeable — which is why the
reporter saw it worst at z19 and the earlier cover-fill A/B (opaque fills hide
the clip by construction) measured 0-pixel diffs.
The fix
Raise the MVT buffer and the matching
marginenvelope from 64 to 256(= 1/16 of the tile = 16 px at z19) in:
importer/shared.go— shared layers (margin => (256.0/4096),buffer => 256)importer/layer.go— per-country layers, both themvtFuncand themvtFuncUnionAllbenchmark variantdocs/geo-primer.md— the buffer/margin explanation now documents the 256value and why 64 was wrong
How it was verified (A/B, the maintainer's exact request)
Rendered the same cameras at z19 with b64 and b256 via
scripts/cdp-map-check.mjs(real Chrome over CDP, no virtual time), 2 rendersper buffer, and pixel-diffed:
The b64-vs-b256 diff is concentrated at tile seams (57% of pixels within 30 px
of a tile edge), and at b64 the diff pixels show the background cover colour
where b256 draws road — i.e. the road copy was missing past the seam. Decoded
tiles confirm the geometry clip moved from 4160 to 4352. Visually: b64 shows
the casing break + rounded cap; b256 is clean. Screenshots are attached to the
verification comment on #37 (comment id 422).
⚠️ One methodology trap hit during the run: the first A/B renders were
byte-identical between b64 and b256 because a stale headless-Chrome
instance from an earlier session was still holding CDP port 9333 and serving
cached b64 tiles. Kill stray Chrome before re-rendering.
Tile-size cost at z19 (b64 → b256)
Hex-encoded
zxy_mapbytes, five tiles around the Warsaw intersection:The
roadslayer alone: 296→357 (+21%), 307→335 (+9%), 136→141 (+4%),146→147 (+0.7%), 309→365 (+18%). The cost is modest and per-layer; opaque
fill layers render identically at either buffer, so only stroked layers pay.
Deployment without a data reimport
ensureParentSQL()(importer/main.go) regenerates all shared-layerzxy_map_*function bodies via CREATE OR REPLACE FUNCTION on every importer invocation, so
one importer run redeploys the new buffer live — no reimport, no cascade, no
data touched. The live DB is currently running b256.
Left undone / notes
zxy_*functions on layer import;a full reimport is not needed for the buffer change.
.hermes/skills/.../mvt-buffer-investigation.mdis superseded by this A/B(that run only tested opaque cover fills).