Commit d2df398a authored by Alfakhori's avatar Alfakhori
Browse files

optimisation

parent 6d8f61ae
Pipeline #12467 passed with stage
in 26 seconds
This diff is collapsed.
...@@ -4,6 +4,18 @@ let userIcon; ...@@ -4,6 +4,18 @@ let userIcon;
let intervalId; let intervalId;
let modeMarkers = []; let modeMarkers = [];
// PERFORMANCE: Reuse one Vector3 instead of allocating a new
// Vector3 every time updateMap() runs.
let cameraPosition = new THREE.Vector3();
// PERFORMANCE: Cache the map window element once.
let mapWindow = document.getElementById("map-window");
// PERFORMANCE: Remember the last mapped camera position so Leaflet
// is updated only after the user has actually moved.
let lastMapX = null;
let lastMapZ = null;
// ============================================================ // ============================================================
// Proposed plan overlay // Proposed plan overlay
// ============================================================ // ============================================================
...@@ -24,253 +36,141 @@ let planVisible = false; ...@@ -24,253 +36,141 @@ let planVisible = false;
// Longitude = 8.010410216 // Longitude = 8.010410216
const planBounds = [ const planBounds = [
[48.405858385, 7.997080070], // Southwest / bottom-left [48.405858385, 7.99708007],
[48.414966828, 8.010410216] // Northeast / top-right [48.414966828, 8.010410216],
]; ];
const earthRadius = 6378137; // Erdradius in Metern (WGS84) const earthRadius = 6378137;
// ============================================================ // ============================================================
// Initialize map // Initialize map
// ============================================================ // ============================================================
function init_map() { function init_map() {
const mapContainer = document.getElementById("map-container"); const mapContainer = document.getElementById("map-container");
if (mapContainer) { if (mapContainer) {
if (!init) { if (!init) {
// ====================================================
// Create Leaflet map
// ====================================================
mymap = L.map(mapContainer); mymap = L.map(mapContainer);
// ====================================================
// OpenStreetMap Germany basemap
// ====================================================
var OpenStreetMap_DE = L.tileLayer( var OpenStreetMap_DE = L.tileLayer(
'https://tile.openstreetmap.de/{z}/{x}/{y}.png', "https://tile.openstreetmap.de/{z}/{x}/{y}.png",
{ {
//maxZoom: 20,
attribution: attribution:
'&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors' '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
} },
); );
OpenStreetMap_DE.addTo(mymap); OpenStreetMap_DE.addTo(mymap);
// ====================================================
// User icon
// ====================================================
userIcon = L.icon({ userIcon = L.icon({
iconUrl: 'assets/previewImages/map-user.png', iconUrl: "assets/previewImages/map-user.png",
iconSize: [32, 32], iconSize: [32, 32],
iconAnchor: [16, 32], iconAnchor: [16, 32],
popupAnchor: [0, -32] popupAnchor: [0, -32],
}); });
// ====================================================
// Initial map position
// ====================================================
//
// The map is centered on the proposed plan instead
// of the user's current GPS position.
//
// We use fitBounds() so the whole plan is visible.
//
mymap.fitBounds(planBounds, { mymap.fitBounds(planBounds, {
padding: [20, 20] padding: [20, 20],
}); });
userIcon = L.marker([geoLocation.latitude, geoLocation.longitude], {
// ==================================================== icon: userIcon,
// User position marker })
// ==================================================== .bindPopup("Ihre Position")
userIcon = L.marker(
[geoLocation.latitude, geoLocation.longitude],
{
icon: userIcon
}
)
.bindPopup('Ihre Position')
.addTo(mymap); .addTo(mymap);
init = true; init = true;
} }
// ======================================================== // ========================================================
// Remove old model markers // Remove old model markers
// ======================================================== // ========================================================
modeMarkers.forEach(marker => { modeMarkers.forEach((marker) => {
marker.remove(); marker.remove();
}); });
// Clear marker array
modeMarkers = []; modeMarkers = [];
// ======================================================== // ========================================================
// Add currently placed models to map // Add currently placed models to map
// ======================================================== // ========================================================
const models = getAllPlacedModels(); const models = getAllPlacedModels();
models.forEach(model => { models.forEach((model) => {
const { lat, lng } = threeToLeaflet(model.position.x, model.position.z);
const { lat, lng } = threeToLeaflet( const modelMarker = L.marker([lat, lng], {
model.position.x,
model.position.z
);
const modelMarker = L.marker(
[lat, lng],
{
icon: L.icon({ icon: L.icon({
iconUrl: model.modelConfig.image, iconUrl: model.modelConfig.image,
iconSize: [16, 16], iconSize: [16, 16],
iconAnchor: [16, 32], iconAnchor: [16, 32],
popupAnchor: [0, -32] popupAnchor: [0, -32],
}),
}) })
}
)
.addTo(mymap) .addTo(mymap)
.bindPopup( .bindPopup(model.modelConfig?.name || "Unbenannt");
model.modelConfig?.name || "Unbenannt"
);
modeMarkers.push(modelMarker); modeMarkers.push(modelMarker);
}); });
// ======================================================== // ========================================================
// Add proposed plan // Add proposed plan
// ======================================================== // ========================================================
addPlanOverlay(); addPlanOverlay();
// ======================================================== // ========================================================
// Make sure Leaflet knows the map container dimensions // Make sure Leaflet knows the map container dimensions
// ======================================================== // ========================================================
setTimeout(() => { setTimeout(() => {
centerOnPlan(); centerOnPlan();
}, 100); }, 100);
// ======================================================== // ========================================================
// Update map position continuously // Update map position continuously
// ======================================================== // ========================================================
// PERFORMANCE: Start only one map update interval.
if (!intervalId) {
intervalId = setInterval(updateMap, 500); intervalId = setInterval(updateMap, 500);
} }
}
} }
// ============================================================ // ============================================================
// Center map on proposed plan // Center map on proposed plan
// ============================================================ // ============================================================
function centerOnPlan() { function centerOnPlan() {
if (!mymap) { if (!mymap) {
console.error("Map ist noch nicht initialisiert.");
console.error(
"Map ist noch nicht initialisiert."
);
return; return;
} }
// Tell Leaflet to recalculate the map container size.
// This is important because map-window may initially
// be hidden when the map is initialized.
mymap.invalidateSize(); mymap.invalidateSize();
mymap.fitBounds(planBounds, {
// Center and zoom the map on the proposed plan. padding: [20, 20],
});
mymap.fitBounds(
planBounds,
{
padding: [20, 20]
}
);
} }
// ============================================================ // ============================================================
// Add georeferenced proposed plan // Add georeferenced proposed plan
// ============================================================ // ============================================================
//
// Original coordinate system:
// DHDN / Gauss-Krüger Zone 3
// EPSG:31467
//
// Image extent:
//
// Southwest:
// X = 3425822.00
// Y = 5363602.00
//
// Northeast:
// X = 3426822.00
// Y = 5364602.00
//
// Converted to WGS84:
//
// Southwest:
// Latitude = 48.405858385
// Longitude = 7.997080070
//
// Northeast:
// Latitude = 48.414966828
// Longitude = 8.010410216
//
// Image:
//
// assets/plans/proposed-plan.png
// ============================================================
function addPlanOverlay() { function addPlanOverlay() {
if (!mymap) { if (!mymap) {
console.error("Map ist noch nicht initialisiert.");
console.error(
"Map ist noch nicht initialisiert."
);
return; return;
} }
// ========================================================
// If overlay already exists, show it
// ========================================================
if (planOverlay) { if (planOverlay) {
planOverlay.addTo(mymap); planOverlay.addTo(mymap);
planVisible = true; planVisible = true;
...@@ -278,45 +178,25 @@ function addPlanOverlay() { ...@@ -278,45 +178,25 @@ function addPlanOverlay() {
return; return;
} }
planOverlay = L.imageOverlay("assets/plans/proposed-plan.png", planBounds, {
// ========================================================
// Create image overlay
// ========================================================
planOverlay = L.imageOverlay(
'assets/plans/proposed-plan.png',
planBounds,
{
// Transparency
opacity: 0.7, opacity: 0.7,
interactive: false,
// The plan does not capture mouse/touch events });
interactive: false
}
);
// ========================================================
// Add overlay to map
// ========================================================
planOverlay.addTo(mymap); planOverlay.addTo(mymap);
planVisible = true; planVisible = true;
} }
// ============================================================ // ============================================================
// Update map // Update map
// ============================================================ // ============================================================
function updateMap() { function updateMap() {
// The interval is normally stopped by closeMap().
if ( // This guard also handles cases where the map is hidden
document.getElementById("map-window").style.display === 'none' // by another UI action.
&& intervalId if (mapWindow && mapWindow.style.display === "none" && intervalId) {
) {
clearInterval(intervalId); clearInterval(intervalId);
intervalId = null; intervalId = null;
...@@ -324,176 +204,121 @@ function updateMap() { ...@@ -324,176 +204,121 @@ function updateMap() {
return; return;
} }
if (!camera || !userIcon) {
return;
}
let vec = new THREE.Vector3(); // PERFORMANCE: Reuse the same Vector3 object.
camera.getWorldPosition(cameraPosition);
const userPosition = camera.getWorldPosition(vec);
const { lat, lng } = threeToLeaflet( // PERFORMANCE: Do not update Leaflet if the user
userPosition.x, // has not moved.
userPosition.z if (
); lastMapX !== null &&
Math.abs(cameraPosition.x - lastMapX) < 0.1 &&
Math.abs(cameraPosition.z - lastMapZ) < 0.1
) {
return;
}
lastMapX = cameraPosition.x;
lastMapZ = cameraPosition.z;
if (userIcon) { const { lat, lng } = threeToLeaflet(cameraPosition.x, cameraPosition.z);
userIcon.setLatLng([ userIcon.setLatLng([lat, lng]);
lat,
lng
]);
}
} }
// ============================================================ // ============================================================
// Convert Three.js coordinates to Leaflet coordinates // Convert Three.js coordinates to Leaflet coordinates
// ============================================================ // ============================================================
function threeToLeaflet(threeX, threeZ) { function threeToLeaflet(threeX, threeZ) {
if (!geoLocation) { if (!geoLocation) {
console.error("GeoLocation ist noch nicht verfügbar");
console.error(
"GeoLocation ist noch nicht verfügbar"
);
return; return;
} }
const originLat = geoLocation.latitude; const originLat = geoLocation.latitude;
const originLng = geoLocation.longitude;
const deltaLat = const originLng = geoLocation.longitude;
(threeZ / earthRadius) *
(180 / Math.PI);
const deltaLat = (threeZ / earthRadius) * (180 / Math.PI);
const deltaLng = const deltaLng =
( (threeX / (earthRadius * Math.cos((Math.PI * originLat) / 180))) *
threeX /
(
earthRadius *
Math.cos(
Math.PI * originLat / 180
)
)
) *
(180 / Math.PI); (180 / Math.PI);
const globalLat = originLat + deltaLat;
const globalLat = const globalLng = originLng + deltaLng;
originLat + deltaLat;
const globalLng =
originLng + deltaLng;
return { return {
lat: globalLat, lat: globalLat,
lng: globalLng lng: globalLng,
}; };
} }
// ============================================================ // ============================================================
// Convert Leaflet coordinates to Three.js coordinates // Convert Leaflet coordinates to Three.js coordinates
// ============================================================ // ============================================================
function leafletToThree(lat, lng) { function leafletToThree(lat, lng) {
if (!geoLocation) { if (!geoLocation) {
console.error("GeoLocation ist noch nicht verfügbar");
console.error(
"GeoLocation ist noch nicht verfügbar"
);
return; return;
} }
const originLat = geoLocation.latitude; const originLat = geoLocation.latitude;
const originLng = geoLocation.longitude;
const deltaLat =
lat - originLat;
const deltaLng = const originLng = geoLocation.longitude;
lng - originLng;
const deltaLat = lat - originLat;
const threeZ = const deltaLng = lng - originLng;
deltaLat *
(Math.PI / 180) *
earthRadius;
const threeZ = deltaLat * (Math.PI / 180) * earthRadius;
const threeX = const threeX =
deltaLng * deltaLng *
(Math.PI / 180) * (Math.PI / 180) *
earthRadius * earthRadius *
Math.cos( Math.cos((Math.PI * originLat) / 180);
Math.PI * originLat / 180
);
return { return {
x: threeX, x: threeX,
z: threeZ z: threeZ,
}; };
} }
// ============================================================ // ============================================================
// Round number // Round number
// ============================================================ // ============================================================
function roundTo(n, digits) { function roundTo(n, digits) {
var negative = false; var negative = false;
if (digits === undefined) { if (digits === undefined) {
digits = 0; digits = 0;
} }
if (n < 0) { if (n < 0) {
negative = true; negative = true;
n = n * -1; n = n * -1;
} }
var multiplicator = Math.pow(10, digits);
var multiplicator = n = parseFloat((n * multiplicator).toFixed(11));
Math.pow(10, digits);
n = parseFloat(
(n * multiplicator).toFixed(11)
);
n =
(
Math.round(n) /
multiplicator
).toFixed(digits);
n = (Math.round(n) / multiplicator).toFixed(digits);
if (negative) { if (negative) {
n = (n * -1).toFixed(digits);
n =
(n * -1).toFixed(digits);
} }
return parseFloat(n); return parseFloat(n);
} }
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment