diff --git a/main.js b/main.js index f498747..7d0837f 100644 --- a/main.js +++ b/main.js @@ -1,4 +1,191 @@ -/*import maplibregl from "maplibre-gl"; +import maplibregl from "maplibre-gl"; +import proj4 from "proj4"; +import * as THREE from "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, +}); + +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)}°`; +}); + +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.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; + +var quality = 'medium'; + +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`, + }; +} + +let currentPointCloud = null; +let isVisible = true; + +function loadPointCloud(path) { + if (currentPointCloud) { + const index = viewer.scene.pointclouds.indexOf(currentPointCloud); + if (index !== -1) viewer.scene.pointclouds.splice(index, 1); + 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); + + let material = currentPointCloud.material; + material.size = 1; + material.pointSizeType = Potree.PointSizeType.ADAPTIVE; + + viewer.fitToScreen(); + setTimeout(() => syncCamera(), 500); + }); +} + +function syncCamera() { + if (!currentPointCloud) return; + + const center = map.getCenter(); + const [x, y] = proj4("EPSG:4326", "EPSG:25832", [center.lng, center.lat]); + + const pitch = map.getPitch() * Math.PI / 180; + const bearing = map.getBearing() * Math.PI / 180; + const zoom = map.getZoom(); + + const earthCircumference = 40075016.686; + const metersPerPixel = earthCircumference * Math.cos(center.lat * Math.PI / 180) / Math.pow(2, zoom + 8); + const distance = metersPerPixel * (map.getCanvas().height / 2) / Math.cos(pitch); + + const target = new THREE.Vector3(x, y, 0); + const offset = new THREE.Vector3(0, -distance * Math.sin(pitch), distance * Math.cos(pitch)); + offset.applyAxisAngle(new THREE.Vector3(0, 0, 1), -bearing); + + const cameraPosition = target.clone().add(offset); + + viewer.scene.view.position.copy(cameraPosition); + viewer.scene.view.lookAt(target); + viewer.renderer.resetState(); +} + +map.on('move', syncCamera); +map.on('zoom', syncCamera); +map.on('pitch', syncCamera); +map.on('rotate', syncCamera); + +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 }, 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: {} }; + break; + } + map.setStyle(basemapStyle); +} + +document.querySelector('#disable').addEventListener('click', function() { + isVisible = !isVisible; + if (currentPointCloud) currentPointCloud.visible = isVisible; + this.textContent = isVisible ? "Punktwolke ausblenden" : "Punktwolke anzeigen"; +}); + +document.querySelector('select[name="basemap"]').addEventListener('change', (e) => changeBaseMap(e.target.value)); + +document.querySelector('select[name="pointcloud"]').addEventListener('change', (e) => { + loadPointCloud(getPointCloudFiles()[e.target.value]); +}); + +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); +}; + +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`; + openButton.addEventListener("click", () => { + sidebar.style.display = "flex"; + openOuter.innerHTML = ""; + }); + }); +} + +document.querySelectorAll('.qualityButtons').forEach(btn => { + btn.addEventListener('click', () => { + quality = btn.id; + if (currentPointCloud) loadPointCloud(getPointCloudFiles()[document.getElementById("pointcloud").value]); + document.querySelectorAll('.qualityButtons').forEach(b => b.classList.remove('active')); + btn.classList.add('active'); + }); +}); + +document.querySelectorAll('.colorButtons').forEach(btn => { + btn.addEventListener('click', () => { + document.querySelectorAll('.colorButtons').forEach(b => b.classList.remove('active')); + btn.classList.add('active'); + }); +});/* + +import maplibregl from "maplibre-gl"; import proj4 from "proj4"; import * as THREE from "three"; console.log(THREE); @@ -17,6 +204,7 @@ const map = new maplibregl.Map({ zoom: 17, maxZoom: 24, }); +window.map=map; map.addControl( new maplibregl.NavigationControl({ @@ -43,6 +231,9 @@ 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); @@ -101,6 +292,7 @@ function loadPointCloud(path){ currentPointCloud=e.pointcloud; viewer.scene.addPointCloud(currentPointCloud); + // View-Objekt inspizieren console.log("view:", viewer.scene.view); console.log("view.lookAt:", viewer.scene.view.lookAt); @@ -111,78 +303,66 @@ function loadPointCloud(path){ let material =currentPointCloud.material; material.size =1; material.pointSizeType=Potree.PointSizeType.ADAPTIVE; + material.activeAttributeName="rgba"; - viewer.fitToScreen(); - setTimeout(() => syncCamera(), 500); + }); } +const originMercator = maplibregl.MercatorCoordinate.fromLngLat( + { lng: center[0], lat: center[1] }, 0 +); +const metersToMercator = originMercator.meterInMercatorCoordinateUnits(); -function syncCamera() { +const potreeLayer = { + id: "potree-pointcloud", + type: "custom", + renderingMode: "3d", - if (!currentPointCloud) return; + onAdd(map, gl) { + this.map = map; + this.camera = new THREE.Camera(); +}, - const center = map.getCenter(); + onRemove(){ + this.renderer.dispose(); + this.renderer=null; + }, - // ----------------------------------------- - // WGS84 -> ETRS89 / UTM32 - // ----------------------------------------- + render(gl, args) { + if (!currentPointCloud) return; - const [x, y] = proj4( - "EPSG:4326", - "EPSG:25832", - [center.lng, center.lat] - ); + const [originX, originY] = proj4("EPSG:4326", "EPSG:25832", [center[0], center[1]]); - // ----------------------------------------- - // Map Parameter - // ----------------------------------------- + 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); - const pitch = map.getPitch() * Math.PI / 180; - const bearing = map.getBearing() * Math.PI / 180; - const zoom = map.getZoom(); + const projMatrix = m.multiply(l); - // ----------------------------------------- - // Abstand abhängig vom Zoom - // ----------------------------------------- - const earthCircumference = 40075016.686; - const metersPerPixel = earthCircumference * Math.cos(center.lat * Math.PI / 180) / Math.pow(2, zoom + 8); - const distance = metersPerPixel * (map.getCanvas().height/2); + // MapLibre Matrix direkt auf Potree's eigene Kamera setzen + const potreeCamera = viewer.scene.getActiveCamera(); + potreeCamera.projectionMatrix.copy(projMatrix); + potreeCamera.projectionMatrixInverse.copy(projMatrix.clone().invert()); - // ----------------------------------------- - // Zielpunkt = Kartenzentrum - // ----------------------------------------- - const target = new THREE.Vector3(x, y, 0); + // Potree normal rendern lassen in eigenem Canvas + viewer.update(viewer.clock.getDelta(), performance.now()); + viewer.renderDefault(); - // ----------------------------------------- - // Kameraoffset - // ----------------------------------------- - const offset = new THREE.Vector3(0, -distance * Math.sin(pitch), distance * Math.cos(pitch) - ); - - // Bearing rotieren - offset.applyAxisAngle(new THREE.Vector3(0, 0, 1), -bearing); - - // ----------------------------------------- - // Kameraposition - // ----------------------------------------- - const cameraPosition = target.clone().add(offset); - - // ----------------------------------------- - // Potree Kamera setzen - // ----------------------------------------- - - viewer.scene.view.position.copy(cameraPosition); - viewer.scene.view.lookAt(target); - viewer.renderer.resetState(); -} - -// Kameras bei jeder Kartenbewegung synchronisieren - map.on('move', syncCamera); - map.on('zoom', syncCamera); - map.on('pitch', syncCamera); - map.on('rotate', syncCamera); + this.map.triggerRepaint(); +}, +}; +map.on("style.load", () => { + map.addLayer(potreeLayer); +}); @@ -306,6 +486,9 @@ function changeBaseMap(newMap){ } map.setStyle(basemapStyle); + map.once("style.load", ()=> { + map.addLayer(potreeLayer); + }); } @@ -433,278 +616,4 @@ colorButtons.forEach(button => { }); -});*/ -import maplibregl from "maplibre-gl"; -import proj4 from "proj4"; -import * as THREE from "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, - canvasContextAttributes: { antialias: true }, -}); - -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)}°`; -}); - -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.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; - -const originLngLat = { lng: center[0], lat: center[1] }; -const originMercator = maplibregl.MercatorCoordinate.fromLngLat(originLngLat, 0); -const metersToMercator = originMercator.meterInMercatorCoordinateUnits(); - -const potreeLayer = { - id: "potree-pointcloud", - type: "custom", - renderingMode: "3d", - - onAdd(map, gl) { - this.map = map; - this.gl = gl; - this.camera = new THREE.Camera(); - this.renderer = new THREE.WebGLRenderer({ - canvas: map.getCanvas(), - context: gl, - antialias: true, - }); - this.renderer.autoClear = false; - this.scene = new THREE.Scene(); - }, - - render(gl, args) { - if (!currentPointCloud) return; - - const m = new THREE.Matrix4().fromArray( - args.defaultProjectionData.mainMatrix - ); - - const [originX, originY] = proj4("EPSG:4326", "EPSG:25832", [ - center[0], - center[1], - ]); - - const l = new THREE.Matrix4() - .makeTranslation( - -originX * metersToMercator + originMercator.x, - originY * metersToMercator - originMercator.y, - 0 - ) - .premultiply( - new THREE.Matrix4().makeScale( - metersToMercator, - -metersToMercator, - metersToMercator - ) - ); - - this.camera.projectionMatrix = m.multiply(l); - - this.renderer.resetState(); - this.renderer.render(viewer.scene.scene, this.camera); - this.map.triggerRepaint(); - }, -}; - -map.on("style.load", () => { - map.addLayer(potreeLayer); -}); - -var quality = "medium"; -let currentPointCloud = null; -let isVisible = true; - -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`, - }; -} - -function loadPointCloud(path) { - if (currentPointCloud) { - const index = viewer.scene.pointclouds.indexOf(currentPointCloud); - if (index !== -1) viewer.scene.pointclouds.splice(index, 1); - if (currentPointCloud.parent) currentPointCloud.parent.remove(currentPointCloud); - currentPointCloud = null; - map.triggerRepaint(); - } - - if (!path || !isVisible) return; - - Potree.loadPointCloud(path, "punktwolke", function (e) { - currentPointCloud = e.pointcloud; - viewer.scene.addPointCloud(currentPointCloud); - - let material = currentPointCloud.material; - material.size = 1; - material.pointSizeType = Potree.PointSizeType.ADAPTIVE; - - map.triggerRepaint(); - }); -} - -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 }, - 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: {}, - }; - break; - } - map.setStyle(basemapStyle); - map.once("style.load", () => { - map.addLayer(potreeLayer); - }); -} - -document.querySelector("#disable").addEventListener("click", function () { - isVisible = !isVisible; - if (currentPointCloud) currentPointCloud.visible = isVisible; - this.textContent = isVisible ? "Punktwolke ausblenden" : "Punktwolke anzeigen"; -}); - -document.querySelector('select[name="basemap"]').addEventListener("change", (e) => { - changeBaseMap(e.target.value); -}); - -document.querySelector('select[name="pointcloud"]').addEventListener("change", (e) => { - const files = getPointCloudFiles(); - loadPointCloud(files[e.target.value]); -}); - -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); -}; - -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`; - openButton.addEventListener("click", () => { - sidebar.style.display = "flex"; - openOuter.innerHTML = ""; - }); - }); -} - -document.querySelectorAll(".qualityButtons").forEach((btn) => { - btn.addEventListener("click", () => { - quality = btn.id; - if (currentPointCloud) { - const files = getPointCloudFiles(); - loadPointCloud(files[document.getElementById("pointcloud").value]); - } - document.querySelectorAll(".qualityButtons").forEach((b) => b.classList.remove("active")); - btn.classList.add("active"); - }); -}); - -document.querySelectorAll(".colorButtons").forEach((btn) => { - btn.addEventListener("click", () => { - document.querySelectorAll(".colorButtons").forEach((b) => b.classList.remove("active")); - btn.classList.add("active"); - }); -}); \ No newline at end of file +});*/ \ No newline at end of file