292 lines
8.4 KiB
JavaScript
292 lines
8.4 KiB
JavaScript
import maplibregl from "maplibre-gl";
|
||
|
||
|
||
const center = [9.209116842757239, 52.26520546238239]
|
||
|
||
const map = new maplibregl.Map({
|
||
container: 'map',
|
||
style: "https://tiles.openfreemap.org/styles/bright",
|
||
center: center,
|
||
zoom: 17
|
||
});
|
||
|
||
map.addControl(
|
||
new maplibregl.NavigationControl({
|
||
visualizePitch: true,
|
||
showZoom: true,
|
||
showCompass: true
|
||
})
|
||
);
|
||
|
||
|
||
const elRenderArea=document.getElementById("potree_render_area");
|
||
|
||
const viewer=new Potree.Viewer(elRenderArea, {noDragAndDrop:true});
|
||
viewer.setEDLEnabled(true);
|
||
viewer.setFOV(60);
|
||
viewer.setPointBudget(3*1000*1000);
|
||
viewer.setMinNodeSize(0);
|
||
viewer.setBackground("none");
|
||
|
||
//viewer.setControls(null);
|
||
|
||
//Dateipfade der Punktwolken
|
||
const pointCloudFiles={
|
||
//Namen sind gerade nur Platzhalter. Richtige namen müssen rein
|
||
first: 'output/metadata.json',
|
||
second: 'standpunkt2/metadata.json',
|
||
third: 'punktwolke_3_converted/metadata.json',
|
||
}
|
||
//Aktuelle Datei und Sichtbarkeit
|
||
let currentPointCloud=null;
|
||
let isVisible=true;
|
||
|
||
function loadPointCloud(path){
|
||
console.log("Laden aufgerufen")
|
||
if(currentPointCloud){
|
||
viewer.scene.removePointCloud(currentPointCloud);
|
||
currentPointCloud=null;
|
||
}
|
||
|
||
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;
|
||
|
||
viewer.fitToScreen();
|
||
syncCamera();
|
||
});
|
||
}
|
||
|
||
// Geo-Koordinaten der Punktwolke (müssen zu euren Daten passen!)
|
||
// Das ist der Georeferenzpunkt – idealerweise aus den Metadaten der Punktwolke
|
||
const CLOUD_GEO_ORIGIN = {
|
||
lng: 9.209116842757239,
|
||
lat: 52.26520546238239
|
||
};
|
||
|
||
// Hilfsfunktion: MapLibre Mercator → Meter-Offset relativ zum Ursprung
|
||
function lngLatToMeters(lng, lat, originLng, originLat) {
|
||
const R = 6378137; // Erdradius in Metern (WGS84)
|
||
const dLng = (lng - originLng) * Math.PI / 180;
|
||
const dLat = (lat - originLat) * Math.PI / 180;
|
||
const dx = R * dLng * Math.cos(originLat * Math.PI / 180);
|
||
const dy = R * dLat;
|
||
return { x: dx, y: dy };
|
||
}
|
||
|
||
function syncCamera() {
|
||
if (!currentPointCloud) return;
|
||
|
||
const mapCenter = map.getCenter();
|
||
const zoom = map.getZoom();
|
||
const pitch = map.getPitch(); // Grad, 0 = top-down
|
||
const bearing = map.getBearing(); // Grad
|
||
|
||
const box = currentPointCloud.boundingBox;
|
||
const cx = (box.min.x + box.max.x) / 2;
|
||
const cy = (box.min.y + box.max.y) / 2;
|
||
const cz = (box.min.z + box.max.z) / 2;
|
||
|
||
// Radius aus Zoom ableiten (Abstand Kamera → Target)
|
||
const earthCircumference = 2 * Math.PI * 6378137;
|
||
const canvas = map.getCanvas();
|
||
const metersPerPixel = (earthCircumference * Math.cos(mapCenter.lat * Math.PI / 180))
|
||
/ (Math.pow(2, zoom) * 512);
|
||
const radius = metersPerPixel * canvas.height;
|
||
|
||
// Potree View direkt setzen
|
||
const view = viewer.scene.view;
|
||
|
||
// Target = Wolken-Zentrum (lookAt mit 3 Argumenten nutzt new Vector3(...arguments))
|
||
view.lookAt(cx, cy, cz);
|
||
|
||
// yaw = Himmelsrichtung: MapLibre bearing 0° = Nord, Potree yaw 0° = ??
|
||
// bearing in Potree-yaw umrechnen (ggf. Vorzeichen anpassen)
|
||
view.yaw = -bearing * Math.PI / 180;
|
||
|
||
// pitch: MapLibre 0° = top-down, 60° = schräg
|
||
// Potree pitch: 0 = horizontal, -PI/2 = top-down → invertieren
|
||
view.pitch = -(90 - pitch) * Math.PI / 180;
|
||
|
||
// Radius = Zoom-abhängiger Abstand
|
||
view.radius = radius;
|
||
}
|
||
|
||
map.on('move', ()=>{
|
||
console.log(viewer.scene.view)
|
||
syncCamera();
|
||
});
|
||
map.on('zoom', syncCamera);
|
||
map.on('pitch', syncCamera);
|
||
map.on('rotate', syncCamera);
|
||
|
||
|
||
|
||
|
||
// 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://mt0.google.com/vt/lyrs=s&x={x}&y={y}&z={z}",
|
||
"https://mt1.google.com/vt/lyrs=s&x={x}&y={y}&z={z}",
|
||
"https://mt2.google.com/vt/lyrs=s&x={x}&y={y}&z={z}",
|
||
"https://mt3.google.com/vt/lyrs=s&x={x}&y={y}&z={z}",
|
||
],
|
||
tileSize: 256,
|
||
},
|
||
},
|
||
layers: [{ id: "raster-layer", type: "raster", source: "raster-tiles" }],
|
||
}
|
||
break;
|
||
case "terrain":
|
||
basemapStyle = {
|
||
version: 8,
|
||
sources: {
|
||
osm: {
|
||
type: 'raster',
|
||
tiles: ['https://a.tile.openstreetmap.org/{z}/{x}/{y}.png'],
|
||
tileSize: 256,
|
||
attribution: '© OpenStreetMap Contributors',
|
||
maxzoom: 19
|
||
},
|
||
// 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: 'osm',
|
||
type: 'raster',
|
||
source: 'osm'
|
||
},
|
||
{
|
||
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: {
|
||
osm: {
|
||
type: 'raster',
|
||
tiles: [
|
||
"https://mt0.google.com/vt/lyrs=s&x={x}&y={y}&z={z}",
|
||
"https://mt1.google.com/vt/lyrs=s&x={x}&y={y}&z={z}",
|
||
"https://mt2.google.com/vt/lyrs=s&x={x}&y={y}&z={z}",
|
||
"https://mt3.google.com/vt/lyrs=s&x={x}&y={y}&z={z}",
|
||
],
|
||
tileSize: 256,
|
||
attribution: '© OpenStreetMap Contributors',
|
||
maxzoom: 19
|
||
},
|
||
// 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: 'osm',
|
||
type: 'raster',
|
||
source: 'osm'
|
||
},
|
||
{
|
||
id: 'hills',
|
||
type: 'hillshade',
|
||
source: 'hillshadeSource',
|
||
layout: {visibility: 'visible'},
|
||
paint: {'hillshade-shadow-color': '#473B24'}
|
||
}
|
||
],
|
||
terrain: {
|
||
source: 'terrainSource',
|
||
exaggeration: 1
|
||
},
|
||
sky: {}
|
||
}
|
||
|
||
}
|
||
map.setStyle(basemapStyle);
|
||
}
|
||
|
||
|
||
document.querySelector('input[type="checkbox"]').addEventListener('change', (event)=>
|
||
{
|
||
isVisible=!event.target.checked;
|
||
if (currentPointCloud){
|
||
currentPointCloud.visible=isVisible;
|
||
};
|
||
})
|
||
|
||
|
||
// 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) => {
|
||
loadPointCloud(pointCloudFiles[event.target.value]);
|
||
});
|
||
|
||
|
||
// Auf Zentrum zurück zoomen
|
||
document.getElementById("location").addEventListener("click", () => {
|
||
map.flyTo({center, zoom: 17 })
|
||
});
|
||
|