tools(audit): whole-surface mesh artifact audit with historical controls (L48, tool only); research R15
AuditWholeSurfaceL48.py scans every LOD0 triangle in the route corridor + 3 m and the chamber box + 3 m: welded-edge normal variation, high-angle edge density, max jumps and sliver area in 1 m cells, clustered and located, with thresholds from native patches in the same export, plus a detrended full-width floor profile. L45 ramp, L46 entrance and L47 wall-foot meshes fail it; plain native terrain passes. Red-triangle SVG maps included. Not wired into the tiers yet; the attempted Core fix is parked on wip/l48-surface-audit. Research R15: mesh artifact metrics. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016dhxM43dnWvUu2B5Ph1iG1
This commit is contained in:
1 parent
c091e4434f
commit
3073d1b2fd
16 files changed
+346656
No files matched your search
@@ -0,0 +1,52 @@
|
||||
# R15 — Whole-surface artifact audit
|
||||
|
||||
## Key recommendations
|
||||
|
||||
1. Scan every LOD0 triangle in the exported region using three area-weighted metrics over overlapping surface patches: **detrended geometric residual**, **smoothed normal variation**, and **periodic-band coherence**. Group adjacent anomalous patches into clusters before failing the mesh.
|
||||
2. Calibrate each scale against plain native terrain exported by the same mesher at 25 cm. Choose thresholds on held-out clean regions, then lock them. The gate should pass clean references and reject **each of the five pre-fix defect meshes**; if one slips through, improve the detector rather than tune the threshold around that mesh.
|
||||
3. Add the offline check after mesh export in `verify.py`’s medium capture-and-audit stage. Report cluster coordinates and scores, plus a false-color mesh or marked capture. Full tier already reuses passed medium evidence; fast would need a small LOD0 export to include this gate.
|
||||
|
||||
## Metrics
|
||||
|
||||
For triangle \(f=(v_0,v_1,v_2)\), compute area \(A_f=\frac12\|(v_1-v_0)\times(v_2-v_0)\|\) and **geometric** face normal \(n_f\) from its positions. Use these normals for shape checks; stored smooth MC normals can hide or exaggerate geometric changes.
|
||||
|
||||
- **Detrended residual \(D_r\):** Fit a robust local quadric \(q_r\) over a geodesic neighborhood of radius \(r\), and measure the area-weighted RMS signed normal distance:
|
||||
\[
|
||||
D_r(P)=\sqrt{\frac{\sum_{v\in P}A_v\,\delta_r(v)^2}{\sum_{v\in P}A_v}},
|
||||
\qquad \delta_r(v)=(v-q_r(v))\cdot n_r(v).
|
||||
\]
|
||||
Also retain the 95th percentile and largest adjacent residual jump in the patch. This measures relief and steps without assuming the surface is a floor or wall.
|
||||
|
||||
- **Smoothed normal variation \(G_r\):** For adjacent faces \(f,g\), let \(\theta_{fg}=\cos^{-1}(n_f\cdot n_g)\) and \(d_{fg}\) be their geodesic center distance. Average normals over radius \(r\) first, then compute an area-weighted RMS of \(\theta_{fg}/d_{fg}\). This catches clustered creases and teeth while reducing single-triangle MC facet noise.
|
||||
|
||||
- **Periodic coherence \(C_\lambda\):** Take a spectrum or autocorrelation of \(\delta_r\) across overlapping surface patches, in all local tangent directions. Score the strongest narrow-band energy relative to neighboring frequencies, and require phase coherence across adjacent patches. Search wavelengths from roughly two to 32 voxels (0.5–8 m); use multiple window sizes so the longest periods have enough support. This detects repeated ribs, washboard, and seams without relying on a chosen rail.
|
||||
|
||||
Use all three as a small, interpretable suite. A raw dihedral histogram loses location and mixes ordinary MC facets with real creases. Discrete Gaussian curvature \(K_i=(2\pi-\sum_j\theta_{ij})/A_i^*\) and cotangent-Laplacian mean curvature are useful visual diagnostics, but raw one-ring estimates can be noisy on irregular MC triangles; prefer multi-scale smoothing or quadric fits. Triangle quality, such as \(2r/R\) or minimum altitude-to-edge ratio, is a useful secondary mesh-health check, not a primary artifact detector: ridges and staircases need not contain slivers.
|
||||
|
||||
MC linearly interpolates grid-edge crossings; the output can miss undersampled details, contain poor-shaped facets, and fail to preserve sharp features. That makes universal angle, curvature, or triangle-quality cutoffs unreliable. [CGAL’s isosurfacing manual](https://cgal.github.io/9465/doc/Isosurfacing_3/index.html) and [Dietrich et al. on MC triangle quality](https://doi.org/10.1109/TVCG.2008.60) document these limitations. [MeshLab](https://github.com/cnr-isti-vclab/meshlab/blob/main/docs/dox/filter.dox) and [libigl](https://libigl.github.io/tutorial/) provide useful curvature and quality measures; libigl also documents quadric curvature fitting. The specific three-metric combination above is a recommendation inferred from those methods and VoxelForge’s regressions, not a published universal detector.
|
||||
|
||||
## Reference and threshold method
|
||||
|
||||
Build a reference set from native-only LOD0 meshes using the same 25 cm mesher, recipes, and export path. Match patches by surface orientation and broad shape class; compare patch scores, not individual triangle scores. Use a held-out clean set to set per-scale thresholds from the distribution of **per-export maximum cluster scores** (with block bootstrap or equivalent uncertainty), so scanning more surface does not silently increase false alarms.
|
||||
|
||||
Threshold a connected cluster of adjacent anomalous patches, with a minimum footprint calibrated to the smallest visible defect. Ignore isolated single-triangle excursions unless a separate topology or fragment check catches them. Lock thresholds before scoring candidate fixes. Require every pre-fix defect mesh to fail individually and clean native references to pass. Keep all five bad meshes as fixtures; the native holdout guards against thresholds that simply reject rough terrain.
|
||||
|
||||
## Defect-to-metric map
|
||||
|
||||
| Known defect | Primary detector | Evidence and expected signal |
|
||||
|---|---|---|
|
||||
| **L35 wall ribs** | \(C_\lambda + G_r\) | The old wall has measured periods near 4.75 m in normals and 7.44 m in radius. A coherent band should cluster over the wall area. [L35 report](/home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Linux35/REPORT.md:5) |
|
||||
| **L36 floor washboard** | \(C_\lambda + D_r\) | The old floor repeats at 1.438 m and 7.250 m, with 2.25–2.48 cm amplitude. Whole-surface patches include the tread that the wall-only scan missed. [L36 report](/home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Linux36/REPORT.md:5) |
|
||||
| **L45 segmented ramp** | \(C_\lambda + D_r\) | Segment seams create repeated surface residuals along the ramp. The L45 control already fails its floor-ripple gate at 17.9 mm against a 15 mm limit. [L45 report](/home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Linux45/REPORT.md:42) [L46 report](/home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Linux46/REPORT.md:15) |
|
||||
| **L46 entrance staircase** | \(D_r\), including adjacent residual jump; \(G_r\) | The first 7 m measures 39.9–51.4 mm ripple and 81.8–82.9 mm residual steps. Detrending against the sloped floor separates the steps from the intended grade. [L47 report](/home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Linux47/REPORT.md:5) |
|
||||
| **L47 wall-foot sawteeth** | \(G_r + D_r\), clustered | Scan all connected faces, including the wall foot. The existing three floor rails do not reach it. [L47 report](/home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Linux47/REPORT.md:31) |
|
||||
|
||||
This three-metric set should catch all five while passing smooth native terrain **if** the matched reference and control gate confirm the separation. The reports establish the defects and measured signals; they do not establish final mesh-wide thresholds.
|
||||
|
||||
## Implementation and reporting
|
||||
|
||||
The existing `.vfmesh` readers expose tile LOD, voxel size, positions, normals, indices, and masks. Extend the tile-streaming approach used by [the ring audit](/home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Linux32/AuditRingTerraceL32.py) and [the tile scanner](/home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Linux32/ScanMeshSurfaceTilesL32.py): analyze the whole target region at LOD0, include all face orientations, and weld duplicate vertices at same-LOD tile boundaries. Keep the audit offline on exported geometry.
|
||||
|
||||
The natural insertion point is after `CaptureLandmarkL47.py` and passage mesh exports in [`run_captures_and_mesh_audits()`](/home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Tools/verify/verify.py:651). That stage runs in medium and is reused by full; fast currently has no equivalent capture export. A fast-tier version would need a small targeted LOD0 export. [Voxel Tools’ smooth-terrain documentation](https://voxel-tools.readthedocs.io/en/latest/smooth_terrain/) notes that voxel LOD stitches can still show sharp steps, while [SAGA’s Terrain Ruggedness Index](https://saga-gis.sourceforge.io/saga_tool_doc/7.6.1/ta_morphometry_16.html) illustrates the value of neighborhood-scale terrain measures; its DEM assumptions do not cover arbitrary tunnel surfaces.
|
||||
|
||||
For each cluster, report world-space centroid, bounds, geodesic area and extent, triangle IDs, strongest metric, scale or wavelength, value, threshold, LOD, voxel size, and mesh/layout identity. Emit JSON plus a compact CSV, and a false-color mesh or marked image with cluster IDs and a reproducible camera pose. MeshLab’s face-quality coloring is one available review path.
|
||||
Reference in new issue
Block a user