diff --git a/index.html b/index.html index 95e0bbf..2a32f57 100644 --- a/index.html +++ b/index.html @@ -38,7 +38,7 @@ - + diff --git a/main.js b/main.js index 325b6b2..fe9c263 100644 --- a/main.js +++ b/main.js @@ -1,11 +1,19 @@ import maplibregl from "maplibre-gl"; import proj4 from "proj4"; import * as THREE from "three"; +// !!! NPM import +import { LidarControl } from "maplibre-gl-lidar"; +// CSS Styles importieren! +import "maplibre-gl/dist/maplibre-gl.css"; +import "maplibre-gl-lidar/style.css"; proj4.defs("EPSG:25832", "+proj=utm +zone=32 +ellps=GRS80 +units=m +no_defs"); -const center = [9.209116842757239, 52.26520546238239] +// Koordinaten des Obernkirchener Sandstein +const center = [9.209116842757239, 52.26520546238239]; + +// die Grundkarte const map = new maplibregl.Map({ container: 'map', style: "https://tiles.openfreemap.org/styles/bright", @@ -14,35 +22,53 @@ const map = new maplibregl.Map({ maxZoom: 24, }); +// Karten-Bedienelemente map.addControl(new maplibregl.NavigationControl({ visualizePitch: true, showZoom: true, showCompass: true })); -const coordinatesDiv = document.getElementById('coordinates'); -map.on('mousemove', (e) => { - coordinatesDiv.innerHTML = `Lon: ${e.lngLat.lng.toFixed(5)}° | Lat: ${e.lngLat.lat.toFixed(5)}°`; + +//-------------------------LOGIK DECK.GL - aktuell beim Laden der Karte - hier rausnehmen------------------------------------------------------ +let lidarControl; +// WICHTIG: Layer/Controls immer erst im 'load'-Event der Karte hinzufügen +map.on('load', () => { + lidarControl = new LidarControl({ + title: 'Mein LiDAR-Viewer', + collapsed: false, + pointSize: 2, + colorScheme: 'rgb', // 'elevation' oder 'rgb' + pickable: false + }); + + //map.addControl(lidarControl, 'top-right'); + lidarControl.onAdd(map); + + // COPC-Datei laden + lidarControl.loadPointCloudStreaming('http://ar2350.web-01.fbbgg.hs-woe.de/copc%20Daten/sp3_low.copc.laz') }); -var pointBudget = document.getElementById("pointSlider").value; + +//---------------Potree Eigenschaften-------------------------- +var pointBudget = document.getElementById("pointSlider").value; // wahrscheinlich noch rausschmeißen var pointSize = document.getElementById("pointSizeSlider").value; const elRenderArea = document.getElementById("potree_render_area"); - const viewer = new Potree.Viewer(elRenderArea, {noDragAndDrop: true}); viewer.setEDLEnabled(false); viewer.setFOV(60); viewer.setPointBudget(pointBudget); viewer.setMinNodeSize(pointSize); viewer.setBackground("none"); - viewer.orbitControls.enabled = false; viewer.fpControls.enabled = false; viewer.deviceControls.enabled = false; +// Standardwert der Punktwolkenqualität var quality = 'medium'; -function getPointCloudFiles() { +// Punktwolkendaten im Potree-Format +function getPointCloudFilesPOTREE() { return { first: `http://ar2350.web-01.fbbgg.hs-woe.de/Punktwolken%20konvertiert%20potree%20Format/sp1_${quality}/metadata.json`, second: `http://ar2350.web-01.fbbgg.hs-woe.de/Punktwolken%20konvertiert%20potree%20Format/sp2_${quality}/metadata.json`, @@ -50,12 +76,24 @@ function getPointCloudFiles() { }; } +// Punktwolkendaten im COPC (Cloud Optimised Point Cloud)-Format für deck.gl +function getPointCloudFilesCOPC() { + return { + first: `http://ar2350.web-01.fbbgg.hs-woe.de/copc%20Daten/sp1_${quality}.copc.laz`, + second: `http://ar2350.web-01.fbbgg.hs-woe.de/copc%20Daten/sp1_${quality}.copc.laz`, + third: `http://ar2350.web-01.fbbgg.hs-woe.de/copc%20Daten/sp1_${quality}.copc.laz`, + }; +} + +// aktuell dargestellte Punktwolke let currentPointCloud = null; let isVisible = true; + +//------------------------lädt Punktwolke im Potree Format @hauke: entweder hier copc einbauen mit if else oder eigene Funktion dafür machen----------------------------- function loadPointCloud(path) { viewer.scene.view.yaw = 0; -viewer.scene.view.pitch = 0; + viewer.scene.view.pitch = 0; if (currentPointCloud) { const index = viewer.scene.pointclouds.indexOf(currentPointCloud); @@ -75,7 +113,6 @@ viewer.scene.view.pitch = 0; material.size = 1; material.pointSizeType = Potree.PointSizeType.ADAPTIVE; - // 1. Three.js zwingen, die Wolke sofort in der 3D-Welt zu platzieren currentPointCloud.updateMatrixWorld(true); @@ -96,9 +133,11 @@ viewer.scene.view.pitch = 0; // Variable, um Endlosschleifen zu verhindern let isSyncing = false; +/* + Kamera von Potree und MapLibre syncronisieren +*/ function syncCamera() { - if (!currentPointCloud || isSyncing) return; isSyncing = true; @@ -161,7 +200,7 @@ map.on('movestart', () => { map.getCanvasContainer().style.cursor = 'grabbing'; }); -// Anstatt des trägen 'render'-Events, nutzen wir eine Kombination aus 'draw' und 'precombine' +// bei jeder Kartenbwegeung die Kameras synchronisieren map.on('zoom', syncCamera); map.on('move', syncCamera); map.on('rotate', syncCamera); @@ -177,48 +216,167 @@ map.on('draw', syncCamera); elRenderArea.style.pointerEvents = "none"; map.getCanvas().style.pointerEvents = "auto"; + +/* + Hintergrundkarte ändern, Optionen: hell, dunkel, 3D-Gebäudemodelle, Satellit, Terrain, Satellit+Terrain +*/ function changeBaseMap(newMap) { var basemapStyle; switch(newMap) { - case "openfree_dark": basemapStyle = "https://tiles.openfreemap.org/styles/dark"; break; - case "openfree_bright": basemapStyle = "https://tiles.openfreemap.org/styles/bright"; break; - case "openfree_liberty": basemapStyle = "https://tiles.openfreemap.org/styles/liberty"; break; - case "google_satellite": - basemapStyle = { version: 8, sources: { "raster-tiles": { type: "raster", tiles: ["https://api.maptiler.com/tiles/satellite-v2/{z}/{x}/{y}.jpg?key=6mG881AthmTTWyLvFyjH"], tileSize: 256, attribution: "© MapTiler" } }, layers: [{ id: "satellite-layer", type: "raster", source: "raster-tiles" }] }; + case "openfree_dark": + basemapStyle = "https://tiles.openfreemap.org/styles/dark"; + break; + case "openfree_bright": + basemapStyle = "https://tiles.openfreemap.org/styles/bright"; + break; + case "openfree_liberty": + basemapStyle = "https://tiles.openfreemap.org/styles/liberty"; + break; + case "satellite": + basemapStyle = { + version: 8, + sources: { + "raster-tiles": { + type: "raster", + tiles: ["https://api.maptiler.com/tiles/satellite-v2/{z}/{x}/{y}.jpg?key=6mG881AthmTTWyLvFyjH"], + tileSize: 256, + attribution: "© MapTiler" + } + }, + layers: [{ + id: "satellite-layer", + type: "raster", + source: "raster-tiles" + }] + }; break; case "terrain": - basemapStyle = { version: 8, sources: { topo: { type: 'raster', url: 'https://api.maptiler.com/maps/topo-v4/tiles.json?key=6mG881AthmTTWyLvFyjH', tileSize: 256 }, terrainSource: { type: 'raster-dem', url: 'https://tiles.mapterhorn.com/tilejson.json' }, hillshadeSource: { type: 'raster-dem', url: 'https://tiles.mapterhorn.com/tilejson.json' } }, layers: [{ id: 'topo', type: 'raster', source: 'topo' }, { id: 'hills', type: 'hillshade', source: 'hillshadeSource', layout: { visibility: 'visible' }, paint: { 'hillshade-shadow-color': '#473B24' } }], terrain: { source: 'terrainSource', exaggeration: 1 }, sky: {} }; + basemapStyle = { + version: 8, + sources: { + topo: { + type: 'raster', + url: 'https://api.maptiler.com/maps/topo-v4/tiles.json?key=6mG881AthmTTWyLvFyjH', + tileSize: 256 + }, + terrainSource: { + type: 'raster-dem', + url: 'https://tiles.mapterhorn.com/tilejson.json' + }, + hillshadeSource: { + type: 'raster-dem', + url: 'https://tiles.mapterhorn.com/tilejson.json' + } + }, + layers: [{ + id: 'topo', + type: 'raster', + source: 'topo' + }, { + id: 'hills', + type: 'hillshade', + source: 'hillshadeSource', + layout: { + visibility: 'visible' + }, + paint: { + 'hillshade-shadow-color': '#473B24' + } + }], + terrain: { + source: 'terrainSource', + exaggeration: 1 + }, + sky: {} + }; break; case "satellite_terrain": - basemapStyle = { version: 8, sources: { "raster-tiles": { type: "raster", tiles: ["https://api.maptiler.com/tiles/satellite-v2/{z}/{x}/{y}.jpg?key=6mG881AthmTTWyLvFyjH"], tileSize: 256, attribution: "© MapTiler" }, terrainSource: { type: 'raster-dem', url: 'https://tiles.mapterhorn.com/tilejson.json' }, hillshadeSource: { type: 'raster-dem', url: 'https://tiles.mapterhorn.com/tilejson.json' } }, layers: [{ id: 'raster-tiles', type: 'raster', source: 'raster-tiles' }, { id: 'hills', type: 'hillshade', source: 'hillshadeSource', layout: { visibility: 'visible' }, paint: { 'hillshade-shadow-color': '#473B24' } }], terrain: { source: 'terrainSource', exaggeration: 1 }, sky: {} }; + basemapStyle = { + version: 8, + sources: { + "raster-tiles": { + type: "raster", + tiles: ["https://api.maptiler.com/tiles/satellite-v2/{z}/{x}/{y}.jpg?key=6mG881AthmTTWyLvFyjH"], + tileSize: 256, + attribution: "© MapTiler" + }, + terrainSource: { + type: 'raster-dem', + url: 'https://tiles.mapterhorn.com/tilejson.json' + }, + hillshadeSource: { + type: 'raster-dem', + url: 'https://tiles.mapterhorn.com/tilejson.json' + } + }, + layers: [{ + id: 'raster-tiles', + type: 'raster', + source: 'raster-tiles' + }, { + id: 'hills', + type: 'hillshade', + source: 'hillshadeSource', + layout: { + visibility: 'visible' + }, + paint: { + 'hillshade-shadow-color': '#473B24' + } + }], + terrain: { + source: 'terrainSource', + exaggeration: 1 + }, + sky: {} + }; break; } map.setStyle(basemapStyle); } +//------------------------------------------------------Action-Listener und Event-Handler--------------------------------------------------------------------------------- + +// Punktwolke aus/einblenden document.querySelector('#disable').addEventListener('click', function() { isVisible = !isVisible; - if (currentPointCloud) currentPointCloud.visible = isVisible; - if(isVisible){ + + if (currentPointCloud) + currentPointCloud.visible = isVisible; + + if(isVisible) { this.textContent = "Punktwolke ausblenden"; this.classList.add("active-state"); this.classList.remove("inactive-state"); - } else{ + } else { this.textContent = "Punktwolke anzeigen"; this.classList.add("inactive-state"); this.classList.remove("active-state"); } - }); + +// Koordinaten an der Mausposition darstellen (auf 5 Nachkommastellen begrenzt) +const coordinatesDiv = document.getElementById('coordinates'); +map.on('mousemove', (e) => { + coordinatesDiv.innerHTML = `Lon: ${e.lngLat.lng.toFixed(5)}° | Lat: ${e.lngLat.lat.toFixed(5)}°`; +}); + + +// Hintergrundkarte ändern, wenn anderes Element im DropDown gewählt wird document.querySelector('select[name="basemap"]').addEventListener('change', (e) => changeBaseMap(e.target.value)); + +// Punktwolke austauschen, wenn anderes Element im DropDown gewählt wird document.querySelector('select[name="pointcloud"]').addEventListener('change', (e) => { - loadPointCloud(getPointCloudFiles()[e.target.value]); + loadPointCloud(getPointCloudFilesPOTREE()[e.target.value]); }); + +// Kartenausschnitt auf Ursprung zurücksetzen document.getElementById("location").addEventListener("click", () => map.flyTo({center, zoom: 17})); + var pointCountSlider = document.getElementById("pointSlider"); var pointCountOutput = document.getElementById("pointSliderValue"); pointCountOutput.innerHTML = "Dargestellte Punkte: " + Number(pointCountSlider.value).toLocaleString(); @@ -257,6 +415,7 @@ document.querySelectorAll('.qualityButtons').forEach(btn => { }); }); + document.querySelectorAll('.colorButtons').forEach(btn => { btn.addEventListener('click', () => { if (!currentPointCloud) return; // Abbrechen, falls noch keine Wolke geladen ist @@ -288,11 +447,13 @@ document.querySelectorAll('.colorButtons').forEach(btn => { }); }); + // Sobald die Karte das allererste Mal stabil steht, Kamera abgleichen map.once('idle', () => { syncCamera(); }); + // Falls du beim Start direkt eine Standard-Punktwolke lädst, // stelle sicher, dass das Dropdown nach dem ersten stabilen Frame getriggert wird: map.once('load', () => { @@ -391,431 +552,3 @@ document.querySelector('select[name="pointcloud"]').addEventListener("change", ( }); }); - -/* -import maplibregl from "maplibre-gl"; -import proj4 from "proj4"; -import * as THREE from "three"; -console.log(THREE); -proj4.defs( - "EPSG:25832", - "+proj=utm +zone=32 +ellps=GRS80 +units=m +no_defs" -); - - -const center = [9.209116842757239, 52.26520546238239] - -const map = new maplibregl.Map({ - container: 'map', - style: "https://tiles.openfreemap.org/styles/bright", - center: center, - zoom: 17, - maxZoom: 24, -}); -window.map=map; - -map.addControl( - new maplibregl.NavigationControl({ - visualizePitch: true, - showZoom: true, - showCompass: true - }) -); - -// 2. Create an HTML element to display coordinates (e.g.,
)
-const coordinatesDiv = document.getElementById('coordinates');
-
-// 3. Listen for mouse movement
-map.on('mousemove', (e) => {
-    // e.lngLat contains the longitude and latitude
-    const lng = e.lngLat.lng.toFixed(5);
-    const lat = e.lngLat.lat.toFixed(5);
-    
-    coordinatesDiv.innerHTML = `Lon: ${lng}° | Lat: ${lat}°`;
-});
-
-var pointBudget = document.getElementById("pointSlider").value;
-var pointSize = document.getElementById("pointSizeSlider").value;
-const elRenderArea=document.getElementById("potree_render_area");
-
-const viewer=new Potree.Viewer(elRenderArea, {noDragAndDrop:true});
-viewer.renderer.domElement.style.zIndex="1";
-map.getCanvas().style.zIndex="0";
-window.viewer=viewer;
-viewer.setEDLEnabled(false); // sieht realistischer aus
-viewer.setFOV(60);
-viewer.setPointBudget(pointBudget);
-viewer.setMinNodeSize(pointSize);
-viewer.setBackground("none"); 
-
-console.log(viewer.orbitControls);
-console.log(viewer.fpControls);
-console.log(viewer.deviceControls);
-
-viewer.orbitControls.enabled=false;
-viewer.fpControls.enabled=false;
-viewer.deviceControls.enabled=false;
-
-
-var quality = 'medium';
-
-// Dateipfade der Punktwolke
-// Funktion für aktuelle Pfade
-function getPointCloudFiles() {
-    return {
-      first: `http://ar2350.web-01.fbbgg.hs-woe.de/Punktwolken%20konvertiert%20potree%20Format/sp1_${quality}/metadata.json`,
-      second: `http://ar2350.web-01.fbbgg.hs-woe.de/Punktwolken%20konvertiert%20potree%20Format/sp2_${quality}/metadata.json`,
-      third: `http://ar2350.web-01.fbbgg.hs-woe.de/Punktwolken%20konvertiert%20potree%20Format/sp3_${quality}/metadata.json`,
-    };
-}
-
-//Aktuelle Datei und Sichtbarkeit
-let currentPointCloud=null;
-let isVisible=true;
-
-function loadPointCloud(path){
-  console.log("Laden aufgerufen")
-  console.log("Pfad "+ path);
-    // Vorherige Punktwolke entfernen
-    if (currentPointCloud) {
-      // Aus Potree-Liste entfernen
-      const index = viewer.scene.pointclouds.indexOf(currentPointCloud);
-
-      if (index !== -1) {
-        viewer.scene.pointclouds.splice(index, 1);
-      }
-
-      // Aus Three.js Szene entfernen
-      if (currentPointCloud.parent) {
-        currentPointCloud.parent.remove(currentPointCloud);
-      }
-
-      currentPointCloud = null;
-      viewer.render();
-    }
-
-  if(!path ||!isVisible) return;
-
-  Potree.loadPointCloud(path, "punktwolke", function(e) {
-    currentPointCloud=e.pointcloud;
-    viewer.scene.addPointCloud(currentPointCloud);
-
-
-   // View-Objekt inspizieren
-    console.log("view:", viewer.scene.view);
-    console.log("view.lookAt:", viewer.scene.view.lookAt);
-    console.log("view.position:", viewer.scene.view.position);
-    console.log("view keys:", Object.keys(viewer.scene.view));
-    
-
-    let material =currentPointCloud.material;
-    material.size =1;
-    material.pointSizeType=Potree.PointSizeType.ADAPTIVE;
-    material.activeAttributeName="rgba";
-    
-   
-  });
-}
-
-const originMercator = maplibregl.MercatorCoordinate.fromLngLat(
-  { lng: center[0], lat: center[1] }, 0
-);
-const metersToMercator = originMercator.meterInMercatorCoordinateUnits();
-
-const potreeLayer = {
-  id: "potree-pointcloud",
-  type: "custom",
-  renderingMode: "3d",
-
- onAdd(map, gl) {
-  this.map = map;
-  this.camera = new THREE.Camera();
-},
-
-  onRemove(){
-    this.renderer.dispose();
-    this.renderer=null;
-  },
-
-  render(gl, args) {
-  if (!currentPointCloud) return;
-
-  const [originX, originY] = proj4("EPSG:4326", "EPSG:25832", [center[0], center[1]]);
-
-  const m = new THREE.Matrix4().fromArray(args.defaultProjectionData.mainMatrix);
-  const scale = new THREE.Matrix4().makeScale(
-    metersToMercator, -metersToMercator, metersToMercator
-  );
-  const translate = new THREE.Matrix4().makeTranslation(
-    originMercator.x - originX * metersToMercator,
-    originMercator.y + originY * metersToMercator,
-    0
-  );
-  const l = translate.multiply(scale);
-
-  this.camera.projectionMatrix = m.multiply(l);
-
-  viewer.renderer.resetState();
-  viewer.renderer.render(viewer.scene.scenePointCloud, this.camera);
-  this.map.triggerRepaint();
-},
-};
-
-map.on("style.load", () => {
-  map.addLayer(potreeLayer);
-});
-
-
-
-// Hintergrundkarte ändern
-function changeBaseMap(newMap){
-  var basemapStyle;
-  switch(newMap){
-    case "openfree_dark":
-      basemapStyle = "https://tiles.openfreemap.org/styles/dark"
-      break;
-    case "openfree_bright":
-      basemapStyle = "https://tiles.openfreemap.org/styles/bright"
-      break;
-    case "openfree_liberty":
-      basemapStyle = "https://tiles.openfreemap.org/styles/liberty"
-      break;
-    case "google_satellite":
-   basemapStyle = {
-    version: 8,
-    sources: {
-      "raster-tiles": {
-        type: "raster",
-        tiles: [
-          "https://api.maptiler.com/tiles/satellite-v2/{z}/{x}/{y}.jpg?key=6mG881AthmTTWyLvFyjH"
-        ],
-        tileSize: 256,
-        attribution: "© MapTiler",
-      }
-    },
-    layers: [
-      {
-        id: "satellite-layer",
-        type: "raster",
-        source: "raster-tiles"
-      }
-    ]
-  }
-    break;
-  case "terrain":
-    basemapStyle = {
-        version: 8,
-        sources: {
-            topo: {
-        type: 'raster',
-        url: 'https://api.maptiler.com/maps/topo-v4/tiles.json?key=6mG881AthmTTWyLvFyjH',
-        tileSize: 256,
-      },
-            // Use a different source for terrain and hillshade layers, to improve render quality
-            terrainSource: {
-                type: 'raster-dem',
-                url: 'https://tiles.mapterhorn.com/tilejson.json',
-            },
-            hillshadeSource: {
-                type: 'raster-dem',
-                url: 'https://tiles.mapterhorn.com/tilejson.json'
-            }
-        },
-        layers: [
-            {
-                id: 'topo',
-                type: 'raster',
-                source: 'topo'
-            },
-            {
-                id: 'hills',
-                type: 'hillshade',
-                source: 'hillshadeSource',
-                layout: {visibility: 'visible'},
-                paint: {'hillshade-shadow-color': '#473B24'}
-            }
-        ],
-        terrain: {
-            source: 'terrainSource',
-            exaggeration: 1
-        },
-        sky: {}
-    }
-    break;
-    case "satellite_terrain": 
-      basemapStyle =  {
-        version: 8,
-        sources: {
-             "raster-tiles": {
-        type: "raster",
-        tiles: [
-          "https://api.maptiler.com/tiles/satellite-v2/{z}/{x}/{y}.jpg?key=6mG881AthmTTWyLvFyjH"
-        ],
-        tileSize: 256,
-        attribution: "© MapTiler",
-      },
-            // Use a different source for terrain and hillshade layers, to improve render quality
-            terrainSource: {
-                type: 'raster-dem',
-                url: 'https://tiles.mapterhorn.com/tilejson.json',
-            },
-            hillshadeSource: {
-                type: 'raster-dem',
-                url: 'https://tiles.mapterhorn.com/tilejson.json'
-            }
-        },
-        layers: [
-            {
-                id: 'raster-tiles',
-                type: 'raster',
-                source: 'raster-tiles'
-            },
-            {
-                id: 'hills',
-                type: 'hillshade',
-                source: 'hillshadeSource',
-                layout: {visibility: 'visible'},
-                paint: {'hillshade-shadow-color': '#473B24'}
-            }
-        ],
-        terrain: {
-            source: 'terrainSource',
-            exaggeration: 1
-        },
-        sky: {}
-    }
-	
-  }
-  map.setStyle(basemapStyle);
-  map.once("style.load", ()=> {
-    map.addLayer(potreeLayer);
-  });
-}
-
-
-const button = document.querySelector('#disable')
-
-button.addEventListener('click', () => {
-
-    isVisible = !isVisible;
-
-    if(currentPointCloud){
-        currentPointCloud.visible = isVisible;
-    }
-
-    button.textContent = isVisible
-        ? "Punktwolke ausblenden"
-        : "Punktwolke anzeigen";
-
-});
-
-
-// ausgewähltes Element im BaseMap DropDown Feld
-const selectElement = document.querySelector('select[name="basemap"]');
-selectElement.addEventListener('change', (event) => {
-  changeBaseMap(event.target.value);
-});
-
-
-
-// ausgewähltes Element im Punktwolken DropDown Feld
-
-document.querySelector('select[name="pointcloud"]').addEventListener('change', (event) => {
-  const pointCloudFiles = getPointCloudFiles();
-  var pointcloud = pointCloudFiles[event.target.value];
-  loadPointCloud(pointcloud);
-  console.log(pointCloudFiles[event.target.value]);
-});
-
-
-// Auf Zentrum zurück zoomen
-document.getElementById("location").addEventListener("click", () => {
- map.flyTo({center, zoom: 17 })
-});
-
-
-var pointCountSlider = document.getElementById("pointSlider");
-var pointCountOutput = document.getElementById("pointSliderValue");
-pointCountOutput.innerHTML = "Dargestellte Punkte: " + Number(pointCountSlider.value).toLocaleString();
-
-pointCountSlider.oninput = function() {
-  pointCountOutput.innerHTML = "Dargestellte Punkte: " + Number(this.value).toLocaleString('de-DE');;
-  pointBudget = document.getElementById("pointSlider").value;
-  viewer.setPointBudget(pointBudget);
-}
-
-
-
-var pointSizeSlider = document.getElementById("pointSizeSlider");
-
-pointSizeSlider.oninput = function() {
-  pointSize = document.getElementById("pointSizeSlider").value;
-  viewer.setMinNodeSize(pointSize);
-  console.log(pointSize);
-}
-
-const closeButton = document.getElementById("closeSideBarButton");
-const sidebar = document.getElementById("sidebar");
-const openOuter = document.getElementById("openButtonOuter");
-
-if (closeButton) {
-    closeButton.addEventListener("click", () => {
-      const rect = closeButton.getBoundingClientRect();  
-      sidebar.style.display = "none";
-        
-        openOuter.innerHTML = "";
-        const openButton = document.getElementById("openSideBarButton");
-        openButton.style.top = `${rect.top + window.scrollY -2}px`;
-        if (openButton) {
-            openButton.addEventListener("click", () => {
-                sidebar.style.display = "flex";
-              
-                openOuter.innerHTML = ""; 
-            });
-        }
-    });
-}
-
-// Qualitätsbuttons aktivieren/deaktivieren
-const qualityButtons = document.querySelectorAll('.qualityButtons');
-
-qualityButtons.forEach(button => {
-
-    button.addEventListener('click', () => {
-        console.log(button.id);
-        quality=button.id;
-
-        if (currentPointCloud) {
-          const pointCloudFiles = getPointCloudFiles();
-          var pointCloudValue = document.getElementById("pointcloud").value
-          var pointcloud = pointCloudFiles[pointCloudValue];
-          loadPointCloud(pointcloud);
-        }
-        qualityButtons.forEach(btn => {
-            btn.classList.remove('active');
-        });
-
-        button.classList.add('active');
-
-    });
-
-});
-
-
-// Farbbuttons aktivieren/deaktivieren
-const colorButtons = document.querySelectorAll('.colorButtons');
-
-colorButtons.forEach(button => {
-
-    button.addEventListener('click', () => {
-
-        colorButtons.forEach(btn => {
-            btn.classList.remove('active');
-        });
-
-        button.classList.add('active');
-
-    });
-
-});
-*/
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index 835e3d5..ae30105 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9,11 +9,15 @@
       "version": "1.0.0",
       "license": "ISC",
       "dependencies": {
-        "@loaders.gl/core": "^4.4.1",
-        "@loaders.gl/las": "^4.4.1",
+        "@deck.gl/core": "^9.3.3",
+        "@deck.gl/layers": "^9.3.3",
+        "@deck.gl/mapbox": "^9.3.3",
+        "@loaders.gl/core": "^4.4.2",
+        "@loaders.gl/las": "^4.4.2",
         "deck.gl": "^9.3.1",
         "latest": "^0.2.0",
         "maplibre-gl": "^5.22.0",
+        "maplibre-gl-lidar": "^0.15.0",
         "proj4": "^2.20.8",
         "three": "^0.124.0",
         "vite": "^8.0.13"
@@ -192,9 +196,9 @@
       }
     },
     "node_modules/@deck.gl/core": {
-      "version": "9.3.2",
-      "resolved": "https://registry.npmjs.org/@deck.gl/core/-/core-9.3.2.tgz",
-      "integrity": "sha512-32Va3np0Zdlz/LBNtDWCs4EkKqdHmXcbGmVp4+7i1Cpdza8y8CFmJs2VPOmSX1fwHvNCGkAZV/SFZOfDb2INsg==",
+      "version": "9.3.3",
+      "resolved": "https://registry.npmjs.org/@deck.gl/core/-/core-9.3.3.tgz",
+      "integrity": "sha512-P8IPB0VJyyKBGEUC6wT2sfqNYY/IClzYIqi0iyHBunKTUKQNwiKhPasQLCEfb157KNoCdeZxjnohkyRYqbas+A==",
       "license": "MIT",
       "dependencies": {
         "@loaders.gl/core": "^4.4.1",
@@ -303,9 +307,9 @@
       }
     },
     "node_modules/@deck.gl/layers": {
-      "version": "9.3.2",
-      "resolved": "https://registry.npmjs.org/@deck.gl/layers/-/layers-9.3.2.tgz",
-      "integrity": "sha512-TeVfhQ/cQU1oTlTn16mCp7268d1uBJ6dwfgmKXThe2TzW9hql3iJaxbYTKg2phDg5YSiGmeEOpXbeBh59jyUcA==",
+      "version": "9.3.3",
+      "resolved": "https://registry.npmjs.org/@deck.gl/layers/-/layers-9.3.3.tgz",
+      "integrity": "sha512-sp7rvAe/SM/Ja8sVKF0r5ZFj+W5y1h9HpmFZUGv+knkBhrwWLfxa6p3sycimdLMd22tCguw7ps4klKgZjgYTtw==",
       "license": "MIT",
       "dependencies": {
         "@loaders.gl/images": "^4.4.1",
@@ -325,9 +329,9 @@
       }
     },
     "node_modules/@deck.gl/mapbox": {
-      "version": "9.3.2",
-      "resolved": "https://registry.npmjs.org/@deck.gl/mapbox/-/mapbox-9.3.2.tgz",
-      "integrity": "sha512-+T9pJwsOXwjUxyGN6oiBMfIs28VtDIG1V1Rqz4qqn4TjjNEFFw+xO0olJIg8FO5IAqw2OtePdsrMj0tX8tHdGQ==",
+      "version": "9.3.3",
+      "resolved": "https://registry.npmjs.org/@deck.gl/mapbox/-/mapbox-9.3.3.tgz",
+      "integrity": "sha512-aUPqrwF6wkx+EtvKA3SaiK+UROMnZSmgEJWZ1qSKFSiH//kPuo5imbtXyan8sGhOet7NjnfEwJqFA3EBk7zDLA==",
       "license": "MIT",
       "dependencies": {
         "@math.gl/web-mercator": "^4.1.0"
@@ -1349,9 +1353,6 @@
       "cpu": [
         "arm64"
       ],
-      "libc": [
-        "glibc"
-      ],
       "license": "MIT",
       "optional": true,
       "os": [
@@ -1368,9 +1369,6 @@
       "cpu": [
         "arm64"
       ],
-      "libc": [
-        "musl"
-      ],
       "license": "MIT",
       "optional": true,
       "os": [
@@ -1387,9 +1385,6 @@
       "cpu": [
         "ppc64"
       ],
-      "libc": [
-        "glibc"
-      ],
       "license": "MIT",
       "optional": true,
       "os": [
@@ -1406,9 +1401,6 @@
       "cpu": [
         "s390x"
       ],
-      "libc": [
-        "glibc"
-      ],
       "license": "MIT",
       "optional": true,
       "os": [
@@ -1425,9 +1417,6 @@
       "cpu": [
         "x64"
       ],
-      "libc": [
-        "glibc"
-      ],
       "license": "MIT",
       "optional": true,
       "os": [
@@ -1444,9 +1433,6 @@
       "cpu": [
         "x64"
       ],
-      "libc": [
-        "musl"
-      ],
       "license": "MIT",
       "optional": true,
       "os": [
@@ -2596,6 +2582,22 @@
         "@floating-ui/utils": "^0.2.5"
       }
     },
+    "node_modules/copc": {
+      "version": "0.0.8",
+      "resolved": "https://registry.npmjs.org/copc/-/copc-0.0.8.tgz",
+      "integrity": "sha512-OWjfOZKhh7EkSYIMST/yxmegMwCR5Gye3Koq3ov1+oHFozBbPwlK1bsSWB9aNdJrXElaTh374bNhOSPxx1xSog==",
+      "license": "MIT",
+      "dependencies": {
+        "cross-fetch": "^3.1.5",
+        "laz-perf": "^0.0.7"
+      }
+    },
+    "node_modules/copc/node_modules/laz-perf": {
+      "version": "0.0.7",
+      "resolved": "https://registry.npmjs.org/laz-perf/-/laz-perf-0.0.7.tgz",
+      "integrity": "sha512-2xRqm/f/2UqDS5qqkjOyDb6uVIjkVw6SGmQlMoTQliVWkZhPfIbUJTubUl3mTloaWqKcjlS/urmP1CYoxelsEg==",
+      "license": "Apache-2.0"
+    },
     "node_modules/core-assert": {
       "version": "0.2.1",
       "resolved": "https://registry.npmjs.org/core-assert/-/core-assert-0.2.1.tgz",
@@ -2615,6 +2617,15 @@
       "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
       "license": "MIT"
     },
+    "node_modules/cross-fetch": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.2.0.tgz",
+      "integrity": "sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==",
+      "license": "MIT",
+      "dependencies": {
+        "node-fetch": "^2.7.0"
+      }
+    },
     "node_modules/crypt": {
       "version": "0.0.2",
       "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz",
@@ -3240,6 +3251,66 @@
         }
       }
     },
+    "node_modules/deck.gl/node_modules/@deck.gl/core": {
+      "version": "9.3.2",
+      "resolved": "https://registry.npmjs.org/@deck.gl/core/-/core-9.3.2.tgz",
+      "integrity": "sha512-32Va3np0Zdlz/LBNtDWCs4EkKqdHmXcbGmVp4+7i1Cpdza8y8CFmJs2VPOmSX1fwHvNCGkAZV/SFZOfDb2INsg==",
+      "license": "MIT",
+      "dependencies": {
+        "@loaders.gl/core": "^4.4.1",
+        "@loaders.gl/images": "^4.4.1",
+        "@luma.gl/core": "^9.3.3",
+        "@luma.gl/engine": "^9.3.3",
+        "@luma.gl/shadertools": "^9.3.3",
+        "@luma.gl/webgl": "^9.3.3",
+        "@math.gl/core": "^4.1.0",
+        "@math.gl/sun": "^4.1.0",
+        "@math.gl/types": "^4.1.0",
+        "@math.gl/web-mercator": "^4.1.0",
+        "@probe.gl/env": "^4.1.1",
+        "@probe.gl/log": "^4.1.1",
+        "@probe.gl/stats": "^4.1.1",
+        "@types/offscreencanvas": "^2019.6.4",
+        "gl-matrix": "^3.0.0",
+        "mjolnir.js": "^3.0.0"
+      }
+    },
+    "node_modules/deck.gl/node_modules/@deck.gl/layers": {
+      "version": "9.3.2",
+      "resolved": "https://registry.npmjs.org/@deck.gl/layers/-/layers-9.3.2.tgz",
+      "integrity": "sha512-TeVfhQ/cQU1oTlTn16mCp7268d1uBJ6dwfgmKXThe2TzW9hql3iJaxbYTKg2phDg5YSiGmeEOpXbeBh59jyUcA==",
+      "license": "MIT",
+      "dependencies": {
+        "@loaders.gl/images": "^4.4.1",
+        "@loaders.gl/schema": "^4.4.1",
+        "@luma.gl/shadertools": "^9.3.3",
+        "@mapbox/tiny-sdf": "^2.0.5",
+        "@math.gl/core": "^4.1.0",
+        "@math.gl/polygon": "^4.1.0",
+        "@math.gl/web-mercator": "^4.1.0",
+        "earcut": "^2.2.4"
+      },
+      "peerDependencies": {
+        "@deck.gl/core": "~9.3.0",
+        "@loaders.gl/core": "^4.4.1",
+        "@luma.gl/core": "~9.3.3",
+        "@luma.gl/engine": "~9.3.3"
+      }
+    },
+    "node_modules/deck.gl/node_modules/@deck.gl/mapbox": {
+      "version": "9.3.2",
+      "resolved": "https://registry.npmjs.org/@deck.gl/mapbox/-/mapbox-9.3.2.tgz",
+      "integrity": "sha512-+T9pJwsOXwjUxyGN6oiBMfIs28VtDIG1V1Rqz4qqn4TjjNEFFw+xO0olJIg8FO5IAqw2OtePdsrMj0tX8tHdGQ==",
+      "license": "MIT",
+      "dependencies": {
+        "@math.gl/web-mercator": "^4.1.0"
+      },
+      "peerDependencies": {
+        "@deck.gl/core": "~9.3.0",
+        "@luma.gl/core": "~9.3.3",
+        "@math.gl/web-mercator": "^4.1.0"
+      }
+    },
     "node_modules/deep-equal": {
       "version": "1.1.2",
       "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.2.tgz",
@@ -4048,9 +4119,6 @@
       "cpu": [
         "arm64"
       ],
-      "libc": [
-        "glibc"
-      ],
       "license": "MPL-2.0",
       "optional": true,
       "os": [
@@ -4071,9 +4139,6 @@
       "cpu": [
         "arm64"
       ],
-      "libc": [
-        "musl"
-      ],
       "license": "MPL-2.0",
       "optional": true,
       "os": [
@@ -4094,9 +4159,6 @@
       "cpu": [
         "x64"
       ],
-      "libc": [
-        "glibc"
-      ],
       "license": "MPL-2.0",
       "optional": true,
       "os": [
@@ -4117,9 +4179,6 @@
       "cpu": [
         "x64"
       ],
-      "libc": [
-        "musl"
-      ],
       "license": "MPL-2.0",
       "optional": true,
       "os": [
@@ -4273,6 +4332,55 @@
         "url": "https://github.com/maplibre/maplibre-gl-js?sponsor=1"
       }
     },
+    "node_modules/maplibre-gl-layer-control": {
+      "version": "0.14.1",
+      "resolved": "https://registry.npmjs.org/maplibre-gl-layer-control/-/maplibre-gl-layer-control-0.14.1.tgz",
+      "integrity": "sha512-WnhDdq7vyp+r+ICErg9wW6Y8dBXxNtkPRCPiAgOjupngapeL8THFLs0qBiQYJtYMsc07wRwlmP4/5g8OroGosg==",
+      "license": "MIT",
+      "peerDependencies": {
+        "maplibre-gl": ">=3.0.0",
+        "react": ">=18.0.0",
+        "react-dom": ">=18.0.0"
+      },
+      "peerDependenciesMeta": {
+        "react": {
+          "optional": true
+        },
+        "react-dom": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/maplibre-gl-lidar": {
+      "version": "0.15.0",
+      "resolved": "https://registry.npmjs.org/maplibre-gl-lidar/-/maplibre-gl-lidar-0.15.0.tgz",
+      "integrity": "sha512-5KbFuuhS647JuNfsu2hzuqqa3cpDhKNeBhcFPJCtUo3tYiE20tPrdANVZP40nFmFNAGLZvU2obk5Ftojdjp1ig==",
+      "license": "MIT",
+      "dependencies": {
+        "@deck.gl/core": ">=9.3.2",
+        "@deck.gl/extensions": ">=9.3.2",
+        "@deck.gl/layers": ">=9.3.2",
+        "@deck.gl/mapbox": ">=9.3.2",
+        "@loaders.gl/core": ">=4.4.2",
+        "@loaders.gl/las": ">=4.4.2",
+        "copc": ">=0.0.8",
+        "maplibre-gl-layer-control": ">=0.14.1",
+        "proj4": ">=2.20.8"
+      },
+      "peerDependencies": {
+        "maplibre-gl": ">=3.0.0",
+        "react": ">=18.0.0",
+        "react-dom": ">=18.0.0"
+      },
+      "peerDependenciesMeta": {
+        "react": {
+          "optional": true
+        },
+        "react-dom": {
+          "optional": true
+        }
+      }
+    },
     "node_modules/maplibre-gl/node_modules/@mapbox/point-geometry": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/@mapbox/point-geometry/-/point-geometry-1.1.0.tgz",
@@ -4415,6 +4523,26 @@
         "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
       }
     },
+    "node_modules/node-fetch": {
+      "version": "2.7.0",
+      "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
+      "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
+      "license": "MIT",
+      "dependencies": {
+        "whatwg-url": "^5.0.0"
+      },
+      "engines": {
+        "node": "4.x || >=6.0.0"
+      },
+      "peerDependencies": {
+        "encoding": "^0.1.0"
+      },
+      "peerDependenciesMeta": {
+        "encoding": {
+          "optional": true
+        }
+      }
+    },
     "node_modules/npm": {
       "version": "2.15.12",
       "resolved": "https://registry.npmjs.org/npm/-/npm-2.15.12.tgz",
@@ -6811,6 +6939,12 @@
       "integrity": "sha512-gRa9gwYU3ECmQYv3lslts5hxuIa90veaEcxDYuu3QGOIAEM2mOZkVHp48ANJuu1CURtRdHKUBY5Lm1tHV+sD4g==",
       "license": "ISC"
     },
+    "node_modules/tr46": {
+      "version": "0.0.3",
+      "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
+      "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
+      "license": "MIT"
+    },
     "node_modules/tslib": {
       "version": "2.8.1",
       "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
@@ -6957,6 +7091,22 @@
         }
       }
     },
+    "node_modules/webidl-conversions": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
+      "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
+      "license": "BSD-2-Clause"
+    },
+    "node_modules/whatwg-url": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
+      "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
+      "license": "MIT",
+      "dependencies": {
+        "tr46": "~0.0.3",
+        "webidl-conversions": "^3.0.0"
+      }
+    },
     "node_modules/wkt-parser": {
       "version": "1.5.5",
       "resolved": "https://registry.npmjs.org/wkt-parser/-/wkt-parser-1.5.5.tgz",
diff --git a/package.json b/package.json
index 8f8ed2e..2a4ed56 100644
--- a/package.json
+++ b/package.json
@@ -12,11 +12,15 @@
   "license": "ISC",
   "type": "commonjs",
   "dependencies": {
-    "@loaders.gl/core": "^4.4.1",
-    "@loaders.gl/las": "^4.4.1",
+    "@deck.gl/core": "^9.3.3",
+    "@deck.gl/layers": "^9.3.3",
+    "@deck.gl/mapbox": "^9.3.3",
+    "@loaders.gl/core": "^4.4.2",
+    "@loaders.gl/las": "^4.4.2",
     "deck.gl": "^9.3.1",
     "latest": "^0.2.0",
     "maplibre-gl": "^5.22.0",
+    "maplibre-gl-lidar": "^0.15.0",
     "proj4": "^2.20.8",
     "three": "^0.124.0",
     "vite": "^8.0.13"
diff --git a/style.css b/style.css
index da18068..913daa0 100644
--- a/style.css
+++ b/style.css
@@ -505,4 +505,4 @@ position: absolute;
 #info-image-counter {
     font-size: 12px;
     color: #555;
-}
\ No newline at end of file
+}