Skip to content

7 elevation range control #20

Merged
merged 4 commits into from
Oct 1, 2025
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@
type="text/css"
href="/libs/jstree/themes/mixed/style.css"
/>
<link rel="stylesheet" type="text/css" href="src/style.css" />
<link
rel="stylesheet"
type="text/css"
href="src/ElevationControl/elevationControl.css"
/>
</head>

<body>
Expand Down Expand Up @@ -53,6 +59,7 @@
<div id="potree_sidebar_container"></div>
</div>

<script src="src/ElevationControl/elevationControl.js"></script>
<script type="module">
window.viewer = new Potree.Viewer(
document.getElementById('potree_render_area')
Expand All @@ -72,6 +79,10 @@
$('#menu_scene').next().show()
$('#menu_filters').next().show()
viewer.toggleSidebar()

if (window.initElevationControls) {
window.initElevationControls(viewer)
}
})

let url = './pointclouds/data_converted/metadata.json'
Expand All @@ -82,11 +93,12 @@
material.pointSizeType = Potree.PointSizeType.ADAPTIVE
material.shape = Potree.PointShape.CIRCLE
material.activeAttributeName = 'elevation'
material.gradient = Potree.Gradients['RAINBOW']
material.gradient = Potree.Gradients['VIRIDIS']

viewer.scene.addPointCloud(pointcloud)
viewer.fitToScreen()
})
</script>
<script type="module" src="src/main.js"></script>
</body>
</html>
107 changes: 107 additions & 0 deletions src/ElevationControl/elevationControl.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
//Cerating a customized section "Elevation Control"
window.createElevationPanel = function createElevationPanel(viewer) {
const container = document.getElementById('elevation_list')
let targetContainer = container
if (!targetContainer) {
// Create a new accordion section for Elevation Control
const menu = document.getElementById('potree_menu')
if (menu) {
const header = document.createElement('h3')
header.id = 'menu_elevation'
header.innerHTML = '<span>Elevation Control</span>'
const panel = document.createElement('div')
panel.className = 'pv-menu-list'
panel.innerHTML = '<div id="elevation_list" class="auto"></div>'
const about = document.getElementById('menu_appearance')
if (about) {
menu.insertBefore(panel, about)
menu.insertBefore(header, panel)
} else {
menu.appendChild(header)
menu.appendChild(panel)
}
// Activate accordion behavior if jQuery UI accordion already initialized
if ($(menu).accordion) {
try {
$(menu).accordion('refresh')
} catch (e) {}
}
// Toggle on header click if not managed by accordion refresh
header.addEventListener(
'click',
() =>
(panel.style.display = panel.style.display === 'none' ? '' : 'none')
)
targetContainer = panel.querySelector('#elevation_list')
}
}
}

//Select the fist pointcloud in the sidebar so that the Elevation section is built
function autoSelectFirstPointCloud() {
const cloudIcon = document.querySelector(
'#scene_objects i.jstree-themeicon-custom'
)
if (cloudIcon) {
cloudIcon.dispatchEvent(new MouseEvent('click', { bubbles: true }))
return true
}
return false
}

//(re)connect the elevation labels to the slider after the container is moved (was not handled by default)
function rebindElevationLabel() {
const slider = window.jQuery ? window.jQuery('#sldHeightRange') : null
const label = document.getElementById('lblHeightRange')
if (!slider || !slider.length || !label) return

const update = () => {
const low = slider.slider('values', 0)
const high = slider.slider('values', 1)
label.textContent = `${low.toFixed(2)} to ${high.toFixed(2)}`
}

//clear any old namespaced handlers and attach fresh ones
slider.off('slide.custom slidestop.custom change.custom')
slider.on('slide.custom', update)
slider.on('slidestop.custom change.custom', update)
update()
}

//Move the elevation range section to the customised "Elevation Control" section
function moveElevationContainer() {
const target = document.getElementById('elevation_list')
const elevationContainer = document.querySelector(
'#materials\\.elevation_container'
)
if (!elevationContainer) return false
target.appendChild(elevationContainer)
rebindElevationLabel()
return true
}

//initiate and orchestrate all funcitons to render the Evelation control section of the sidebar propperly
window.initElevationControls = function initElevationControls(viewer) {

//Creates the section
createElevationPanel(viewer)

//Only move the ElevationContainer if the source container to exist
const menu =
document.getElementById('potree_menu') ||
document.getElementById('menu') ||
document.body
const observer = new MutationObserver(() => {
const found = document.querySelector('#materials\\.elevation_container')
if (found) {
observer.disconnect()
//Move and rebind once it exists
const ok = moveElevationContainer()
if (!ok) console.warn('[Elevation] moveElevationContainer failed')
}
})
observer.observe(menu, { childList: true, subtree: true })

//Trigger Potree to build Materials UI by selecting the first point cloud (if nothing selected yet)
autoSelectFirstPointCloud()
}
1 change: 0 additions & 1 deletion src/main.js
Original file line number Diff line number Diff line change
@@ -1 +0,0 @@
/* Empty for now, add logic later */
1 change: 0 additions & 1 deletion src/style.css
Original file line number Diff line number Diff line change
@@ -1 +0,0 @@
/* Empty for now, add styles later */