@ifc-lite/clash 1.7.0 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/README.md +18 -0
  2. package/dist/adapters/ifcx.d.ts.map +1 -1
  3. package/dist/adapters/ifcx.js +22 -36
  4. package/dist/adapters/ifcx.js.map +1 -1
  5. package/dist/adapters/shared.d.ts +61 -0
  6. package/dist/adapters/shared.d.ts.map +1 -0
  7. package/dist/adapters/shared.js +143 -0
  8. package/dist/adapters/shared.js.map +1 -0
  9. package/dist/adapters/step.d.ts +62 -3
  10. package/dist/adapters/step.d.ts.map +1 -1
  11. package/dist/adapters/step.js +180 -89
  12. package/dist/adapters/step.js.map +1 -1
  13. package/dist/analysis.d.ts +10 -1
  14. package/dist/analysis.d.ts.map +1 -1
  15. package/dist/analysis.js +20 -0
  16. package/dist/analysis.js.map +1 -1
  17. package/dist/contact/index.d.ts +14 -0
  18. package/dist/contact/index.d.ts.map +1 -1
  19. package/dist/contact/index.js +14 -0
  20. package/dist/contact/index.js.map +1 -1
  21. package/dist/contact/min-distance.d.ts +87 -0
  22. package/dist/contact/min-distance.d.ts.map +1 -0
  23. package/dist/contact/min-distance.js +255 -0
  24. package/dist/contact/min-distance.js.map +1 -0
  25. package/dist/contact/narrow-phase.d.ts +3 -2
  26. package/dist/contact/narrow-phase.d.ts.map +1 -1
  27. package/dist/contact/narrow-phase.js +32 -14
  28. package/dist/contact/narrow-phase.js.map +1 -1
  29. package/dist/contact/shared-faces.js +10 -1
  30. package/dist/contact/shared-faces.js.map +1 -1
  31. package/dist/contact/tri-tri.d.ts +33 -7
  32. package/dist/contact/tri-tri.d.ts.map +1 -1
  33. package/dist/contact/tri-tri.js +37 -14
  34. package/dist/contact/tri-tri.js.map +1 -1
  35. package/dist/duplicate-metric.d.ts +26 -8
  36. package/dist/duplicate-metric.d.ts.map +1 -1
  37. package/dist/duplicate-metric.js +26 -8
  38. package/dist/duplicate-metric.js.map +1 -1
  39. package/dist/duplicates.d.ts +9 -0
  40. package/dist/duplicates.d.ts.map +1 -1
  41. package/dist/duplicates.js +53 -18
  42. package/dist/duplicates.js.map +1 -1
  43. package/dist/engine-ts/broad.js +20 -2
  44. package/dist/engine-ts/broad.js.map +1 -1
  45. package/dist/engine-ts/depth.d.ts +99 -0
  46. package/dist/engine-ts/depth.d.ts.map +1 -0
  47. package/dist/engine-ts/depth.js +172 -0
  48. package/dist/engine-ts/depth.js.map +1 -0
  49. package/dist/engine-ts/kernel.d.ts +3 -1
  50. package/dist/engine-ts/kernel.d.ts.map +1 -1
  51. package/dist/engine-ts/narrow.d.ts +7 -1
  52. package/dist/engine-ts/narrow.d.ts.map +1 -1
  53. package/dist/engine-ts/narrow.js +53 -95
  54. package/dist/engine-ts/narrow.js.map +1 -1
  55. package/dist/engine-ts/obb.d.ts +116 -0
  56. package/dist/engine-ts/obb.d.ts.map +1 -0
  57. package/dist/engine-ts/obb.js +331 -0
  58. package/dist/engine-ts/obb.js.map +1 -0
  59. package/dist/engine-ts/orchestrator.d.ts.map +1 -1
  60. package/dist/engine-ts/orchestrator.js +3 -13
  61. package/dist/engine-ts/orchestrator.js.map +1 -1
  62. package/dist/engine-ts/tri-mesh.d.ts +88 -22
  63. package/dist/engine-ts/tri-mesh.d.ts.map +1 -1
  64. package/dist/engine-ts/tri-mesh.js +155 -48
  65. package/dist/engine-ts/tri-mesh.js.map +1 -1
  66. package/dist/engine-ts/ts-kernel.d.ts.map +1 -1
  67. package/dist/engine-ts/ts-kernel.js +1 -0
  68. package/dist/engine-ts/ts-kernel.js.map +1 -1
  69. package/dist/engine-wasm/wasm-kernel.d.ts.map +1 -1
  70. package/dist/engine-wasm/wasm-kernel.js +7 -0
  71. package/dist/engine-wasm/wasm-kernel.js.map +1 -1
  72. package/dist/index.d.ts +2 -2
  73. package/dist/index.d.ts.map +1 -1
  74. package/dist/index.js +2 -2
  75. package/dist/index.js.map +1 -1
  76. package/dist/math/aabb.d.ts +10 -1
  77. package/dist/math/aabb.d.ts.map +1 -1
  78. package/dist/math/aabb.js +33 -13
  79. package/dist/math/aabb.js.map +1 -1
  80. package/dist/selectors.d.ts.map +1 -1
  81. package/dist/selectors.js +20 -4
  82. package/dist/selectors.js.map +1 -1
  83. package/dist/triage.d.ts.map +1 -1
  84. package/dist/triage.js +11 -3
  85. package/dist/triage.js.map +1 -1
  86. package/dist/types.d.ts +39 -0
  87. package/dist/types.d.ts.map +1 -1
  88. package/dist/types.js.map +1 -1
  89. package/package.json +10 -9
