From 7e063db32e71ad4ecfbd81411ff094cfbd37aa4c Mon Sep 17 00:00:00 2001 From: Hauke Kahrs Date: Tue, 16 Jun 2026 13:15:38 +0200 Subject: [PATCH] =?UTF-8?q?Deckgl=20version=20fertiggestellt.=20Switch=20z?= =?UTF-8?q?wischen=20deckgl=20und=20Potree=20m=C3=B6glich.=20Pointbudget?= =?UTF-8?q?=20entfernt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.html | 11 +-- main.js | 200 ++++++++++++++++++++++++++++++++++++----------------- style.css | 45 +++++++++++- 3 files changed, 187 insertions(+), 69 deletions(-) diff --git a/index.html b/index.html index 2a32f57..ecb6ebb 100644 --- a/index.html +++ b/index.html @@ -65,15 +65,18 @@ -

-

Punktgröße

Klein Groß
- - + +

Renderer

+ +
diff --git a/main.js b/main.js index 9ccf90c..a2af2c1 100644 --- a/main.js +++ b/main.js @@ -29,9 +29,17 @@ map.addControl(new maplibregl.NavigationControl({ showCompass: true })); +let currentPointCloud = null; +let isVisible = true; +let currentRenderer='deckgl'; +let currentColorMode='rgb'; +let currentPointSize=Number(document.getElementById("pointSizeSlider").value); +let currentPointcloudKey = null; +let lidarControl=null; +var quality = 'medium'; //-------------------------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({ @@ -42,30 +50,51 @@ map.on('load', () => { pickable: false }); - //map.addControl(lidarControl, 'top-right'); - lidarControl.onAdd(map); + 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') + const selectBox=document.querySelector('select[name="pointcloud"]'); + if (selectBox && selectBox.value){ + currentPointcloudKey=selectBox.value; + loadCurrentPointCloud(); + } + loadInfoJSON(); + //lidarControl.loadPointCloudStreaming('http://ar2350.web-01.fbbgg.hs-woe.de/copc%20Daten/sp3_low.copc.laz') }); //---------------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'; +elRenderArea.style.display='none'; + +function resetLidarControl() { + if (!lidarControl) return; + try { + map.removeControl(lidarControl); + } catch(e) {} + lidarControl = null; + + lidarControl = new LidarControl({ + title: 'Mein LiDAR-Viewer', + collapsed: false, + pointSize: currentPointSize > 0 ? currentPointSize : 2, + colorScheme: currentColorMode === 'rgb' ? 'rgb' : 'elevation', + pickable: false + }); + map.addControl(lidarControl, 'top-right'); +} + // Punktwolkendaten im Potree-Format function getPointCloudFilesPOTREE() { @@ -80,14 +109,85 @@ function getPointCloudFilesPOTREE() { 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`, + second: `http://ar2350.web-01.fbbgg.hs-woe.de/copc%20Daten/sp2_${quality}.copc.laz`, + third: `http://ar2350.web-01.fbbgg.hs-woe.de/copc%20Daten/sp3_${quality}.copc.laz`, }; } + +function loadCurrentPointCloud() { + if (!currentPointcloudKey) return; + if (currentRenderer === 'deckgl') { + loadDeckGL(getPointCloudFilesCOPC()[currentPointcloudKey]); + } else { + loadPointCloud(getPointCloudFilesPOTREE()[currentPointcloudKey]); + } +} + +function loadDeckGL(path) { + if (!lidarControl || !path) return; + resetLidarControl(); + lidarControl.loadPointCloudStreaming(path); + setTimeout(() => applyDeckGLSettings(), 500); +} + +function applyDeckGLSettings() { + if (!lidarControl) return; + try { + lidarControl.setPointSize(currentPointSize > 0 ? currentPointSize : 2); + lidarControl.setColorScheme(currentColorMode === 'rgb' ? 'rgb' : 'elevation'); + } catch(e) { console.warn("LidarControl API:", e); } +} + +function switchRenderer(renderer) { + currentRenderer = renderer; + if (renderer === 'deckgl') { + elRenderArea.style.display = 'none'; + if (currentPointCloud) currentPointCloud.visible = false; + if (lidarControl && currentPointcloudKey) loadDeckGL(getPointCloudFilesCOPC()[currentPointcloudKey]); + document.getElementById('rendererToggle').dataset.active = 'deckgl'; + document.getElementById('rendererLabel').textContent = 'Renderer: Deck.gl'; + } else { + resetLidarControl(); + elRenderArea.style.display = 'block'; + if (currentPointcloudKey) loadPointCloud(getPointCloudFilesPOTREE()[currentPointcloudKey]); + document.getElementById('rendererToggle').dataset.active = 'potree'; + document.getElementById('rendererLabel').textContent = 'Renderer: Potree'; + } + applyVisibility(); +} + +function applyVisibility() { + if (currentRenderer === 'potree' && currentPointCloud) { + currentPointCloud.visible = isVisible; + } + if (currentRenderer === 'deckgl' && lidarControl) { + try { lidarControl.setVisible(isVisible); } catch(e) { console.warn("setVisible:", e); } + } +} + +function applyColorModePotree() { + if (!currentPointCloud) return; + let mat = currentPointCloud.material; + mat.activeAttributeName = currentColorMode === 'rgb' ? "rgba" : "elevation"; + viewer.renderer.resetState(); + viewer.render(); + map.triggerRepaint(); +} + +function applyColorMode() { + if (currentRenderer === 'potree') { applyColorModePotree(); } + else { applyDeckGLSettings(); } +} + +function loadInfoJSON() { + fetch("info.json") + .then(r => r.json()) + .then(data => { pointCloudInfo = data; }) + .catch(e => console.error("Fehler beim Laden der JSON:", e)); +} // 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----------------------------- @@ -138,7 +238,7 @@ let isSyncing = false; */ function syncCamera() { - if (!currentPointCloud || isSyncing) return; + if (!currentPointCloud || isSyncing || currentRenderer!== 'potree') return; isSyncing = true; const transform = map.transform; @@ -341,8 +441,9 @@ function changeBaseMap(newMap) { document.querySelector('#disable').addEventListener('click', function() { isVisible = !isVisible; - if (currentPointCloud) - currentPointCloud.visible = isVisible; + //if (currentPointCloud) + // currentPointCloud.visible = isVisible; + applyVisibility(); if(isVisible) { this.textContent = "Punktwolke ausblenden"; @@ -369,24 +470,23 @@ document.querySelector('select[name="basemap"]').addEventListener('change', (e) // Punktwolke austauschen, wenn anderes Element im DropDown gewählt wird document.querySelector('select[name="pointcloud"]').addEventListener('change', (e) => { - loadPointCloud(getPointCloudFilesPOTREE()[e.target.value]); + //loadPointCloud(getPointCloudFilesPOTREE()[e.target.value]); + currentPointcloudKey = e.target.value; + loadCurrentPointCloud(); }); // 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(); -pointCountSlider.oninput = function() { - pointCountOutput.innerHTML = "Dargestellte Punkte: " + Number(this.value).toLocaleString('de-DE'); - viewer.setPointBudget(this.value); -}; - document.getElementById("pointSizeSlider").oninput = function() { - viewer.setMinNodeSize(this.value); + //viewer.setMinNodeSize(this.value); + currentPointSize = Number(this.value); +if (currentRenderer === 'potree') { + viewer.setMinNodeSize(currentPointSize); +} else if (lidarControl) { + try { lidarControl.setPointSize(currentPointSize); } catch(e) {} +} }; const closeButton = document.getElementById("closeSideBarButton"); @@ -409,7 +509,8 @@ if (closeButton) { document.querySelectorAll('.qualityButtons').forEach(btn => { btn.addEventListener('click', () => { quality = btn.id; - if (currentPointCloud) loadPointCloud(getPointCloudFiles()[document.getElementById("pointcloud").value]); + //if (currentPointCloud) loadPointCloud(getPointCloudFiles()[document.getElementById("pointcloud").value]); + if (currentPointcloudKey) loadCurrentPointCloud(); document.querySelectorAll('.qualityButtons').forEach(b => b.classList.remove('active')); btn.classList.add('active'); }); @@ -418,32 +519,12 @@ document.querySelectorAll('.qualityButtons').forEach(btn => { document.querySelectorAll('.colorButtons').forEach(btn => { btn.addEventListener('click', () => { - if (!currentPointCloud) return; // Abbrechen, falls noch keine Wolke geladen ist - + //if (!currentPointCloud) return; // Abbrechen, falls noch keine Wolke geladen ist + document.querySelectorAll('.colorButtons').forEach(b => b.classList.remove('active')); btn.classList.add('active'); - - let value = btn.id; - console.log("WERT: " + value); - - // Greife immer das aktuelle Material ab - let currentMaterial = currentPointCloud.material; - - if (value === "rgb") { - // "rgba" stellt die echten RGB-Farben der Punkte dar - currentMaterial.activeAttributeName = "rgba"; - } else if (value === "height") { - // "elevation" wechselt auf die Einfärbung nach Höhe (Z-Wert) - currentMaterial.activeAttributeName = "elevation"; - } - - // POTREE RE-RENDER TRICK: - // Potree muss wissen, dass sich das Material verändert hat, damit die Shader neu geladen werden. - viewer.renderer.resetState(); - viewer.render(); - - // MapLibre ebenfalls Bescheid geben, dass sich die Overlays geändert haben - map.triggerRepaint(); + currentColorMode = btn.id; + applyColorMode(); }); }); @@ -456,25 +537,17 @@ map.once('idle', () => { // 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', () => { +/*map.once('load', () => { const selectBox = document.querySelector('select[name="pointcloud"]'); if (selectBox && selectBox.value) { loadPointCloud(getPointCloudFiles()[selectBox.value]); - } + }*/ // Informationen über die Punktwolken zentral in einer JSON-Datei -const pointCloudInfoFile = "info.json"; +//const pointCloudInfoFile = "info.json"; let pointCloudInfo = {}; -// die JSON-Datei laden -fetch(pointCloudInfoFile) - .then(response => response.json()) - .then(data => { - pointCloudInfo = data; - }) - .catch(error => console.error("Fehler beim Laden der JSON:", error)); - const infoPanel = document.getElementById("info-panel"); const infoPanelTitle = document.getElementById("info-panel-title"); @@ -549,5 +622,8 @@ closeInfoPanel.addEventListener("click", () => { document.querySelector('select[name="pointcloud"]').addEventListener("change", () => { updateInfoPanel(); }); +document.getElementById('rendererToggle').addEventListener('click', function() { + const next = currentRenderer === 'deckgl' ? 'potree' : 'deckgl'; + switchRenderer(next); }); diff --git a/style.css b/style.css index 913daa0..5b9776b 100644 --- a/style.css +++ b/style.css @@ -251,7 +251,7 @@ margin:0; margin-bottom: -2px; } -#pointSlider, #pointSizeSlider{ +#pointSizeSlider{ width: 100%; margin: 0; padding: 0; @@ -405,14 +405,47 @@ position: absolute; transform: translateY(-50%); z-index: 30; } +#rendererToggle { + width: 100%; + padding: 10px 16px; + border: none; + border-radius: 14px; + font-size: 13px; + font-weight: 500; + cursor: pointer; + display: flex; + align-items: center; + justify-content: space-between; + box-shadow: 0 5px 10px rgba(0,0,0,0.278); + transition: 0.2s; +} + +#rendererToggle[data-active="deckgl"] { + background: linear-gradient(135deg, rgba(18,77,216,0.92) 10%, rgba(13,61,175,0.92) 60%, rgba(6,45,135,0.92) 100%); + color: #ffffff; +} + +#rendererToggle[data-active="potree"] { + background: linear-gradient(135deg, rgba(22,163,74,0.92) 10%, rgba(15,118,54,0.92) 60%, rgba(6,78,32,0.92) 100%); + color: #ffffff; +} + +#rendererToggle:hover { + transform: translateY(-1px); + box-shadow: 0 6px 18px rgba(0,0,0,0.12); +} + +#rendererIcon { + font-size: 16px; +} #openInfoPanel { margin-top: 12px; border: none; border-radius: 14px; - width: auto; + width: 100%; padding: 10px 16px; - font-size: 17px; + font-size: 14px; font-weight: 500; cursor: pointer; background: rgba(255,255,255,0.9); @@ -429,6 +462,12 @@ position: absolute; transform: translateY(-1px); } +#openInfoPanel img { + width: 16px; + height: 16px; + object-fit: contain; +} + #info-panel { display: none; position: absolute;