Skip to content

Commit

Permalink
Merge pull request #42 from TDT4290-group-4/13-minimap
Browse files Browse the repository at this point in the history
13 minimap
  • Loading branch information
adriahso authored Oct 27, 2025
2 parents 5f93b94 + df56307 commit 9186fa3
Show file tree
Hide file tree
Showing 2 changed files with 157 additions and 1 deletion.
154 changes: 154 additions & 0 deletions src/MiniMap/miniMap.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
/**
* Initializes the Potree minimap to work with offline map and EPSG:4978 coordinates.
*
* @param {Potree.Viewer} viewer - The Potree viewer instance
*/
export function initMiniMap(viewer) {
if (!viewer.mapView) return
const map = viewer.mapView.map
const layers = map.getLayers()

replaceMiniMapLayers(layers)

removeTileTools(map)

overrideMapViewUpdate(viewer)

setMiniMapBackground(map, '#d6ecff')

// Transform minimap center [lon, lat] from EPSG:4326 to EPSG:3857
const center = proj4('EPSG:4326', 'EPSG:3857', [2, 69])
map.getView().setCenter(center)
}

/**
* Sets the background color for the Minimap so that it is not seethrough.
* Makes it easier to get an overview when deep in a survey.
*
* @param {*} map
* @param {*} color
*/
function setMiniMapBackground(map, color) {
// OL ≥ 6.5 supports a map background property
try {
map.set && map.set('background', color)
} catch {}

// Fallbacks that work on older OL + Potree
const viewport = map.getViewport && map.getViewport()
if (viewport) viewport.style.background = color

const target = map.getTargetElement && map.getTargetElement()
if (target) target.style.background = color

// As a last resort, paint the canvas background
const canvas = viewport && viewport.querySelector('canvas')
if (canvas) canvas.style.background = color
}

/**
* Replaces default Open Street Map layer with custom GeoJSON in order for it to work offline.
* Also removes the extent layer.
*
* @param {ol.Collection} layers - Collection of OpenLayers layers
*/
function replaceMiniMapLayers(layers) {
// Remove the old Open Street Map layer
const oldOSMLayer = layers.item(0)
layers.remove(oldOSMLayer)

// Add new offline GeoJSON layer
const newGeojsonLayer = new ol.layer.Vector({
source: new ol.source.Vector({
url: '/data/geo/world_simplified.geojson',
format: new ol.format.GeoJSON()
})
})
layers.insertAt(0, newGeojsonLayer)

// Remove the extent layer
const extentLayer = layers.item(6)
layers.remove(extentLayer)
}

/**
* Removes the tools for downloading and showing/hiding tiles, denoted D and T in the minimap.
*
* @param {ol.Map} map - The OpenLayers map instance
*/
function removeTileTools(map) {
map.getControls().forEach((control) => {
if (
control.constructor &&
control.constructor.name === 'DownloadSelectionControl'
) {
map.removeControl(control)
}
})
}

/**
* Overrides the minimap pointer update logic to use 3D coordinates and correct direction.
*
* @param {Potree.Viewer} viewer - The Potree viewer instance
*/
function overrideMapViewUpdate(viewer) {
const Vector3 = THREE.Vector3
const Vector2 = THREE.Vector2
viewer.mapView.update = function (delta) {
if (!this.sceneProjection) {
return
}

let pm = $('#potree_map')

if (!this.enabled) {
return
}

let mapSize = this.map.getSize()
let resized = pm.width() !== mapSize[0] || pm.height() !== mapSize[1]
if (resized) {
this.map.updateSize()
}

let camera = this.viewer.scene.getActiveCamera()

let scale = this.map.getView().getResolution()
let campos = camera.position
let camdir = camera.getWorldDirection(new Vector3())
let sceneLookAt = camdir
.clone()
.multiplyScalar(30 * scale)
.add(campos)
let geoPos = camera.position
let geoLookAt = sceneLookAt

// Include z-coordinate to handle EPSG:4978 properly
let mapPos = new Vector2().fromArray(
this.toMap.forward([geoPos.x, geoPos.y, geoPos.z])
)
let mapLookAt = new Vector2().fromArray(
this.toMap.forward([geoLookAt.x, geoLookAt.y, geoLookAt.z])
)

// Reverse direction so pointer faces correct way
let mapDir = new Vector2().subVectors(mapPos, mapLookAt).normalize()

mapLookAt = mapPos.clone().add(mapDir.clone().multiplyScalar(30 * scale))
let mapLength = mapPos.distanceTo(mapLookAt)
let mapSide = new Vector2(-mapDir.y, mapDir.x)

let p1 = mapPos.toArray()
let p2 = mapLookAt
.clone()
.sub(mapSide.clone().multiplyScalar(0.3 * mapLength))
.toArray()
let p3 = mapLookAt
.clone()
.add(mapSide.clone().multiplyScalar(0.3 * mapLength))
.toArray()

this.gCamera.setCoordinates([p1, p2, p3, p1])
}
}
4 changes: 3 additions & 1 deletion src/potreeViewer.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { initAnnotationsPanel } from './AnnotationControl/annotationPanel.js'
import { initMeasurementsPanel } from './MeasurementControl/measurementsPanel.js'
import { initMiniMap } from './MiniMap/miniMap.js'
import {
initThreePanels,
toggleAcceptedLegend
Expand Down Expand Up @@ -126,11 +127,12 @@ export async function createPotreeViewer(

initMeasurementsPanel(viewer)
initAnnotationsPanel(viewer)
initMiniMap(viewer)
})

// Initialize camera position and target point (manually chosen)
viewer.scene.view.setView(
[3961574.044, 1494736.334, 8348318.575], // Initial camera position
[4094989.813, 59057.337, 8363694.681], // Initial camera position
[1500922.651, 510673.03, 5427934.722] // Initial target point
)

Expand Down

0 comments on commit 9186fa3

Please sign in to comment.