Skip to content

Commit 0027fb2

Browse files
committed
fix(raster): render restored rasters and keep globe view on the WASM engine
Two follow-ups to making cog-tiler-wasm the default engine. Opening a saved project in a running app left the raster invisible. The engine deferred its first layer-add until the style could accept it, but waited on MapLibre's `load` event, which fires exactly once per map -- so an engine whose first apply landed after the map had loaded (while the project's style swap was in flight) attached a handler that never fired and never added its layers at all. The layer sat in the panel with correct bounds, bands, and symbology, rendering nothing. Fixed upstream in maplibre-gl-raster v0.14.1 (opengeos/maplibre-gl-raster#57), which waits on `styledata` instead; this bumps to it. Adding a raster no longer drops the map out of globe view. The mercator switch exists because deck.gl's COG tile traversal cannot draw on the globe -- which is true of the deck.gl engine only. The WASM and TiTiler engines render through a native MapLibre raster layer that draws on the globe like any other raster source, so the switch is now gated on the engine. It still fires on `rasterchange`, which is what setEngine emits, so switching back to the GPU engine forces mercator for the rasters already on the map rather than only the next one added.
1 parent 13b5a3a commit 0027fb2

6 files changed

Lines changed: 37 additions & 9 deletions

File tree

apps/geolibre-desktop/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@
7676
"maplibre-gl-nasa-earthdata": "^0.1.4",
7777
"maplibre-gl-national-map": "^0.1.1",
7878
"maplibre-gl-planetary-computer": "^0.4.0",
79-
"maplibre-gl-raster": "^0.14.0",
79+
"maplibre-gl-raster": "^0.14.1",
8080
"maplibre-gl-splat": "^0.2.8",
8181
"maplibre-gl-streetview": "^0.7.0",
8282
"maplibre-gl-swipe": "^0.11.0",

package-lock.json

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/plugins/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252
"maplibre-gl-national-map": "^0.1.1",
5353
"maplibre-gl-overture-maps": "^0.3.1",
5454
"maplibre-gl-planetary-computer": "^0.4.0",
55-
"maplibre-gl-raster": "^0.14.0",
55+
"maplibre-gl-raster": "^0.14.1",
5656
"maplibre-gl-splat": "^0.2.8",
5757
"maplibre-gl-streetview": "^0.7.0",
5858
"maplibre-gl-swipe": "^0.11.0",

packages/plugins/src/plugins/maplibre-raster.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import {
1616
import {
1717
isRasterControlStoreLayer,
1818
rememberLocalRasterPath,
19+
rendersNativeMapLibreLayer,
1920
resetRasterStoreSyncSuspension,
2021
runWithRasterStoreSyncSuspended,
2122
savedRasterState,
@@ -729,7 +730,20 @@ function createRasterControl(RasterControlClass: RasterControlConstructor): Rast
729730
// deck.gl's COG tile traversal does not support MapLibre's globe view
730731
// ("TODO: implement getBoundingVolume in Globe view"), so adding a raster
731732
// switches the map to mercator, like the other deck.gl-backed plugins.
732-
control.on("rasteradd", () => ensureMercatorProjection(control.getMap()));
733+
// Only the deck.gl engine needs this: the WASM and TiTiler engines render
734+
// through a native MapLibre raster layer, which draws on the globe just like
735+
// any other raster source, so forcing mercator there would drop the user out
736+
// of globe view for no reason.
737+
// Also on rasterchange, which is what setEngine emits: switching the panel
738+
// from the WASM engine back to the deck.gl one has to force mercator for the
739+
// rasters already on the map, not just for the next one added.
740+
for (const event of ["rasteradd", "rasterchange"] as const) {
741+
control.on(event, () => {
742+
if (rendersNativeMapLibreLayer(control.getEngine())) return;
743+
if (control.getRasters().length === 0) return;
744+
ensureMercatorProjection(control.getMap());
745+
});
746+
}
733747
for (const event of ["rasteradd", "rasterchange", "rasterremove"] as const) {
734748
control.on(event, () => syncRasterLayersToStoreForRuntime(control));
735749
}

packages/plugins/src/plugins/raster-layer-sync.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ export type RasterSyncOptions = {
6666
* where the deck.gl overlay is a separate stacked canvas with no style layer at
6767
* all (issue #1463).
6868
*/
69-
function rendersNativeMapLibreLayer(engine: RenderEngine): boolean {
69+
export function rendersNativeMapLibreLayer(engine: RenderEngine): boolean {
7070
return engine === "cog-tiler-wasm" || engine === "titiler";
7171
}
7272

tests/raster-layer-sync.test.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
localRasterPath,
99
rememberLocalRasterPath,
1010
removeRasterStoreLayers,
11+
rendersNativeMapLibreLayer,
1112
runWithRasterStoreSyncSuspended,
1213
savedRasterState,
1314
syncRasterLayersToStore,
@@ -78,6 +79,19 @@ function otherStoreLayer(id = "unrelated"): GeoLibreLayer {
7879
};
7980
}
8081

82+
// The projection rule in maplibre-raster.ts keys off this: only the deck.gl
83+
// engine cannot draw on the globe, so only it forces the map to mercator.
84+
describe("rendersNativeMapLibreLayer", () => {
85+
it("is true for the engines backed by a real MapLibre raster layer", () => {
86+
assert.equal(rendersNativeMapLibreLayer("cog-tiler-wasm"), true);
87+
assert.equal(rendersNativeMapLibreLayer("titiler"), true);
88+
});
89+
90+
it("is false for the deck.gl engine", () => {
91+
assert.equal(rendersNativeMapLibreLayer("maplibre-gl-raster"), false);
92+
});
93+
});
94+
8195
describe("createRasterStoreLayer", () => {
8296
it("mirrors a URL raster as an external custom cog layer", () => {
8397
const layer = createRasterStoreLayer(

0 commit comments

Comments
 (0)