Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 23 additions & 4 deletions packages/Main/src/Converter/Feature2Mesh.js
Original file line number Diff line number Diff line change
Expand Up @@ -606,6 +606,7 @@ function updateExtrudedPolygonBuffers(featureMesh, buffers, id) {
style.setContext(context);

const { vertices, colors, batchIds, indices } = buffers;
const { levelled_roofs } = style.fill;

// geometry range
const geometry = context.geometry;
Expand All @@ -620,6 +621,15 @@ function updateExtrudedPolygonBuffers(featureMesh, buffers, id) {
const startTop = start + numVertices / 3;
const endIn = startIn + count * 3;

let minAltitude = Infinity;
if (levelled_roofs) {
for (let i = startIn; i < endIn; i += 3) {
if (!vertices) { continue; }
context.setLocalCoordinatesFromArray(feature.vertices, i);
minAltitude = Math.min(minAltitude, style.fill.base_altitude);
}
}

for (let i = startIn; i < endIn; i += 3) {
const t = numVertices + i;

Expand All @@ -641,9 +651,15 @@ function updateExtrudedPolygonBuffers(featureMesh, buffers, id) {
.toArray(vertices, i);

// populate top geometry buffers
topCoord.copy(up)
.multiplyScalar(extrusion_height).add(baseCoord)
.toArray(vertices, t);
if (levelled_roofs) {
topCoord.copy(up)
.multiplyScalar(minAltitude - worldCoord.z + extrusion_height).add(localCoord)
.toArray(vertices, t);
} else {
topCoord.copy(up)
.multiplyScalar(extrusion_height).add(baseCoord)
.toArray(vertices, t);
}
}

if (batchIds) {
Expand Down Expand Up @@ -874,7 +890,10 @@ export default {
style.addEventListener('style-property-changed', (event) => {
if (event.parameter === 'color') {
this._styleColorVersion++;
} else if (event.parameter === 'extrusion_height' || event.parameter === 'base_altitude') {
} else if (
event.parameter === 'extrusion_height' ||
event.parameter === 'base_altitude' ||
event.parameter === 'levelled_roofs') {
this._stylePositionVersion++;
}
});
Expand Down
19 changes: 19 additions & 0 deletions packages/Main/src/Core/Style.js
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,10 @@ function _addIcon(icon, domElement, opt) {
* then the altitude value is set to 0.
* @property {number | Function} [fill.extrusion_height] - Only for {@link GeometryLayer} and if user sets it.
* If defined, polygons will be extruded by the specified amount.
* @property {boolean} [fill.levelled_roofs=false] - Only for {@link GeometryLayer} with extrusion.
* When true, all roof vertices are placed at a uniform height equal to the polygon's minimum
* base altitude plus the extrusion height, producing flat-topped extrusions even over uneven
* terrain. Cannot be set to a function.
* @property {object} stroke - Lines and polygons edges.
* @property {string | Function | THREE.Color} stroke.color The color of the line. Can be any [valid
* color string](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value).
Expand Down Expand Up @@ -534,6 +538,21 @@ class Style extends EventDispatcher {
defineStyleProperty(this, 'fill', 'pattern', params.pattern);
defineStyleProperty(this, 'fill', 'base_altitude', params.base_altitude, baseAltitudeDefault);

// levelled_roofs is a raw boolean. No function evaluation or data-source fallback
this._levelledRoofs = params.levelled_roofs ?? false;
Object.defineProperty(this.fill, 'levelled_roofs', {
enumerable: true,
get: () => this._levelledRoofs,
set: (v) => {
this._levelledRoofs = Boolean(v);
this.dispatchEvent({
type: 'style-property-changed',
style: this,
parameter: 'levelled_roofs',
});
},
});

// define a special case for extrusion_height
// to be able to know if user set it or not without calling the getter
this._extrusionHeight = params.extrusion_height;
Expand Down
Loading