@ifc-lite/clash 1.2.0 → 1.4.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 (59) hide show
  1. package/dist/adapters/step.d.ts.map +1 -1
  2. package/dist/adapters/step.js +27 -1
  3. package/dist/adapters/step.js.map +1 -1
  4. package/dist/contact/aabb.d.ts +20 -0
  5. package/dist/contact/aabb.d.ts.map +1 -0
  6. package/dist/contact/aabb.js +88 -0
  7. package/dist/contact/aabb.js.map +1 -0
  8. package/dist/contact/bvh.d.ts +39 -0
  9. package/dist/contact/bvh.d.ts.map +1 -0
  10. package/dist/contact/bvh.js +173 -0
  11. package/dist/contact/bvh.js.map +1 -0
  12. package/dist/contact/index.d.ts +31 -0
  13. package/dist/contact/index.d.ts.map +1 -0
  14. package/dist/contact/index.js +33 -0
  15. package/dist/contact/index.js.map +1 -0
  16. package/dist/contact/mesh-bvh.d.ts +21 -0
  17. package/dist/contact/mesh-bvh.d.ts.map +1 -0
  18. package/dist/contact/mesh-bvh.js +96 -0
  19. package/dist/contact/mesh-bvh.js.map +1 -0
  20. package/dist/contact/narrow-phase.d.ts +37 -0
  21. package/dist/contact/narrow-phase.d.ts.map +1 -0
  22. package/dist/contact/narrow-phase.js +49 -0
  23. package/dist/contact/narrow-phase.js.map +1 -0
  24. package/dist/contact/plane.d.ts +38 -0
  25. package/dist/contact/plane.d.ts.map +1 -0
  26. package/dist/contact/plane.js +83 -0
  27. package/dist/contact/plane.js.map +1 -0
  28. package/dist/contact/polygon-clip.d.ts +27 -0
  29. package/dist/contact/polygon-clip.d.ts.map +1 -0
  30. package/dist/contact/polygon-clip.js +162 -0
  31. package/dist/contact/polygon-clip.js.map +1 -0
  32. package/dist/contact/shared-faces.d.ts +61 -0
  33. package/dist/contact/shared-faces.d.ts.map +1 -0
  34. package/dist/contact/shared-faces.js +251 -0
  35. package/dist/contact/shared-faces.js.map +1 -0
  36. package/dist/contact/tri-tri.d.ts +34 -0
  37. package/dist/contact/tri-tri.d.ts.map +1 -0
  38. package/dist/contact/tri-tri.js +195 -0
  39. package/dist/contact/tri-tri.js.map +1 -0
  40. package/dist/contact/triangle.d.ts +22 -0
  41. package/dist/contact/triangle.d.ts.map +1 -0
  42. package/dist/contact/triangle.js +60 -0
  43. package/dist/contact/triangle.js.map +1 -0
  44. package/dist/contact/types.d.ts +33 -0
  45. package/dist/contact/types.d.ts.map +1 -0
  46. package/dist/contact/types.js +5 -0
  47. package/dist/contact/types.js.map +1 -0
  48. package/dist/contact/vec3.d.ts +19 -0
  49. package/dist/contact/vec3.d.ts.map +1 -0
  50. package/dist/contact/vec3.js +50 -0
  51. package/dist/contact/vec3.js.map +1 -0
  52. package/dist/engine-ts/narrow.d.ts.map +1 -1
  53. package/dist/engine-ts/narrow.js +102 -6
  54. package/dist/engine-ts/narrow.js.map +1 -1
  55. package/dist/engine-ts/tri-mesh.d.ts +10 -0
  56. package/dist/engine-ts/tri-mesh.d.ts.map +1 -1
  57. package/dist/engine-ts/tri-mesh.js +24 -0
  58. package/dist/engine-ts/tri-mesh.js.map +1 -1
  59. package/package.json +9 -5
@@ -0,0 +1,251 @@
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 { liftTo3D, planeBasis, planeFromNormalPoint, planeKey, projectTo2D } from "./plane.js";
5
+ import { convexHull2, polygonArea, polygonCentroid, sutherlandHodgman } from "./polygon-clip.js";
6
+ import { triangleNormalRaw } from "./triangle.js";
7
+ import { cross3, dot3, length3, normalize3 } from "./vec3.js";
8
+ export function clusterSharedFaces(pairs, opts = {}) {
9
+ const planeDistSnap = opts.planeDistSnap ?? 1e-3;
10
+ const planeAngleSnap = opts.planeAngleSnap ?? 1e-3;
11
+ const lineSnap = opts.lineSnap ?? 1e-3;
12
+ const surfaceAreaM2 = opts.surfaceAreaM2 ?? 0.01;
13
+ const pointAreaM2 = opts.pointAreaM2 ?? 0.001;
14
+ const lineLengthM = opts.lineLengthM ?? 0.05;
15
+ if (pairs.length === 0)
16
+ return [];
17
+ // 1. Split into coplanar clusters and cross clusters.
18
+ const coplanarBuckets = new Map();
19
+ const crossBuckets = new Map();
20
+ for (const p of pairs) {
21
+ if (p.kind === "coplanar") {
22
+ const n = triangleNormalRaw(p.a);
23
+ const ln = length3(n);
24
+ if (ln === 0)
25
+ continue;
26
+ const plane = planeFromNormalPoint(n, p.a.v0);
27
+ const key = planeKey(plane, planeAngleSnap, planeDistSnap);
28
+ const entry = coplanarBuckets.get(key) ?? { plane, pairs: [] };
29
+ entry.pairs.push(p);
30
+ coplanarBuckets.set(key, entry);
31
+ }
32
+ else if (p.kind === "cross") {
33
+ const seg = [p.p1[0] - p.p0[0], p.p1[1] - p.p0[1], p.p1[2] - p.p0[2]];
34
+ const len = length3(seg);
35
+ if (len < 1e-12)
36
+ continue;
37
+ const dir = normalize3(seg);
38
+ // Canonicalise direction so parallel + anti-parallel hash identically.
39
+ const canon = canonicaliseDir(dir);
40
+ const base = closestPointOnLineFromOrigin(p.p0, canon);
41
+ const key = `${quant(canon[0], lineSnap)}|${quant(canon[1], lineSnap)}|${quant(canon[2], lineSnap)}|${quant(base[0], lineSnap)}|${quant(base[1], lineSnap)}|${quant(base[2], lineSnap)}`;
42
+ const entry = crossBuckets.get(key) ?? { dir: canon, point: base, pairs: [] };
43
+ entry.pairs.push(p);
44
+ crossBuckets.set(key, entry);
45
+ }
46
+ }
47
+ const out = [];
48
+ for (const { plane, pairs: bucketPairs } of coplanarBuckets.values()) {
49
+ out.push(classify(buildSurfaceCluster(plane, bucketPairs), surfaceAreaM2, pointAreaM2, lineLengthM));
50
+ }
51
+ for (const { dir, pairs: bucketPairs } of crossBuckets.values()) {
52
+ out.push(classify(buildLineCluster(dir, bucketPairs), surfaceAreaM2, pointAreaM2, lineLengthM));
53
+ }
54
+ return out;
55
+ }
56
+ // -------- surface / coplanar clusters --------
57
+ function buildSurfaceCluster(plane, bucketPairs) {
58
+ const basis = planeBasis(plane);
59
+ let totalArea = 0;
60
+ const boundaryPts = [];
61
+ for (const p of bucketPairs) {
62
+ const pa = [projectTo2D(basis, p.a.v0), projectTo2D(basis, p.a.v1), projectTo2D(basis, p.a.v2)];
63
+ const pb = [projectTo2D(basis, p.b.v0), projectTo2D(basis, p.b.v1), projectTo2D(basis, p.b.v2)];
64
+ // Clip A against B; union of these clip polygons approximates the
65
+ // true shared face. For typical IFC meshes (tiled, non-overlapping)
66
+ // summed clip area ≤ true contact area ≤ the total area of A-triangles
67
+ // whose pair is in the bucket. We take the clipped sum.
68
+ const clipped = sutherlandHodgman(pa, pb);
69
+ if (clipped.length >= 3) {
70
+ totalArea += polygonArea(clipped);
71
+ boundaryPts.push(...clipped);
72
+ }
73
+ }
74
+ const boundary2d = boundaryPts.length >= 3 ? convexHull2(boundaryPts) : boundaryPts;
75
+ const centroid2d = boundary2d.length >= 3
76
+ ? polygonCentroid(boundary2d)
77
+ : boundary2d.length === 0
78
+ ? [0, 0]
79
+ : averagePoint2(boundary2d);
80
+ const centroid = liftTo3D(basis, centroid2d);
81
+ const boundary = boundary2d.map((p) => liftTo3D(basis, p));
82
+ const spans = polygonSpans(boundary2d);
83
+ return {
84
+ plane,
85
+ centroid,
86
+ normal: plane.normal,
87
+ area_m2: totalArea,
88
+ length_m: 0,
89
+ spanMin: spans.min,
90
+ spanMax: spans.max,
91
+ boundary,
92
+ pairs: bucketPairs,
93
+ };
94
+ }
95
+ /**
96
+ * Narrowest and widest dimensions of a convex 2D polygon (metres). `max` is
97
+ * the diameter (largest vertex-pair distance); `min` is the rotating-calipers
98
+ * width — the smallest gap between two parallel supporting lines. Degenerate
99
+ * (< 3 pts) polygons have width 0.
100
+ */
101
+ function polygonSpans(pts) {
102
+ const n = pts.length;
103
+ if (n === 0)
104
+ return { min: 0, max: 0 };
105
+ let max = 0;
106
+ for (let i = 0; i < n; i++) {
107
+ for (let j = i + 1; j < n; j++) {
108
+ const a = pts[i];
109
+ const b = pts[j];
110
+ const d = Math.hypot(a[0] - b[0], a[1] - b[1]);
111
+ if (d > max)
112
+ max = d;
113
+ }
114
+ }
115
+ if (n < 3)
116
+ return { min: 0, max };
117
+ let min = Number.POSITIVE_INFINITY;
118
+ for (let i = 0; i < n; i++) {
119
+ const a = pts[i];
120
+ const b = pts[(i + 1) % n];
121
+ const ex = b[0] - a[0];
122
+ const ey = b[1] - a[1];
123
+ const elen = Math.hypot(ex, ey);
124
+ if (elen < 1e-12)
125
+ continue;
126
+ const nx = -ey / elen;
127
+ const ny = ex / elen;
128
+ let lo = Number.POSITIVE_INFINITY;
129
+ let hi = Number.NEGATIVE_INFINITY;
130
+ for (const p of pts) {
131
+ const d = (p[0] - a[0]) * nx + (p[1] - a[1]) * ny;
132
+ if (d < lo)
133
+ lo = d;
134
+ if (d > hi)
135
+ hi = d;
136
+ }
137
+ const width = hi - lo;
138
+ if (width < min)
139
+ min = width;
140
+ }
141
+ return { min: Number.isFinite(min) ? min : 0, max };
142
+ }
143
+ // -------- line / cross clusters --------
144
+ function buildLineCluster(dir, bucketPairs) {
145
+ // Project every segment onto the line direction to get 1D intervals,
146
+ // union them, sum to get length.
147
+ const intervals = [];
148
+ let refPoint = null;
149
+ for (const p of bucketPairs) {
150
+ if (p.kind !== "cross")
151
+ continue;
152
+ if (!refPoint)
153
+ refPoint = p.p0;
154
+ const t0 = projectOnto(p.p0, refPoint, dir);
155
+ const t1 = projectOnto(p.p1, refPoint, dir);
156
+ intervals.push([Math.min(t0, t1), Math.max(t0, t1)]);
157
+ }
158
+ if (!refPoint || intervals.length === 0) {
159
+ return {
160
+ centroid: [0, 0, 0],
161
+ normal: dir,
162
+ area_m2: 0,
163
+ length_m: 0,
164
+ spanMin: 0,
165
+ spanMax: 0,
166
+ boundary: [],
167
+ pairs: bucketPairs,
168
+ };
169
+ }
170
+ intervals.sort((a, b) => a[0] - b[0]);
171
+ const merged = [];
172
+ for (const iv of intervals) {
173
+ if (merged.length === 0) {
174
+ merged.push([iv[0], iv[1]]);
175
+ continue;
176
+ }
177
+ const last = merged[merged.length - 1];
178
+ if (iv[0] <= last[1])
179
+ last[1] = Math.max(last[1], iv[1]);
180
+ else
181
+ merged.push([iv[0], iv[1]]);
182
+ }
183
+ const length = merged.reduce((s, iv) => s + (iv[1] - iv[0]), 0);
184
+ // Pick the union's overall min/max as the line's centroid basis.
185
+ const tMin = merged[0][0];
186
+ const tMax = merged[merged.length - 1][1];
187
+ const centroidT = (tMin + tMax) / 2;
188
+ const centroid = [
189
+ refPoint[0] + dir[0] * centroidT,
190
+ refPoint[1] + dir[1] * centroidT,
191
+ refPoint[2] + dir[2] * centroidT,
192
+ ];
193
+ const boundary = [
194
+ [refPoint[0] + dir[0] * tMin, refPoint[1] + dir[1] * tMin, refPoint[2] + dir[2] * tMin],
195
+ [refPoint[0] + dir[0] * tMax, refPoint[1] + dir[1] * tMax, refPoint[2] + dir[2] * tMax],
196
+ ];
197
+ return {
198
+ centroid,
199
+ normal: dir,
200
+ area_m2: 0,
201
+ length_m: length,
202
+ spanMin: 0,
203
+ spanMax: length,
204
+ boundary,
205
+ pairs: bucketPairs,
206
+ };
207
+ }
208
+ // -------- helpers --------
209
+ function classify(base, surfaceAreaM2, pointAreaM2, lineLengthM) {
210
+ if (base.area_m2 >= surfaceAreaM2)
211
+ return { ...base, kind: "surface" };
212
+ if (base.length_m >= lineLengthM)
213
+ return { ...base, kind: "line" };
214
+ if (base.area_m2 >= pointAreaM2)
215
+ return { ...base, kind: "line" };
216
+ return { ...base, kind: "point" };
217
+ }
218
+ function canonicaliseDir(v) {
219
+ // Flip so the first significant component is positive.
220
+ if (Math.abs(v[0]) > 1e-9)
221
+ return v[0] > 0 ? v : [-v[0], -v[1], -v[2]];
222
+ if (Math.abs(v[1]) > 1e-9)
223
+ return v[1] > 0 ? v : [-v[0], -v[1], -v[2]];
224
+ return v[2] > 0 ? v : [-v[0], -v[1], -v[2]];
225
+ }
226
+ function closestPointOnLineFromOrigin(point, dir) {
227
+ const t = dot3(point, dir);
228
+ return [point[0] - dir[0] * t, point[1] - dir[1] * t, point[2] - dir[2] * t];
229
+ }
230
+ function projectOnto(point, refPoint, dir) {
231
+ return ((point[0] - refPoint[0]) * dir[0] +
232
+ (point[1] - refPoint[1]) * dir[1] +
233
+ (point[2] - refPoint[2]) * dir[2]);
234
+ }
235
+ function quant(x, snap) {
236
+ return Math.round(x / snap);
237
+ }
238
+ function averagePoint2(pts) {
239
+ if (pts.length === 0)
240
+ return [0, 0];
241
+ let x = 0;
242
+ let y = 0;
243
+ for (const p of pts) {
244
+ x += p[0];
245
+ y += p[1];
246
+ }
247
+ return [x / pts.length, y / pts.length];
248
+ }
249
+ // keep symbol imports that downstream modules may re-export
250
+ void cross3;
251
+ //# sourceMappingURL=shared-faces.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared-faces.js","sourceRoot":"","sources":["../../src/contact/shared-faces.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Triangle-triangle overlap tests based on Tomas Möller,
3
+ * "A Fast Triangle-Triangle Intersection Test" (1997),
4
+ * extended to report both strict crossings (with a 3D intersection segment)
5
+ * and the coplanar-overlap case, which is the signal shared-face detection
6
+ * downstream actually cares about.
7
+ */
8
+ import type { Triangle } from "./triangle.js";
9
+ import type { Vec3 } from "./types.js";
10
+ export type TriTriResult = {
11
+ readonly kind: "none";
12
+ } | {
13
+ readonly kind: "cross";
14
+ readonly p0: Vec3;
15
+ readonly p1: Vec3;
16
+ } | {
17
+ readonly kind: "coplanar";
18
+ };
19
+ /**
20
+ * Full Möller test.
21
+ *
22
+ * `planeEps` is the absolute tolerance on signed plane distance — distances
23
+ * with |d| / |N| ≤ planeEps are treated as zero (on-plane). Defaults to 1e-6
24
+ * in model-native units.
25
+ */
26
+ export declare function triTriIntersect(a: Triangle, b: Triangle, planeEps?: number): TriTriResult;
27
+ /**
28
+ * True when triangles lie in the same plane within `planeEps`.
29
+ * Both triangles must be non-degenerate.
30
+ */
31
+ export declare function trianglesCoplanar(a: Triangle, b: Triangle, planeEps?: number): boolean;
32
+ /** Signed distance (unit-normalised) from point `p` to triangle's plane. */
33
+ export declare function signedDistanceToPlane(t: Triangle, p: Vec3): number;
34
+ //# sourceMappingURL=tri-tri.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tri-tri.d.ts","sourceRoot":"","sources":["../../src/contact/tri-tri.ts"],"names":[],"mappings":"AAIA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAGvC,MAAM,MAAM,YAAY,GACpB;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACzB;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAA;CAAE,GAChE;IAAE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAA;CAAE,CAAC;AAElC;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,QAAQ,SAAO,GAAG,YAAY,CAwDvF;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,QAAQ,SAAO,GAAG,OAAO,CAmBpF;AAED,4EAA4E;AAC5E,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,IAAI,GAAG,MAAM,CAMlE"}
@@ -0,0 +1,195 @@
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 { isDegenerate, triangleNormalRaw } from "./triangle.js";
5
+ import { cross3, dot3, length3, lerp3, sub3 } from "./vec3.js";
6
+ /**
7
+ * Full Möller test.
8
+ *
9
+ * `planeEps` is the absolute tolerance on signed plane distance — distances
10
+ * with |d| / |N| ≤ planeEps are treated as zero (on-plane). Defaults to 1e-6
11
+ * in model-native units.
12
+ */
13
+ export function triTriIntersect(a, b, planeEps = 1e-6) {
14
+ if (isDegenerate(a) || isDegenerate(b))
15
+ return { kind: "none" };
16
+ // Plane of B
17
+ const N2 = triangleNormalRaw(b);
18
+ const ln2 = length3(N2);
19
+ const d2 = -dot3(N2, b.v0);
20
+ const dA0 = (dot3(N2, a.v0) + d2) / ln2;
21
+ const dA1 = (dot3(N2, a.v1) + d2) / ln2;
22
+ const dA2 = (dot3(N2, a.v2) + d2) / ln2;
23
+ const sA0 = signOf(dA0, planeEps);
24
+ const sA1 = signOf(dA1, planeEps);
25
+ const sA2 = signOf(dA2, planeEps);
26
+ if (sA0 === sA1 && sA1 === sA2 && sA0 !== 0)
27
+ return { kind: "none" };
28
+ // Plane of A
29
+ const N1 = triangleNormalRaw(a);
30
+ const ln1 = length3(N1);
31
+ const d1 = -dot3(N1, a.v0);
32
+ const dB0 = (dot3(N1, b.v0) + d1) / ln1;
33
+ const dB1 = (dot3(N1, b.v1) + d1) / ln1;
34
+ const dB2 = (dot3(N1, b.v2) + d1) / ln1;
35
+ const sB0 = signOf(dB0, planeEps);
36
+ const sB1 = signOf(dB1, planeEps);
37
+ const sB2 = signOf(dB2, planeEps);
38
+ if (sB0 === sB1 && sB1 === sB2 && sB0 !== 0)
39
+ return { kind: "none" };
40
+ // All-zero on either side → coplanar
41
+ if (sA0 === 0 && sA1 === 0 && sA2 === 0)
42
+ return { kind: "coplanar" };
43
+ if (sB0 === 0 && sB1 === 0 && sB2 === 0)
44
+ return { kind: "coplanar" };
45
+ // Chord endpoints: 3D points where each triangle's edges cross the opposite plane.
46
+ const chordA = triChord(a, dA0, dA1, dA2);
47
+ const chordB = triChord(b, dB0, dB1, dB2);
48
+ if (!chordA || !chordB)
49
+ return { kind: "none" };
50
+ // Overlap along the common intersection line.
51
+ const D = cross3(N1, N2);
52
+ const dAxis = dominantAxis(D);
53
+ const ta0 = chordA[0][dAxis];
54
+ const ta1 = chordA[1][dAxis];
55
+ const tb0 = chordB[0][dAxis];
56
+ const tb1 = chordB[1][dAxis];
57
+ const aMin = Math.min(ta0, ta1);
58
+ const aMax = Math.max(ta0, ta1);
59
+ const bMin = Math.min(tb0, tb1);
60
+ const bMax = Math.max(tb0, tb1);
61
+ const oMin = Math.max(aMin, bMin);
62
+ const oMax = Math.min(aMax, bMax);
63
+ if (oMax < oMin - planeEps)
64
+ return { kind: "none" };
65
+ // Reconstruct 3D endpoints of the overlap on the intersection line by
66
+ // picking the chord whose parameter interval matches the overlap.
67
+ const p0 = pointAtLineParam(chordA, chordB, dAxis, oMin);
68
+ const p1 = pointAtLineParam(chordA, chordB, dAxis, oMax);
69
+ return { kind: "cross", p0, p1 };
70
+ }
71
+ /**
72
+ * True when triangles lie in the same plane within `planeEps`.
73
+ * Both triangles must be non-degenerate.
74
+ */
75
+ export function trianglesCoplanar(a, b, planeEps = 1e-6) {
76
+ if (isDegenerate(a) || isDegenerate(b))
77
+ return false;
78
+ const N2 = triangleNormalRaw(b);
79
+ const d2 = -dot3(N2, b.v0);
80
+ const n2Len = length3(N2);
81
+ if (n2Len === 0)
82
+ return false;
83
+ if (Math.abs(dot3(N2, a.v0) + d2) / n2Len > planeEps)
84
+ return false;
85
+ if (Math.abs(dot3(N2, a.v1) + d2) / n2Len > planeEps)
86
+ return false;
87
+ if (Math.abs(dot3(N2, a.v2) + d2) / n2Len > planeEps)
88
+ return false;
89
+ const N1 = triangleNormalRaw(a);
90
+ const d1 = -dot3(N1, a.v0);
91
+ const n1Len = length3(N1);
92
+ if (n1Len === 0)
93
+ return false;
94
+ if (Math.abs(dot3(N1, b.v0) + d1) / n1Len > planeEps)
95
+ return false;
96
+ if (Math.abs(dot3(N1, b.v1) + d1) / n1Len > planeEps)
97
+ return false;
98
+ if (Math.abs(dot3(N1, b.v2) + d1) / n1Len > planeEps)
99
+ return false;
100
+ return true;
101
+ }
102
+ /** Signed distance (unit-normalised) from point `p` to triangle's plane. */
103
+ export function signedDistanceToPlane(t, p) {
104
+ const n = triangleNormalRaw(t);
105
+ const ln = length3(n);
106
+ if (ln === 0)
107
+ return 0;
108
+ const d = -dot3(n, t.v0);
109
+ return (dot3(n, p) + d) / ln;
110
+ }
111
+ function signOf(x, eps) {
112
+ if (x > eps)
113
+ return 1;
114
+ if (x < -eps)
115
+ return -1;
116
+ return 0;
117
+ }
118
+ function dominantAxis(v) {
119
+ const ax = Math.abs(v[0]);
120
+ const ay = Math.abs(v[1]);
121
+ const az = Math.abs(v[2]);
122
+ if (ax >= ay && ax >= az)
123
+ return 0;
124
+ if (ay >= az)
125
+ return 1;
126
+ return 2;
127
+ }
128
+ /** Intersection point of segment `p→q` with a plane, given signed distances `dp,dq` (opposite signs). */
129
+ function edgePlane(p, q, dp, dq) {
130
+ const t = dp / (dp - dq);
131
+ return lerp3(p, q, t);
132
+ }
133
+ /** Two 3D points where triangle's edges cross the opposite plane. */
134
+ function triChord(tri, d0, d1, d2) {
135
+ const pts = [];
136
+ // Count crossings by edge
137
+ if ((d0 > 0 && d1 < 0) || (d0 < 0 && d1 > 0))
138
+ pts.push(edgePlane(tri.v0, tri.v1, d0, d1));
139
+ if ((d1 > 0 && d2 < 0) || (d1 < 0 && d2 > 0))
140
+ pts.push(edgePlane(tri.v1, tri.v2, d1, d2));
141
+ if ((d2 > 0 && d0 < 0) || (d2 < 0 && d0 > 0))
142
+ pts.push(edgePlane(tri.v2, tri.v0, d2, d0));
143
+ // On-plane vertices contribute themselves once
144
+ if (d0 === 0)
145
+ pts.push(tri.v0);
146
+ if (d1 === 0)
147
+ pts.push(tri.v1);
148
+ if (d2 === 0)
149
+ pts.push(tri.v2);
150
+ if (pts.length < 2)
151
+ return null;
152
+ const first = pts[0];
153
+ const last = pts[pts.length - 1];
154
+ return [first, last];
155
+ }
156
+ /**
157
+ * Given two chord segments on the same line, parametrised by their
158
+ * dominant-axis coordinate, return the 3D point whose dominant-axis
159
+ * coordinate is `t`. We look up the chord whose interval contains `t`
160
+ * (or the closer one) and lerp along it in 3D.
161
+ */
162
+ function pointAtLineParam(chordA, chordB, axis, t) {
163
+ // Prefer chord A unless B clearly contains t better.
164
+ const ta0 = chordA[0][axis];
165
+ const ta1 = chordA[1][axis];
166
+ const tb0 = chordB[0][axis];
167
+ const tb1 = chordB[1][axis];
168
+ const aMin = Math.min(ta0, ta1);
169
+ const aMax = Math.max(ta0, ta1);
170
+ const bMin = Math.min(tb0, tb1);
171
+ const bMax = Math.max(tb0, tb1);
172
+ const aContains = t >= aMin - 1e-12 && t <= aMax + 1e-12;
173
+ const bContains = t >= bMin - 1e-12 && t <= bMax + 1e-12;
174
+ if (aContains)
175
+ return lerpChord(chordA, axis, t);
176
+ if (bContains)
177
+ return lerpChord(chordB, axis, t);
178
+ // numerical fallback — pick whichever is closer
179
+ const distA = Math.min(Math.abs(t - aMin), Math.abs(t - aMax));
180
+ const distB = Math.min(Math.abs(t - bMin), Math.abs(t - bMax));
181
+ return distA <= distB ? lerpChord(chordA, axis, t) : lerpChord(chordB, axis, t);
182
+ }
183
+ function lerpChord(chord, axis, t) {
184
+ const a = chord[0][axis];
185
+ const b = chord[1][axis];
186
+ const denom = b - a;
187
+ if (Math.abs(denom) < 1e-15)
188
+ return chord[0];
189
+ const u = (t - a) / denom;
190
+ return lerp3(chord[0], chord[1], u);
191
+ }
192
+ // Keep import of sub3 so bundlers don't eagerly tree-shake indirect users;
193
+ // triangleNormalRaw uses it transitively.
194
+ void sub3;
195
+ //# sourceMappingURL=tri-tri.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tri-tri.js","sourceRoot":"","sources":["../../src/contact/tri-tri.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import type { AABB, Mesh, Vec3 } from "./types.js";
2
+ /** Triangle as three world-space vertices. */
3
+ export interface Triangle {
4
+ readonly v0: Vec3;
5
+ readonly v1: Vec3;
6
+ readonly v2: Vec3;
7
+ }
8
+ /** Read the `triIndex`-th triangle from a mesh. */
9
+ export declare function triangleAt(mesh: Mesh, triIndex: number): Triangle;
10
+ /** Total triangle count in a mesh. */
11
+ export declare function triangleCount(mesh: Mesh): number;
12
+ /** Unnormalised triangle normal = (v1-v0) × (v2-v0). Useful as a plane direction. */
13
+ export declare function triangleNormalRaw(t: Triangle): Vec3;
14
+ /** Triangle area (geometric). */
15
+ export declare function triangleArea(t: Triangle): number;
16
+ /** Triangle centroid. */
17
+ export declare function triangleCentroid(t: Triangle): Vec3;
18
+ /** Tight AABB of a triangle. */
19
+ export declare function triangleAabb(t: Triangle): AABB;
20
+ /** True when the triangle is degenerate (zero area within tolerance). */
21
+ export declare function isDegenerate(t: Triangle, eps?: number): boolean;
22
+ //# sourceMappingURL=triangle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"triangle.d.ts","sourceRoot":"","sources":["../../src/contact/triangle.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAGnD,8CAA8C;AAC9C,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAClB,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAClB,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;CACnB;AAED,mDAAmD;AACnD,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAG,QAAQ,CAUjE;AAOD,sCAAsC;AACtC,wBAAgB,aAAa,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAEhD;AAED,qFAAqF;AACrF,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,QAAQ,GAAG,IAAI,CAEnD;AAED,iCAAiC;AACjC,wBAAgB,YAAY,CAAC,CAAC,EAAE,QAAQ,GAAG,MAAM,CAEhD;AAED,yBAAyB;AACzB,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,QAAQ,GAAG,IAAI,CAMlD;AAED,gCAAgC;AAChC,wBAAgB,YAAY,CAAC,CAAC,EAAE,QAAQ,GAAG,IAAI,CAa9C;AAED,yEAAyE;AACzE,wBAAgB,YAAY,CAAC,CAAC,EAAE,QAAQ,EAAE,GAAG,SAAQ,GAAG,OAAO,CAE9D"}
@@ -0,0 +1,60 @@
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 { cross3, length3, sub3 } from "./vec3.js";
5
+ /** Read the `triIndex`-th triangle from a mesh. */
6
+ export function triangleAt(mesh, triIndex) {
7
+ const base = triIndex * 3;
8
+ const i0 = mesh.indices[base];
9
+ const i1 = mesh.indices[base + 1];
10
+ const i2 = mesh.indices[base + 2];
11
+ return {
12
+ v0: readVertex(mesh.positions, i0),
13
+ v1: readVertex(mesh.positions, i1),
14
+ v2: readVertex(mesh.positions, i2),
15
+ };
16
+ }
17
+ function readVertex(positions, index) {
18
+ const b = index * 3;
19
+ return [positions[b], positions[b + 1], positions[b + 2]];
20
+ }
21
+ /** Total triangle count in a mesh. */
22
+ export function triangleCount(mesh) {
23
+ return mesh.indices.length / 3;
24
+ }
25
+ /** Unnormalised triangle normal = (v1-v0) × (v2-v0). Useful as a plane direction. */
26
+ export function triangleNormalRaw(t) {
27
+ return cross3(sub3(t.v1, t.v0), sub3(t.v2, t.v0));
28
+ }
29
+ /** Triangle area (geometric). */
30
+ export function triangleArea(t) {
31
+ return length3(triangleNormalRaw(t)) / 2;
32
+ }
33
+ /** Triangle centroid. */
34
+ export function triangleCentroid(t) {
35
+ return [
36
+ (t.v0[0] + t.v1[0] + t.v2[0]) / 3,
37
+ (t.v0[1] + t.v1[1] + t.v2[1]) / 3,
38
+ (t.v0[2] + t.v1[2] + t.v2[2]) / 3,
39
+ ];
40
+ }
41
+ /** Tight AABB of a triangle. */
42
+ export function triangleAabb(t) {
43
+ return {
44
+ min: [
45
+ Math.min(t.v0[0], t.v1[0], t.v2[0]),
46
+ Math.min(t.v0[1], t.v1[1], t.v2[1]),
47
+ Math.min(t.v0[2], t.v1[2], t.v2[2]),
48
+ ],
49
+ max: [
50
+ Math.max(t.v0[0], t.v1[0], t.v2[0]),
51
+ Math.max(t.v0[1], t.v1[1], t.v2[1]),
52
+ Math.max(t.v0[2], t.v1[2], t.v2[2]),
53
+ ],
54
+ };
55
+ }
56
+ /** True when the triangle is degenerate (zero area within tolerance). */
57
+ export function isDegenerate(t, eps = 1e-12) {
58
+ return length3(triangleNormalRaw(t)) <= eps;
59
+ }
60
+ //# sourceMappingURL=triangle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"triangle.js","sourceRoot":"","sources":["../../src/contact/triangle.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Core geometric and identity types for connection detection.
3
+ *
4
+ * IDs are opaque strings. In an ifc-lite integration they'd be
5
+ * federation-aware GlobalIds, but this package treats them as
6
+ * strings so it stays independent of the viewer.
7
+ */
8
+ export type Vec3 = readonly [number, number, number];
9
+ /** Axis-aligned bounding box in world coordinates. */
10
+ export interface AABB {
11
+ readonly min: Vec3;
12
+ readonly max: Vec3;
13
+ }
14
+ /** An entity's bounds, keyed by an opaque id. */
15
+ export interface MeshBounds {
16
+ readonly id: string;
17
+ readonly aabb: AABB;
18
+ }
19
+ /** Triangulated mesh in world coordinates (Z-up, matching IFC). */
20
+ export interface Mesh {
21
+ readonly id: string;
22
+ /** Flat array of positions, length = 3 * vertexCount. */
23
+ readonly positions: Float32Array | Float64Array;
24
+ /** Flat array of triangle indices, length = 3 * triangleCount. */
25
+ readonly indices: Uint32Array;
26
+ }
27
+ /** Unordered pair of ids, canonicalised to (min, max) lexicographically. */
28
+ export type IdPair = readonly [string, string];
29
+ /** Classification types emitted by the shared-face pipeline. */
30
+ export type ConnectionType = "point" | "line" | "surface";
31
+ /** Reference type for an element's buildup origin. */
32
+ export type ReferenceType = "outer_face" | "center" | "upper_face";
33
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/contact/types.ts"],"names":[],"mappings":"AAIA;;;;;;GAMG;AAEH,MAAM,MAAM,IAAI,GAAG,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AAErD,sDAAsD;AACtD,MAAM,WAAW,IAAI;IACnB,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC;IACnB,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC;CACpB;AAED,iDAAiD;AACjD,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;CACrB;AAED,mEAAmE;AACnE,MAAM,WAAW,IAAI;IACnB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,yDAAyD;IACzD,QAAQ,CAAC,SAAS,EAAE,YAAY,GAAG,YAAY,CAAC;IAChD,kEAAkE;IAClE,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;CAC/B;AAED,4EAA4E;AAC5E,MAAM,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAE/C,gEAAgE;AAChE,MAAM,MAAM,cAAc,GAAG,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;AAE1D,sDAAsD;AACtD,MAAM,MAAM,aAAa,GAAG,YAAY,GAAG,QAAQ,GAAG,YAAY,CAAC"}