From 9c0c73d10712f093dff9aa18cfc9d78da5c80235 Mon Sep 17 00:00:00 2001 From: franmagn Date: Wed, 29 Oct 2025 12:55:44 +0100 Subject: [PATCH] fix(#47): :bug: fix conflict bug with other measurement tools visualization fixed a graphic bug that made not possible to see x,y and z coordinates on other measurement tools sections in the sidebar, and that showed Latitude, Longitude and Elevation in those sections --- src/MeasurementControl/measurementsPanel.js | 107 +++++++++++++++++--- 1 file changed, 94 insertions(+), 13 deletions(-) diff --git a/src/MeasurementControl/measurementsPanel.js b/src/MeasurementControl/measurementsPanel.js index 1152df6..a64202f 100644 --- a/src/MeasurementControl/measurementsPanel.js +++ b/src/MeasurementControl/measurementsPanel.js @@ -8,7 +8,7 @@ import { ecef, wgs84 } from '../config.js' */ export function initMeasurementsPanel(viewer) { // Track last selected measurement label for dynamic data title - const lastSelection = { uuid: null, label: '' } + const lastSelection = { uuid: null, label: '', type: null } // Resolve or create measurements container in Potree menu const existingListContainer = document.getElementById('measurements_list') let targetContainer = existingListContainer @@ -198,6 +198,15 @@ export function initMeasurementsPanel(viewer) { } } } + // Set or remove the mounted marker to run only for + // single-point measurements. + try { + if (lastSelection && lastSelection.type === 'Point') { + originalPropertiesPanel.setAttribute('data-mp-mounted', '1') + } else { + originalPropertiesPanel.removeAttribute('data-mp-mounted') + } + } catch (e) {} requestAnimationFrame(() => { roundCoordinates(originalPropertiesPanel) insertLatLonRows(originalPropertiesPanel) @@ -212,6 +221,7 @@ export function initMeasurementsPanel(viewer) { originalPropertiesPanel, placeholder.nextSibling ) + try { originalPropertiesPanel.removeAttribute('data-mp-mounted') } catch (e) {} } if (targetContainer && targetContainer.children.length === 0) { targetContainer.innerHTML = '' @@ -236,6 +246,11 @@ export function initMeasurementsPanel(viewer) { if (!originalPropertiesPanel || coordRoundObserver) return coordRoundObserver = new MutationObserver(() => { requestAnimationFrame(() => { + // Only run post-processing when the properties panel is mounted into + // our measurements area. + if (!originalPropertiesPanel) return + const mounted = originalPropertiesPanel.getAttribute && originalPropertiesPanel.getAttribute('data-mp-mounted') === '1' + if (!mounted) return roundCoordinates(originalPropertiesPanel) pruneMeasurementRows(originalPropertiesPanel) insertLatLonRows(originalPropertiesPanel) @@ -248,25 +263,43 @@ export function initMeasurementsPanel(viewer) { } function roundCoordinates(rootEl) { + if (!rootEl) rootEl = originalPropertiesPanel if (!rootEl) return + // Only run post-processing when the properties panel is mounted into + // our measurements area. + const mounted = originalPropertiesPanel && originalPropertiesPanel.getAttribute && originalPropertiesPanel.getAttribute('data-mp-mounted') === '1' + if (!mounted) return // Find first table that has a header row with th: x y z const tables = rootEl.querySelectorAll('table.measurement_value_table') let coordTable = null + const looksLikeNumber = (s) => { + if (!s) return false + const cleaned = (s + '').replace(/[^0-9+\-.,eE]/g, '').replace(/,+/g, '') + return /[-+]?\d*\.?\d+(e[-+]?\d+)?/.test(cleaned) + } for (const tbl of tables) { const headerRow = tbl.querySelector('tr') - if (!headerRow) continue - const ths = [...headerRow.querySelectorAll('th')].map((th) => - (th.textContent || '').trim().toLowerCase() - ) - if ( - ths.length >= 3 && - ths[0] === 'x' && - ths[1] === 'y' && - ths[2] === 'z' - ) { - coordTable = tbl - break + let found = false + if (headerRow) { + const ths = [...headerRow.querySelectorAll('th')].map((th) => + (th.textContent || '').trim().toLowerCase() + ) + if (ths.length >= 3 && ths[0] === 'x' && ths[1] === 'y' && ths[2] === 'z') { + coordTable = tbl + break + } + } + // Fallback: detect a row with 3 numeric td cells (some panels use td headers) + const rows = Array.from(tbl.querySelectorAll('tr')) + for (const r of rows) { + const tds = Array.from(r.querySelectorAll('td')) + if (tds.length >= 3 && tds.every((td) => looksLikeNumber(td.textContent))) { + coordTable = tbl + found = true + break + } } + if (found) break } if (!coordTable) return @@ -296,6 +329,10 @@ export function initMeasurementsPanel(viewer) { function pruneMeasurementRows(rootEl) { if (!rootEl) rootEl = originalPropertiesPanel if (!rootEl) return + // Only run post-processing when the properties panel is mounted into + // our measurements area. + const mounted = originalPropertiesPanel && originalPropertiesPanel.getAttribute && originalPropertiesPanel.getAttribute('data-mp-mounted') === '1' + if (!mounted) return const tables = rootEl.querySelectorAll('table.measurement_value_table') if (!tables || tables.length === 0) return // Labels we want to keep @@ -312,6 +349,11 @@ export function initMeasurementsPanel(viewer) { // Detect if this table is the coordinates table (header with th: x y z) const headerRow = tbl.querySelector('tr') let isCoordTable = false + const looksLikeNumber = (s) => { + if (!s) return false + const cleaned = (s + '').replace(/[^0-9+\-.,eE]/g, '').replace(/,+/g, '') + return /[-+]?\d*\.?\d+(e[-+]?\d+)?/.test(cleaned) + } if (headerRow) { const ths = [...headerRow.querySelectorAll('th')].map((th) => (th.textContent || '').trim().toLowerCase() @@ -320,6 +362,16 @@ export function initMeasurementsPanel(viewer) { isCoordTable = true } } + if (!isCoordTable) { + const rows = Array.from(tbl.querySelectorAll('tr')) + for (const r of rows) { + const tds = Array.from(r.querySelectorAll('td')) + if (tds.length >= 3 && tds.every((td) => looksLikeNumber(td.textContent))) { + isCoordTable = true + break + } + } + } ;[...tbl.querySelectorAll('tr')].forEach((row) => { const tds = [...row.querySelectorAll('td')] @@ -351,6 +403,9 @@ export function initMeasurementsPanel(viewer) { function insertLatLonRows(rootEl) { if (!rootEl) rootEl = originalPropertiesPanel if (!rootEl) return + // Only insert Lat/Lon/Elev when the properties panel is explicitly mounted + const mounted = originalPropertiesPanel && originalPropertiesPanel.getAttribute && originalPropertiesPanel.getAttribute('data-mp-mounted') === '1' + if (!mounted) return const tables = Array.from(rootEl.querySelectorAll('table.measurement_value_table')) if (!tables.length) return @@ -390,6 +445,22 @@ export function initMeasurementsPanel(viewer) { } break } + // Fallback: look for a row with 3 numeric tds anywhere in the table + const rows = Array.from(tbl.querySelectorAll('tr')) + for (let j = 0; j < rows.length; j++) { + const tds = Array.from(rows[j].querySelectorAll('td')) + if (tds.length >= 3) { + const nx = parseNum(tds[0].textContent) + const ny = parseNum(tds[1].textContent) + const nz = parseNum(tds[2].textContent) + if (nx != null && ny != null && nz != null) { + coordTable = tbl + coordinateRow = rows[j] + break + } + } + } + if (coordinateRow) break } let x = null, y = null, z = null @@ -489,10 +560,20 @@ export function initMeasurementsPanel(viewer) { if (labelEl) { lastSelection.uuid = uuid lastSelection.label = labelEl.textContent.trim() + // Also store the measurement type (Point/Profile/Area/Height/etc.) + try { + const scene = viewer.scene + const all = [...scene.measurements, ...scene.profiles, ...scene.volumes] + const obj = all.find((o) => o.uuid === uuid) + lastSelection.type = obj ? resolveType(obj) : null + } catch (_e) { + lastSelection.type = null + } } } else { lastSelection.uuid = null lastSelection.label = '' + lastSelection.type = null } }