brepjs 20.5.0 → 20.7.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 (117) hide show
  1. package/README.md +1 -0
  2. package/dist/2d.cjs +9 -11
  3. package/dist/2d.js +9 -11
  4. package/dist/{adjacencyFns-DeyXahej.js → adjacencyFns-BgJQQjdt.js} +5 -6
  5. package/dist/{adjacencyFns-1rxgJ6Hw.cjs → adjacencyFns-_RTYhwtD.cjs} +5 -6
  6. package/dist/{arrayAccess-DrUGPADn.js → arrayAccess-BpgouNir.js} +1 -2
  7. package/dist/{arrayAccess-e4H9cBfh.cjs → arrayAccess-DpJYARwv.cjs} +1 -2
  8. package/dist/{blueprint-rwJjYPzo.js → blueprint-Bth4EVaO.js} +24 -37
  9. package/dist/{blueprint-Yyoiz-U1.cjs → blueprint-wq2TU1XP.cjs} +24 -37
  10. package/dist/{blueprintFns-Q3Sq-Fse.js → blueprintFns-DQmNe1p6.js} +5 -7
  11. package/dist/{blueprintFns-Ce6OoPSX.cjs → blueprintFns-Dd0gm1rX.cjs} +5 -7
  12. package/dist/{blueprintSketcher-CzKbxeTk.cjs → blueprintSketcher-CSDqr27-.cjs} +19 -31
  13. package/dist/{blueprintSketcher-FywUpRiV.js → blueprintSketcher-DNp87aQZ.js} +19 -31
  14. package/dist/{boolean2D-D8igCYc9.js → boolean2D-BAb4SnIL.js} +13 -19
  15. package/dist/{boolean2D-BzZ9iBSn.cjs → boolean2D-BkgOjMRt.cjs} +13 -19
  16. package/dist/brepjs.cjs +113 -187
  17. package/dist/brepjs.js +113 -188
  18. package/dist/{bug-O02CsAmt.cjs → bug-CBcpIPuf.cjs} +2 -4
  19. package/dist/{bug-BdOHwn_e.js → bug-ClMTAJhe.js} +2 -4
  20. package/dist/{cameraFns-Cs6v3bWQ.js → cameraFns-9AGyuZVp.js} +8 -11
  21. package/dist/{cameraFns-RHCb1F1s.cjs → cameraFns-CKUN90f_.cjs} +8 -11
  22. package/dist/{constants-ITRzCnCp.js → constants-iraOnb2p.js} +1 -2
  23. package/dist/{constants-BOVyEYGH.cjs → constants-oee0S_x6.cjs} +1 -2
  24. package/dist/core/errors.d.ts +3 -0
  25. package/dist/core.cjs +8 -8
  26. package/dist/core.js +8 -8
  27. package/dist/{cornerFinder-Dlae8IX5.js → cornerFinder-Cr_04etw.js} +4 -5
  28. package/dist/{cornerFinder-Cji_BK-R.cjs → cornerFinder-DJWo6h1Z.cjs} +4 -5
  29. package/dist/{curveFns-KS1BWGhF.js → curveFns-CkA2WJP2.js} +3 -4
  30. package/dist/{curveFns-6-ULFrEB.cjs → curveFns-U7srQ3ZA.cjs} +3 -4
  31. package/dist/{drawFns-3yRVBDgI.js → drawFns-C6bmFijD.js} +32 -45
  32. package/dist/{drawFns-Ddlgp9gQ.cjs → drawFns-DlCxozRP.cjs} +32 -45
  33. package/dist/{errors-jwhfQJZK.cjs → errors-GVyCnpi0.cjs} +6 -5
  34. package/dist/{errors-Zb3jBa0u.js → errors-vxP5FT8B.js} +6 -5
  35. package/dist/{faceFns-CTlJC5IY.js → faceFns-BBk6XKJO.js} +6 -8
  36. package/dist/{faceFns-CZeHWke7.cjs → faceFns-DSRREV5G.cjs} +6 -8
  37. package/dist/{faceRoleFns-CWU1-Pm8.js → faceRoleFns-BPxzQF-n.js} +1 -2
  38. package/dist/{faceRoleFns-CtH_48MO.cjs → faceRoleFns-Db5bYj4Q.cjs} +1 -2
  39. package/dist/{healingFns-DwSpJZfg.cjs → healingFns-C9G3yjOe.cjs} +148 -51
  40. package/dist/{healingFns-Ct3gEMvk.js → healingFns-CEr0afli.js} +148 -51
  41. package/dist/{helpers-NRZVshPb.cjs → helpers-JuPoaP_b.cjs} +15 -21
  42. package/dist/{helpers-BN1mVMuZ.js → helpers-sDialr0f.js} +15 -21
  43. package/dist/{importFns-BEi-HsSw.cjs → importFns-ClqPJCFR.cjs} +12 -19
  44. package/dist/{importFns-0kHGg-b8.js → importFns-DSUfSQn2.js} +12 -19
  45. package/dist/io.cjs +2 -2
  46. package/dist/io.js +2 -2
  47. package/dist/kernel/capabilities.d.ts +8 -0
  48. package/dist/kernel/occtWasm/occtWasmAdapter.cjs +1 -1
  49. package/dist/kernel/occtWasm/occtWasmAdapter.js +1 -2
  50. package/dist/{loftFns-B5mq1WDh.js → loftFns-B8DSoG-F.js} +7 -10
  51. package/dist/{loftFns-DL9UsQhd.cjs → loftFns-mkJeOaII.cjs} +7 -10
  52. package/dist/{measureFns-D_GpQw5z.cjs → measureFns-BvNkzSR6.cjs} +6 -8
  53. package/dist/{measureFns-CyDVZomf.js → measureFns-PRM3gOjw.js} +6 -8
  54. package/dist/measurement.cjs +2 -2
  55. package/dist/measurement.js +2 -2
  56. package/dist/{meshFns-COlno8TY.js → meshFns-CgbT3uuO.js} +6 -8
  57. package/dist/{meshFns-CAxkaRTm.cjs → meshFns-W7ZTKqiJ.cjs} +6 -8
  58. package/dist/{occtWasmAdapter-CA6PmIIj.cjs → occtWasmAdapter-BSQeA69d.cjs} +49 -57
  59. package/dist/{occtWasmAdapter-BX10fyla.js → occtWasmAdapter-PzZJHUAd.js} +44 -58
  60. package/dist/operations.cjs +2 -2
  61. package/dist/operations.js +2 -2
  62. package/dist/{originTrackingFns-DiHy5BZC.js → originTrackingFns-D8SNCDKj.js} +4 -5
  63. package/dist/{originTrackingFns-CWo6NWHK.cjs → originTrackingFns-DJDTRJh3.cjs} +4 -5
  64. package/dist/{planeOps-DJuclNxa.cjs → planeOps-C9d2Y56B.cjs} +5 -6
  65. package/dist/{planeOps-Cxws4Tiu.js → planeOps-Dp0YvuFE.js} +5 -6
  66. package/dist/{primitiveFns-ZV3aMbqG.cjs → primitiveFns-EtHyTqhw.cjs} +8 -10
  67. package/dist/{primitiveFns-CGJzS4MO.js → primitiveFns-W3RYNJcm.js} +8 -10
  68. package/dist/{principalBoxFns-BJgGEoik.js → principalBoxFns-Cbtty-2_.js} +7 -8
  69. package/dist/{principalBoxFns-5FSbxAj-.cjs → principalBoxFns-CmZa7qHi.cjs} +7 -8
  70. package/dist/projection.cjs +1 -1
  71. package/dist/projection.js +1 -2
  72. package/dist/query.cjs +2 -2
  73. package/dist/query.js +2 -2
  74. package/dist/{refResolveFns-CpVZoeOT.js → refResolveFns-BkciKtNP.js} +14 -21
  75. package/dist/{refResolveFns-Ct52Uw7R.cjs → refResolveFns-D99Vqe7a.cjs} +14 -21
  76. package/dist/result.cjs +2 -2
  77. package/dist/result.js +2 -2
  78. package/dist/{rolldown-runtime-C0BPl7ul.cjs → rolldown-runtime-BW-eSwOZ.cjs} +1 -2
  79. package/dist/{shapeFns-C2j6oZ2u.cjs → shapeFns-B54CsPyk.cjs} +5 -6
  80. package/dist/{shapeFns--1wNlcc_.js → shapeFns-DB3l3ULC.js} +5 -6
  81. package/dist/shapeRef.cjs +1 -1
  82. package/dist/shapeRef.js +1 -2
  83. package/dist/{shapeTypes-CqNJoSam.js → shapeTypes-CgbUTASh.js} +82 -161
  84. package/dist/{shapeTypes-DH2ShBU_.cjs → shapeTypes-D_anqiRe.cjs} +82 -161
  85. package/dist/sketching.cjs +4 -5
  86. package/dist/sketching.js +4 -5
  87. package/dist/{solidBuilders-CgicU3le.cjs → solidBuilders-CUd-korS.cjs} +17 -23
  88. package/dist/{solidBuilders-IstbiWju.js → solidBuilders-DE_na4G3.js} +17 -23
  89. package/dist/{surfaceBuilders-vYgSvgI6.cjs → surfaceBuilders-DOn2jWkh.cjs} +8 -12
  90. package/dist/{surfaceBuilders-8nLk2PWk.js → surfaceBuilders-wdGNiImD.js} +8 -12
  91. package/dist/text.cjs +2 -2
  92. package/dist/text.js +2 -2
  93. package/dist/{textBlueprints-fa7VHJZz.cjs → textBlueprints-BQ60Rc96.cjs} +24 -32
  94. package/dist/{textBlueprints-C13NAA3C.js → textBlueprints-B_jwMuej.js} +23 -31
  95. package/dist/{textMetrics--cikHkGX.cjs → textMetrics-Bm0a4kh7.cjs} +4 -6
  96. package/dist/{textMetrics-Dcc63qRm.js → textMetrics-Dj3yfZNQ.js} +4 -6
  97. package/dist/{threadFns-BUQPg_vI.cjs → threadFns-BuRPVenB.cjs} +21 -33
  98. package/dist/{threadFns-3U9x4v_M.js → threadFns-DlL5VnMf.js} +21 -33
  99. package/dist/topology/modifierFns.d.ts +5 -0
  100. package/dist/topology/thickResultCheck.d.ts +18 -0
  101. package/dist/topology.cjs +9 -9
  102. package/dist/topology.js +9 -9
  103. package/dist/{topologyQueryFns-DnfjQgP7.js → topologyQueryFns-6M_dbT1R.js} +10 -10
  104. package/dist/{topologyQueryFns-q2bGyuEV.cjs → topologyQueryFns-ENxs8uu2.cjs} +15 -9
  105. package/dist/{types-D24Y27N0.js → types-CKXsIm9-.js} +1 -2
  106. package/dist/{types-KjA8tY4Y.cjs → types-CjF9Rofr.cjs} +1 -2
  107. package/dist/{validityTypes-r0A2YdNq.cjs → validityTypes-BPamqRZ8.cjs} +3 -4
  108. package/dist/{validityTypes-t7JpS0Ki.js → validityTypes-BTuI0vcR.js} +3 -4
  109. package/dist/{vecOps-CCnJt-yH.cjs → vecOps-CrGEPPQM.cjs} +1 -2
  110. package/dist/{vecOps-SKPRvPH-.js → vecOps-S-m9H_fe.js} +1 -2
  111. package/dist/vectors.cjs +4 -4
  112. package/dist/vectors.js +4 -4
  113. package/dist/worker.cjs +1 -1
  114. package/dist/worker.js +1 -2
  115. package/dist/{workerPool-XcYX2UZ0.js → workerPool-Bc5hmJc4.js} +5 -10
  116. package/dist/{workerPool-D30NsiIW.cjs → workerPool-D5tiNXrI.cjs} +5 -10
  117. package/package.json +10 -10
