3D-BETA: VISUALISIERUNG VON LOD2-GEBÄUDEN

Beschreibung

Die nachfolgenden Anwendungen basieren auf dem 3D-Datenbestand "LoD2-DE" der ZSHH. Für die Visualisierung werden die Daten der Gebäude von CityGML nach 3D-Tiles überführt und mit MaplibreGL JS bzw. CesiumJS dargestellt. Beide Bibliotheken nutzen WebGL um die Berechnung der 3D-Modelle mithilfe der Hardware zu beschleunigen, wodurch die Visualisierung direkt im Browser erfolgen kann. Es ist keine Installation und keine Registrierung notwendig.
Die Beispielanwendungen visualisieren deutschlandweit die LoD2-Gebäude. Durch einen Klick mit der linken Maustaste auf die Gebäude können diese ausgewählt und zusätzliche Features abgerufen werden. Aktuell erscheinen nur die GML-ID und die Gebäudefunktion. Es können aber beliebige Informationen mit den Gebäuden verknüpft und dargestellt werden. Dieses ist aber nicht nachträglich möglich, sondern muss schon beim Erzeugen der 3D-Tiles beachtet werden.
MapLibre GL JS
Cesium JS
MaplibreGL JS ist eine Open-Source Weiterentwicklung von MapboxGL JS, da Mapbox mit der Veröffentlichung der Version 2.0 zu einer proprietären Lizenz gewechselt ist.
Im Smart-Mapping Projekt wird MaplibreGL JS für die Kartendarstellung im Web-Browser und für weitere Funktionen genutzt. Darauf aufbauend erfolgt die Visualisierung der Gebäude über eine externe Javascript-Datei mittels ThreeJS.
 <html lang="en">
  <head>
   <meta charset="utf-8">
   <title> LoD2 Gebaeude </title>
   <!-- Laden der benötigen Javascript und CSS-Datei von Maplibre -->
   <script src="https://unpkg.com/maplibre-gl@2.4.0/dist/maplibre-gl.js"></script>
   <link href="https://unpkg.com/maplibre-gl@2.4.0/dist/maplibre-gl.css" rel="stylesheet">
   <script src="https://web3d.basemap.de/maplibre/Mapbox3DTiles.js"></script>

   <style>
       body { margin:0; padding:0; }
       #map { position:absolute; top:0; bottom:0; width:100%; }
       .container {
          position: absolute;
          left: 5px;
          padding: 5px;
          border: 1px solid gray;
          border-radius: 2px;
          background-color: black;
          color: white;
          min-width: 200px;
       }
       #controls { position:absolute; top:0; left:0; }
       #info {
           top:120px;
           min-height: 75px;
       }
   </style>
 </head>

 <body>
    <div id="map"></div>
    <div id="info" class="container"></div>
    <script>
        <!-- Initialisiern des Viewer mit der definierten Hintergrundkarte --> 
        var map = new maplibregl.Map({
          container: 'map',
          style:'https://sgx.geodatenzentrum.de/gdz_basemapde_vektor/styles/bm_web_col.json',
          center: [6.959092,50.941485],
          zoom: 16.3,
          bearing: -20,
          pitch: 40,
          hash: true
        });

        map.addControl(new maplibregl.NavigationControl(),'top-left');

        <!-- Holen der Gebaeude und hinzufuegen als eigenen Layer--> 
        map.on('style.load', function() {
          let lod2_layer = new Mapbox3DTiles.Mapbox3DTilesLayer( {
              id: 'lod2_building',
              url: 'https://web3d.basemap.de/maplibre/buildings-floor/red_root.json',
              colorWall: '#c2c2c2',
              colorRoof: '#ff5c4d',
              colorBridge: '#999999'
          } );
          map.addLayer(lod2_layer, 'Gebaeude3D_nicht_oeffentlich');
          map.setLayoutProperty('Gebaeude3D_oeffentlich', 'visibility', 'none');
          map.setLayoutProperty('Gebaeude3D_nicht_oeffentlich', 'visibility', 'none');
          map.setLayoutProperty('Hauskoordinate', 'visibility', 'none');
        });

        <!-- Gebaeude erst ab Zoomstufe 16 darstellen, fuer eine schnellere Visualisierung--> 
        map.on('zoom', () => {
          var zoom=map.getZoom();
          if (zoom<15) {
              map.setLayoutProperty('lod2_building', 'visibility', 'none');
          }          
          else {
              map.setLayoutProperty('lod2_building', 'visibility', 'visible');
          }
        });

        <!-- Anzeigen der Gebaeude-Features in der Info-Box --> 
        map.on('click', (event)=>{
                let infoElement = document.querySelector('#info');
                let features = map.queryRenderedFeatures(event.point, {outline: true, outlineColor: 0xff0000});
                if (features.length ) {
                    console.log(features)
                    infoElement.innerHTML =
                        features.filter(feature=> feature.layer.id == 'lod2_building')
                                 .map(feature=>`Layer: ${feature.layer.id}<br>
                                                          ${Object.entries(feature.properties)
                                                          .map(entry=>`<b>${entry[0]}:</b>${entry[1]}`)
                                                          .join('<br>\n')}
                        `).join('<hr>\n')
                } else {
                    infoElement.innerHTML = "Klicke auf ein Gebaeude";
                }
            })
    </script>
 </body>
