/* detect.js — tuned ArUco 4x4 detection. * Phantom-ID fix: reject any marker decoded with hamming distance > 0 (maxHamming: 0). */ export function createDetector() { return new AR.Detector({ dictionaryName: 'ARUCO_4X4_1000', maxHammingDistance: 0 }); } /* Returns the markers usable for solving: present in the scene, sane geometry. * The returned array also carries diagnostics so the HUD can distinguish * "nothing detected" from "detected but not in the scene" — the latter looks * identical on screen but means the scene never loaded, or the crest belongs to * a different layout. knownIds may be null/empty; then nothing is solvable and * rawIds tells you what the camera actually saw. */ export function detectMarkers(detector, imageData, knownIds) { const raw = detector.detect(imageData).filter(m => quadArea(m.corners) > 100); const usable = (knownIds && knownIds.size) ? raw.filter(m => knownIds.has(m.id)) : []; usable.rawCount = raw.length; usable.rawIds = raw.map(m => m.id); return usable; } export function quadArea(c) { // shoelace let a = 0; for (let i = 0; i < 4; i++) { const p = c[i], q = c[(i + 1) % 4]; a += p.x * q.y - q.x * p.y; } return Math.abs(a) / 2; }