Visualize a layer underground/pitch a map underground
Motivation
First of all thank you for your awesome work at Mapbox! I love building with your platform!
Now, the feature request: In urban planning/smart city visualization (among other areas) it is necessary to visualize data underground. For example pipes, drainage basins or subways should be visible when displaying a city and planning for it, as else valuable information might get lost. Here, it would be great to have the option to visualize such data under and not above the ground. Or preferably even pitch the map underground.
Design
- The currently experimental z-offset of layers should extend to negative values
- If possible an easy "glassview" toggle configuration property should be available to make all layers at/above ground level transparent.
- If possible the pitch (and/or zoom) property should extend beyond zero to view the layers from 1 in detail. I am aware that this might be more difficult with the current map
Mock-Up
There is a good example for ESRI's sceneview how this could look like. Of course with the nicer Mapbox models and styling.
Help welcome
In the meantime I would be very grateful for any hints on how too implement this using the current Mapbox state!
Thank you for the very detailed request! This is definitely an interesting topic and something we consider exploring.
The line-z-offset should already allow you to set a negative value to the z-axis to render lines blow surface. Same holds true for the symbol z-offset and model-translation altitude offset, which enables you to place 2D icons and 3D models underground as well.
While we do not support a 'glassview' toggle out of the box, there are a few tools that might help you achieve the desired effect.
- You can use the line-occlusion-opacity to make underground content “shine through” the ground.
- You can use the clip layer to remove basemap content that overlaps with your underground geometries.
- On legacy and custom styles you should also be able to control the opacity and visibility of map layers to achieve the "glassview" look. While Standard Style does not support layer opacity controls for all layers, you can still toggle label and 3D content visibility.
I'd appreciate if you could try out these suggestions and get back to us with feedback!
I tried to use line-occlusion-opacity for this, but it does not work. Should'nt the lines be invisible under the 3D buildings? I am using the standard mapbox 3D style.
This is my layer:
export const chargerLine = {
type: "line",
source: "line",
id: "line-background",
paint: {
"line-occlusion-opacity": 0,
"line-color": "#00D48E",
"line-width": 6,
},
};
@kamami could you try to disable line-occlusion-opacity and just place the layer below the layer of the buildings? If you use standard style, you can set the slot of the layer to be middle.
Yes, the slot did the trick! Thanks
Thanks a lot for the quick response and all the hints @oosafff !! I tried them out, but so far I haven't been able to achieve the effect.
Testing configuration
The screenshot shows:
- setting all layers fill-color and background-color to be transparent (0.1):
if (layer.paint && layer.paint['fill-color']) {
layer.paint['fill-color'] = 'rgba(255, 255, 255, 0.1)';
}
if (layer.paint && layer.paint['background-color']) {
layer.paint['background-color'] = 'rgba(255, 255, 255, 0.1)';
}
if (layer.paint['hillshade-accent-color']) {
layer.paint['hillshade-accent-color'] = 'rgba(255, 255, 255, 0.1)';
}
if (layer.paint['hillshade-shadow-color']) {
layer.paint['hillshade-shadow-color'] = 'rgba(0, 0, 0, 0.1)';
}
if (layer.paint['hillshade-highlight-color']) {
layer.paint['hillshade-highlight-color'] = 'rgba(255, 255, 255, 0.1)';
}
- Adding a line layer to slot: "bottom" and setting line-z-offset and line-elevation-reference:
paint: {
'line-color': '#3b70d4',
'line-width': 2,
'line-elevation-reference': 'ground',
'line-z-offset': -10,
},
- setting projection to mercator as from the docs I understand that globe doesnt support z-offset:
newStyle.projection.name = 'mercator';
Feedback
From this I noticed: i. For my configuration, line-z-offset has no effect (also for positive values) - thus, the line is always rendered above the layers below slot bottom. Does line-z-offset have other dependencies that I am missing? fill-z-offset works for the same map.
ii. The 3D terrain is still fully visible, hiding the background below. Is there a way to make the 3D terrain transparent as well, that I am missing? Setting opacity on the terrain raster would be really great!
iii. Out of curiosity I tried model-translation on the 3D building model layer but it seems to have no effect neither: layer.paint['model-translation'] = [100, 100, -100]; I suppose this only works on custom models, correct?
Again thank you! If you have any further hints, I would really appreciate it!
Btw. I am using 3.7.0: ├─┬ @types/[email protected] │ └── [email protected] deduped ├── [email protected] └─┬ [email protected] └── [email protected] deduped
Edit
I managed to get the glassview toggle more or less by adding a new slot layer below the background layer and then toggle the opacity of all layers:
//add slot at the bottom
const newLayer = {
id: 'underground',
type: 'slot',
metadata: {
'mapbox:description': 'Slot below the ground',
},
};
const backgroundLayerIndex = newStyle.imports[0].data.layers.findIndex(
(layer: { type: string }) => layer.type === 'background',
);
if (backgroundLayerIndex !== -1) {
newStyle.imports[0].data.layers.splice(backgroundLayerIndex, 0, newLayer);
}
This is already nice! However, having the line-z-offset working and being able to set opacity on the terrain raster would be a great add on, as it would allow to show more accurate information