@@ -1,5 +1,5 @@
1
- const require_bug = require("./bug-O02CsAmt.cjs");
2
- //#region src/core/result.ts
1
+ const require_bug = require("./bug-CBcpIPuf.cjs");
2
+ // src/core/result.ts
3
3
  function ok(value) {
4
4
  return {
5
5
  ok: true,
@@ -164,8 +164,7 @@ function pipeline(input) {
164
164
  }
165
165
  return makePipeline(initial);
166
166
  }
167
- //#endregion
168
- //#region src/core/errors.ts
167
+ // src/core/errors.ts
169
168
  /**
170
169
  * Domain error types and constructors for brepjs.
171
170
  * Re-exports bug/BrepBugError from utils (Layer 0) for convenience.
@@ -233,7 +232,10 @@ var BrepErrorCode = {
233
232
  CHAMFER_ANGLE_FAILED: "CHAMFER_ANGLE_FAILED",
234
233
  CSG_NOT_3D: "CSG_NOT_3D",
235
234
  SHELL_NOT_3D: "SHELL_NOT_3D",
235
+ SHELL_NO_EFFECT: "SHELL_NO_EFFECT",
236
+ SHELL_INVALID_RESULT: "SHELL_INVALID_RESULT",
236
237
  OFFSET_NOT_3D: "OFFSET_NOT_3D",
238
+ OFFSET_INVALID_RESULT: "OFFSET_INVALID_RESULT",
237
239
  NULL_SHAPE: "NULL_SHAPE",
238
240
  NO_WRAPPER: "NO_WRAPPER",
239
241
  WELD_NOT_SHELL: "WELD_NOT_SHELL",
@@ -381,7 +383,6 @@ function safeIndex(arr, index, context) {
381
383
  if (index < 0 || index >= arr.length) require_bug.bug(context ?? "safeIndex", `Index ${index} is out of bounds (array length ${arr.length})`);
382
384
  return require_bug.wasmIndex(arr, index);
383
385
  }
384
- //#endregion
385
386
  Object.defineProperty(exports, "BrepErrorCode", {
386
387
  enumerable: true,
387
388
  get: function() {
@@ -1,5 +1,5 @@
1
- import { i as wasmIndex, n as bug } from "./bug-BdOHwn_e.js";
2
- //#region src/core/result.ts
1
+ import { i as wasmIndex, n as bug } from "./bug-ClMTAJhe.js";
2
+ // src/core/result.ts
3
3
  function ok(value) {
4
4
  return {
5
5
  ok: true,
@@ -164,8 +164,7 @@ function pipeline(input) {
164
164
  }
165
165
  return makePipeline(initial);
166
166
  }
167
- //#endregion
168
- //#region src/core/errors.ts
167
+ // src/core/errors.ts
169
168
  /**
170
169
  * Domain error types and constructors for brepjs.
171
170
  * Re-exports bug/BrepBugError from utils (Layer 0) for convenience.
@@ -233,7 +232,10 @@ var BrepErrorCode = {
233
232
  CHAMFER_ANGLE_FAILED: "CHAMFER_ANGLE_FAILED",
234
233
  CSG_NOT_3D: "CSG_NOT_3D",
235
234
  SHELL_NOT_3D: "SHELL_NOT_3D",
235
+ SHELL_NO_EFFECT: "SHELL_NO_EFFECT",
236
+ SHELL_INVALID_RESULT: "SHELL_INVALID_RESULT",
236
237
  OFFSET_NOT_3D: "OFFSET_NOT_3D",
238
+ OFFSET_INVALID_RESULT: "OFFSET_INVALID_RESULT",
237
239
  NULL_SHAPE: "NULL_SHAPE",
238
240
  NO_WRAPPER: "NO_WRAPPER",
239
241
  WELD_NOT_SHELL: "WELD_NOT_SHELL",
@@ -381,5 +383,4 @@ function safeIndex(arr, index, context) {
381
383
  if (index < 0 || index >= arr.length) bug(context ?? "safeIndex", `Index ${index} is out of bounds (array length ${arr.length})`);
382
384
  return wasmIndex(arr, index);
383
385
  }
384
- //#endregion
385
386
  export { tap as A, mapBoth as C, or as D, ok as E, unwrapErr as F, unwrapOr as I, unwrapOrElse as L, tryCatch as M, tryCatchAsync as N, orElse as O, unwrap as P, zip as R, map as S, match as T, flatMap as _, moduleInitError as a, isErr as b, sketcherStateError as c, validationError as d, OK as f, err as g, collect as h, kernelError as i, tapErr as j, pipeline as k, typeCastError as l, andThen as m, computationError as n, queryError as o, all as p, ioError as r, safeIndex as s, BrepErrorCode as t, unsupportedError as u, flatten as v, mapErr as w, isOk as x, fromNullable as y };
@@ -1,8 +1,8 @@
1
- import { i as castShape, q as getKernel } from "./shapeTypes-CqNJoSam.js";
2
- import { E as ok, P as unwrap, g as err, l as typeCastError } from "./errors-Zb3jBa0u.js";
3
- import { a as getCachedSurfaceType } from "./topologyQueryFns-DnfjQgP7.js";
4
- import { r as toVec3 } from "./types-D24Y27N0.js";
5
- //#region src/topology/cast.ts
1
+ import { i as castShape, q as getKernel } from "./shapeTypes-CgbUTASh.js";
2
+ import { E as ok, P as unwrap, g as err, l as typeCastError } from "./errors-vxP5FT8B.js";
3
+ import { a as getCachedSurfaceType } from "./topologyQueryFns-6M_dbT1R.js";
4
+ import { r as toVec3 } from "./types-CKXsIm9-.js";
5
+ // src/topology/cast.ts
6
6
  var TOPO_ENUM = {
7
7
  compound: 0,
8
8
  solidCompound: 1,
@@ -99,8 +99,7 @@ function isCompSolid(shape) {
99
99
  function fromBREP(data) {
100
100
  return cast(getKernel().fromBREP(data));
101
101
  }
102
- //#endregion
103
- //#region src/topology/faceFns.ts
102
+ // src/topology/faceFns.ts
104
103
  /**
105
104
  * Face-specific functions — functional replacements for Face class methods.
106
105
  * All functions accept branded Face handles and return plain values or branded shapes.
@@ -239,5 +238,4 @@ function innerWires(face) {
239
238
  const outer = outerWire(face);
240
239
  return Array.from(iterTopo(face.wrapped, "wire")).map((w) => castShape(unwrap(downcast(w)))).filter((w) => !getKernel().isSame(w.wrapped, outer.wrapped));
241
240
  }
242
- //#endregion
243
241
  export { shapeType as C, iterTopo as S, cast as _, faceOrientation as a, fromBREP as b, innerWires as c, pointOnSurface as d, projectPointOnFace as f, asTopo as g, uvCoordinates as h, faceGeomType as i, normalAt as l, uvBounds as m, faceAxis as n, flipFaceOrientation as o, removeHolesFromFace as p, faceCenter as r, getSurfaceType as s, classifyPointOnFace as t, outerWire as u, copyShape as v, isCompSolid as x, downcast as y };
@@ -1,8 +1,8 @@
1
- const require_shapeTypes = require("./shapeTypes-DH2ShBU_.cjs");
2
- const require_errors = require("./errors-jwhfQJZK.cjs");
3
- const require_topologyQueryFns = require("./topologyQueryFns-q2bGyuEV.cjs");
4
- const require_types = require("./types-KjA8tY4Y.cjs");
5
- //#region src/topology/cast.ts
1
+ const require_shapeTypes = require("./shapeTypes-D_anqiRe.cjs");
2
+ const require_errors = require("./errors-GVyCnpi0.cjs");
3
+ const require_topologyQueryFns = require("./topologyQueryFns-ENxs8uu2.cjs");
4
+ const require_types = require("./types-CjF9Rofr.cjs");
5
+ // src/topology/cast.ts
6
6
  var TOPO_ENUM = {
7
7
  compound: 0,
8
8
  solidCompound: 1,
@@ -99,8 +99,7 @@ function isCompSolid(shape) {
99
99
  function fromBREP(data) {
100
100
  return cast(require_shapeTypes.getKernel().fromBREP(data));
101
101
  }
102
- //#endregion
103
- //#region src/topology/faceFns.ts
102
+ // src/topology/faceFns.ts
104
103
  /**
105
104
  * Face-specific functions — functional replacements for Face class methods.
106
105
  * All functions accept branded Face handles and return plain values or branded shapes.
@@ -239,7 +238,6 @@ function innerWires(face) {
239
238
  const outer = outerWire(face);
240
239
  return Array.from(iterTopo(face.wrapped, "wire")).map((w) => require_shapeTypes.castShape(require_errors.unwrap(downcast(w)))).filter((w) => !require_shapeTypes.getKernel().isSame(w.wrapped, outer.wrapped));
241
240
  }
242
- //#endregion
243
241
  Object.defineProperty(exports, "asTopo", {
244
242
  enumerable: true,
245
243
  get: function() {
@@ -1,4 +1,4 @@
1
- //#region src/topology/metadata/faceRoleFns.ts
1
+ // src/topology/metadata/faceRoleFns.ts
2
2
  var faceRoleStore = /* @__PURE__ */ new WeakMap();
3
3
  /** O(1) check whether a shape carries recorded face roles. */
4
4
  function hasFaceRoles(shape) {
@@ -33,5 +33,4 @@ function propagateFaceRolesFromEvolution(evolution, inputs, result) {
33
33
  }
34
34
  setFaceRoles(result, resultRoles);
35
35
  }
36
- //#endregion
37
36
  export { setFaceRoles as i, hasFaceRoles as n, propagateFaceRolesFromEvolution as r, getFaceRoles as t };
@@ -1,4 +1,4 @@
1
- //#region src/topology/metadata/faceRoleFns.ts
1
+ // src/topology/metadata/faceRoleFns.ts
2
2
  var faceRoleStore = /* @__PURE__ */ new WeakMap();
3
3
  /** O(1) check whether a shape carries recorded face roles. */
4
4
  function hasFaceRoles(shape) {
@@ -33,7 +33,6 @@ function propagateFaceRolesFromEvolution(evolution, inputs, result) {
33
33
  }
34
34
  setFaceRoles(result, resultRoles);
35
35
  }
36
- //#endregion
37
36
  Object.defineProperty(exports, "getFaceRoles", {
38
37
  enumerable: true,
39
38
  get: function() {
@@ -1,11 +1,11 @@
1
- const require_shapeTypes = require("./shapeTypes-DH2ShBU_.cjs");
2
- const require_errors = require("./errors-jwhfQJZK.cjs");
3
- const require_topologyQueryFns = require("./topologyQueryFns-q2bGyuEV.cjs");
4
- const require_constants = require("./constants-BOVyEYGH.cjs");
5
- const require_faceFns = require("./faceFns-CZeHWke7.cjs");
6
- const require_solidBuilders = require("./solidBuilders-CgicU3le.cjs");
7
- const require_arrayAccess = require("./arrayAccess-e4H9cBfh.cjs");
8
- //#region src/topology/threeHelpers.ts
1
+ const require_shapeTypes = require("./shapeTypes-D_anqiRe.cjs");
2
+ const require_errors = require("./errors-GVyCnpi0.cjs");
3
+ const require_topologyQueryFns = require("./topologyQueryFns-ENxs8uu2.cjs");
4
+ const require_constants = require("./constants-oee0S_x6.cjs");
5
+ const require_faceFns = require("./faceFns-DSRREV5G.cjs");
6
+ const require_solidBuilders = require("./solidBuilders-CUd-korS.cjs");
7
+ const require_arrayAccess = require("./arrayAccess-DpJYARwv.cjs");
8
+ // src/topology/threeHelpers.ts
9
9
  /**
10
10
  * Convert a ShapeMesh into BufferGeometry-compatible typed arrays.
11
11
  *
@@ -106,8 +106,100 @@ function toLODGeometryLevels(lods, options) {
106
106
  distance: distances?.[idx] ?? (last - idx) * step
107
107
  }));
108
108
  }
109
- //#endregion
110
- //#region src/topology/modifierFns.ts
109
+ // src/topology/thickResultCheck.ts
110
+ var UNCHANGED_VOLUME_REL_TOL = 1e-7;
111
+ var WALL_DISTANCE_REL_TOL = .001;
112
+ function facesByHash(shape) {
113
+ const kernel = require_shapeTypes.getKernel();
114
+ const byHash = /* @__PURE__ */ new Map();
115
+ for (const face of require_topologyQueryFns.getFaces(shape)) byHash.set(kernel.hashCode(face.wrapped, require_constants.HASH_CODE_MAX), face);
116
+ return byHash;
117
+ }
118
+ function volumeFailure(distance, input, result) {
119
+ if (Math.abs(result.volume - input.volume) <= UNCHANGED_VOLUME_REL_TOL * Math.abs(input.volume) && result.faceCount === input.faceCount) return "unchanged";
120
+ if (result.volume <= 0) return "volume";
121
+ return result.volume > input.volume === distance > 0 ? void 0 : "volume";
122
+ }
123
+ /** Distance from the middle of a generated wall's surface to its source face. */
124
+ function wallGap(source, generated) {
125
+ const kernel = require_shapeTypes.getKernel();
126
+ const uv = kernel.uvBounds(generated.wrapped);
127
+ const p = kernel.pointOnSurface(generated.wrapped, (uv.uMin + uv.uMax) / 2, (uv.vMin + uv.vMax) / 2);
128
+ const q = kernel.projectPointOnFace(source.wrapped, p);
129
+ return Math.hypot(p[0] - q[0], p[1] - q[1], p[2] - q[2]);
130
+ }
131
+ function worstWallDeviation(input, result, evolution, spec) {
132
+ if (evolution.generated.size === 0) return 0;
133
+ const sources = facesByHash(input);
134
+ const produced = facesByHash(result);
135
+ const wall = Math.abs(spec.distance);
136
+ let worst = 0;
137
+ for (const [sourceHash, generatedHashes] of evolution.generated) {
138
+ if (spec.openedFaceHashes?.has(sourceHash)) continue;
139
+ const source = sources.get(sourceHash);
140
+ if (!source) continue;
141
+ for (const hash of generatedHashes) {
142
+ const face = produced.get(hash);
143
+ if (!face) continue;
144
+ worst = Math.max(worst, Math.abs(wallGap(source, face) - wall));
145
+ }
146
+ }
147
+ return worst;
148
+ }
149
+ function failure(spec, reason, metadata) {
150
+ const wall = Math.abs(spec.distance);
151
+ const isShell = spec.operation === "shell";
152
+ if (isShell && reason === "unchanged") {
153
+ const code = require_errors.BrepErrorCode.SHELL_NO_EFFECT;
154
+ return require_errors.err(require_errors.kernelError(code, `Shell left the solid unchanged: a ${wall} wall is too thick for this body`, void 0, {
155
+ operation: "shell",
156
+ reason,
157
+ thickness: wall,
158
+ ...metadata
159
+ }, require_topologyQueryFns.getSuggestionForCode(code)));
160
+ }
161
+ const code = isShell ? require_errors.BrepErrorCode.SHELL_INVALID_RESULT : require_errors.BrepErrorCode.OFFSET_INVALID_RESULT;
162
+ const what = isShell ? `a ${wall} wall` : `an offset of ${spec.distance}`;
163
+ return require_errors.err(require_errors.kernelError(code, `${spec.operation} gave no usable solid (${reason}): ${what} is too large for this body`, void 0, {
164
+ operation: spec.operation,
165
+ reason,
166
+ distance: spec.distance,
167
+ ...metadata
168
+ }, require_topologyQueryFns.getSuggestionForCode(code)));
169
+ }
170
+ /**
171
+ * Verify a shell/offset result against its input. The wall-distance check
172
+ * needs `evolution` built from every input face hash and a kernel with native
173
+ * history; pass `undefined` to skip it.
174
+ */
175
+ function checkThickResult(input, result, evolution, spec) {
176
+ const kernel = require_shapeTypes.getKernel();
177
+ if (kernel.isNull(result.wrapped)) return failure(spec, "empty", {});
178
+ const inputVolume = kernel.volume(input.wrapped);
179
+ const resultVolume = kernel.volume(result.wrapped);
180
+ const byVolume = volumeFailure(spec.distance, {
181
+ volume: inputVolume,
182
+ faceCount: require_topologyQueryFns.getFaces(input).length
183
+ }, {
184
+ volume: resultVolume,
185
+ faceCount: require_topologyQueryFns.getFaces(result).length
186
+ });
187
+ if (byVolume) return failure(spec, byVolume, {
188
+ inputVolume,
189
+ resultVolume
190
+ });
191
+ if (!kernel.isValid(result.wrapped)) return failure(spec, "invalid", {});
192
+ if (evolution && require_shapeTypes.getKernelCapabilities().nativeHistory === true) {
193
+ const deviation = worstWallDeviation(input, result, evolution, spec);
194
+ const allowed = Math.max(10 * spec.tolerance, WALL_DISTANCE_REL_TOL * Math.abs(spec.distance));
195
+ if (deviation > allowed) return failure(spec, "wall-distance", {
196
+ deviation,
197
+ allowed
198
+ });
199
+ }
200
+ return require_errors.ok(void 0);
201
+ }
202
+ // src/topology/modifierFns.ts
111
203
  /**
112
204
  * Functional modifier operations — fillet, chamfer, shell, thicken, offset, draft.
113
205
  *
@@ -325,6 +417,22 @@ function chamfer(shape, edges, distance) {
325
417
  }));
326
418
  }
327
419
  }
420
+ function acceptThickResult(input, cast, evolution, spec, propagateMetadata = true) {
421
+ let checked;
422
+ try {
423
+ if (require_shapeTypes.isShape3D(cast) || require_shapeTypes.getKernel().isNull(cast.wrapped)) checked = checkThickResult(input, cast, evolution, spec);
424
+ else checked = require_errors.err(spec.operation === "shell" ? require_errors.kernelError("SHELL_RESULT_NOT_3D", "Shell result is not a 3D shape") : require_errors.kernelError("OFFSET_RESULT_NOT_3D", "Offset result is not a 3D shape"));
425
+ } catch (e) {
426
+ require_shapeTypes.disposeResultShape(cast);
427
+ throw e;
428
+ }
429
+ if (require_errors.isErr(checked)) {
430
+ require_shapeTypes.disposeResultShape(cast);
431
+ return checked;
432
+ }
433
+ if (evolution && propagateMetadata) require_solidBuilders.propagateAllMetadata(evolution, [input], cast);
434
+ return require_errors.ok(cast);
435
+ }
328
436
  /**
329
437
  * Create a hollow shell by removing faces and offsetting remaining walls.
330
438
  *
@@ -332,31 +440,29 @@ function chamfer(shape, edges, distance) {
332
440
  * @param faces - Faces to remove.
333
441
  * @param thickness - Wall thickness.
334
442
  * @param tolerance - Shell operation tolerance (default 1e-3).
443
+ * @returns Err `SHELL_NO_EFFECT` when the wall is too thick and the kernel
444
+ * hands back the input, `SHELL_INVALID_RESULT` when the result is not a
445
+ * usable hollow body.
335
446
  */
336
447
  function shell(shape, faces, thickness, tolerance = .001, { trackEvolution = true } = {}) {
337
448
  const check = validateNotNull$1(shape, "shell: shape");
338
449
  if (require_errors.isErr(check)) return check;
339
450
  if (thickness <= 0) return require_errors.err(require_errors.validationError("INVALID_THICKNESS", "Shell thickness must be positive"));
340
451
  if (faces.length === 0) return require_errors.err(require_errors.validationError("NO_FACES", "At least one face must be specified for shell"));
452
+ const kernel = require_shapeTypes.getKernel();
453
+ const spec = {
454
+ operation: "shell",
455
+ distance: -thickness,
456
+ tolerance,
457
+ openedFaceHashes: new Set(faces.map((f) => kernel.hashCode(f.wrapped, require_constants.HASH_CODE_MAX)))
458
+ };
341
459
  try {
342
- if (!trackEvolution) {
343
- const resultShape = require_shapeTypes.getKernel().shell(shape.wrapped, faces.map((f) => f.wrapped), thickness, tolerance);
344
- const cast = require_shapeTypes.castResultShape(resultShape);
345
- if (!require_shapeTypes.isShape3D(cast)) {
346
- require_shapeTypes.disposeResultShape(cast);
347
- return require_errors.err(require_errors.kernelError("SHELL_RESULT_NOT_3D", "Shell result is not a 3D shape"));
348
- }
349
- return require_errors.ok(cast);
350
- }
351
- const inputFaceHashes = require_solidBuilders.collectInputFaceHashes([shape]);
352
- const { shape: resultShape, evolution } = require_shapeTypes.getKernel().shellWithHistory(shape.wrapped, faces.map((f) => f.wrapped), thickness, inputFaceHashes, require_constants.HASH_CODE_MAX, tolerance);
353
- const cast = require_shapeTypes.castResultShape(resultShape);
354
- if (!require_shapeTypes.isShape3D(cast)) {
355
- require_shapeTypes.disposeResultShape(cast);
356
- return require_errors.err(require_errors.kernelError("SHELL_RESULT_NOT_3D", "Shell result is not a 3D shape"));
460
+ if (!trackEvolution && require_shapeTypes.getKernelCapabilities().nativeHistory !== true) {
461
+ const resultShape = kernel.shell(shape.wrapped, faces.map((f) => f.wrapped), thickness, tolerance);
462
+ return acceptThickResult(shape, require_shapeTypes.castResultShape(resultShape), void 0, spec);
357
463
  }
358
- require_solidBuilders.propagateAllMetadata(evolution, [shape], cast);
359
- return require_errors.ok(cast);
464
+ const { shape: resultShape, evolution } = kernel.shellWithHistory(shape.wrapped, faces.map((f) => f.wrapped), thickness, require_topologyQueryFns.subShapeHashes(shape, "face"), require_constants.HASH_CODE_MAX, tolerance);
465
+ return acceptThickResult(shape, require_shapeTypes.castResultShape(resultShape), evolution, spec, trackEvolution);
360
466
  } catch (e) {
361
467
  const raw = e instanceof Error ? e.message : String(e);
362
468
  return require_errors.err(require_errors.kernelError("SHELL_FAILED", `Shell operation failed: ${raw}`, e, {
@@ -372,21 +478,20 @@ function shell(shape, faces, thickness, tolerance = .001, { trackEvolution = tru
372
478
  * @param shape - The shape to offset (must be a 3D shape with faces).
373
479
  * @param distance - Offset distance (positive = outward, negative = inward).
374
480
  * @param tolerance - Offset tolerance (default 1e-6).
481
+ * @returns Err `OFFSET_INVALID_RESULT` when the offset consumes the body or
482
+ * gives no usable solid.
375
483
  */
376
484
  function offset(shape, distance, tolerance = 1e-6) {
377
485
  const check = validateNotNull$1(shape, "offset: shape");
378
486
  if (require_errors.isErr(check)) return check;
379
487
  if (Math.abs(distance) < 1e-10) return require_errors.err(require_errors.validationError("ZERO_OFFSET", "Offset distance cannot be zero"));
380
488
  try {
381
- const inputFaceHashes = require_solidBuilders.collectInputFaceHashes([shape]);
382
- const { shape: resultShape, evolution } = require_shapeTypes.getKernel().offsetWithHistory(shape.wrapped, distance, inputFaceHashes, require_constants.HASH_CODE_MAX, tolerance);
383
- const cast = require_shapeTypes.castResultShape(resultShape);
384
- if (!require_shapeTypes.isShape3D(cast)) {
385
- require_shapeTypes.disposeResultShape(cast);
386
- return require_errors.err(require_errors.kernelError("OFFSET_RESULT_NOT_3D", "Offset result is not a 3D shape"));
387
- }
388
- require_solidBuilders.propagateAllMetadata(evolution, [shape], cast);
389
- return require_errors.ok(cast);
489
+ const { shape: resultShape, evolution } = require_shapeTypes.getKernel().offsetWithHistory(shape.wrapped, distance, require_topologyQueryFns.subShapeHashes(shape, "face"), require_constants.HASH_CODE_MAX, tolerance);
490
+ return acceptThickResult(shape, require_shapeTypes.castResultShape(resultShape), evolution, {
491
+ operation: "offset",
492
+ distance,
493
+ tolerance
494
+ });
390
495
  } catch (e) {
391
496
  const raw = e instanceof Error ? e.message : String(e);
392
497
  return require_errors.err(require_errors.kernelError("OFFSET_FAILED", `Offset operation failed: ${raw}`, e));
@@ -481,8 +586,7 @@ function variableFillet(shape, edge, radii) {
481
586
  return require_errors.err(require_errors.kernelError(require_errors.BrepErrorCode.VARIABLE_FILLET_FAILED, "Variable-radius fillet failed", e));
482
587
  }
483
588
  }
484
- //#endregion
485
- //#region src/topology/chamferAngleFns.ts
589
+ // src/topology/chamferAngleFns.ts
486
590
  /**
487
591
  * Chamfer with distance + angle — functional API.
488
592
  *
@@ -532,8 +636,7 @@ function chamferDistAngle(shape, edges, distance, angleDeg) {
532
636
  }
533
637
  return require_errors.ok(wrapped);
534
638
  }
535
- //#endregion
536
- //#region src/topology/nurbsFns.ts
639
+ // src/topology/nurbsFns.ts
537
640
  /**
538
641
  * Extract NURBS data from a BSpline or Bezier edge.
539
642
  * Returns null if the edge is not a NURBS curve (e.g., line, circle).
@@ -552,8 +655,7 @@ function getNurbsSurfaceData(face) {
552
655
  if (!kernel.getNurbsSurfaceData) return null;
553
656
  return kernel.getNurbsSurfaceData(face.wrapped);
554
657
  }
555
- //#endregion
556
- //#region src/topology/booleanBatchFns.ts
658
+ // src/topology/booleanBatchFns.ts
557
659
  var REAL_OPS = {
558
660
  cut: require_solidBuilders.cut,
559
661
  cutAll: require_solidBuilders.cutAll,
@@ -675,8 +777,7 @@ function tryBatch(fn) {
675
777
  return null;
676
778
  }
677
779
  }
678
- //#endregion
679
- //#region src/topology/booleanDiagnosticFns.ts
780
+ // src/topology/booleanDiagnosticFns.ts
680
781
  /**
681
782
  * Boolean pre-validation diagnostics.
682
783
  */
@@ -697,8 +798,7 @@ function tryBatch(fn) {
697
798
  function checkBoolean(base, tool, op) {
698
799
  return require_shapeTypes.getKernel().checkBoolean(base.wrapped, tool.wrapped, op);
699
800
  }
700
- //#endregion
701
- //#region src/topology/evolutionFns.ts
801
+ // src/topology/evolutionFns.ts
702
802
  /**
703
803
  * Evolution-tracking variants of boolean and modifier operations.
704
804
  *
@@ -941,8 +1041,7 @@ function shellWithEvolution(shape, faces, thickness, tolerance = .001) {
941
1041
  }));
942
1042
  }
943
1043
  }
944
- //#endregion
945
- //#region src/topology/positionFns.ts
1044
+ // src/topology/positionFns.ts
946
1045
  /**
947
1046
  * Curve-based positioning operations.
948
1047
  */
@@ -970,8 +1069,7 @@ function positionOnCurve(shape, spine, param) {
970
1069
  return require_errors.err(require_errors.kernelError(require_errors.BrepErrorCode.POSITION_ON_CURVE_FAILED, `Failed to position shape on curve at param ${param}`, e));
971
1070
  }
972
1071
  }
973
- //#endregion
974
- //#region src/topology/healingFns.ts
1072
+ // src/topology/healingFns.ts
975
1073
  /**
976
1074
  * Shape healing and validation functions.
977
1075
  *
@@ -1258,7 +1356,6 @@ function fixSelfIntersection(wire) {
1258
1356
  return require_errors.err(require_errors.kernelError(require_errors.BrepErrorCode.FIX_SELF_INTERSECTION_FAILED, "Failed to fix wire self-intersection", e));
1259
1357
  }
1260
1358
  }
1261
- //#endregion
1262
1359
  Object.defineProperty(exports, "autoHeal", {
1263
1360
  enumerable: true,
1264
1361
  get: function() {