The pipeline works on non-indexed triangle soup: every triangle carries its
own copy of each corner, so "the same point" exists many times with possible
float noise. Welding maps each position, quantised onto a grid, to one
small integer id. All modules do this through QuantizedPointMap /
weldVertices in js/meshIndex.js — an open-addressing hash table over typed
arrays (no string keys, no per-vertex allocation).
The grid decides which points count as "the same". The app deliberately uses three grids; do not change a call site's grid casually — it changes watertightness behaviour:
| Grid | Cell | Used by | Why |
|---|---|---|---|
| 1e4 | 100 µm | export (3MF), meshRepair, meshValidation, exclusion/adjacency, main.js masking | matches the 4-decimal precision exports are written with |
| 1e5 | 10 µm | subdivision, regularize, displacement | fine enough to keep small fillet vertices distinct (1e4 merged them → needle artifacts); coarse enough to absorb float32 noise |
| 1e6 | 1 µm | decimation (own packed-key welder in decimation.js) | collapse positioning needs the finest grid |
resolveTJunctions (meshRepair.js) snaps coordinates onto the 1e4 grid
before export, so the exporter's weld only merges grid-identical points and the
export's decimal rounding is a no-op.
A handful of residual non-manifold edges in exports trace back to decimation/bottom-snap folds; the cross-module grid differences above are a suspected contributor. If unifying grids is ever attempted, it is a behaviour change — verify with the export→import round-trip, not the in-memory mesh.