@@ -0,0 +1,172 @@
1
+ /* This Source Code Form is subject to the terms of the Mozilla Public
2
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
+ import { isThroughPenetration, obbPenetrationDepth } from './obb.js';
5
+ export function boxPenetration(small, large) {
6
+ const oa = small.getObb();
7
+ const ob = large.getObb();
8
+ if (!oa || !ob)
9
+ return null;
10
+ const mtd = obbPenetrationDepth(oa, ob);
11
+ if (mtd == null)
12
+ return null;
13
+ return { mtd, through: isThroughPenetration(oa, ob) };
14
+ }
15
+ /**
16
+ * f32-ULP scale factor for a "worst-case" single-precision coordinate: for a
17
+ * value with magnitude in `[2, 4)` the true float32 ULP is `2^-22`, and for
18
+ * larger magnitudes the ULP only grows. Same `2^-22` term (and reasoning) as
19
+ * `near_band_from_extent` in `rust/geometry/src/kernel/mesh_bridge.rs` — see
20
+ * that function's doc for the derivation; kept here rather than shared
21
+ * because the two live in different language runtimes.
22
+ */
23
+ const F32_ULP_SCALE = 1 / 4_194_304; // 2^-22
24
+ /**
25
+ * Penetration-depth floor below which a computed overlap cannot be
26
+ * distinguished from float32 rounding noise, scaled to the pair's own
27
+ * coordinate magnitude (not a fixed constant — infra models sit far from the
28
+ * origin, where a fixed epsilon would be far too tight, and small models sit
29
+ * near it, where a fixed epsilon would be far too loose).
30
+ *
31
+ * `rust/clash/src/tri_mesh.rs` ingests geometry from f32 buffers and stores/
32
+ * queries it in f64, so f64 arithmetic cannot recover precision the source
33
+ * data never had: two surfaces authored to be flush round to adjacent f32
34
+ * values, and the resulting "penetration" is bit-noise at the ULP of
35
+ * whichever operand coordinate is largest, not a measured overlap. Extent is
36
+ * the max abs coordinate over both elements' AABBs (world space, matching
37
+ * `near_band_from_extent`'s use of the actual compared coordinates) with a
38
+ * floor of 1.0 so a model near the origin still gets the single-unit ULP,
39
+ * not zero.
40
+ *
41
+ * The floor grows linearly with the pair's distance from the origin — that
42
+ * is the point, since f32 precision itself degrades the same way. The
43
+ * consequence: on a georeferenced model whose elements sit at real map
44
+ * coordinates (hundreds of kilometres out, which real IFC files do), the
45
+ * floor reaches decimetre scale, and a genuine clash below that threshold
46
+ * reclassifies as `touch`. That is not a bug in this function — at those
47
+ * magnitudes f32 genuinely cannot represent a finer distinction, so the
48
+ * "penetration" is not reliably measurable either way — but it means the
49
+ * floor tracks a limitation of the source data, not of clash detection.
50
+ * The fix for a model in that position is ingesting geometry closer to the
51
+ * origin (or in f64), not lowering this floor.
52
+ */
53
+ function precisionFloor(elA, elB) {
54
+ let extent = 1.0;
55
+ for (const b of [elA.bounds, elB.bounds]) {
56
+ for (const v of [b.min, b.max]) {
57
+ for (const c of v) {
58
+ const a = Math.abs(c);
59
+ if (a > extent)
60
+ extent = a;
61
+ }
62
+ }
63
+ }
64
+ return extent * F32_ULP_SCALE;
65
+ }
66
+ /**
67
+ * Deepest penetration of `mesh`'s crossing-triangle VERTICES into `other`:
68
+ * the maximum distance-to-surface of `other` over the vertices of the
69
+ * triangles flagged in `crossFlags` (the pairs the narrow phase saw
70
+ * genuinely crossing `other`) that lie inside `other`. Each vertex is
71
+ * visited once (deduped by vertex index, in index order — bit-identical to
72
+ * the Rust `crossing_vertex_penetration`). Returns 0 when no flagged vertex
73
+ * is inside.
74
+ *
75
+ * This is NOT a depth metric and must never be reported as one — it is the
76
+ * sampling probe PR #2536 was held over (`maxPenetrationInto`): its value is
77
+ * an O(edge length) artifact that converges to 0 under retessellation
78
+ * instead of to the true depth. It survives with exactly one client: the
79
+ * f32 noise-floor gate for a CONTAINED pair (`depthClashResult`), where the
80
+ * question is not "how deep?" but "is any mesh-level penetration measurably
81
+ * above the floor at all?" — sub-floor here means every crossing vertex sits
82
+ * within f32 rounding noise of the other surface, i.e. surfaces authored
83
+ * flush, which no amount of retessellation turns into a real overlap. For
84
+ * that yes/no question the probe's underestimation is harmless:
85
+ * underestimating can only keep a pair BELOW the floor, and the floor is
86
+ * the very thing being tested.
87
+ */
88
+ export function crossingVertexPenetration(mesh, other, crossFlags) {
89
+ const seen = new Uint8Array(mesh.vertexCount());
90
+ let depth = 0;
91
+ for (let t = 0; t < mesh.count; t += 1) {
92
+ if (crossFlags[t] === 0)
93
+ continue;
94
+ for (const vi of mesh.triIndices(t)) {
95
+ if (seen[vi] === 1)
96
+ continue;
97
+ seen[vi] = 1;
98
+ const v = mesh.vertex(vi);
99
+ if (!other.containsPoint(v))
100
+ continue;
101
+ const d = other.distanceToSurface(v);
102
+ if (d > depth)
103
+ depth = d;
104
+ }
105
+ }
106
+ return depth;
107
+ }
108
+ /**
109
+ * Turns the candidate penetration depths into the final `(status,
110
+ * distanceKind, distance)` triple. This is the ONLY place in the narrow
111
+ * phase allowed to build a `'mesh'`- or `'estimate'`-labelled `hard` result
112
+ * off a depth number — every branch in `narrow.ts` that can label a result
113
+ * `'mesh'` off `boxPenetration` (or its AABB-estimate fallback) MUST route
114
+ * through here rather than building the `NarrowResult` literal itself. That
115
+ * is what makes the f32 floor apply to all of them, and what enforces its
116
+ * precedence.
117
+ *
118
+ * THE FLOOR WINS (#2536 rebase decision): a pair below the f32 noise floor
119
+ * is `touch` regardless of how its depth was derived — at that magnitude the
120
+ * number is not measurable either way — so the floor is tested against EVERY
121
+ * candidate depth the pair has, not against whichever one the estimate-vs-
122
+ * mesh selection would report. Three candidates exist:
123
+ *
124
+ * - the AABB `estimate` (always present);
125
+ * - the box MTD, when both elements are certified boxes (`box`);
126
+ * - the crossing-vertex penetration, for a CONTAINED pair with a crossing
127
+ * vertex inside the other solid (`meshEvidence`) — evidence for this gate
128
+ * only, never a reported depth (see `crossingVertexPenetration`).
129
+ *
130
+ * The pair is `hard` only when the SMALLEST available candidate clears the
131
+ * floor. That is what makes the floor unreachable by depth-source selection:
132
+ * a sub-floor box MTD cannot be promoted by the through-penetration guard
133
+ * swapping in a larger AABB estimate; a sub-floor crossing-vertex
134
+ * penetration on a contained pair (surfaces authored flush — the eight
135
+ * Infra-Bridge pairs that moved #2594's 50-hard-clash pin to 58 when this
136
+ * PR's depth rework replaced their noise-scale mesh depth with the
137
+ * fabricated 4 m AABB estimate) cannot be promoted by that estimate; and a
138
+ * sub-floor AABB estimate cannot be promoted by a larger MTD (a through-
139
+ * penetration far from the origin, where the MTD is inflated by the
140
+ * piercing member's own extent). Only a pair already above the floor
141
+ * reaches the selection below, which then merely picks WHICH above-floor
142
+ * reportable number is used and how it is labelled — so a `hard` result's
143
+ * distance clears the floor by construction, whichever quantity it came
144
+ * from.
145
+ */
146
+ export function depthClashResult(box, estimate, meshEvidence, elA, elB, rule, point, bounds) {
147
+ let floorDepth = estimate;
148
+ if (box != null && box.mtd < floorDepth)
149
+ floorDepth = box.mtd;
150
+ if (meshEvidence != null && meshEvidence < floorDepth)
151
+ floorDepth = meshEvidence;
152
+ if (floorDepth <= precisionFloor(elA, elB)) {
153
+ if (!rule.reportTouch)
154
+ return null;
155
+ // distance is exactly 0 here (the classification, not a measurement, is
156
+ // what changed), so `mesh` — consistent with the other exact-distance
157
+ // `touch` result.
158
+ return { status: 'touch', distance: 0, distanceKind: 'mesh', point, bounds };
159
+ }
160
+ // Estimate-vs-mesh selection, reachable only above the floor: the box MTD
161
+ // is certified (`mesh`) unless the pair is a through-penetration, where
162
+ // the AABB estimate is the honest number (see `boxPenetration`).
163
+ const measured = box != null && !box.through;
164
+ return {
165
+ status: 'hard',
166
+ distance: -(measured ? box.mtd : estimate),
167
+ distanceKind: measured ? 'mesh' : 'estimate',
168
+ point,
169
+ bounds,
170
+ };
171
+ }
172
+ //# sourceMappingURL=depth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"depth.js","sourceRoot":"","sources":["../../src/engine-ts/depth.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import type { AABB, ClashElement, ClashRule, ClashStatus, Vec3 } from '../types.js';
1
+ import type { AABB, ClashDistanceKind, ClashElement, ClashRule, ClashStatus, Vec3 } from '../types.js';
2
2
  /**
3
3
  * One detected clash, in kernel terms: a pair of GLOBAL element indices plus the
4
4
  * geometric verdict. The orchestrator turns this into a `Clash` (identity,
@@ -12,6 +12,8 @@ export interface NarrowRecord {
12
12
  b: number;
13
13
  status: ClashStatus;
14
14
  distance: number;
15
+ /** Whether `distance` was measured on the meshes or estimated from the AABBs. */
16
+ distanceKind: ClashDistanceKind;
15
17
  point: Vec3;
16
18
  bounds: AABB;
17
19
  }
@@ -1 +1 @@
1
- {"version":3,"file":"kernel.d.ts","sourceRoot":"","sources":["../../src/engine-ts/kernel.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAEpF;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IAC3B,uDAAuD;IACvD,CAAC,EAAE,MAAM,CAAC;IACV,uDAAuD;IACvD,CAAC,EAAE,MAAM,CAAC;IACV,MAAM,EAAE,WAAW,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,IAAI,CAAC;IACZ,MAAM,EAAE,IAAI,CAAC;CACd;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,mFAAmF;IACnF,mBAAmB,EAAE,MAAM,CAAC;IAC5B,wEAAwE;IACxE,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;;GAMG;AACH,MAAM,WAAW,WAAW;IAC1B,oDAAoD;IACpD,OAAO,CAAC,QAAQ,EAAE,YAAY,EAAE,GAAG,IAAI,CAAC;IACxC;;;;OAIG;IACH,UAAU,CACR,QAAQ,EAAE,YAAY,EAAE,EACxB,MAAM,EAAE,MAAM,EAAE,EAChB,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,EACvB,IAAI,EAAE,SAAS,EACf,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM;IAChB;;;;;;OAMG;IACH,MAAM,CAAC,EAAE,WAAW;IACpB;;;;OAIG;IACH,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,GACjD,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IAC1C,6DAA6D;IAC7D,OAAO,CAAC,IAAI,IAAI,CAAC;CAClB"}
1
+ {"version":3,"file":"kernel.d.ts","sourceRoot":"","sources":["../../src/engine-ts/kernel.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,IAAI,EAAE,iBAAiB,EAAE,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAEvG;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IAC3B,uDAAuD;IACvD,CAAC,EAAE,MAAM,CAAC;IACV,uDAAuD;IACvD,CAAC,EAAE,MAAM,CAAC;IACV,MAAM,EAAE,WAAW,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,iFAAiF;IACjF,YAAY,EAAE,iBAAiB,CAAC;IAChC,KAAK,EAAE,IAAI,CAAC;IACZ,MAAM,EAAE,IAAI,CAAC;CACd;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,mFAAmF;IACnF,mBAAmB,EAAE,MAAM,CAAC;IAC5B,wEAAwE;IACxE,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;;GAMG;AACH,MAAM,WAAW,WAAW;IAC1B,oDAAoD;IACpD,OAAO,CAAC,QAAQ,EAAE,YAAY,EAAE,GAAG,IAAI,CAAC;IACxC;;;;OAIG;IACH,UAAU,CACR,QAAQ,EAAE,YAAY,EAAE,EACxB,MAAM,EAAE,MAAM,EAAE,EAChB,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,EACvB,IAAI,EAAE,SAAS,EACf,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM;IAChB;;;;;;OAMG;IACH,MAAM,CAAC,EAAE,WAAW;IACpB;;;;OAIG;IACH,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,GACjD,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IAC1C,6DAA6D;IAC7D,OAAO,CAAC,IAAI,IAAI,CAAC;CAClB"}
@@ -1,8 +1,14 @@
1
- import type { AABB, ClashElement, ClashRule, ClashStatus, Vec3 } from '../types.js';
1
+ import type { AABB, ClashDistanceKind, ClashElement, ClashRule, ClashStatus, Vec3 } from '../types.js';
2
2
  import type { TriMesh } from './tri-mesh.js';
3
3
  export interface NarrowResult {
4
4
  status: ClashStatus;
5
5
  distance: number;
6
+ /**
7
+ * Whether `distance` was measured on the meshes or estimated from the AABBs.
8
+ * Set on every result, so a caller never has to guess which of the two very
9
+ * different quantities it is holding.
10
+ */
11
+ distanceKind: ClashDistanceKind;
6
12
  point: Vec3;
7
13
  bounds: AABB;
8
14
  }
@@ -1 +1 @@
1
- {"version":3,"file":"narrow.d.ts","sourceRoot":"","sources":["../../src/engine-ts/narrow.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAKpF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAE7C,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,WAAW,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,IAAI,CAAC;IACZ,MAAM,EAAE,IAAI,CAAC;CACd;AAsDD;;;;;;;;;;;;GAYG;AACH,wBAAgB,QAAQ,CACtB,GAAG,EAAE,YAAY,EACjB,IAAI,EAAE,OAAO,EACb,GAAG,EAAE,YAAY,EACjB,IAAI,EAAE,OAAO,EACb,IAAI,EAAE,SAAS,EACf,SAAS,EAAE,MAAM,GAChB,YAAY,GAAG,IAAI,CAqOrB"}
1
+ {"version":3,"file":"narrow.d.ts","sourceRoot":"","sources":["../../src/engine-ts/narrow.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,IAAI,EAAE,iBAAiB,EAAE,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAKvG,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAG7C,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,WAAW,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,YAAY,EAAE,iBAAiB,CAAC;IAChC,KAAK,EAAE,IAAI,CAAC;IACZ,MAAM,EAAE,IAAI,CAAC;CACd;AAID;;;;;;;;;;;;GAYG;AACH,wBAAgB,QAAQ,CACtB,GAAG,EAAE,YAAY,EACjB,IAAI,EAAE,OAAO,EACb,GAAG,EAAE,YAAY,EACjB,IAAI,EAAE,OAAO,EACb,IAAI,EAAE,SAAS,EACf,SAAS,EAAE,MAAM,GAChB,YAAY,GAAG,IAAI,CA8PrB"}
@@ -5,57 +5,7 @@ import { aabbContains, boundsOfPoints, center, inflate, overlapBounds, signedGap
5
5
  import { centroid, mid } from '../math/vec3.js';
6
6
  import { triTriIntersect } from '../math/triangle-intersect.js';
7
7
  import { triTriDistance } from '../math/triangle-distance.js';
8
- /**
9
- * f32-ULP scale factor for a "worst-case" single-precision coordinate: for a
10
- * value with magnitude in `[2, 4)` the true float32 ULP is `2^-22`, and for
11
- * larger magnitudes the ULP only grows. Same `2^-22` term (and reasoning) as
12
- * `near_band_from_extent` in `rust/geometry/src/kernel/mesh_bridge.rs` — see
13
- * that function's doc for the derivation; kept here rather than shared
14
- * because the two live in different language runtimes.
15
- */
16
- const F32_ULP_SCALE = 1 / 4_194_304; // 2^-22
17
- /**
18
- * Penetration-depth floor below which a computed overlap cannot be
19
- * distinguished from float32 rounding noise, scaled to the pair's own
20
- * coordinate magnitude (not a fixed constant — infra models sit far from the
21
- * origin, where a fixed epsilon would be far too tight, and small models sit
22
- * near it, where a fixed epsilon would be far too loose).
23
- *
24
- * `rust/clash/src/tri_mesh.rs` ingests geometry from f32 buffers and stores/
25
- * queries it in f64, so f64 arithmetic cannot recover precision the source
26
- * data never had: two surfaces authored to be flush round to adjacent f32
27
- * values, and the resulting "penetration" is bit-noise at the ULP of
28
- * whichever operand coordinate is largest, not a measured overlap. Extent is
29
- * the max abs coordinate over both elements' AABBs (world space, matching
30
- * `near_band_from_extent`'s use of the actual compared coordinates) with a
31
- * floor of 1.0 so a model near the origin still gets the single-unit ULP,
32
- * not zero.
33
- *
34
- * The floor grows linearly with the pair's distance from the origin — that
35
- * is the point, since f32 precision itself degrades the same way. The
36
- * consequence: on a georeferenced model whose elements sit at real map
37
- * coordinates (hundreds of kilometres out, which real IFC files do), the
38
- * floor reaches decimetre scale, and a genuine clash below that threshold
39
- * reclassifies as `touch`. That is not a bug in this function — at those
40
- * magnitudes f32 genuinely cannot represent a finer distinction, so the
41
- * "penetration" is not reliably measurable either way — but it means the
42
- * floor tracks a limitation of the source data, not of clash detection.
43
- * The fix for a model in that position is ingesting geometry closer to the
44
- * origin (or in f64), not lowering this floor.
45
- */
46
- function precisionFloor(elA, elB) {
47
- let extent = 1.0;
48
- for (const b of [elA.bounds, elB.bounds]) {
49
- for (const v of [b.min, b.max]) {
50
- for (const c of v) {
51
- const a = Math.abs(c);
52
- if (a > extent)
53
- extent = a;
54
- }
55
- }
56
- }
57
- return extent * F32_ULP_SCALE;
58
- }
8
+ import { boxPenetration, crossingVertexPenetration, depthClashResult } from './depth.js';
59
9
  /**
60
10
  * Narrow-phase test for one candidate element pair.
61
11
  *
@@ -75,10 +25,14 @@ export function testPair(elA, triA, elB, triB, rule, tolerance) {
75
25
  const aSmaller = triA.count <= triB.count;
76
26
  const small = aSmaller ? triA : triB;
77
27
  const large = aSmaller ? triB : triA;
78
- // One AABB containing the other flags the contained-contact case (#1866):
79
- // for such pairs the AABB signed gap measures how deep the small BOX sits in
80
- // the big one (its own extent), not how far the MESHES interpenetrate, so
81
- // collect the crossing triangles for a mesh-level depth measurement instead.
28
+ // A CONTAINED pair (one element's AABB wholly inside the other's) is the
29
+ // one class whose AABB estimate is fabricated the signed gap reads the
30
+ // small element's own extent, not anything about the overlap (#1866) so
31
+ // for such pairs collect the crossing triangles: their vertices are the
32
+ // mesh-level evidence `depthClashResult`'s f32 noise-floor gate needs (see
33
+ // `crossingVertexPenetration` — evidence for the floor test only, never a
34
+ // reported depth). Allocated only for contained pairs; every other pair
35
+ // has a genuine AABB overlap bound to floor-test instead.
82
36
  const contained = aabbContains(elB.bounds, elA.bounds) || aabbContains(elA.bounds, elB.bounds);
83
37
  const crossSmall = contained ? new Uint8Array(small.count) : null;
84
38
  const crossLarge = contained ? new Uint8Array(large.count) : null;
@@ -198,33 +152,30 @@ export function testPair(elA, triA, elB, triB, rule, tolerance) {
198
152
  const point = contactN > 0
199
153
  ? [contactSumX / contactN, contactSumY / contactN, contactSumZ / contactN]
200
154
  : center(overlap);
201
- // Penetration estimate from the AABB overlap...
202
- let penetration = Math.max(0, -signedGap(elA.bounds, elB.bounds));
203
- // ...EXCEPT for a contained pair (#1866): there the AABB overlap equals the
204
- // small element's own extent, wildly overstating depth for designed face
205
- // contacts (e.g. opening fills inset in their host). Measure the real
206
- // mesh-level depth instead: the deepest crossing-triangle vertex of either
207
- // mesh inside the other solid. Falls back to the AABB estimate when no such
208
- // vertex lies inside (thin member piercing straight through).
155
+ // Exact box-box penetration depth when both elements are rectangular
156
+ // boxes (see `boxPenetration`); otherwise fall back to the AABB overlap,
157
+ // i.e. the smallest overlapping box dimension. That fallback is an
158
+ // estimate, not a measured depth for a non-box shape it can report a
159
+ // dimension of one of the elements rather than how far they interpenetrate.
160
+ // `depthClashResult` applies the f32 floor to EVERY candidate depth
161
+ // before any estimate-vs-mesh selection, so a pair below the floor
162
+ // reports `touch` regardless of which quantity would have been reported.
163
+ // For a contained pair the crossing-vertex penetration is that third
164
+ // candidate: the estimate is fabricated there (the small element's own
165
+ // extent), so without it a flush contained pair — whose only measurable
166
+ // penetration is f32 noise — would be promoted to `hard` at a number
167
+ // that measures nothing (the eight Infra-Bridge pairs, see
168
+ // `depthClashResult`).
169
+ let meshEvidence = null;
209
170
  if (crossSmall !== null && crossLarge !== null) {
210
- const meshDepth = Math.max(small.maxPenetrationInto(large, crossSmall), large.maxPenetrationInto(small, crossLarge));
211
- if (meshDepth > 0)
212
- penetration = meshDepth;
213
- }
214
- // A genuine triangle crossing was found, but the measured depth is at or
215
- // below the f32 precision floor for this pair's coordinate scale: it
216
- // cannot be distinguished from rounding noise (see `precisionFloor`),
217
- // so it is not a measured overlap. Reclassify as `touch` rather than
218
- // `hard` — the crossing still means the surfaces are in contact, which
219
- // is real information (and this codebase already distinguishes touching
220
- // from overlapping, e.g. the viewer's `clashHideTouching` toggle) —
221
- // rather than silently dropping the pair or reporting a fabricated depth.
222
- if (penetration <= precisionFloor(elA, elB)) {
223
- if (!rule.reportTouch)
224
- return null;
225
- return { status: 'touch', distance: 0, point, bounds: contactBounds };
171
+ const d = Math.max(crossingVertexPenetration(small, large, crossSmall), crossingVertexPenetration(large, small, crossLarge));
172
+ // 0 means "no crossing vertex inside at all" (e.g. a thin member
173
+ // piercing straight through) — no evidence either way, not evidence
174
+ // of a sub-floor contact.
175
+ if (d > 0)
176
+ meshEvidence = d;
226
177
  }
227
- return { status: 'hard', distance: -penetration, point, bounds: contactBounds };
178
+ return depthClashResult(boxPenetration(small, large), Math.max(0, -signedGap(elA.bounds, elB.bounds)), meshEvidence, elA, elB, rule, point, contactBounds);
228
179
  }
229
180
  // Fully-enclosed solid: no surface crossing, but one element's AABB is wholly
230
181
  // inside the other's, so it may be buried (e.g. equipment inside a slab). With
@@ -234,15 +185,18 @@ export function testPair(elA, triA, elB, triB, rule, tolerance) {
234
185
  // correctly returns "outside" when the inner sits in a concave notch.
235
186
  // Test B-contains-A first, then A-contains-B, so the inner pick is
236
187
  // deterministic (and identical to the Rust kernel) on equal AABBs.
237
- if (aabbContains(elB.bounds, elA.bounds)) {
238
- if (triA.count > 0 && triB.containsPoint(triA.tri(0)[0])) {
239
- return { status: 'hard', distance: signedGap(elA.bounds, elB.bounds), point: center(overlap), bounds: overlap };
240
- }
241
- }
242
- else if (aabbContains(elA.bounds, elB.bounds)) {
243
- if (triB.count > 0 && triA.containsPoint(triB.tri(0)[0])) {
244
- return { status: 'hard', distance: signedGap(elA.bounds, elB.bounds), point: center(overlap), bounds: overlap };
245
- }
188
+ // Either way there is no surface crossing. When both elements are boxes the
189
+ // exact box-box depth is available (see `boxPenetration`) and is reported
190
+ // as measured; otherwise the AABB gap is an estimate, not a measured depth.
191
+ const enclosed = aabbContains(elB.bounds, elA.bounds)
192
+ ? triA.count > 0 && triB.containsPoint(triA.tri(0)[0])
193
+ : aabbContains(elA.bounds, elB.bounds) && triB.count > 0 && triA.containsPoint(triB.tri(0)[0]);
194
+ if (enclosed) {
195
+ // `depthClashResult` may return `null` here (below the f32 floor and
196
+ // `!rule.reportTouch`) — that is a suppressed touch, not "no clash",
197
+ // so return it as-is rather than falling through to the coincide check
198
+ // below.
199
+ return depthClashResult(boxPenetration(small, large), -signedGap(elA.bounds, elB.bounds), null, elA, elB, rule, center(overlap), overlap);
246
200
  }
247
201
  if (minDist === Infinity) {
248
202
  // Broad-phase candidate with no triangle-level proximity — not a clash.
@@ -270,12 +224,13 @@ export function testPair(elA, triA, elB, triB, rule, tolerance) {
270
224
  // actually coincide), clamped to the element overlap — not the whole-
271
225
  // element AABB intersection, which for angled members spans nearly the
272
226
  // full member length and sits away from the real contact (#1362/#1402).
273
- return {
274
- status: 'hard',
275
- distance: gap,
276
- point: mid(closestA, closestB),
277
- bounds: contactBounds,
278
- };
227
+ // When both elements are boxes the exact box-box depth is available
228
+ // (see `boxPenetration`) and is reported as measured, not estimated.
229
+ // `depthClashResult` may return `null` (below the f32 floor and
230
+ // `!rule.reportTouch`) — a suppressed touch, not "no shared volume",
231
+ // so return it as-is rather than falling through to the face-touch
232
+ // handling meant for the "probes failed" case below.
233
+ return depthClashResult(boxPenetration(small, large), -gap, null, elA, elB, rule, mid(closestA, closestB), contactBounds);
279
234
  }
280
235
  // Only a face touch (no shared volume): fall through to the touch handling
281
236
  // below, which suppresses it unless reportTouch is set.
@@ -288,6 +243,8 @@ export function testPair(elA, triA, elB, triB, rule, tolerance) {
288
243
  return {
289
244
  status: 'clearance',
290
245
  distance: minDist,
246
+ // `minDist` is an exact triangle-to-triangle distance.
247
+ distanceKind: 'mesh',
291
248
  point: mid(closestA, closestB),
292
249
  bounds: boundsOfPoints(closestA, closestB),
293
250
  };
@@ -300,6 +257,7 @@ export function testPair(elA, triA, elB, triB, rule, tolerance) {
300
257
  return {
301
258
  status: 'touch',
302
259
  distance: minDist,
260
+ distanceKind: 'mesh',
303
261
  point: mid(closestA, closestB),
304
262
  bounds: boundsOfPoints(closestA, closestB),
305
263
  };
@@ -1 +1 @@
1
- {"version":3,"file":"narrow.js","sourceRoot":"","sources":["../../src/engine-ts/narrow.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"narrow.js","sourceRoot":"","sources":["../../src/engine-ts/narrow.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Exact penetration depth for the one shape family it can be exact for:
3
+ * rectangular boxes. `maxPenetrationInto` (removed) measured the distance from
4
+ * the nearest crossing-triangle VERTEX to the other surface — an O(edge
5
+ * length) sampling artifact that converges to 0 as a mesh is retessellated,
6
+ * the opposite of what a depth metric should do (see the analytic-oracle
7
+ * fixtures in `obb.test.ts`).
8
+ *
9
+ * This module instead detects when both meshes ARE (within tolerance)
10
+ * axis-independent rectangular boxes and, only then, reports the minimum
11
+ * translation distance along a separating axis — the classical two-OBB
12
+ * penetration depth, which for boxes is provably exact and, because it is
13
+ * derived from the box's face-plane geometry rather than its triangulation,
14
+ * provably unchanged by retessellation. When either mesh is not confirmed to
15
+ * be a box, the caller falls back to the AABB estimate (never a wrong 'mesh'
16
+ * label) — a smaller true thing rather than a large wrong one.
17
+ */
18
+ import type { Vec3 } from '../types.js';
19
+ /** Tolerance for normal-direction dedup and offset-plane clustering. Same
20
+ * literal in the Rust kernel — see `rust/clash/src/obb.rs`. */
21
+ export declare const OBB_EPS = 0.000001;
22
+ export interface Obb {
23
+ center: Vec3;
24
+ /** Three mutually orthogonal unit axes. */
25
+ axes: [Vec3, Vec3, Vec3];
26
+ /** Half-extent along each axis, matching `axes` by index. */
27
+ half: [number, number, number];
28
+ }
29
+ /** Minimal structural view of `TriMesh` this module needs — avoids a
30
+ * circular import between `obb.ts` and `tri-mesh.ts`. */
31
+ export interface MeshLike {
32
+ readonly count: number;
33
+ tri(t: number): [Vec3, Vec3, Vec3];
34
+ }
35
+ /**
36
+ * Detect whether `mesh` is a rectangular box: every (non-degenerate)
37
+ * triangle's normal falls into exactly 3 mutually orthogonal canonical
38
+ * directions, and every vertex of the triangles in a direction group lies on
39
+ * one of exactly two offset planes along that direction. That combination —
40
+ * 3 orthogonal face families, 2 planes each — forces the mesh to be a closed
41
+ * rectangular box (it rejects, for example, an axis-aligned L-shape, whose
42
+ * notch adds a third offset plane on two of the axes). Triangulation-
43
+ * independent: subdividing a box's faces adds triangles but never a new
44
+ * canonical direction or a third offset plane, so the detection (and the
45
+ * resulting `Obb`) is identical at any tessellation.
46
+ *
47
+ * Returns `null` — not a best-effort guess — when the check fails, so a
48
+ * caller that only trusts a non-null result never certifies a shape this
49
+ * function could not confirm.
50
+ */
51
+ export declare function detectObb(mesh: MeshLike): Obb | null;
52
+ /**
53
+ * Bound, in f64 ulps, on the absolute error of one component of the cross
54
+ * product of two UNIT vectors (each component is a product-difference of
55
+ * magnitude-<=1 terms: ~2 ulps), with headroom for the normalisation and the
56
+ * per-projection dot rounding it feeds. Shared by the axis noise bound in
57
+ * {@link obbPenetrationDepth}; same literal in the Rust kernel.
58
+ */
59
+ export declare const AXIS_NOISE_ULPS = 8;
60
+ /**
61
+ * Exact penetration depth between two oriented boxes: the minimum overlap
62
+ * over the 15 canonical OBB-OBB separating-axis candidates (each box's 3 face
63
+ * normals, plus the 9 pairwise cross products of one box's axes with the
64
+ * other's) — the standard result (Gottschalk, "Collision Queries using
65
+ * Oriented Bounding Boxes") that the minimum-translation-distance axis for two
66
+ * boxes is always among these 15.
67
+ *
68
+ * Cross-product candidates are conditioned by their length: both operands are
69
+ * unit axes, so `|L| = sin(angle between them)`, and normalising amplifies
70
+ * the ~ulp-level absolute error of the cross product into a direction error
71
+ * of up to `AXIS_NOISE_ULPS * EPS / |L|` radians. Each candidate's verdict
72
+ * therefore carries a SCALE-RELATIVE noise bound (see `testAxis`), and a
73
+ * verdict inside its own noise band is skipped — not trusted to separate,
74
+ * not trusted as a depth (review: #2536; the same
75
+ * tolerance-from-the-wrong-quantity class as #2598/#2600/#2529 — an earlier
76
+ * ABSOLUTE `len > 1e-6` guard here both divided by lengths whose noise
77
+ * dwarfs a thin overlap at large operand scale, and hard-dropped axes that
78
+ * were fine: for kilometre-scale near-parallel beams the dropped common
79
+ * normal IS the
80
+ * minimum-translation axis, and the min over the remaining axes over-reported
81
+ * a 0.02 m edge contact as a certified 0.45 m depth — see `obb.test.ts`).
82
+ *
83
+ * Returns `null` if any candidate axis reports, beyond its noise band, zero
84
+ * or negative overlap — the boxes would be separated along it, contradicting
85
+ * the caller's own crossing test — so a numerical edge case degrades to
86
+ * `null` (caller falls back to the AABB estimate) rather than reporting a
87
+ * wrong depth.
88
+ */
89
+ export declare function obbPenetrationDepth(a: Obb, b: Obb): number | null;
90
+ /**
91
+ * Whether `a` and `b` are in a THROUGH-PENETRATION configuration: one box's
92
+ * cross-section, in the plane perpendicular to one of ITS OWN axes, is fully
93
+ * inside the other's footprint there, while along that axis it extends
94
+ * beyond the other and out the far side — a thin member piercing clean
95
+ * through a wall/slab, not a partial overlap. The relation is checked BOTH
96
+ * ways, so it also holds for the MUTUAL case: two walls crossing at an
97
+ * X-junction, each piercing the other clean through in thickness.
98
+ *
99
+ * This matters because {@link obbPenetrationDepth} reports the minimum
100
+ * TRANSLATION distance to separate the pair, which for this shape is
101
+ * dominated by the piercing member's own extent along the piercing axis, not
102
+ * by how much material it actually crossed (review: #2536 — a 2 m duct
103
+ * through a 200 mm wall reported 1.1 m, not 0.2 m). Detecting the shape lets
104
+ * the caller decline to certify that number as a measured depth.
105
+ *
106
+ * Tests containment against EACH box's own axes independently (via
107
+ * {@link piercesAlong}'s general per-axis projection, the same projection
108
+ * {@link obbPenetrationDepth} already computes for its 15 SAT candidates) —
109
+ * unlike an earlier version restricted to a frame shared by both boxes'
110
+ * axes up to sign, this also catches a member piercing through at a generic
111
+ * relative rotation (e.g. a duct crossing a wall at 15 degrees, review:
112
+ * #2536 follow-up — the earlier version measured -1.1177 there, `'mesh'`-
113
+ * labelled, against a true ~0.207 m).
114
+ */
115
+ export declare function isThroughPenetration(a: Obb, b: Obb): boolean;
116
+ //# sourceMappingURL=obb.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"obb.d.ts","sourceRoot":"","sources":["../../src/engine-ts/obb.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAGxC;+DAC+D;AAC/D,eAAO,MAAM,OAAO,WAAO,CAAC;AAE5B,MAAM,WAAW,GAAG;IAClB,MAAM,EAAE,IAAI,CAAC;IACb,2CAA2C;IAC3C,IAAI,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;IACzB,6DAA6D;IAC7D,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC;AAED;yDACyD;AACzD,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;CACpC;AAqBD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,QAAQ,GAAG,GAAG,GAAG,IAAI,CA4EpD;AAED;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,IAAI,CAAC;AAEjC;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,GAAG,MAAM,GAAG,IAAI,CAoEjE;AAkED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,GAAG,OAAO,CAK5D"}