@ifc-lite/clash 1.6.6 → 1.6.7

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.
@@ -21,7 +21,10 @@ export declare const SEVERITY_RANK: Record<ClashSeverity, number>;
21
21
  */
22
22
  export declare function penetrationDepth(c: Clash): number;
23
23
  /** Default band (m) under which a `hard` clash is really a face/edge *contact*
24
- * rather than a genuine interpenetration — see {@link isTouching}. */
24
+ * rather than a genuine interpenetration — see {@link isTouching}. Also the
25
+ * floor for {@link touchingEpsilonFor}'s scale-relative default: near the
26
+ * origin this constant IS the default (bit-for-bit), it only grows once the
27
+ * pair's own coordinate magnitude pushes the f32 noise floor past it. */
25
28
  export declare const TOUCHING_EPSILON = 0.0001;
26
29
  /**
27
30
  * Whether a clash is effectively a zero-distance *contact* rather than a real
@@ -29,6 +32,10 @@ export declare const TOUCHING_EPSILON = 0.0001;
29
32
  * penetration is within `eps` — typically coincident faces (a wall meeting a
30
33
  * slab, a column sitting on a footing) reported with a ~0 m depth, which users
31
34
  * reasonably distrust when they appear in the clash list.
35
+ *
36
+ * `eps` defaults to {@link touchingEpsilonFor}, scaled to this clash's own
37
+ * coordinate magnitude (see that function) so the touching band stays valid
38
+ * far from the origin. An explicit `eps` overrides the default entirely.
32
39
  */
33
40
  export declare function isTouching(c: Clash, eps?: number): boolean;
34
41
  export type ClashSortBy = 'severity' | 'depth' | 'distance';
@@ -1 +1 @@
1
- {"version":3,"file":"analysis.d.ts","sourceRoot":"","sources":["../src/analysis.ts"],"names":[],"mappings":"AAIA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEvD,uEAAuE;AACvE,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,aAAa,EAAE,MAAM,CAKvD,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,KAAK,GAAG,MAAM,CAEjD;AAED;uEACuE;AACvE,eAAO,MAAM,gBAAgB,SAAO,CAAC;AAErC;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,KAAK,EAAE,GAAG,GAAE,MAAyB,GAAG,OAAO,CAE5E;AAED,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,OAAO,GAAG,UAAU,CAAC;AAM5D;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,SAAS,KAAK,EAAE,EAAE,EAAE,EAAE,WAAW,GAAG,KAAK,EAAE,CAmB/E"}
1
+ {"version":3,"file":"analysis.d.ts","sourceRoot":"","sources":["../src/analysis.ts"],"names":[],"mappings":"AAIA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEvD,uEAAuE;AACvE,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,aAAa,EAAE,MAAM,CAKvD,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,KAAK,GAAG,MAAM,CAEjD;AAED;;;;0EAI0E;AAC1E,eAAO,MAAM,gBAAgB,SAAO,CAAC;AA4CrC;;;;;;;;;;GAUG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,KAAK,EAAE,GAAG,GAAE,MAA8B,GAAG,OAAO,CAEjF;AAED,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,OAAO,GAAG,UAAU,CAAC;AAM5D;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,SAAS,KAAK,EAAE,EAAE,EAAE,EAAE,WAAW,GAAG,KAAK,EAAE,CAmB/E"}
package/dist/analysis.js CHANGED
@@ -20,16 +20,64 @@ export function penetrationDepth(c) {
20
20
  return c.distance < 0 ? -c.distance : 0;
21
21
  }
22
22
  /** Default band (m) under which a `hard` clash is really a face/edge *contact*
23
- * rather than a genuine interpenetration — see {@link isTouching}. */
23
+ * rather than a genuine interpenetration — see {@link isTouching}. Also the
24
+ * floor for {@link touchingEpsilonFor}'s scale-relative default: near the
25
+ * origin this constant IS the default (bit-for-bit), it only grows once the
26
+ * pair's own coordinate magnitude pushes the f32 noise floor past it. */
24
27
  export const TOUCHING_EPSILON = 1e-4;
28
+ /**
29
+ * f32-ULP scale factor for a "worst-case" single-precision coordinate: for a
30
+ * value with magnitude in `[2, 4)` the true float32 ULP is `2^-22`, and for
31
+ * larger magnitudes the ULP only grows. Same term (and reasoning) as
32
+ * `precisionFloor` in `engine-ts/narrow.ts` and `narrowPhase`'s `planeEps` in
33
+ * `contact/narrow-phase.ts` — kept local because this is a different job
34
+ * (the *reported* touching band, not the narrow-phase's own depth floor) on
35
+ * a `Clash`, which doesn't carry the element bounds those two derive from.
36
+ */
37
+ const F32_ULP_SCALE = 1 / 4_194_304; // 2^-22
38
+ /**
39
+ * The touching band for one specific clash, scaled to that clash's own
40
+ * coordinate magnitude rather than a fixed constant.
41
+ *
42
+ * Geometry is ingested from f32 buffers, so a fixed `TOUCHING_EPSILON` is
43
+ * only valid near the origin: the f32 ULP exceeds `1e-4` above roughly 1 km
44
+ * from the origin (a `Clash`'s own coordinate magnitude — see below — decides
45
+ * exactly where). Past that distance, a genuinely flush pair (a wall meeting
46
+ * a slab) can pick up more than `1e-4` of pure rounding noise in its measured
47
+ * penetration depth, and the fixed band then misses it, letting it reappear
48
+ * as a hard clash in a list the user asked to de-noise.
49
+ *
50
+ * `Clash` carries no element bounds (that lives on `ClashElement`, not on the
51
+ * detection result), but it does carry `bounds` — the contact/overlap region
52
+ * itself, in the same world coordinates as the elements — so that is the
53
+ * scale source: the max absolute coordinate over the clash's own contact
54
+ * box. Floored at {@link TOUCHING_EPSILON} (not the raw single-unit f32
55
+ * floor `precisionFloor` uses) so a clash near the origin gets exactly the
56
+ * old fixed band, unchanged.
57
+ */
58
+ function touchingEpsilonFor(c) {
59
+ let extent = 0;
60
+ for (const v of [c.bounds.min, c.bounds.max]) {
61
+ for (const coord of v) {
62
+ const a = Math.abs(coord);
63
+ if (a > extent)
64
+ extent = a;
65
+ }
66
+ }
67
+ return Math.max(TOUCHING_EPSILON, extent * F32_ULP_SCALE);
68
+ }
25
69
  /**
26
70
  * Whether a clash is effectively a zero-distance *contact* rather than a real
27
71
  * overlap (#1273). True for `touch`-status clashes and for `hard` clashes whose
28
72
  * penetration is within `eps` — typically coincident faces (a wall meeting a
29
73
  * slab, a column sitting on a footing) reported with a ~0 m depth, which users
30
74
  * reasonably distrust when they appear in the clash list.
75
+ *
76
+ * `eps` defaults to {@link touchingEpsilonFor}, scaled to this clash's own
77
+ * coordinate magnitude (see that function) so the touching band stays valid
78
+ * far from the origin. An explicit `eps` overrides the default entirely.
31
79
  */
