Skip to content

fix: clip AffineTilesetLevel tile corners to array extent#580

Open
kylebarron wants to merge 1 commit into
mainfrom
kyle/affine-tile-corners-clip
Open

fix: clip AffineTilesetLevel tile corners to array extent#580
kylebarron wants to merge 1 commit into
mainfrom
kyle/affine-tile-corners-clip

Conversation

@kylebarron
Copy link
Copy Markdown
Member

Summary

AffineTilesetLevel.projectedTileCorners extrapolates past the array when matrixWidth*tileWidth > arrayWidth (or height equivalent). For projections whose valid domain isn't aligned with the affine — Mollweide, Sinusoidal, Equal Earth — those extrapolated points fall outside the projection's domain, proj4 maps them to the pole, and the Web Mercator clamp collapses every such corner onto a single horizontal line at ±85.05°. The bounding-volume sampler then produces a zero-height OBB, the tileMaxY > minY test in insideBounds fails (0 > 0 is false), and every tile gets culled.

Net effect: a full-world Mollweide COG (e.g. Vizzuality HFP 100) loads, fires onGeoTIFFLoad, then getTileIndices returns [] and nothing renders — not even the debug overlay.

This PR clips the tile's pixel-space rectangle to [0, arrayWidth] × [0, arrayHeight] in projectedTileCorners so every corner stays inside the data extent. Interior tiles are unaffected (their nominal corners are already inside the array). The hfp file now correctly selects tiles, traverses to finer levels, and renders. See screenshot below: debug overlay showing the two selected z=1 tiles spanning the world.

Adds a HFP 100 entry to the cog-basic example dropdown for manual verification — the data renders ~black against the dark basemap on its own (a separate render-pipeline ergonomics issue for unscaled uint16 data), but the debug overlay confirms the traversal is correct.

Test plan

  • pnpm -r test — 384 pass (+2 new edge-clipping tests in affine-tileset-level.test.ts)
  • pnpm -r typecheck — clean across all 23 projects
  • pnpm biome check — clean
  • Headless Chrome + CDP: navigate cog-basic to the HFP Mollweide entry, toggle the debug overlay — tile boundaries appear at x=0 y=0 z=1 and x=1 y=0 z=1 (pre-fix: nothing)
  • Spot-check a non-edge-case example (e.g. NLCD, NAIP) still renders normally

Written by Claude on behalf of @kylebarron

🤖 Generated with Claude Code

Tiles at the right/bottom edge of a level's matrix can nominally extend
past the array when matrixWidth*tileWidth > arrayWidth (likewise for
height). The affine still extrapolates past the data, but for
projections whose valid domain isn't a rectangle aligned with the
affine — Mollweide, Sinusoidal, Equal Earth — those extrapolated
points fall outside the projection's domain and proj4 collapses them
onto the pole. The downstream Web Mercator clamp then sends every such
corner to one horizontal line at ±85.05°, producing a degenerate
bounding volume that the `tileMaxY > minY` check in `insideBounds`
rejects (0 > 0 is false). Every tile gets culled and nothing renders.

Clip the tile's pixel-space rectangle to [0, arrayWidth]×[0, arrayHeight]
before applying the affine so every corner stays inside the data
extent. Interior tiles are unaffected.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added the fix label May 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant