Interleaving Data and Basemap Layers #442
-
One of the downsides of most, if not all, Python-based geospatial visualization libraries is that it is impossible to insert one or more data layers into the basemap such that place names are on top of the data layers. This is critical in my view for maintaining geospatial context. Is it possible in lonboard to perform this interleaving? I sure hope so! Scanning through the documentation, it is not clear to me how this would be done. Rather it seems like all data layers are stacked on top of the basemap, forcing one to rely on opacity to maintain some level of geospatial context. |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 10 replies
-
It's not possible today, though it could be an option in the future. It depends on some architectural decisions that haven't been set in stone yet. The following is a braindump on the options here: Most JS mapping libraries focus primarily either on the basemap or on the data visualization. Mapbox, Maplibre, Google Maps JS, Leaflet, OpenLayers... I'd say that all of these have a primary focus on the basemap. Sure, it's possible to render small amounts of data or tiled layers in these tools, but they don't aim for performant large-scale data visualization. Deck.gl is the opposite; it focuses exclusively on the data visualization but doesn't attempt to render a basemap at all. The default approach is to render Maplibre on the bottom with Deck above it, using two separate WebGL contexts. This suffers from the problem that the entire basemap is hidden behind whatever Deck renders. I'd say there are three main options to solve this, outlined below Render Deck and Maplibre into the same WebGL contextMapbox/Maplibre expose a "custom style layer" where a user can write WebGL that gets added to the same context as Maplibre is already using. Deck.gl implements this with MapboxOverlay, so you can render some deck layers in the same context as Maplibre. However this suffers from having "two cooks in the kitchen", where each tries to render in the same canvas but neither is truly aware of the other. So for example in this demo you can see poor polygon rendering when panning as the buildings drawn by Mapbox and the radius drawn by Deck z-fight. Another downside here is that Maplibre needs to be the parent and that Deck needs to be the child. This means that Deck is forced into all of Maplibre's constructs. It can only support Web Mercator. It can't use WebGPU. Deck can't manage view state itself. More discussion in #437. Render multiple copies of MaplibreAnother option, which I believe kepler.gl uses, is to render a Maplibre sandwich, where you render Maplibre above and below Deck: maplibre - deck - maplibre. So you render most of the basemap below the Deck context and the text/label layers above the deck context. This is pretty resource intensive because now you have three WebGL/WebGPU contexts! Additionally you always have to keep all three map views in sync. This is less tied to Maplibre because deck is drawing into its own canvas, so you won't get z-fighting like with MapboxOverlay. But it still can't use alternate projections. Additionally, this requires intricate knowledge of the Maplibre style being used for the basemap because you have to know which layer ids to render in the lower basemap and which in the upper basemap. Render some basemap context in deckA third option is to render some basemap context in deck.gl. Deck.gl has a TileLayer and an MVTLayer, which can render things like text as part of the Deck canvas. This would also be necessary if/when we try to support alternate projections, as we couldn't use Maplibre for alternate projections. But this has the downside of having to re-implement basemap properties in deck.gl, which may not be trivial. But if it's just light basemap context like admin boundaries and text labels, maybe that's a good approach. Overall, interleaving data with the basemap is a really hard problem, which is why not many tools have tried to solve it. |
Beta Was this translation helpful? Give feedback.
It's not possible today, though it could be an option in the future. It depends on some architectural decisions that haven't been set in stone yet. The following is a braindump on the options here:
Most JS mapping libraries focus primarily either on the basemap or on the data visualization. Mapbox, Maplibre, Google Maps JS, Leaflet, OpenLayers... I'd say that all of these have a primary focus on the basemap. Sure, it's possible to render small amounts of data or tiled layers in these tools, but they don't aim for performant large-scale data visualization. Deck.gl is the opposite; it focuses exclusively on the data visualization but doesn't attempt to render a basemap at all.
The default a…