diff --git a/static/css/globe.css b/static/css/globe.css
index b260a09..d111c1c 100644
--- a/static/css/globe.css
+++ b/static/css/globe.css
@@ -795,6 +795,7 @@ html, body { height: 100%; overflow: hidden; background: var(--bg-primary); colo
.dot-nightlights { background: #ffd740; box-shadow: 0 0 4px rgba(255,215,64,0.4); }
.dot-celltowers { background: #e040fb; }
.dot-firms { background: #ff4400; box-shadow: 0 0 4px rgba(255,68,0,0.4); }
+.dot-buildings { background: #88aacc; box-shadow: 0 0 4px rgba(136,170,204,0.4); }
.geoint-btn-row {
display: flex;
diff --git a/static/index.html b/static/index.html
index b4a9a10..0032db3 100644
--- a/static/index.html
+++ b/static/index.html
@@ -186,7 +186,7 @@
+
@@ -337,6 +338,7 @@
+
diff --git a/static/js/app.js b/static/js/app.js
index 2a9bd8f..0d482fe 100644
--- a/static/js/app.js
+++ b/static/js/app.js
@@ -185,6 +185,7 @@ const Globe = {
'layer-nightlights': function(on) { on ? NightlightsLayer.start(Globe.viewer) : NightlightsLayer.stop(); },
'layer-celltowers': function(on) { on ? CelltowersLayer.start(Globe.viewer) : CelltowersLayer.stop(); },
'layer-iss': function(on) { on ? ISSLayer.start(Globe.viewer) : ISSLayer.stop(); },
+ 'layer-buildings': function(on) { on ? BuildingsLayer.start(Globe.viewer) : BuildingsLayer.stop(); },
'layer-disasters': function(on) { on ? DisastersLayer.start(Globe.viewer) : DisastersLayer.stop(); },
'layer-weather': function(on) { on ? WeatherLayer.start(Globe.viewer) : WeatherLayer.stop(); },
'layer-firms': function(on) { on ? FirmsLayer.start(Globe.viewer) : FirmsLayer.stop(); },
diff --git a/static/js/layers/buildings.js b/static/js/layers/buildings.js
new file mode 100644
index 0000000..64f7c7f
--- /dev/null
+++ b/static/js/layers/buildings.js
@@ -0,0 +1,36 @@
+/**
+ * 3D-Gebaeude-Layer: OpenStreetMap Buildings via Cesium Ion.
+ * Zeigt weltweite 3D-Gebaeude mit Hoehen aus OSM-Daten.
+ */
+const BuildingsLayer = {
+ _viewer: null,
+ _tileset: null,
+
+ start: function(viewer) {
+ if (this._tileset) return;
+ this._viewer = viewer;
+ var self = this;
+ Cesium.createOsmBuildingsAsync().then(function(tileset) {
+ if (!self._viewer) return;
+ self._tileset = tileset;
+ self._tileset.style = new Cesium.Cesium3DTileStyle({
+ color: {
+ conditions: [
+ ["${feature['building']} === 'military'", "color('#ff2222', 0.7)"],
+ ["${feature['building']} === 'industrial'", "color('#ff8800', 0.6)"],
+ ["${feature['building']} === 'government' || ${feature['building']} === 'public'", "color('#4488ff', 0.6)"],
+ ["true", "color('#88aacc', 0.45)"],
+ ],
+ },
+ });
+ self._viewer.scene.primitives.add(self._tileset);
+ });
+ },
+
+ stop: function() {
+ if (this._tileset && this._viewer) {
+ this._viewer.scene.primitives.remove(this._tileset);
+ this._tileset = null;
+ }
+ },
+};