x-axis justierung: lines

This commit is contained in:
chk
2026-06-10 18:40:57 +02:00
parent 3084324f4a
commit 145c14842a

View File

@@ -213,8 +213,13 @@ const gPaper = new THREE.Group(); // weißes A0-Papier
const gMarkers = new THREE.Group(); // Modell-Rechtecke
const gMeasured = new THREE.Group(); // gemessene Positionen (3b)
const gCameras = new THREE.Group(); // Kamera-Frusta
const gCompare = new THREE.Group(); // Vergleichs-Punkte (anderer Timestamp, nur fremd)
scene.add(gPaper, gMarkers, gMeasured, gCameras, gCompare);
const gCompare = new THREE.Group(); // Vergleichs-Punkte (anderer Timestamp, nur fremd)
const gCompareLines = new THREE.Group(); // Verbindungslinien Basis↔Vergleich
scene.add(gPaper, gMarkers, gMeasured, gCameras, gCompare, gCompareLines);
// ── Zustand für Vergleichs-Linien ─────────────────────────────────────────────
let _primaryFremdMarkers = []; // [{marker_id, position_mm, num_cameras}]
let _compareFremdMarkers = []; // [{marker_id, position_mm, num_cameras}]
function clearGroup(g) {
while (g.children.length) {
@@ -573,6 +578,48 @@ function buildTable(data) {
wrap.innerHTML = html;
}
// ── Vergleichs-Overlay: Transparenz + Linien ─────────────────────────────────
/**
* Setzt Board-Marker und Papier-Ebene auf geringere Deckkraft, wenn der
* Vergleichs-Modus aktiv ist (compareActive=true → 10 % Deckkraft).
* Ursprüngliche Deckkraft wird pro Material einmalig gespeichert.
*/
function setSceneOpacity(compareActive) {
for (const obj of [...gPaper.children, ...gMarkers.children]) {
const mats = obj.material
? (Array.isArray(obj.material) ? obj.material : [obj.material])
: [];
for (const mat of mats) {
if (!mat) continue;
if (mat._origOpacity === undefined) mat._origOpacity = mat.opacity ?? 1.0;
if (mat._origTransparent === undefined) mat._origTransparent = mat.transparent ?? false;
mat.transparent = compareActive || mat._origTransparent;
mat.opacity = compareActive ? mat._origOpacity * 0.10 : mat._origOpacity;
mat.needsUpdate = true;
}
}
}
/**
* Zeichnet Verbindungslinien von Basis-fremd-Markern zu gleich-ID-Vergleichs-Markern.
* Aktualisiert gleichzeitig die Board-Transparenz.
*/
function buildCompareLines() {
clearGroup(gCompareLines);
const compareActive = _compareFremdMarkers.length > 0;
setSceneOpacity(compareActive);
if (!compareActive || !_primaryFremdMarkers.length) return;
const primaryMap = new Map(_primaryFremdMarkers.map(m => [m.marker_id, m]));
for (const cm of _compareFremdMarkers) {
const pm = primaryMap.get(cm.marker_id);
if (!pm) continue;
// Linie: Basis-Position (blau) → Vergleichs-Position (orange)
gCompareLines.add(makeLine(r2vArr(pm.position_mm), r2vArr(cm.position_mm), 0xfb923c, 0.85));
}
}
// ── Daten laden ───────────────────────────────────────────────────────────────
/** Haupt-Run laden (Basis-Dropdown). Ohne Selektion → neuester Run. */
@@ -595,6 +642,10 @@ async function loadData() {
}
buildScene(data);
buildTable(data);
// Fremd-Marker für Verbindungslinien merken (Marker, die nicht in Board-Link stehen)
const bIds = new Set((data.robot?.links?.Board?.markers ?? []).map(m => m.id));
_primaryFremdMarkers = (data.measuredMarkers?.markers ?? []).filter(m => !bIds.has(m.marker_id));
buildCompareLines();
const robotLabel = data.robotFile ? ` • Robot: ${data.robotFile}` : '';
statusEl.textContent = `Run: ${data.runDir}${robotLabel}${new Date().toLocaleTimeString('de-CH')}`;
} catch (err) {
@@ -602,26 +653,31 @@ async function loadData() {
}
}
/** Vergleichs-Run laden (Compare-Dropdown) zeigt nur fremd-triangulierte Marker als orange Kugeln. */
/**
* Vergleichs-Run laden (Compare-Dropdown).
* Zeigt nur fremd-triangulierte Marker (nicht im Board-Link) als orange Kugeln.
* Zieht außerdem Verbindungslinien zu gleich-ID-Markern im Basis-Run.
*/
async function loadCompareData() {
clearGroup(gCompare);
_compareFremdMarkers = [];
const selRun = document.getElementById('sel-run-compare')?.value ?? '';
if (!selRun) return;
if (!selRun) { buildCompareLines(); return; }
try {
const r = await fetch(`/api/board/latest?run=${encodeURIComponent(selRun)}`);
if (!r.ok) return;
const data = await r.json();
if (!r.ok) { buildCompareLines(); return; }
const data = await r.json();
const markers = data.measuredMarkers?.markers ?? [];
if (!markers.length) return;
// Board-Marker-IDs aus Robot.json (für diesen Run)
// Board-Marker-IDs aus Robot.json dieses Runs
const boardIds = new Set((data.robot?.links?.Board?.markers ?? []).map(m => m.id));
for (const m of markers) {
if (!boardIds.has(m.marker_id)) {
// Nicht zugeordnet → orange Kugel (Vergleich)
gCompare.add(makeSphere(r2vArr(m.position_mm), 0.006, 0xf97316));
_compareFremdMarkers.push(m); // für Linien
gCompare.add(makeSphere(r2vArr(m.position_mm), 0.006, 0xf97316)); // orange Kugel
}
}
} catch { /* kein 3b-Output für diesen Run */ }
buildCompareLines(); // Linien + Transparenz aktualisieren
}
/** Run-Listen laden und beide Dropdowns befüllen. */