11import { draw , select } from 'maplibre/edit'
22import { removeDescBanner , renderDescBanners , showDescBanners , syncDescBanner } from 'maplibre/layers/geojson/desc_banners'
3- import { bufferLoaded , buildLineExtrusion , loadBuffer } from 'maplibre/layers/geojson/extrusion'
3+ import { buildLineExtrusion } from 'maplibre/layers/geojson/extrusion'
44import {
55 removeFeatureImageOverlay ,
66 renderImageOverlays ,
@@ -24,10 +24,10 @@ import {
2424import { highlightFeature } from 'maplibre/feature'
2525import { Layer , queryFeaturesNear } from 'maplibre/layers/layer'
2626import { frontFeature , getFeature , layers } from 'maplibre/layers/layers'
27- import { addGeoJSONSource , map , mapProperties , noValidate , removeGeoJSONSource } from 'maplibre/map'
27+ import { addGeoJSONSource , map , noValidate , removeGeoJSONSource } from 'maplibre/map'
2828import { pruneShapeImages } from 'maplibre/styles/circle_image'
2929import { prunePatternImages } from 'maplibre/styles/pattern_image'
30- import { clusterStyles , initializeClusterStyles , initializeViewStyles , styles , viewStyleNames } from 'maplibre/styles/styles'
30+ import { clusterStyles , extrusionOpacityBuckets , initializeClusterStyles , initializeViewStyles , styles , viewStyleNames } from 'maplibre/styles/styles'
3131
3232// Every layer counts, so that the render of one layer never drops the shape images of another
3333function pruneShapes ( ) {
@@ -36,13 +36,12 @@ function pruneShapes() {
3636 prunePatternImages ( features )
3737}
3838
39- // Whether a feature needs a buffered extrusion polygon: a LineString with a height set, not
40- // already rendered as a route-extras segment (which builds its own extrusion), and not hidden by 3D terrain .
39+ // Whether a feature needs an extrusion polygon: a LineString with a height set, not
40+ // already rendered as a route-extras segment (which builds its own extrusion).
4141function needsExtrusionPolygon ( feature ) {
4242 return feature . geometry ?. type === 'LineString' &&
4343 ! ! feature . properties ?. [ 'fill-extrusion-height' ] &&
44- ! feature . properties ?. [ 'show-route-extras' ] &&
45- ! mapProperties . terrain
44+ ! feature . properties ?. [ 'show-route-extras' ]
4645}
4746
4847export class GeoJSONLayer extends Layer {
@@ -76,8 +75,10 @@ export class GeoJSONLayer extends Layer {
7675 createSource ( ) {
7776 super . createSource ( )
7877 addGeoJSONSource ( this . kmMarkerSourceId , false )
79- addGeoJSONSource ( this . routeExtrasSourceId , false )
80- addGeoJSONSource ( this . extrusionSourceId , false )
78+ // Wall pieces are 0.5 m quads. Simplification below the source maxzoom drops them or
79+ // collapses them to two points, which MapLibre draws as thin vertical sticks.
80+ addGeoJSONSource ( this . routeExtrasSourceId , false , null , 0 )
81+ addGeoJSONSource ( this . extrusionSourceId , false , null , 0 )
8182 }
8283
8384 setupClickHandler ( ) {
@@ -129,6 +130,15 @@ export class GeoJSONLayer extends Layer {
129130 initializeViewStyles ( this . routeExtrasSourceId )
130131 initializeExtrasLabelStyles ( this . routeExtrasSourceId )
131132 initializeViewStyles ( this . extrusionSourceId )
133+ // Walls are built from short quads (see extrusion.js). Rounded corners and the vertical
134+ // gradient shade every quad on its own, which shows each seam as a dark band.
135+ for ( const sourceId of [ this . routeExtrasSourceId , this . extrusionSourceId ] ) {
136+ extrusionOpacityBuckets . forEach ( ( _ , i ) => {
137+ const id = `polygon-layer-extrusion-${ i + 1 } _${ sourceId } `
138+ map . setLayoutProperty ( id , 'fill-extrusion-rounded-corner-distance' , 0 , noValidate )
139+ map . setPaintProperty ( id , 'fill-extrusion-vertical-gradient' , false , noValidate )
140+ } )
141+ }
132142
133143 map . setFilter ( `line-layer_${ this . sourceId } ` , withLevelFilter ( this . mainLineFilter ) , noValidate )
134144 // Hide the outline layer for route extras - we only want the colored segments visible
@@ -240,7 +250,6 @@ export class GeoJSONLayer extends Layer {
240250 detectLevels ( )
241251
242252 const features = this . layer . geojson . features
243- this . ensureBuffer ( features )
244253
245254 renderKmMarkers ( features , this . kmMarkerSourceId )
246255 renderRouteExtras ( features , this . routeExtrasSourceId )
@@ -307,7 +316,6 @@ export class GeoJSONLayer extends Layer {
307316 const source = map . getSource ( this . sourceId )
308317 if ( ! source ) { return }
309318 source . updateData ( { remove : [ feature . id ] , add : sourceFeatures } )
310- this . ensureBuffer ( [ feature ] )
311319
312320 // Route-extras segments copy the parent's style properties (see inheritedProps) and build
313321 // their own extrusion, so ANY property edit on a route feature leaves them stale.
@@ -317,7 +325,7 @@ export class GeoJSONLayer extends Layer {
317325
318326 // Extrusion polygon lives in a separate source (only LineStrings ever have one): upsert it
319327 // for a non-route extrusion line, otherwise remove any stale polygon (height cleared,
320- // route-extras enabled, terrain on, …).
328+ // route-extras enabled, …).
321329 const extrusionSource = map . getSource ( this . extrusionSourceId )
322330 if ( extrusionSource && feature . geometry ?. type === 'LineString' ) {
323331 const polygon = needsExtrusionPolygon ( feature ) ? buildLineExtrusion ( feature ) : null
@@ -347,7 +355,6 @@ export class GeoJSONLayer extends Layer {
347355 const source = map . getSource ( this . sourceId )
348356 if ( ! source ) { return }
349357 source . updateData ( { add : [ feature ] } )
350- this . ensureBuffer ( [ feature ] )
351358
352359 if ( hasRouteExtras ( feature ) ) {
353360 renderRouteExtras ( this . layer . geojson . features , this . routeExtrasSourceId )
@@ -429,26 +436,11 @@ export class GeoJSONLayer extends Layer {
429436 }
430437 }
431438
432- // buildLineExtrusion() returns null until @turf/buffer is loaded, so the extrusions render again then
433- ensureBuffer ( features ) {
434- if ( bufferLoaded ( ) || ! features . some ( f => needsExtrusionPolygon ( f ) || hasRouteExtras ( f ) ) ) { return }
435- loadBuffer ( ) . then ( ( ) => {
436- if ( ! this . layer ?. geojson ?. features ) { return }
437- renderRouteExtras ( this . layer . geojson . features , this . routeExtrasSourceId )
438- this . renderExtrusionLines ( this . layer . geojson . features )
439- } )
440- }
441-
442439 renderExtrusionLines ( features ) {
443440 const source = map . getSource ( this . extrusionSourceId )
444441 if ( ! source ) { return }
445442
446- if ( mapProperties . terrain ) {
447- source . setData ( { type : 'FeatureCollection' , features : [ ] } )
448- return
449- }
450-
451- // LineStrings with fill-extrusion-height are buffered into polygons for MapLibre's fill-extrusion layer.
443+ // LineStrings with fill-extrusion-height are turned into polygons for MapLibre's fill-extrusion layer.
452444 // Placed in a separate non-selectable source so the polygons are never clickable.
453445 // Skipped when 'show-route-extras' renders its own extrusion.
454446 const extrusionFeatures = features
0 commit comments