Lodapi mit CesiumJS
CesiumJS ist der Mainstream-3D-Globe-Renderer für Web. Lodapi exponiert alle Buildings als 3D-Tiles-1.1-Tilesets, die Cesium nativ konsumieren kann. Das DGM1-Terrain ist ebenfalls als 3D-Tiles-Mesh verfügbar (Phase 2 beta).
Minimal-Setup
<!doctype html>
<html>
<head>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/cesium@1.130/Build/Cesium/Widgets/widgets.css">
<style>html, body, #c { width: 100%; height: 100%; margin: 0; }</style>
</head>
<body>
<div id="c"></div>
<script type="module">
import * as Cesium from "https://cdn.jsdelivr.net/npm/cesium@1.130/Build/Cesium/index.js";
// Ohne Ion-Key: ein leerer Standard-Imagery-Layer + Cesium-Default-Terrain.
const viewer = new Cesium.Viewer("c", {
baseLayerPicker: false,
geocoder: false,
timeline: false,
animation: false,
});
// 1. Lodapi-Tilesets in der Frankfurter Innenstadt holen.
const bbox = "8.65,50.10,8.70,50.12";
const r = await fetch(`https://api.lodapi.de/v1/tilesets?bbox=${bbox}`);
const { tilesets } = await r.json();
// 2. Tilesets in den Cesium-Viewer hängen.
for (const t of tilesets) {
const ts = await Cesium.Cesium3DTileset.fromUrl(t.tileset_url);
viewer.scene.primitives.add(ts);
}
// 3. Kamera auf die Tilesets fliegen.
if (tilesets.length > 0) {
viewer.zoomTo(viewer.scene.primitives.get(0));
}
</script>
</body>
</html>
Speichere als index.html, öffne in einem Browser. Du hast LoD2-Frankfurt in einem laufenden Cesium-Viewer.
Terrain dazu
// Terrain-Mesh-Tilesets sind separate 3D-Tilesets, KEIN Cesium-Terrain-Provider.
// Building-Z ist absolut aus dem CityGML — beide Layer liegen ohne Provider-Magic
// koordinaten-korrekt übereinander.
const r2 = await fetch("https://api.lodapi.de/v1/terrain-mesh/datasets");
const { datasets } = await r2.json();
for (const t of datasets) {
const ts = await Cesium.Cesium3DTileset.fromUrl(t.tileset_url);
viewer.scene.primitives.add(ts);
}
Attribution einbinden
Lodapi liefert pro Antwort einen lodapi.attribution[]-Block. Cesium zeigt Credits in seiner unteren Toolbar — füge die Lodapi-Quellen hinzu:
const attrs = tilesets.length > 0 ? (await fetch(
`https://api.lodapi.de/v1/tilesets?bbox=${bbox}`
)).then(r => r.json()).then(d => d.lodapi.attribution) : [];
for (const a of attrs) {
viewer.scene.creditDisplay.addStaticCredit(
new Cesium.Credit(`${a.source} (${a.license})`, true)
);
}
Building anklicken → Detail-API
Cesium-3D-Tilesets unterstützen Per-Building-Picking. Die feature.gmlid ist als Batch-Table-Property eingebettet und matched die Lodapi-API:
viewer.screenSpaceEventHandler.setInputAction(async (movement) => {
const f = viewer.scene.pick(movement.position);
if (f instanceof Cesium.Cesium3DTileFeature) {
const gmlid = f.getProperty("gmlid");
if (!gmlid) return;
const detail = await fetch(`https://api.lodapi.de/v1/buildings/${gmlid}`).then(r => r.json());
console.log("Building:", detail.building_id, "BL:", detail.bundesland_code, "LoD:", detail.lod);
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
Performance-Tipps
maximumScreenSpaceErrorauf 8–16 setzen (Default 16). Niedriger = mehr Detail, mehr Memory.cullWithChildrenBounds: truestandardmäßig, lass das.preferLeaves: falsefür initial-snap-in, danachtruefür hohes Detail.- Mehrere BL parallel laden: jede
tileset_urlals eigenesCesium3DTileset.fromUrl(...)— keine Sammelladung nötig.
Voller Demo-Code
Lodapi-Repo hat einen fertigen Cesium-Viewer unter code/demo/api-tilesets/index.html — der gleiche Code, aber mit BL-Switcher und Inspector-Panel.
Stolperdrähte
- Ion-Key nicht zwingend, aber ohne Imagery-Provider sieht der Globus leer aus. Setze
Cesium.Ion.defaultAccessToken = "..."für hochauflösende Sat-Karten. - CesiumJS ≥ 1.118 für 3D-Tiles-1.1-Support (Implicit Tiling). Lodapi-Tilesets sind 1.1.
- CORS:
https://api.lodapi.deerlaubt*.lodapi.deundlocalhost:*. Andere Origins brauchen einen Custom-Eintrag — Issue eröffnen.