feat: Globe view, antimeridian, and polar projection support#266
feat: Globe view, antimeridian, and polar projection support#266espg wants to merge 9 commits intodevelopmentseed:mainfrom
Conversation
Expand __TEST_EXPORTS to expose helper functions (getOverlappingChildRange, getMetersPerPixel, rescaleEPSG3857ToCommonSpace, sampleReferencePointsInEPSG3857) and add 21 tests covering: - computeProjectedTileBounds for WebMercatorQuad and UTM31 - rescaleEPSG3857ToCommonSpace coordinate mapping and clamping - sampleReferencePointsInEPSG3857 interpolation - getOverlappingChildRange parent-child tile relationships - getMetersPerPixel zoom/latitude behavior - RasterTileNode.insideBounds AABB overlap logic - RasterTileNode.getBoundingVolume OBB computation (Mercator path) - RasterTileNode.children quadtree traversal Establishes regression baseline before globe view changes.
Remove the assert(false, "TODO") blocker in getBoundingVolume() and implement full globe view support in the tile traversal code: - Thread projectTo4326 through TileMatrixSetTileset → getTileIndices() → RasterTileNode (alongside existing projectTo3857) - Add _getGlobeBoundingVolume() which samples reference points in WGS84 and projects them into globe common space via viewport.projectPosition - Add sampleReferencePointsInWgs84() helper (parallel to the existing sampleReferencePointsInEPSG3857) - Return centerLatitude from getBoundingVolume() so LOD computation works in both Mercator and Globe views without calling worldToLngLat() - Handle globe-mode bounds conversion in getTileIndices() by projecting WGS84 bounds corners through the globe project function instead of lngLatToWorld() - Remove unused assert import Closes developmentseed#82
Detect when a tile's output positions span the ±180° meridian and normalize longitudes to a continuous range (e.g., [170, 190] instead of [170, -170]). This prevents mesh triangles from spanning 340° of longitude and ensures correct GPU-side interpolation for tiles near the date line.
Detect tiles containing or near a geographic pole (|lat| > 75° with antimeridian crossing). Add a maxTriangles safety cap to run() to prevent infinite refinement near poles, where the extreme longitude variation can require many more triangles to converge. The existing antimeridian normalization handles the longitude wrapping for polar tiles — the mesh refines around the remaining discontinuity. deck.gl's GlobeView renders the resulting mesh correctly since projectPosition handles arbitrary (lng, lat) values.
Provides a minimal example using deck.gl's GlobeView with COGLayer for visualizing COG imagery on a 3D globe. Includes a dark background sphere, debug mesh controls, and commented URLs for both mid-latitude and polar datasets.
|
Thanks for the PR! It's really exciting! Each of these issues is an important thing to resolve and fix. But given the architectural importance of these three features, I think we really need this as three separate PRs to be able to adequately review it. Seems like Globe view, antimeridian, and polar projection support should be quite separable features? |
kylebarron
left a comment
There was a problem hiding this comment.
Just one comment from an initial read through here.
Let's tackle just the globe view first in a new PR. I think globe view should be easier and more straightforward than the others.
| // Register WebGL adapter — required when DeckGL creates its own context | ||
| // (unlike MapboxOverlay which reuses MaplibreGL's existing context) | ||
| luma.registerAdapters([webgl2Adapter]); |
There was a problem hiding this comment.
I've never seen this before; this isn't required for a standard DeckGL app
There was a problem hiding this comment.
Oops, thought this was needed to get a proper context map background (i.e., coastlines, country borders)-- looks like another change in the same commit fixed that issue and we can excise this.
This is in response to the discussion in this issue , about the possibility of defaulting to a global viewer in the source.coop stac-map viewer.
Summary
projectTo4326through the tileset and computing bounding volumes in 3D globe common space viaviewport.projectPositionRasterReprojector— when a tile's WGS84 longitudes span >180°, normalize them to a continuous range (e.g. [170, 190] instead of [170, -170]) so mesh triangles don't wrap the wrong way around the globemaxTrianglessafety cap onrun()to prevent infinite refinement near polesglobe-viewexample usingGlobeView+COGLayerCloses #82, closes #171, closes #172
Commits
_getGlobeBoundingVolume(),sampleReferencePointsInWgs84(), globe-mode bounds conversion ingetTileIndices(), LOD fix usingcenterLatitudeinstead of Mercator-specificworldToLngLat()maxTrianglesparameter onrun()to cap refinementGlobeView+COGLayerexample with debug controlsTest plan
pnpm testindeck.gl-rasterandraster-reproject)globe-viewexample with NZ imagery URL — verify tiles render on the globecog-basicexample — verify no regression in Mercator rendering