</html>
CesiumJS ist eine JavaScript Bibliothek zum Erstellen von 3D-Globen und 2D-Karten im Browser, welche als Open-Source Software zur Verfügung steht. Es wird aber auch ein kostenpflichtiger Dienst angeboten, um u.a. spezifische Hintergrundkarten zu nutzen. In dem folgenden Beispiel werden nur kostenfreie Dienste verwendet.
<html lang="en">
    <head>
     <meta charset="utf-8">
     <title> LoD2 Gebaeude </title>
     <!-- Laden der benötigen Javascript und CSS-Datei von Cesium -->
     <script script src="https://cesium.com/downloads/cesiumjs/releases/1.93/Build/Cesium/Cesium.js"></script>
     <link href="https://cesium.com/downloads/cesiumjs/releases/1.93/Build/Cesium/Widgets/widgets.css" rel="stylesheet">
     <style>
         html, body, #cesiumContainer {
             width: 100%;
            height: 100%;
            margin: 0;
            padding: 0;
            overflow: hidden;
         }
     </style>
   </head>
  
   <body>
      <div id="cesiumContainer"></div>
      <script>
          <!-- optional: Cesium.Ion.defaultAccessToken = 'XXXX'; -->
  
          <!-- Hintergrundkarte für die Gebiete außerhalb von Deutschland--> 
          var osm= new Cesium.OpenStreetMapImageryProvider({
               url : '//a.tile.openstreetmap.org/',
               credit: new Cesium.Credit("\u003ca href=\"https://www.openstreetmap.org/copyright\""+
                                           "target=\"_blank\"\u003e\u0026copy; OpenStreetMap contributors\u003c/a\u003e", true)
           });
  
          <!-- Initialisiern des Cesium-Viewer--> 
          var viewer = new Cesium.Viewer('cesiumContainer',{ 
              imageryProvider : osm,
              shadows: false, 
              geocoder: false,       
              baseLayerPicker: false
          });
  
          <!-- Hintergrundkarte festlegen - WMS der SmartMapping Karte. Leider unterstützt Cesium keine Vector-Tiles.-->
          const provider = new Cesium.WebMapServiceImageryProvider({
          url : 'https://sgx.geodatenzentrum.de/wms_basemapde?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetCapabilities',
          layers: "de_basemapde_web_raster_farbe",
              parameters: {
                transparent: true,
                format: "image/png",
              }
          });
          viewer.imageryLayers.addImageryProvider(provider);
  
          <!-- 3D-Tileset ergaenzen, welches die LoD2-Gebaeude von der Smart-Mapping Seite laedt -->
          var tileset = viewer.scene.primitives.add(new Cesium.Cesium3DTileset({  
              url : 'https://web3d.basemap.de/cesium/buildings-floor/root.json'
          }));
  
          <!-- Die definierten Flächen können individuell eingefärbt werden.--> 
          var cityStyle = new Cesium.Cesium3DTileStyle({
            color : {
                conditions : [
                   ["${surface} === 'wall'", "color('#f2f2f2')"],
                   ["${surface} === 'roof'", "color('#ff5c4d')"],
                   ["${surface} === 'bridge'", "color('#999999')"]
                ]
            },
         });
         tileset.style = cityStyle
  
          <!-- Kamera auf uebergebenen Punkt zentrieren in einer bestimmten Hoehe-->
          viewer.camera.flyTo({destination:Cesium.Cartesian3.fromDegrees(6.958215,50.932767, 1500.0), 
                               orientation:{ 
                                    heading: Cesium.Math.toRadians(0.0), 
                                    pitch : Cesium.Math.toRadians(-50.0), 
                                    roll : 0.0}
                              });
      </script>
   </body>
  </html>  

Lizenz- und Nutzungsbedingungen

Es gelten folgende Lizenz- und Nutzungsbedingungen:
PDF Datei