32
- export function isTouching(c, eps = TOUCHING_EPSILON) {
80
+ export function isTouching(c, eps = touchingEpsilonFor(c)) {
33
81
  return c.status === 'touch' || (c.status === 'hard' && penetrationDepth(c) <= eps);
34
82
  }
35
83
  function cmpId(a, b) {
@@ -1 +1 @@
1
- {"version":3,"file":"analysis.js","sourceRoot":"","sources":["../src/analysis.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAe/D,uEAAuE;AACvE,MAAM,CAAC,MAAM,aAAa,GAAkC;IAC1D,QAAQ,EAAE,CAAC;IACX,KAAK,EAAE,CAAC;IACR,KAAK,EAAE,CAAC;IACR,IAAI,EAAE,CAAC;CACR,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,UAAU,gBAAgB,CAAC,CAAQ;IACvC,OAAO,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;AAC1C,CAAC;AAED;uEACuE;AACvE,MAAM,CAAC,MAAM,gBAAgB,GAAG,IAAI,CAAC;AAErC;;;;;;GAMG;AACH,MAAM,UAAU,UAAU,CAAC,CAAQ,EAAE,MAAc,gBAAgB;IACjE,OAAO,CAAC,CAAC,MAAM,KAAK,OAAO,IAAI,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,IAAI,gBAAgB,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC;AACrF,CAAC;AAID,SAAS,KAAK,CAAC,CAAQ,EAAE,CAAQ;IAC/B,OAAO,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAChD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CAAC,OAAyB,EAAE,EAAe;IACpE,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IAC5B,QAAQ,EAAE,EAAE,CAAC;QACX,KAAK,UAAU;YACb,GAAG,CAAC,IAAI,CACN,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CACP,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC;gBACrD,gBAAgB,CAAC,CAAC,CAAC,GAAG,gBAAgB,CAAC,CAAC,CAAC;gBACzC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CACd,CAAC;YACF,MAAM;QACR,KAAK,OAAO;YACV,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,gBAAgB,CAAC,CAAC,CAAC,GAAG,gBAAgB,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YAC7E,MAAM;QACR,KAAK,UAAU;YACb,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,IAAI,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YAC3D,MAAM;IACV,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
1
+ {"version":3,"file":"analysis.js","sourceRoot":"","sources":["../src/analysis.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAe/D,uEAAuE;AACvE,MAAM,CAAC,MAAM,aAAa,GAAkC;IAC1D,QAAQ,EAAE,CAAC;IACX,KAAK,EAAE,CAAC;IACR,KAAK,EAAE,CAAC;IACR,IAAI,EAAE,CAAC;CACR,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,UAAU,gBAAgB,CAAC,CAAQ;IACvC,OAAO,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;AAC1C,CAAC;AAED;;;;0EAI0E;AAC1E,MAAM,CAAC,MAAM,gBAAgB,GAAG,IAAI,CAAC;AAErC;;;;;;;;GAQG;AACH,MAAM,aAAa,GAAG,CAAC,GAAG,SAAS,CAAC,CAAC,QAAQ;AAE7C;;;;;;;;;;;;;;;;;;;GAmBG;AACH,SAAS,kBAAkB,CAAC,CAAQ;IAClC,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;QAC7C,KAAK,MAAM,KAAK,IAAI,CAAC,EAAE,CAAC;YACtB,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YAC1B,IAAI,CAAC,GAAG,MAAM;gBAAE,MAAM,GAAG,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC,GAAG,CAAC,gBAAgB,EAAE,MAAM,GAAG,aAAa,CAAC,CAAC;AAC5D,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,UAAU,CAAC,CAAQ,EAAE,MAAc,kBAAkB,CAAC,CAAC,CAAC;IACtE,OAAO,CAAC,CAAC,MAAM,KAAK,OAAO,IAAI,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,IAAI,gBAAgB,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC;AACrF,CAAC;AAID,SAAS,KAAK,CAAC,CAAQ,EAAE,CAAQ;IAC/B,OAAO,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAChD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CAAC,OAAyB,EAAE,EAAe;IACpE,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IAC5B,QAAQ,EAAE,EAAE,CAAC;QACX,KAAK,UAAU;YACb,GAAG,CAAC,IAAI,CACN,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CACP,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC;gBACrD,gBAAgB,CAAC,CAAC,CAAC,GAAG,gBAAgB,CAAC,CAAC,CAAC;gBACzC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CACd,CAAC;YACF,MAAM;QACR,KAAK,OAAO;YACV,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,gBAAgB,CAAC,CAAC,CAAC,GAAG,gBAAgB,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YAC7E,MAAM;QACR,KAAK,UAAU;YACb,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,IAAI,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YAC3D,MAAM;IACV,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ifc-lite/clash",
3
- "version": "1.6.6",
3
+ "version": "1.6.7",
4
4
  "description": "Clash detection for IFC-Lite — representation-agnostic core engine + source adapters",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -33,13 +33,13 @@
33
33
  }
34
34
  },
35
35
  "dependencies": {
36
- "@ifc-lite/geometry": "^3.8.1",
37
36
  "@ifc-lite/spatial": "^1.14.13",
37
+ "@ifc-lite/geometry": "^3.8.2",
38
+ "@ifc-lite/parser": "^4.0.3",
38
39
  "@ifc-lite/query": "^1.14.16",
39
- "@ifc-lite/parser": "^4.0.2",
40
40
  "@ifc-lite/bcf": "^1.18.1",
41
41
  "@ifc-lite/ifcx": "^2.3.5",
42
- "@ifc-lite/wasm": "^4.5.0"
42
+ "@ifc-lite/wasm": "^4.5.1"
43
43
  },
44
44
  "devDependencies": {
45
45
  "typescript": "^6.0.3",