brepjs 18.18.0 → 18.19.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 (102) hide show
  1. package/README.md +24 -14
  2. package/dist/2d.cjs +7 -7
  3. package/dist/2d.js +7 -7
  4. package/dist/{blueprint-Dz0LPfbm.cjs → blueprint-Bl0YQjkk.cjs} +7 -7
  5. package/dist/{blueprint-Dod3Pucj.js → blueprint-Cy5veXS3.js} +7 -7
  6. package/dist/{blueprintFns-BKCwR41V.js → blueprintFns-CSB51aXT.js} +3 -3
  7. package/dist/{blueprintFns-BFFIJd1K.cjs → blueprintFns-Dkccxo6d.cjs} +3 -3
  8. package/dist/{blueprintSketcher-BBWw_BeX.cjs → blueprintSketcher-Cr9A-R8I.cjs} +4 -4
  9. package/dist/{blueprintSketcher-mujcO3uV.js → blueprintSketcher-DeEogKbs.js} +4 -4
  10. package/dist/{boolean2D-Bx0_gvCS.cjs → boolean2D-BZ1UjpjX.cjs} +5 -5
  11. package/dist/{boolean2D-CdSpNYuw.js → boolean2D-lE2uy4Mm.js} +5 -5
  12. package/dist/{booleanFns-CipkzoSX.cjs → booleanFns-CD25YZGm.cjs} +6 -6
  13. package/dist/{booleanFns-D4r10eG8.js → booleanFns-CtvYfQZq.js} +6 -6
  14. package/dist/brepjs.cjs +1721 -34
  15. package/dist/brepjs.js +1735 -54
  16. package/dist/{cameraFns-BbgWV9ea.cjs → cameraFns-CR2inEBU.cjs} +3 -3
  17. package/dist/{cameraFns-DfqWQ17C.js → cameraFns-Dg1lQP0S.js} +3 -3
  18. package/dist/core/errors.d.ts +1 -0
  19. package/dist/core.cjs +3 -3
  20. package/dist/core.js +3 -3
  21. package/dist/{cornerFinder-ATn5SKjb.cjs → cornerFinder-CXN1IxPg.cjs} +1 -1
  22. package/dist/{cornerFinder-KEk4VpTe.js → cornerFinder-tfWhcA2M.js} +1 -1
  23. package/dist/csg/builders.d.ts +36 -0
  24. package/dist/csg/edit.d.ts +5 -0
  25. package/dist/csg/evaluate.d.ts +52 -0
  26. package/dist/csg/evaluators/booleans.d.ts +11 -0
  27. package/dist/csg/evaluators/compound.d.ts +8 -0
  28. package/dist/csg/evaluators/context.d.ts +9 -0
  29. package/dist/csg/evaluators/primitives.d.ts +15 -0
  30. package/dist/csg/evaluators/transforms.d.ts +10 -0
  31. package/dist/csg/expressions.d.ts +72 -0
  32. package/dist/csg/hash.d.ts +9 -0
  33. package/dist/csg/index.d.ts +15 -0
  34. package/dist/csg/optimize.d.ts +4 -0
  35. package/dist/csg/serialize.d.ts +9 -0
  36. package/dist/csg/types.d.ts +128 -0
  37. package/dist/{curveFns-DkpbzRtv.js → curveFns-BEF8t7XY.js} +2 -2
  38. package/dist/{curveFns-DhQVXMK0.cjs → curveFns-CcheHkr4.cjs} +2 -2
  39. package/dist/{drawFns-1JQUg7iu.js → drawFns-CEjshioX.js} +14 -14
  40. package/dist/{drawFns-N-BXk82r.cjs → drawFns-CuzUHFyD.cjs} +14 -14
  41. package/dist/{errors-0fYW_YnO.js → errors-8GZS3vy9.js} +1 -0
  42. package/dist/{errors-Dv6pfNct.cjs → errors-BiY8-q1s.cjs} +1 -0
  43. package/dist/{extrudeFns-DmNzWF1a.cjs → extrudeFns-BwU4ng1V.cjs} +2 -2
  44. package/dist/{extrudeFns-hUNicYgI.js → extrudeFns-gcWJSK9T.js} +2 -2
  45. package/dist/{faceFns-C9tfTZwq.js → faceFns-BNhFoEII.js} +3 -3
  46. package/dist/{faceFns-UQacl82e.cjs → faceFns-BbESdudy.cjs} +3 -3
  47. package/dist/{helpers-D4gm8z-T.cjs → helpers-BU3ANziG.cjs} +7 -7
  48. package/dist/{helpers-D3JzEtZl.js → helpers-D1J5VHbk.js} +7 -7
  49. package/dist/{historyFns-C3iimEbF.cjs → historyFns-DHOoBh6G.cjs} +5 -5
  50. package/dist/{historyFns-B4M2dl-F.js → historyFns-XZp1D_aA.js} +5 -5
  51. package/dist/{importFns-Cu1aMSAb.cjs → importFns-CsRJ9lbm.cjs} +3 -3
  52. package/dist/{importFns-CJd7ltsW.js → importFns-D1oB3yU8.js} +3 -3
  53. package/dist/index.d.ts +1 -0
  54. package/dist/io.cjs +2 -2
  55. package/dist/io.js +2 -2
  56. package/dist/kernel/index.d.ts +6 -0
  57. package/dist/{measureFns-DkNQXgnh.cjs → measureFns-BkoPw5JT.cjs} +4 -4
  58. package/dist/{measureFns-BTip3Aiz.js → measureFns-C3y_WX_E.js} +4 -4
  59. package/dist/measurement.cjs +1 -1
  60. package/dist/measurement.js +1 -1
  61. package/dist/{meshFns-BEGSUUSa.cjs → meshFns-CFMr9FBb.cjs} +3 -3
  62. package/dist/{meshFns-DWsgfwE8.js → meshFns-k0BdoBGR.js} +3 -3
  63. package/dist/ns/csg.d.ts +4 -0
  64. package/dist/operations.cjs +2 -2
  65. package/dist/operations.js +2 -2
  66. package/dist/{planeOps-CH4ruLuj.cjs → planeOps-2EyPq0tU.cjs} +1 -1
  67. package/dist/{planeOps-4i2qEraD.js → planeOps-Bea3T3mc.js} +1 -1
  68. package/dist/{primitiveFns-BLIDnaB4.js → primitiveFns-DF5IAVNP.js} +7 -7
  69. package/dist/{primitiveFns-BLyZbYzv.cjs → primitiveFns-YpYBx4Pd.cjs} +7 -7
  70. package/dist/projection.cjs +1 -1
  71. package/dist/projection.js +1 -1
  72. package/dist/query.cjs +2 -2
  73. package/dist/query.js +2 -2
  74. package/dist/result.cjs +1 -1
  75. package/dist/result.js +1 -1
  76. package/dist/{shapeFns-CsFHf3W8.cjs → shapeFns-CHTLdb_n.cjs} +3 -3
  77. package/dist/{shapeFns-DaqT_8dv.js → shapeFns-x8vqq2fR.js} +3 -3
  78. package/dist/shapeRef.cjs +1 -1
  79. package/dist/shapeRef.js +1 -1
  80. package/dist/{shapeRefFns-WwBIiDUH.cjs → shapeRefFns-CDRLEUik.cjs} +4 -4
  81. package/dist/{shapeRefFns-BEsxgYOo.js → shapeRefFns-CE0yS0EB.js} +4 -4
  82. package/dist/{shapeTypes-BcAUN8Jp.cjs → shapeTypes-BpKhed-9.cjs} +15 -1
  83. package/dist/{shapeTypes-Dqjd8VMv.js → shapeTypes-DGtDTS9s.js} +10 -2
  84. package/dist/sketching.cjs +3 -3
  85. package/dist/sketching.js +3 -3
  86. package/dist/{solidBuilders-C8wxbX4w.cjs → solidBuilders-BlBaFSCS.cjs} +3 -3
  87. package/dist/{solidBuilders-CYtiaHtQ.js → solidBuilders-Cot05qzs.js} +3 -3
  88. package/dist/{surfaceBuilders-D60F6RHs.cjs → surfaceBuilders-frj7YRrD.cjs} +3 -3
  89. package/dist/{surfaceBuilders-CuChXov6.js → surfaceBuilders-zJyikeav.js} +3 -3
  90. package/dist/text.cjs +2 -2
  91. package/dist/text.js +2 -2
  92. package/dist/{textBlueprints-Cm_gPjjQ.js → textBlueprints-Bv6zhEyn.js} +9 -9
  93. package/dist/{textBlueprints-Cg2IOa7K.cjs → textBlueprints-CHh9SChA.cjs} +9 -9
  94. package/dist/{textMetrics-BExS67Zh.cjs → textMetrics-CKNdQX02.cjs} +2 -2
  95. package/dist/{textMetrics-Dbgikkim.js → textMetrics-vUJTTEFi.js} +2 -2
  96. package/dist/topology.cjs +7 -7
  97. package/dist/topology.js +7 -7
  98. package/dist/{topologyQueryFns-C_rxyeER.cjs → topologyQueryFns-CHsPXNbI.cjs} +2 -2
  99. package/dist/{topologyQueryFns-DHbFP_6r.js → topologyQueryFns-CcWaCxeb.js} +2 -2
  100. package/dist/vectors.cjs +1 -1
  101. package/dist/vectors.js +1 -1
  102. package/package.json +1 -1
package/dist/brepjs.cjs CHANGED
@@ -1,36 +1,36 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_textBlueprints = require("./textBlueprints-Cg2IOa7K.cjs");
3
- const require_shapeTypes = require("./shapeTypes-BcAUN8Jp.cjs");
2
+ const require_textBlueprints = require("./textBlueprints-CHh9SChA.cjs");
3
+ const require_shapeTypes = require("./shapeTypes-BpKhed-9.cjs");
4
4
  const require_vec3 = require("./vec3-S4Oh59IX.cjs");
5
5
  const require_occtWasmAdapter = require("./occtWasmAdapter-C2VW-uYg.cjs");
6
- const require_errors = require("./errors-Dv6pfNct.cjs");
7
- const require_topologyQueryFns = require("./topologyQueryFns-C_rxyeER.cjs");
6
+ const require_errors = require("./errors-BiY8-q1s.cjs");
7
+ const require_topologyQueryFns = require("./topologyQueryFns-CHsPXNbI.cjs");
8
8
  const require_constants = require("./constants-DTorLmes.cjs");
9
9
  const require_types = require("./types-CDkxah-M.cjs");
10
10
  const require_vecOps = require("./vecOps-D7xplSx8.cjs");
11
- const require_planeOps = require("./planeOps-CH4ruLuj.cjs");
12
- const require_faceFns = require("./faceFns-UQacl82e.cjs");
13
- const require_shapeFns = require("./shapeFns-CsFHf3W8.cjs");
14
- const require_curveFns = require("./curveFns-DhQVXMK0.cjs");
15
- const require_meshFns = require("./meshFns-BEGSUUSa.cjs");
11
+ const require_planeOps = require("./planeOps-2EyPq0tU.cjs");
12
+ const require_faceFns = require("./faceFns-BbESdudy.cjs");
13
+ const require_shapeFns = require("./shapeFns-CHTLdb_n.cjs");
14
+ const require_curveFns = require("./curveFns-CcheHkr4.cjs");
15
+ const require_meshFns = require("./meshFns-CFMr9FBb.cjs");
16
16
  const require_arrayAccess = require("./arrayAccess-7pTWqkJu.cjs");
17
- const require_surfaceBuilders = require("./surfaceBuilders-D60F6RHs.cjs");
18
- const require_booleanFns = require("./booleanFns-CipkzoSX.cjs");
19
- const require_primitiveFns = require("./primitiveFns-BLyZbYzv.cjs");
20
- const require_historyFns = require("./historyFns-C3iimEbF.cjs");
21
- const require_blueprintSketcher = require("./blueprintSketcher-BBWw_BeX.cjs");
22
- const require_helpers = require("./helpers-D4gm8z-T.cjs");
23
- const require_drawFns = require("./drawFns-N-BXk82r.cjs");
24
- const require_solidBuilders = require("./solidBuilders-C8wxbX4w.cjs");
25
- const require_measureFns = require("./measureFns-DkNQXgnh.cjs");
26
- const require_cornerFinder = require("./cornerFinder-ATn5SKjb.cjs");
27
- const require_boolean2D = require("./boolean2D-Bx0_gvCS.cjs");
28
- const require_blueprintFns = require("./blueprintFns-BFFIJd1K.cjs");
29
- const require_importFns = require("./importFns-Cu1aMSAb.cjs");
30
- const require_extrudeFns = require("./extrudeFns-DmNzWF1a.cjs");
31
- const require_cameraFns = require("./cameraFns-BbgWV9ea.cjs");
32
- const require_textMetrics = require("./textMetrics-BExS67Zh.cjs");
33
- const require_shapeRefFns = require("./shapeRefFns-WwBIiDUH.cjs");
17
+ const require_surfaceBuilders = require("./surfaceBuilders-frj7YRrD.cjs");
18
+ const require_booleanFns = require("./booleanFns-CD25YZGm.cjs");
19
+ const require_primitiveFns = require("./primitiveFns-YpYBx4Pd.cjs");
20
+ const require_historyFns = require("./historyFns-DHOoBh6G.cjs");
21
+ const require_blueprintSketcher = require("./blueprintSketcher-Cr9A-R8I.cjs");
22
+ const require_helpers = require("./helpers-BU3ANziG.cjs");
23
+ const require_drawFns = require("./drawFns-CuzUHFyD.cjs");
24
+ const require_solidBuilders = require("./solidBuilders-BlBaFSCS.cjs");
25
+ const require_measureFns = require("./measureFns-BkoPw5JT.cjs");
26
+ const require_cornerFinder = require("./cornerFinder-CXN1IxPg.cjs");
27
+ const require_boolean2D = require("./boolean2D-BZ1UjpjX.cjs");
28
+ const require_blueprintFns = require("./blueprintFns-Dkccxo6d.cjs");
29
+ const require_importFns = require("./importFns-CsRJ9lbm.cjs");
30
+ const require_extrudeFns = require("./extrudeFns-BwU4ng1V.cjs");
31
+ const require_cameraFns = require("./cameraFns-CR2inEBU.cjs");
32
+ const require_textMetrics = require("./textMetrics-CKNdQX02.cjs");
33
+ const require_shapeRefFns = require("./shapeRefFns-CDRLEUik.cjs");
34
34
  const require_workerHandler = require("./workerHandler-C7seK7H-.cjs");
35
35
  //#region src/topology/shapeBooleans.ts
36
36
  var BOPAlgo_GlueShift = 1;
@@ -2879,12 +2879,12 @@ function makeInternalGearProfileWire(params) {
2879
2879
  }
2880
2880
  function makeProfileWire(params, isInternal) {
2881
2881
  try {
2882
- var _usingCtx$2 = require_shapeTypes._usingCtx();
2882
+ var _usingCtx$3 = require_shapeTypes._usingCtx();
2883
2883
  const { teeth, moduleSize, pressureAngle, shift, clearance, flankThinning, samples = adaptiveSampleCount(moduleSize) } = params;
2884
2884
  if (teeth < 4) return require_errors.err(require_errors.validationError("GEAR_TEETH_TOO_FEW", `gear needs ≥ 4 teeth, got ${teeth}`));
2885
2885
  if (moduleSize <= 0) return require_errors.err(require_errors.validationError("GEAR_MODULE_NONPOSITIVE", `module must be > 0, got ${moduleSize}`));
2886
2886
  const tm = gearGeometry(teeth, moduleSize, pressureAngle, shift, clearance, flankThinning, isInternal);
2887
- const scope = _usingCtx$2.u(new require_shapeTypes.DisposalScope());
2887
+ const scope = _usingCtx$3.u(new require_shapeTypes.DisposalScope());
2888
2888
  const allEdges = [];
2889
2889
  for (let i = 0; i < teeth; i++) {
2890
2890
  const periodEdges = buildToothPeriodEdges(tm, i, teeth, samples, scope);
@@ -2895,9 +2895,9 @@ function makeProfileWire(params, isInternal) {
2895
2895
  if (require_errors.isErr(wireResult)) return wireResult;
2896
2896
  return require_errors.ok(wireResult.value);
2897
2897
  } catch (_) {
2898
- _usingCtx$2.e = _;
2898
+ _usingCtx$3.e = _;
2899
2899
  } finally {
2900
- _usingCtx$2.d();
2900
+ _usingCtx$3.d();
2901
2901
  }
2902
2902
  }
2903
2903
  //#endregion
@@ -3078,8 +3078,8 @@ function resolvePlanetaryParams(params) {
3078
3078
  }
3079
3079
  function makeOuterCircleWire(radius) {
3080
3080
  try {
3081
- var _usingCtx$1 = require_shapeTypes._usingCtx();
3082
- const wireResult = require_surfaceBuilders.assembleWire([_usingCtx$1.u(new require_shapeTypes.DisposalScope()).register(require_surfaceBuilders.makeCircle(radius, [
3081
+ var _usingCtx$2 = require_shapeTypes._usingCtx();
3082
+ const wireResult = require_surfaceBuilders.assembleWire([_usingCtx$2.u(new require_shapeTypes.DisposalScope()).register(require_surfaceBuilders.makeCircle(radius, [
3083
3083
  0,
3084
3084
  0,
3085
3085
  0
@@ -3091,9 +3091,9 @@ function makeOuterCircleWire(radius) {
3091
3091
  if (require_errors.isErr(wireResult)) return wireResult;
3092
3092
  return require_errors.ok(wireResult.value);
3093
3093
  } catch (_) {
3094
- _usingCtx$1.e = _;
3094
+ _usingCtx$2.e = _;
3095
3095
  } finally {
3096
- _usingCtx$1.d();
3096
+ _usingCtx$2.d();
3097
3097
  }
3098
3098
  }
3099
3099
  function finalizeExternalSolid(wire, thickness, bore, geom, diagnostics) {
@@ -3412,6 +3412,1687 @@ var patterns_exports = /* @__PURE__ */ require_textBlueprints.__exportAll({
3412
3412
  linearPattern: () => require_historyFns.linearPattern
3413
3413
  });
3414
3414
  //#endregion
3415
+ //#region src/csg/hash.ts
3416
+ var FNV_OFFSET = 14695981039346656037n;
3417
+ var FNV_PRIME = 1099511628211n;
3418
+ var MASK_64 = 18446744073709551615n;
3419
+ function fnvInit() {
3420
+ return FNV_OFFSET;
3421
+ }
3422
+ function fnvMixByte(h, byte) {
3423
+ return (h ^ BigInt(byte & 255)) * FNV_PRIME & MASK_64;
3424
+ }
3425
+ function fnvMixBytes(h, bytes) {
3426
+ let r = h;
3427
+ for (let i = 0; i < bytes.length; i++) r = fnvMixByte(r, bytes[i] ?? 0);
3428
+ return r;
3429
+ }
3430
+ var ENCODER = new TextEncoder();
3431
+ function fnvMixString(h, s) {
3432
+ return fnvMixBytes(h, ENCODER.encode(s));
3433
+ }
3434
+ var SCRATCH = /* @__PURE__ */ new ArrayBuffer(8);
3435
+ var SCRATCH_VIEW = new DataView(SCRATCH);
3436
+ var SCRATCH_BYTES = new Uint8Array(SCRATCH);
3437
+ function fnvMixNumber(h, n) {
3438
+ SCRATCH_VIEW.setFloat64(0, Object.is(n, -0) ? 0 : n);
3439
+ return fnvMixBytes(h, SCRATCH_BYTES);
3440
+ }
3441
+ function fnvMixHash(h, child) {
3442
+ let r = h;
3443
+ let v = child & MASK_64;
3444
+ for (let i = 0; i < 8; i++) {
3445
+ r = fnvMixByte(r, Number(v & 255n));
3446
+ v >>= 8n;
3447
+ }
3448
+ return r;
3449
+ }
3450
+ function fnvMixInt32(h, n) {
3451
+ let r = h;
3452
+ let v = n | 0;
3453
+ for (let i = 0; i < 4; i++) {
3454
+ r = fnvMixByte(r, v & 255);
3455
+ v >>>= 8;
3456
+ }
3457
+ return r;
3458
+ }
3459
+ function fnvMixBool(h, b) {
3460
+ return fnvMixByte(h, b ? 1 : 0);
3461
+ }
3462
+ function toHex(h) {
3463
+ return (h & MASK_64).toString(16).padStart(16, "0");
3464
+ }
3465
+ //#endregion
3466
+ //#region src/csg/expressions.ts
3467
+ var EMPTY_DEPS$1 = /* @__PURE__ */ new Set();
3468
+ function startHash$1(tag) {
3469
+ return fnvMixString(fnvInit(), tag);
3470
+ }
3471
+ function numLit(value) {
3472
+ return {
3473
+ kind: "NumLit",
3474
+ value,
3475
+ structuralHash: fnvMixNumber(startHash$1("NumLit"), value),
3476
+ freeParams: EMPTY_DEPS$1
3477
+ };
3478
+ }
3479
+ function vec3Lit(value) {
3480
+ let h = startHash$1("Vec3Lit");
3481
+ for (const n of value) h = fnvMixNumber(h, n);
3482
+ return {
3483
+ kind: "Vec3Lit",
3484
+ value,
3485
+ structuralHash: h,
3486
+ freeParams: EMPTY_DEPS$1
3487
+ };
3488
+ }
3489
+ function vec2Lit(value) {
3490
+ let h = startHash$1("Vec2Lit");
3491
+ for (const n of value) h = fnvMixNumber(h, n);
3492
+ return {
3493
+ kind: "Vec2Lit",
3494
+ value,
3495
+ structuralHash: h,
3496
+ freeParams: EMPTY_DEPS$1
3497
+ };
3498
+ }
3499
+ function param(name) {
3500
+ return {
3501
+ kind: "Param",
3502
+ name,
3503
+ structuralHash: fnvMixString(startHash$1("Param"), name),
3504
+ freeParams: new Set([name])
3505
+ };
3506
+ }
3507
+ function binOp(op, a, b) {
3508
+ let h = fnvMixString(startHash$1("BinOp"), op);
3509
+ h = fnvMixHash(h, a.structuralHash);
3510
+ h = fnvMixHash(h, b.structuralHash);
3511
+ return {
3512
+ kind: "BinOp",
3513
+ op,
3514
+ a,
3515
+ b,
3516
+ structuralHash: h,
3517
+ freeParams: unionParams(a.freeParams, b.freeParams)
3518
+ };
3519
+ }
3520
+ function unaryOp(op, arg) {
3521
+ let h = fnvMixString(startHash$1("UnaryOp"), op);
3522
+ h = fnvMixHash(h, arg.structuralHash);
3523
+ return {
3524
+ kind: "UnaryOp",
3525
+ op,
3526
+ arg,
3527
+ structuralHash: h,
3528
+ freeParams: arg.freeParams
3529
+ };
3530
+ }
3531
+ function component(vec, index) {
3532
+ let h = fnvMixInt32(startHash$1("Component"), index);
3533
+ h = fnvMixHash(h, vec.structuralHash);
3534
+ return {
3535
+ kind: "Component",
3536
+ vec,
3537
+ index,
3538
+ structuralHash: h,
3539
+ freeParams: vec.freeParams
3540
+ };
3541
+ }
3542
+ function buildVec(dim, components) {
3543
+ let h = fnvMixInt32(startHash$1("BuildVec"), dim);
3544
+ const deps = /* @__PURE__ */ new Set();
3545
+ for (const c of components) {
3546
+ h = fnvMixHash(h, c.structuralHash);
3547
+ for (const p of c.freeParams) deps.add(p);
3548
+ }
3549
+ return {
3550
+ kind: "BuildVec",
3551
+ dim,
3552
+ components,
3553
+ structuralHash: h,
3554
+ freeParams: deps
3555
+ };
3556
+ }
3557
+ var add = (a, b) => binOp("+", a, b);
3558
+ var mul = (a, b) => binOp("*", a, b);
3559
+ function asScalarExpr(input) {
3560
+ return typeof input === "number" ? numLit(input) : input;
3561
+ }
3562
+ function asVecExpr(input, dim) {
3563
+ if (!Array.isArray(input)) return input;
3564
+ const arr = input;
3565
+ if (arr.every((v) => typeof v === "number")) return dim === 3 ? vec3Lit([
3566
+ arr[0],
3567
+ arr[1],
3568
+ arr[2]
3569
+ ]) : vec2Lit([arr[0], arr[1]]);
3570
+ return buildVec(dim, arr.map(asScalarExpr));
3571
+ }
3572
+ function asVec3Expr(input) {
3573
+ return asVecExpr(input, 3);
3574
+ }
3575
+ function asVec2Expr(input) {
3576
+ return asVecExpr(input, 2);
3577
+ }
3578
+ function unionParams(a, b) {
3579
+ if (a.size === 0) return b;
3580
+ if (b.size === 0) return a;
3581
+ const out = new Set(a);
3582
+ for (const x of b) out.add(x);
3583
+ return out;
3584
+ }
3585
+ function isNumber$2(v) {
3586
+ return typeof v === "number";
3587
+ }
3588
+ function expectNumber(v, where) {
3589
+ if (isNumber$2(v)) return require_errors.ok(v);
3590
+ return require_errors.err(require_errors.validationError(require_errors.BrepErrorCode.NULL_SHAPE_INPUT, `${where}: expected number, got ${Array.isArray(v) ? `vector(${v.length})` : typeof v}`));
3591
+ }
3592
+ function expectVecLen(v, len, where) {
3593
+ if (Array.isArray(v) && v.length === len) return require_errors.ok(v);
3594
+ return require_errors.err(require_errors.validationError(require_errors.BrepErrorCode.NULL_SHAPE_INPUT, `${where}: expected Vec${len}, got ${isNumber$2(v) ? "number" : `vector(${v.length})`}`));
3595
+ }
3596
+ function evalExpr(expr, env) {
3597
+ switch (expr.kind) {
3598
+ case "NumLit": return require_errors.ok(expr.value);
3599
+ case "Vec3Lit": return require_errors.ok(expr.value);
3600
+ case "Vec2Lit": return require_errors.ok(expr.value);
3601
+ case "Param": {
3602
+ const v = env[expr.name];
3603
+ if (v === void 0) return require_errors.err(require_errors.validationError(require_errors.BrepErrorCode.NULL_SHAPE_INPUT, `unbound param: ${expr.name}`));
3604
+ return require_errors.ok(v);
3605
+ }
3606
+ case "BinOp": return evalBinOp(expr, env);
3607
+ case "UnaryOp": return evalUnaryOp(expr, env);
3608
+ case "Component": return evalComponent(expr, env);
3609
+ case "BuildVec": return evalBuildVec(expr, env);
3610
+ }
3611
+ }
3612
+ function evalBinOp(expr, env) {
3613
+ const ar = evalExpr(expr.a, env);
3614
+ if (!ar.ok) return ar;
3615
+ const br = evalExpr(expr.b, env);
3616
+ if (!br.ok) return br;
3617
+ const an = expectNumber(ar.value, `BinOp(${expr.op}).a`);
3618
+ if (!an.ok) return an;
3619
+ const bn = expectNumber(br.value, `BinOp(${expr.op}).b`);
3620
+ if (!bn.ok) return bn;
3621
+ switch (expr.op) {
3622
+ case "+": return require_errors.ok(an.value + bn.value);
3623
+ case "-": return require_errors.ok(an.value - bn.value);
3624
+ case "*": return require_errors.ok(an.value * bn.value);
3625
+ case "/":
3626
+ if (bn.value === 0) return require_errors.err(require_errors.validationError(require_errors.BrepErrorCode.NULL_SHAPE_INPUT, `BinOp(/): division by zero`));
3627
+ return require_errors.ok(an.value / bn.value);
3628
+ }
3629
+ }
3630
+ function evalUnaryOp(expr, env) {
3631
+ const ar = evalExpr(expr.arg, env);
3632
+ if (!ar.ok) return ar;
3633
+ const an = expectNumber(ar.value, `UnaryOp(${expr.op})`);
3634
+ if (!an.ok) return an;
3635
+ const n = an.value;
3636
+ switch (expr.op) {
3637
+ case "neg": return require_errors.ok(-n);
3638
+ case "sin": return require_errors.ok(Math.sin(n));
3639
+ case "cos": return require_errors.ok(Math.cos(n));
3640
+ case "sqrt": return require_errors.ok(Math.sqrt(n));
3641
+ case "abs": return require_errors.ok(Math.abs(n));
3642
+ }
3643
+ }
3644
+ function evalComponent(expr, env) {
3645
+ const vr = evalExpr(expr.vec, env);
3646
+ if (!vr.ok) return vr;
3647
+ if (isNumber$2(vr.value)) return require_errors.err(require_errors.validationError(require_errors.BrepErrorCode.NULL_SHAPE_INPUT, `Component: cannot index a scalar`));
3648
+ const v = vr.value;
3649
+ const c = v[expr.index];
3650
+ if (c === void 0) return require_errors.err(require_errors.validationError(require_errors.BrepErrorCode.NULL_SHAPE_INPUT, `Component: index ${expr.index} out of range for Vec${v.length}`));
3651
+ return require_errors.ok(c);
3652
+ }
3653
+ function evalBuildVec(expr, env) {
3654
+ if (expr.components.length !== expr.dim) return require_errors.err(require_errors.validationError(require_errors.BrepErrorCode.NULL_SHAPE_INPUT, `BuildVec(${expr.dim}): expected ${expr.dim} components, got ${expr.components.length}`));
3655
+ const out = [];
3656
+ for (const c of expr.components) {
3657
+ const r = evalExpr(c, env);
3658
+ if (!r.ok) return r;
3659
+ const n = expectNumber(r.value, "BuildVec.component");
3660
+ if (!n.ok) return n;
3661
+ out.push(n.value);
3662
+ }
3663
+ return require_errors.ok(expr.dim === 2 ? [out[0], out[1]] : [
3664
+ out[0],
3665
+ out[1],
3666
+ out[2]
3667
+ ]);
3668
+ }
3669
+ function evalScalar(expr, env, where) {
3670
+ const r = evalExpr(expr, env);
3671
+ if (!r.ok) return r;
3672
+ return expectNumber(r.value, where);
3673
+ }
3674
+ function evalVec3(expr, env, where) {
3675
+ const r = evalExpr(expr, env);
3676
+ if (!r.ok) return r;
3677
+ const v = expectVecLen(r.value, 3, where);
3678
+ if (!v.ok) return v;
3679
+ const [a, b, c] = v.value;
3680
+ return require_errors.ok([
3681
+ a,
3682
+ b,
3683
+ c
3684
+ ]);
3685
+ }
3686
+ function projectEnv(env, deps) {
3687
+ if (deps.size === 0) return Object.freeze({});
3688
+ const out = {};
3689
+ for (const k of deps) {
3690
+ const v = env[k];
3691
+ if (v !== void 0) out[k] = v;
3692
+ }
3693
+ return Object.freeze(out);
3694
+ }
3695
+ //#endregion
3696
+ //#region src/csg/builders.ts
3697
+ var EMPTY_DEPS = /* @__PURE__ */ new Set();
3698
+ function startHash(tag) {
3699
+ return fnvMixString(fnvInit(), tag);
3700
+ }
3701
+ function mix(h, x) {
3702
+ return fnvMixHash(h, x.structuralHash);
3703
+ }
3704
+ function mixOptExpr(h, e) {
3705
+ if (e === void 0) return fnvMixBool(h, false);
3706
+ return mix(fnvMixBool(h, true), e);
3707
+ }
3708
+ function mixOptNumber(h, n) {
3709
+ if (n === void 0) return fnvMixBool(h, false);
3710
+ return fnvMixNumber(fnvMixBool(h, true), n);
3711
+ }
3712
+ function depsOf(...sources) {
3713
+ const acc = /* @__PURE__ */ new Set();
3714
+ for (const s of sources) {
3715
+ if (!s) continue;
3716
+ for (const p of s.freeParams) acc.add(p);
3717
+ }
3718
+ return acc.size === 0 ? EMPTY_DEPS : acc;
3719
+ }
3720
+ function box$1(x, y, z) {
3721
+ const xe = asScalarExpr(x);
3722
+ const ye = asScalarExpr(y);
3723
+ const ze = asScalarExpr(z);
3724
+ let h = startHash("Box");
3725
+ h = mix(mix(mix(h, xe), ye), ze);
3726
+ return {
3727
+ kind: "Box",
3728
+ x: xe,
3729
+ y: ye,
3730
+ z: ze,
3731
+ structuralHash: h,
3732
+ freeParams: depsOf(xe, ye, ze)
3733
+ };
3734
+ }
3735
+ function sphere$1(radius) {
3736
+ const re = asScalarExpr(radius);
3737
+ return {
3738
+ kind: "Sphere",
3739
+ radius: re,
3740
+ structuralHash: mix(startHash("Sphere"), re),
3741
+ freeParams: re.freeParams
3742
+ };
3743
+ }
3744
+ function cylinder$1(radius, height) {
3745
+ const re = asScalarExpr(radius);
3746
+ const he = asScalarExpr(height);
3747
+ return {
3748
+ kind: "Cylinder",
3749
+ radius: re,
3750
+ height: he,
3751
+ structuralHash: mix(mix(startHash("Cylinder"), re), he),
3752
+ freeParams: depsOf(re, he)
3753
+ };
3754
+ }
3755
+ function cone$1(radius1, radius2, height) {
3756
+ const r1 = asScalarExpr(radius1);
3757
+ const r2 = asScalarExpr(radius2);
3758
+ const he = asScalarExpr(height);
3759
+ let h = startHash("Cone");
3760
+ h = mix(mix(mix(h, r1), r2), he);
3761
+ return {
3762
+ kind: "Cone",
3763
+ radius1: r1,
3764
+ radius2: r2,
3765
+ height: he,
3766
+ structuralHash: h,
3767
+ freeParams: depsOf(r1, r2, he)
3768
+ };
3769
+ }
3770
+ function torus$1(majorRadius, minorRadius) {
3771
+ const ma = asScalarExpr(majorRadius);
3772
+ const mi = asScalarExpr(minorRadius);
3773
+ return {
3774
+ kind: "Torus",
3775
+ majorRadius: ma,
3776
+ minorRadius: mi,
3777
+ structuralHash: mix(mix(startHash("Torus"), ma), mi),
3778
+ freeParams: depsOf(ma, mi)
3779
+ };
3780
+ }
3781
+ function polygon$1(points) {
3782
+ const pts = points.map(asVec3Expr);
3783
+ let h = fnvMixInt32(startHash("Polygon"), pts.length);
3784
+ for (const p of pts) h = mix(h, p);
3785
+ return {
3786
+ kind: "Polygon",
3787
+ points: pts,
3788
+ structuralHash: h,
3789
+ freeParams: depsOf(...pts)
3790
+ };
3791
+ }
3792
+ function circle$1(radius) {
3793
+ const re = asScalarExpr(radius);
3794
+ return {
3795
+ kind: "Circle",
3796
+ radius: re,
3797
+ structuralHash: mix(startHash("Circle"), re),
3798
+ freeParams: re.freeParams
3799
+ };
3800
+ }
3801
+ function line$1(from, to) {
3802
+ const fe = asVec3Expr(from);
3803
+ const te = asVec3Expr(to);
3804
+ return {
3805
+ kind: "Line",
3806
+ from: fe,
3807
+ to: te,
3808
+ structuralHash: mix(mix(startHash("Line"), fe), te),
3809
+ freeParams: depsOf(fe, te)
3810
+ };
3811
+ }
3812
+ function vertex$1(point) {
3813
+ const pe = asVec3Expr(point);
3814
+ return {
3815
+ kind: "Vertex",
3816
+ point: pe,
3817
+ structuralHash: mix(startHash("Vertex"), pe),
3818
+ freeParams: pe.freeParams
3819
+ };
3820
+ }
3821
+ function emptyOf(output) {
3822
+ return {
3823
+ kind: "Empty",
3824
+ output,
3825
+ structuralHash: fnvMixString(startHash("Empty"), output),
3826
+ freeParams: EMPTY_DEPS
3827
+ };
3828
+ }
3829
+ function emptySolid() {
3830
+ return emptyOf("Solid");
3831
+ }
3832
+ function emptyFace() {
3833
+ return emptyOf("Face");
3834
+ }
3835
+ function emptyWire() {
3836
+ return emptyOf("Wire");
3837
+ }
3838
+ function binaryBoolHash(tag, a, b, tol) {
3839
+ return mixOptNumber(mix(mix(startHash(tag), a), b), tol);
3840
+ }
3841
+ function fuse$1(a, b, tolerance) {
3842
+ return {
3843
+ kind: "Fuse",
3844
+ a,
3845
+ b,
3846
+ tolerance,
3847
+ structuralHash: binaryBoolHash("Fuse", a, b, tolerance),
3848
+ freeParams: depsOf(a, b)
3849
+ };
3850
+ }
3851
+ function cut$1(a, b, tolerance) {
3852
+ return {
3853
+ kind: "Cut",
3854
+ a,
3855
+ b,
3856
+ tolerance,
3857
+ structuralHash: binaryBoolHash("Cut", a, b, tolerance),
3858
+ freeParams: depsOf(a, b)
3859
+ };
3860
+ }
3861
+ function intersect$1(a, b, tolerance) {
3862
+ return {
3863
+ kind: "Intersect",
3864
+ a,
3865
+ b,
3866
+ tolerance,
3867
+ structuralHash: binaryBoolHash("Intersect", a, b, tolerance),
3868
+ freeParams: depsOf(a, b)
3869
+ };
3870
+ }
3871
+ function fuseAll$1(shapes, tolerance) {
3872
+ let h = fnvMixInt32(startHash("FuseAll"), shapes.length);
3873
+ for (const s of shapes) h = mix(h, s);
3874
+ h = mixOptNumber(h, tolerance);
3875
+ return {
3876
+ kind: "FuseAll",
3877
+ shapes,
3878
+ tolerance,
3879
+ structuralHash: h,
3880
+ freeParams: depsOf(...shapes)
3881
+ };
3882
+ }
3883
+ function cutAll$1(base, tools, tolerance) {
3884
+ let h = mix(startHash("CutAll"), base);
3885
+ h = fnvMixInt32(h, tools.length);
3886
+ for (const t of tools) h = mix(h, t);
3887
+ h = mixOptNumber(h, tolerance);
3888
+ return {
3889
+ kind: "CutAll",
3890
+ base,
3891
+ tools,
3892
+ tolerance,
3893
+ structuralHash: h,
3894
+ freeParams: depsOf(base, ...tools)
3895
+ };
3896
+ }
3897
+ function optVec3$1(v) {
3898
+ return v !== void 0 ? asVec3Expr(v) : void 0;
3899
+ }
3900
+ function translate$1(target, vector) {
3901
+ const ve = asVec3Expr(vector);
3902
+ return {
3903
+ kind: "Translate",
3904
+ target,
3905
+ vector: ve,
3906
+ structuralHash: mix(mix(startHash("Translate"), target), ve),
3907
+ freeParams: depsOf(target, ve)
3908
+ };
3909
+ }
3910
+ function rotate$1(target, angle, options) {
3911
+ const ae = asScalarExpr(angle);
3912
+ const axisE = optVec3$1(options?.axis);
3913
+ const atE = optVec3$1(options?.at);
3914
+ let h = mix(mix(startHash("Rotate"), target), ae);
3915
+ h = mixOptExpr(h, axisE);
3916
+ h = mixOptExpr(h, atE);
3917
+ return {
3918
+ kind: "Rotate",
3919
+ target,
3920
+ angle: ae,
3921
+ axis: axisE,
3922
+ at: atE,
3923
+ structuralHash: h,
3924
+ freeParams: depsOf(target, ae, axisE, atE)
3925
+ };
3926
+ }
3927
+ function scale$1(target, factor, options) {
3928
+ const fe = asScalarExpr(factor);
3929
+ const cE = optVec3$1(options?.center);
3930
+ let h = mix(mix(startHash("Scale"), target), fe);
3931
+ h = mixOptExpr(h, cE);
3932
+ return {
3933
+ kind: "Scale",
3934
+ target,
3935
+ factor: fe,
3936
+ center: cE,
3937
+ structuralHash: h,
3938
+ freeParams: depsOf(target, fe, cE)
3939
+ };
3940
+ }
3941
+ function mirror$1(target, options) {
3942
+ const nE = optVec3$1(options?.normal);
3943
+ const atE = optVec3$1(options?.at);
3944
+ let h = mix(startHash("Mirror"), target);
3945
+ h = mixOptExpr(h, nE);
3946
+ h = mixOptExpr(h, atE);
3947
+ return {
3948
+ kind: "Mirror",
3949
+ target,
3950
+ normal: nE,
3951
+ at: atE,
3952
+ structuralHash: h,
3953
+ freeParams: depsOf(target, nE, atE)
3954
+ };
3955
+ }
3956
+ function compound$1(children) {
3957
+ let h = fnvMixInt32(startHash("Compound"), children.length);
3958
+ for (const c of children) h = mix(h, c);
3959
+ return {
3960
+ kind: "Compound",
3961
+ children,
3962
+ structuralHash: h,
3963
+ freeParams: depsOf(...children)
3964
+ };
3965
+ }
3966
+ //#endregion
3967
+ //#region src/csg/types.ts
3968
+ function outputKindOf(node) {
3969
+ switch (node.kind) {
3970
+ case "Box":
3971
+ case "Sphere":
3972
+ case "Cylinder":
3973
+ case "Cone":
3974
+ case "Torus": return "Solid";
3975
+ case "Polygon": return "Face";
3976
+ case "Circle":
3977
+ case "Line": return "Edge";
3978
+ case "Vertex": return "Vertex";
3979
+ case "Empty": return node.output;
3980
+ case "Fuse":
3981
+ case "Cut":
3982
+ case "Intersect": return outputKindOf(node.a);
3983
+ case "FuseAll": return node.shapes[0] ? outputKindOf(node.shapes[0]) : "Solid";
3984
+ case "CutAll": return outputKindOf(node.base);
3985
+ case "Translate":
3986
+ case "Rotate":
3987
+ case "Scale":
3988
+ case "Mirror": return outputKindOf(node.target);
3989
+ case "Compound": return "Compound";
3990
+ }
3991
+ }
3992
+ //#endregion
3993
+ //#region src/csg/evaluators/primitives.ts
3994
+ function evalBox(node, ctx) {
3995
+ const x = evalScalar(node.x, ctx.env, "Box.x");
3996
+ if (!x.ok) return x;
3997
+ const y = evalScalar(node.y, ctx.env, "Box.y");
3998
+ if (!y.ok) return y;
3999
+ const z = evalScalar(node.z, ctx.env, "Box.z");
4000
+ if (!z.ok) return z;
4001
+ return require_errors.ok(require_primitiveFns.box(x.value, y.value, z.value));
4002
+ }
4003
+ function evalSphere(node, ctx) {
4004
+ const r = evalScalar(node.radius, ctx.env, "Sphere.radius");
4005
+ if (!r.ok) return r;
4006
+ return require_errors.ok(require_primitiveFns.sphere(r.value));
4007
+ }
4008
+ function evalCylinder(node, ctx) {
4009
+ const r = evalScalar(node.radius, ctx.env, "Cylinder.radius");
4010
+ if (!r.ok) return r;
4011
+ const h = evalScalar(node.height, ctx.env, "Cylinder.height");
4012
+ if (!h.ok) return h;
4013
+ return require_errors.ok(require_primitiveFns.cylinder(r.value, h.value));
4014
+ }
4015
+ function evalCone(node, ctx) {
4016
+ const r1 = evalScalar(node.radius1, ctx.env, "Cone.radius1");
4017
+ if (!r1.ok) return r1;
4018
+ const r2 = evalScalar(node.radius2, ctx.env, "Cone.radius2");
4019
+ if (!r2.ok) return r2;
4020
+ const h = evalScalar(node.height, ctx.env, "Cone.height");
4021
+ if (!h.ok) return h;
4022
+ return require_errors.ok(require_primitiveFns.cone(r1.value, r2.value, h.value));
4023
+ }
4024
+ function evalTorus(node, ctx) {
4025
+ const ma = evalScalar(node.majorRadius, ctx.env, "Torus.majorRadius");
4026
+ if (!ma.ok) return ma;
4027
+ const mi = evalScalar(node.minorRadius, ctx.env, "Torus.minorRadius");
4028
+ if (!mi.ok) return mi;
4029
+ return require_errors.ok(require_primitiveFns.torus(ma.value, mi.value));
4030
+ }
4031
+ function evalPolygon(node, ctx) {
4032
+ const pts = [];
4033
+ for (const p of node.points) {
4034
+ const r = evalVec3(p, ctx.env, "Polygon.point");
4035
+ if (!r.ok) return r;
4036
+ pts.push(r.value);
4037
+ }
4038
+ return require_primitiveFns.polygon(pts);
4039
+ }
4040
+ function evalCircle(node, ctx) {
4041
+ const r = evalScalar(node.radius, ctx.env, "Circle.radius");
4042
+ if (!r.ok) return r;
4043
+ return require_errors.ok(require_primitiveFns.circle(r.value));
4044
+ }
4045
+ function evalLine(node, ctx) {
4046
+ const f = evalVec3(node.from, ctx.env, "Line.from");
4047
+ if (!f.ok) return f;
4048
+ const t = evalVec3(node.to, ctx.env, "Line.to");
4049
+ if (!t.ok) return t;
4050
+ return require_errors.ok(require_primitiveFns.line(f.value, t.value));
4051
+ }
4052
+ function evalVertex(node, ctx) {
4053
+ const p = evalVec3(node.point, ctx.env, "Vertex.point");
4054
+ if (!p.ok) return p;
4055
+ return require_errors.ok(require_primitiveFns.vertex(p.value));
4056
+ }
4057
+ //#endregion
4058
+ //#region src/csg/evaluators/booleans.ts
4059
+ /**
4060
+ * Evaluators for CSG boolean nodes.
4061
+ *
4062
+ * Identity short-circuits are correctness invariants, not optimisations:
4063
+ * Fuse with an Empty operand: short-circuits to the other operand
4064
+ * Cut with an Empty tool: short-circuits to the base
4065
+ * Intersect with any Empty: errors (no empty-solid representation)
4066
+ *
4067
+ * The optimizer pass handles broader rewrites; these inline checks just
4068
+ * keep the evaluator from feeding null operands to the kernel.
4069
+ */
4070
+ function emptyResult$1(kind) {
4071
+ return require_errors.err(require_errors.computationError(require_errors.BrepErrorCode.NULL_SHAPE_INPUT, `${kind}: empty result has no kernel representation`));
4072
+ }
4073
+ function resolveOperand(ctx, node, where) {
4074
+ const r = ctx.evalNode(node);
4075
+ if (!r.ok) return r;
4076
+ if (!require_shapeTypes.isShape3D(r.value)) return require_errors.err(require_errors.typeCastError(require_errors.BrepErrorCode.CSG_NOT_3D, `${where}: operand did not produce a 3D shape`));
4077
+ return require_errors.ok(r.value);
4078
+ }
4079
+ function boolOptions(node, ctx) {
4080
+ return {
4081
+ unsafe: true,
4082
+ fuzzyValue: node.tolerance ?? ctx.tolerance
4083
+ };
4084
+ }
4085
+ function evalFuse(node, ctx) {
4086
+ if (node.a.kind === "Empty") return ctx.evalNode(node.b);
4087
+ if (node.b.kind === "Empty") return ctx.evalNode(node.a);
4088
+ const a = resolveOperand(ctx, node.a, "Fuse.a");
4089
+ if (!a.ok) return a;
4090
+ const b = resolveOperand(ctx, node.b, "Fuse.b");
4091
+ if (!b.ok) return b;
4092
+ return require_booleanFns.fuse(a.value, b.value, boolOptions(node, ctx));
4093
+ }
4094
+ function evalCut(node, ctx) {
4095
+ if (node.a.kind === "Empty") return emptyResult$1("Cut");
4096
+ if (node.b.kind === "Empty") return ctx.evalNode(node.a);
4097
+ const a = resolveOperand(ctx, node.a, "Cut.a");
4098
+ if (!a.ok) return a;
4099
+ const b = resolveOperand(ctx, node.b, "Cut.b");
4100
+ if (!b.ok) return b;
4101
+ return require_booleanFns.cut(a.value, b.value, boolOptions(node, ctx));
4102
+ }
4103
+ function evalIntersect(node, ctx) {
4104
+ if (node.a.kind === "Empty" || node.b.kind === "Empty") return emptyResult$1("Intersect");
4105
+ const a = resolveOperand(ctx, node.a, "Intersect.a");
4106
+ if (!a.ok) return a;
4107
+ const b = resolveOperand(ctx, node.b, "Intersect.b");
4108
+ if (!b.ok) return b;
4109
+ return require_booleanFns.intersect(a.value, b.value, boolOptions(node, ctx));
4110
+ }
4111
+ function resolveAll(ctx, nodes, where) {
4112
+ const out = [];
4113
+ for (const n of nodes) {
4114
+ const r = resolveOperand(ctx, n, where);
4115
+ if (!r.ok) return r;
4116
+ out.push(r.value);
4117
+ }
4118
+ return require_errors.ok(out);
4119
+ }
4120
+ function evalFuseAll(node, ctx) {
4121
+ const non = node.shapes.filter((s) => s.kind !== "Empty");
4122
+ if (non.length === 0) return emptyResult$1("FuseAll");
4123
+ if (non.length === 1 && non[0]) return ctx.evalNode(non[0]);
4124
+ const resolved = resolveAll(ctx, non, "FuseAll.operand");
4125
+ if (!resolved.ok) return resolved;
4126
+ return require_booleanFns.fuseAll(resolved.value, boolOptions(node, ctx));
4127
+ }
4128
+ function evalCutAll(node, ctx) {
4129
+ if (node.base.kind === "Empty") return emptyResult$1("CutAll");
4130
+ const tools = node.tools.filter((s) => s.kind !== "Empty");
4131
+ if (tools.length === 0) return ctx.evalNode(node.base);
4132
+ const base = resolveOperand(ctx, node.base, "CutAll.base");
4133
+ if (!base.ok) return base;
4134
+ const resolved = resolveAll(ctx, tools, "CutAll.tool");
4135
+ if (!resolved.ok) return resolved;
4136
+ return require_booleanFns.cutAll(base.value, resolved.value, boolOptions(node, ctx));
4137
+ }
4138
+ //#endregion
4139
+ //#region src/csg/evaluators/transforms.ts
4140
+ function emptyResult(kind) {
4141
+ return require_errors.err(require_errors.computationError(require_errors.BrepErrorCode.NULL_SHAPE_INPUT, `${kind}: cannot transform an Empty node`));
4142
+ }
4143
+ function optVec3(expr, env, where, fallback) {
4144
+ return expr ? evalVec3(expr, env, where) : require_errors.ok(fallback);
4145
+ }
4146
+ function evalTranslate(node, ctx) {
4147
+ if (node.target.kind === "Empty") return emptyResult("Translate");
4148
+ const v = evalVec3(node.vector, ctx.env, "Translate.vector");
4149
+ if (!v.ok) return v;
4150
+ const r = ctx.evalNode(node.target);
4151
+ if (!r.ok) return r;
4152
+ return require_errors.ok(require_shapeFns.translate(r.value, v.value));
4153
+ }
4154
+ function evalRotate(node, ctx) {
4155
+ if (node.target.kind === "Empty") return emptyResult("Rotate");
4156
+ const a = evalScalar(node.angle, ctx.env, "Rotate.angle");
4157
+ if (!a.ok) return a;
4158
+ const axis = optVec3(node.axis, ctx.env, "Rotate.axis", [
4159
+ 0,
4160
+ 0,
4161
+ 1
4162
+ ]);
4163
+ if (!axis.ok) return axis;
4164
+ const at = optVec3(node.at, ctx.env, "Rotate.at", [
4165
+ 0,
4166
+ 0,
4167
+ 0
4168
+ ]);
4169
+ if (!at.ok) return at;
4170
+ const r = ctx.evalNode(node.target);
4171
+ if (!r.ok) return r;
4172
+ return require_errors.ok(require_shapeFns.rotate(r.value, a.value, at.value, axis.value));
4173
+ }
4174
+ function evalScale(node, ctx) {
4175
+ if (node.target.kind === "Empty") return emptyResult("Scale");
4176
+ const f = evalScalar(node.factor, ctx.env, "Scale.factor");
4177
+ if (!f.ok) return f;
4178
+ const center = optVec3(node.center, ctx.env, "Scale.center", [
4179
+ 0,
4180
+ 0,
4181
+ 0
4182
+ ]);
4183
+ if (!center.ok) return center;
4184
+ const r = ctx.evalNode(node.target);
4185
+ if (!r.ok) return r;
4186
+ return require_errors.ok(require_shapeFns.scale(r.value, f.value, center.value));
4187
+ }
4188
+ function evalMirror(node, ctx) {
4189
+ if (node.target.kind === "Empty") return emptyResult("Mirror");
4190
+ const normal = optVec3(node.normal, ctx.env, "Mirror.normal", [
4191
+ 1,
4192
+ 0,
4193
+ 0
4194
+ ]);
4195
+ if (!normal.ok) return normal;
4196
+ const at = optVec3(node.at, ctx.env, "Mirror.at", [
4197
+ 0,
4198
+ 0,
4199
+ 0
4200
+ ]);
4201
+ if (!at.ok) return at;
4202
+ const r = ctx.evalNode(node.target);
4203
+ if (!r.ok) return r;
4204
+ return require_errors.ok(require_shapeFns.mirror(r.value, normal.value, at.value));
4205
+ }
4206
+ //#endregion
4207
+ //#region src/csg/evaluators/compound.ts
4208
+ function evalCompound(node, ctx) {
4209
+ const non = node.children.filter((c) => c.kind !== "Empty");
4210
+ if (non.length === 0) return require_errors.err(require_errors.computationError(require_errors.BrepErrorCode.NULL_SHAPE_INPUT, "Compound: cannot materialize a compound with zero non-empty children"));
4211
+ const shapes = [];
4212
+ for (const c of non) {
4213
+ const r = ctx.evalNode(c);
4214
+ if (!r.ok) return r;
4215
+ shapes.push(r.value);
4216
+ }
4217
+ return require_errors.ok(require_primitiveFns.compound(shapes));
4218
+ }
4219
+ function evalEmpty() {
4220
+ return require_errors.err(require_errors.computationError(require_errors.BrepErrorCode.NULL_SHAPE_INPUT, "Empty: cannot materialize an Empty node directly — only valid as boolean/transform operand"));
4221
+ }
4222
+ //#endregion
4223
+ //#region src/csg/evaluate.ts
4224
+ function dispatch(node, ctx) {
4225
+ switch (node.kind) {
4226
+ case "Box": return evalBox(node, ctx);
4227
+ case "Sphere": return evalSphere(node, ctx);
4228
+ case "Cylinder": return evalCylinder(node, ctx);
4229
+ case "Cone": return evalCone(node, ctx);
4230
+ case "Torus": return evalTorus(node, ctx);
4231
+ case "Polygon": return evalPolygon(node, ctx);
4232
+ case "Circle": return evalCircle(node, ctx);
4233
+ case "Line": return evalLine(node, ctx);
4234
+ case "Vertex": return evalVertex(node, ctx);
4235
+ case "Empty": return evalEmpty();
4236
+ case "Fuse": return evalFuse(node, ctx);
4237
+ case "Cut": return evalCut(node, ctx);
4238
+ case "Intersect": return evalIntersect(node, ctx);
4239
+ case "FuseAll": return evalFuseAll(node, ctx);
4240
+ case "CutAll": return evalCutAll(node, ctx);
4241
+ case "Translate": return evalTranslate(node, ctx);
4242
+ case "Rotate": return evalRotate(node, ctx);
4243
+ case "Scale": return evalScale(node, ctx);
4244
+ case "Mirror": return evalMirror(node, ctx);
4245
+ case "Compound": return evalCompound(node, ctx);
4246
+ }
4247
+ }
4248
+ function hashExprValue(h, v) {
4249
+ if (typeof v === "number") return fnvMixNumber(fnvMixBool(h, false), v);
4250
+ let r = fnvMixBool(h, true);
4251
+ r = fnvMixInt32(r, v.length);
4252
+ for (const n of v) r = fnvMixNumber(r, n);
4253
+ return r;
4254
+ }
4255
+ function projectedEnvHash(env, deps) {
4256
+ if (deps.size === 0) return fnvInit();
4257
+ const projected = projectEnv(env, deps);
4258
+ const keys = Object.keys(projected).sort();
4259
+ let h = fnvInit();
4260
+ for (const k of keys) {
4261
+ h = fnvMixString(h, k);
4262
+ const v = projected[k];
4263
+ if (v !== void 0) h = hashExprValue(h, v);
4264
+ }
4265
+ return h;
4266
+ }
4267
+ function cacheKey(node, env, kernelId, tolerance) {
4268
+ const projHash = projectedEnvHash(env, node.freeParams);
4269
+ const tolHash = tolerance === void 0 ? "d" : fnvMixNumber(fnvInit(), tolerance).toString(16);
4270
+ return `${toHex(node.structuralHash)}:${kernelId}:${toHex(projHash)}:${tolHash}`;
4271
+ }
4272
+ var Evaluator = class {
4273
+ scope = new require_shapeTypes.DisposalScope();
4274
+ cache = /* @__PURE__ */ new Map();
4275
+ registered = /* @__PURE__ */ new WeakSet();
4276
+ kernelId;
4277
+ defaultTolerance;
4278
+ onStep;
4279
+ hits = 0;
4280
+ misses = 0;
4281
+ constructor(options = {}) {
4282
+ this.kernelId = options.kernel ?? require_shapeTypes.getActiveKernelId() ?? "unregistered";
4283
+ this.defaultTolerance = options.tolerance;
4284
+ if (options.onStep) this.onStep = options.onStep;
4285
+ }
4286
+ /**
4287
+ * Materialize a CSG IR tree against the given parameter environment.
4288
+ * The returned shape is borrowed — valid for as long as this Evaluator is
4289
+ * not disposed. Callers must NOT call `.delete()` / `[Symbol.dispose]()`
4290
+ * on the returned shape; that would invalidate the cache entry for every
4291
+ * future call returning the same handle.
4292
+ */
4293
+ evaluate(node, env = {}) {
4294
+ return require_shapeTypes.withKernel(this.kernelId, () => this.evaluateInner(node, env));
4295
+ }
4296
+ evaluateInner(node, env) {
4297
+ const key = cacheKey(node, env, this.kernelId, this.defaultTolerance);
4298
+ const cached = this.cache.get(key);
4299
+ if (cached !== void 0) {
4300
+ this.hits++;
4301
+ this.onStep?.({
4302
+ node,
4303
+ cacheKey: key,
4304
+ cacheHit: true
4305
+ });
4306
+ return require_errors.ok(cached);
4307
+ }
4308
+ this.misses++;
4309
+ const result = dispatch(node, {
4310
+ env,
4311
+ tolerance: this.defaultTolerance,
4312
+ evalNode: (child) => this.evaluateInner(child, env)
4313
+ });
4314
+ if (!result.ok) return result;
4315
+ if (!this.registered.has(result.value)) {
4316
+ this.scope.register(result.value);
4317
+ this.registered.add(result.value);
4318
+ }
4319
+ this.cache.set(key, result.value);
4320
+ this.onStep?.({
4321
+ node,
4322
+ cacheKey: key,
4323
+ cacheHit: false
4324
+ });
4325
+ return result;
4326
+ }
4327
+ cacheStats() {
4328
+ return {
4329
+ hits: this.hits,
4330
+ misses: this.misses,
4331
+ entries: this.cache.size
4332
+ };
4333
+ }
4334
+ resetStats() {
4335
+ this.hits = 0;
4336
+ this.misses = 0;
4337
+ }
4338
+ [Symbol.dispose]() {
4339
+ this.scope[Symbol.dispose]();
4340
+ this.cache.clear();
4341
+ }
4342
+ };
4343
+ /**
4344
+ * Run a callback with a fresh Evaluator that is disposed when the callback
4345
+ * returns. Sync-only: an async callback would resolve after disposal,
4346
+ * leaving borrowed shapes pointing at freed WASM memory. Mirrors the
4347
+ * Promise-guard pattern in `withKernel`.
4348
+ */
4349
+ function withEvaluator(options, fn) {
4350
+ try {
4351
+ var _usingCtx$1 = require_shapeTypes._usingCtx();
4352
+ const result = fn(_usingCtx$1.u(new Evaluator(options)));
4353
+ if (result instanceof Promise) throw new Error("withEvaluator() callback returned a Promise. Async code must construct an Evaluator directly and dispose it manually — borrowed shapes would otherwise be freed before the Promise resolves.");
4354
+ return result;
4355
+ } catch (_) {
4356
+ _usingCtx$1.e = _;
4357
+ } finally {
4358
+ _usingCtx$1.d();
4359
+ }
4360
+ }
4361
+ function toJSON(node) {
4362
+ return {
4363
+ csgVersion: 1,
4364
+ root: nodeToJson(node)
4365
+ };
4366
+ }
4367
+ function exprToJson(e) {
4368
+ switch (e.kind) {
4369
+ case "NumLit": return {
4370
+ kind: "NumLit",
4371
+ value: e.value
4372
+ };
4373
+ case "Vec3Lit": return {
4374
+ kind: "Vec3Lit",
4375
+ value: [
4376
+ e.value[0],
4377
+ e.value[1],
4378
+ e.value[2]
4379
+ ]
4380
+ };
4381
+ case "Vec2Lit": return {
4382
+ kind: "Vec2Lit",
4383
+ value: [e.value[0], e.value[1]]
4384
+ };
4385
+ case "Param": return {
4386
+ kind: "Param",
4387
+ name: e.name
4388
+ };
4389
+ case "BinOp": return {
4390
+ kind: "BinOp",
4391
+ op: e.op,
4392
+ a: exprToJson(e.a),
4393
+ b: exprToJson(e.b)
4394
+ };
4395
+ case "UnaryOp": return {
4396
+ kind: "UnaryOp",
4397
+ op: e.op,
4398
+ arg: exprToJson(e.arg)
4399
+ };
4400
+ case "Component": return {
4401
+ kind: "Component",
4402
+ vec: exprToJson(e.vec),
4403
+ index: e.index
4404
+ };
4405
+ case "BuildVec": return {
4406
+ kind: "BuildVec",
4407
+ dim: e.dim,
4408
+ components: e.components.map(exprToJson)
4409
+ };
4410
+ }
4411
+ }
4412
+ function primitiveToJson(n) {
4413
+ switch (n.kind) {
4414
+ case "Box": return {
4415
+ kind: "Box",
4416
+ x: exprToJson(n.x),
4417
+ y: exprToJson(n.y),
4418
+ z: exprToJson(n.z)
4419
+ };
4420
+ case "Sphere": return {
4421
+ kind: "Sphere",
4422
+ radius: exprToJson(n.radius)
4423
+ };
4424
+ case "Cylinder": return {
4425
+ kind: "Cylinder",
4426
+ radius: exprToJson(n.radius),
4427
+ height: exprToJson(n.height)
4428
+ };
4429
+ case "Cone": return {
4430
+ kind: "Cone",
4431
+ radius1: exprToJson(n.radius1),
4432
+ radius2: exprToJson(n.radius2),
4433
+ height: exprToJson(n.height)
4434
+ };
4435
+ case "Torus": return {
4436
+ kind: "Torus",
4437
+ majorRadius: exprToJson(n.majorRadius),
4438
+ minorRadius: exprToJson(n.minorRadius)
4439
+ };
4440
+ case "Polygon": return {
4441
+ kind: "Polygon",
4442
+ points: n.points.map(exprToJson)
4443
+ };
4444
+ case "Circle": return {
4445
+ kind: "Circle",
4446
+ radius: exprToJson(n.radius)
4447
+ };
4448
+ case "Line": return {
4449
+ kind: "Line",
4450
+ from: exprToJson(n.from),
4451
+ to: exprToJson(n.to)
4452
+ };
4453
+ case "Vertex": return {
4454
+ kind: "Vertex",
4455
+ point: exprToJson(n.point)
4456
+ };
4457
+ case "Empty": return {
4458
+ kind: "Empty",
4459
+ output: n.output
4460
+ };
4461
+ default: return;
4462
+ }
4463
+ }
4464
+ function booleanToJson(n) {
4465
+ switch (n.kind) {
4466
+ case "Fuse":
4467
+ case "Cut":
4468
+ case "Intersect": return {
4469
+ kind: n.kind,
4470
+ a: nodeToJson(n.a),
4471
+ b: nodeToJson(n.b),
4472
+ tolerance: n.tolerance
4473
+ };
4474
+ case "FuseAll": return {
4475
+ kind: "FuseAll",
4476
+ shapes: n.shapes.map(nodeToJson),
4477
+ tolerance: n.tolerance
4478
+ };
4479
+ case "CutAll": return {
4480
+ kind: "CutAll",
4481
+ base: nodeToJson(n.base),
4482
+ tools: n.tools.map(nodeToJson),
4483
+ tolerance: n.tolerance
4484
+ };
4485
+ default: return;
4486
+ }
4487
+ }
4488
+ function optExprToJson(e) {
4489
+ return e ? exprToJson(e) : void 0;
4490
+ }
4491
+ function transformToJson(n) {
4492
+ switch (n.kind) {
4493
+ case "Translate": return {
4494
+ kind: "Translate",
4495
+ target: nodeToJson(n.target),
4496
+ vector: exprToJson(n.vector)
4497
+ };
4498
+ case "Rotate": return {
4499
+ kind: "Rotate",
4500
+ target: nodeToJson(n.target),
4501
+ angle: exprToJson(n.angle),
4502
+ axis: optExprToJson(n.axis),
4503
+ at: optExprToJson(n.at)
4504
+ };
4505
+ case "Scale": return {
4506
+ kind: "Scale",
4507
+ target: nodeToJson(n.target),
4508
+ factor: exprToJson(n.factor),
4509
+ center: optExprToJson(n.center)
4510
+ };
4511
+ case "Mirror": return {
4512
+ kind: "Mirror",
4513
+ target: nodeToJson(n.target),
4514
+ normal: optExprToJson(n.normal),
4515
+ at: optExprToJson(n.at)
4516
+ };
4517
+ default: return;
4518
+ }
4519
+ }
4520
+ function nodeToJson(n) {
4521
+ if (n.kind === "Compound") return {
4522
+ kind: "Compound",
4523
+ children: n.children.map(nodeToJson)
4524
+ };
4525
+ return primitiveToJson(n) ?? booleanToJson(n) ?? transformToJson(n);
4526
+ }
4527
+ function bad(msg) {
4528
+ return require_errors.err(require_errors.validationError(require_errors.BrepErrorCode.NULL_SHAPE_INPUT, `csg.fromJSON: ${msg}`));
4529
+ }
4530
+ function isObj(v) {
4531
+ return typeof v === "object" && v !== null && !Array.isArray(v);
4532
+ }
4533
+ function isNumber$1(v) {
4534
+ return typeof v === "number" && Number.isFinite(v);
4535
+ }
4536
+ function isString(v) {
4537
+ return typeof v === "string";
4538
+ }
4539
+ function readVec3(v, where) {
4540
+ if (!Array.isArray(v) || v.length !== 3) return bad(`${where}: expected Vec3 array`);
4541
+ const [a, b, c] = v;
4542
+ if (!isNumber$1(a) || !isNumber$1(b) || !isNumber$1(c)) return bad(`${where}: Vec3 contains non-number`);
4543
+ return require_errors.ok([
4544
+ a,
4545
+ b,
4546
+ c
4547
+ ]);
4548
+ }
4549
+ function readVec2(v, where) {
4550
+ if (!Array.isArray(v) || v.length !== 2) return bad(`${where}: expected Vec2 array`);
4551
+ const [a, b] = v;
4552
+ if (!isNumber$1(a) || !isNumber$1(b)) return bad(`${where}: Vec2 contains non-number`);
4553
+ return require_errors.ok([a, b]);
4554
+ }
4555
+ function fromJSON(envelope) {
4556
+ if (!isObj(envelope)) return bad("input is not an object");
4557
+ const v = envelope["csgVersion"];
4558
+ if (v !== 1) return bad(`unsupported csgVersion ${String(v)} (expected 1)`);
4559
+ const root = envelope["root"];
4560
+ return readNode(root);
4561
+ }
4562
+ function readExpr(j) {
4563
+ if (!isObj(j)) return bad("expression: not an object");
4564
+ const kind = j["kind"];
4565
+ switch (kind) {
4566
+ case "NumLit": return isNumber$1(j["value"]) ? require_errors.ok(numLit(j["value"])) : bad("NumLit.value");
4567
+ case "Vec3Lit": {
4568
+ const v = readVec3(j["value"], "Vec3Lit.value");
4569
+ return v.ok ? require_errors.ok(vec3Lit(v.value)) : v;
4570
+ }
4571
+ case "Vec2Lit": {
4572
+ const v = readVec2(j["value"], "Vec2Lit.value");
4573
+ return v.ok ? require_errors.ok(vec2Lit(v.value)) : v;
4574
+ }
4575
+ case "Param": return isString(j["name"]) ? require_errors.ok(param(j["name"])) : bad("Param.name");
4576
+ case "BinOp": return readBinOp(j);
4577
+ case "UnaryOp": return readUnaryOp(j);
4578
+ case "Component": return readComponent(j);
4579
+ case "BuildVec": return readBuildVec(j);
4580
+ default: return bad(`unknown expression kind: ${String(kind)}`);
4581
+ }
4582
+ }
4583
+ function readBinOp(j) {
4584
+ const op = j["op"];
4585
+ if (op !== "+" && op !== "-" && op !== "*" && op !== "/") return bad(`BinOp.op: ${String(op)}`);
4586
+ const a = readExpr(j["a"]);
4587
+ if (!a.ok) return a;
4588
+ const b = readExpr(j["b"]);
4589
+ if (!b.ok) return b;
4590
+ return require_errors.ok(binOp(op, a.value, b.value));
4591
+ }
4592
+ function readUnaryOp(j) {
4593
+ const op = j["op"];
4594
+ if (!isString(op) || ![
4595
+ "neg",
4596
+ "sin",
4597
+ "cos",
4598
+ "sqrt",
4599
+ "abs"
4600
+ ].includes(op)) return bad(`UnaryOp.op: ${String(op)}`);
4601
+ const arg = readExpr(j["arg"]);
4602
+ if (!arg.ok) return arg;
4603
+ return require_errors.ok(unaryOp(op, arg.value));
4604
+ }
4605
+ function readComponent(j) {
4606
+ const index = j["index"];
4607
+ if (index !== 0 && index !== 1 && index !== 2) return bad(`Component.index: ${String(index)}`);
4608
+ const vec = readExpr(j["vec"]);
4609
+ if (!vec.ok) return vec;
4610
+ return require_errors.ok(component(vec.value, index));
4611
+ }
4612
+ function readBuildVec(j) {
4613
+ const dim = j["dim"];
4614
+ if (dim !== 2 && dim !== 3) return bad(`BuildVec.dim: ${String(dim)}`);
4615
+ const comps = j["components"];
4616
+ if (!Array.isArray(comps)) return bad("BuildVec.components: not array");
4617
+ if (comps.length !== dim) return bad(`BuildVec.components: expected ${dim} components, got ${comps.length}`);
4618
+ const out = [];
4619
+ for (const c of comps) {
4620
+ const r = readExpr(c);
4621
+ if (!r.ok) return r;
4622
+ out.push(r.value);
4623
+ }
4624
+ return require_errors.ok(buildVec(dim, out));
4625
+ }
4626
+ function readNodeArray(j, where) {
4627
+ if (!Array.isArray(j)) return bad(`${where}: not array`);
4628
+ const out = [];
4629
+ for (const c of j) {
4630
+ const r = readNode(c);
4631
+ if (!r.ok) return r;
4632
+ out.push(r.value);
4633
+ }
4634
+ return require_errors.ok(out);
4635
+ }
4636
+ function readOptTolerance(j) {
4637
+ const t = j["tolerance"];
4638
+ if (t === void 0 || t === null) return require_errors.ok(void 0);
4639
+ return isNumber$1(t) ? require_errors.ok(t) : bad("tolerance: not a finite number");
4640
+ }
4641
+ function readNode(j) {
4642
+ if (!isObj(j)) return bad("node: not an object");
4643
+ const kind = j["kind"];
4644
+ switch (kind) {
4645
+ case "Box":
4646
+ case "Sphere":
4647
+ case "Cylinder":
4648
+ case "Cone":
4649
+ case "Torus":
4650
+ case "Polygon":
4651
+ case "Circle":
4652
+ case "Line":
4653
+ case "Vertex":
4654
+ case "Empty": return readPrimitive(kind, j);
4655
+ case "Fuse":
4656
+ case "Cut":
4657
+ case "Intersect": return readBinaryBool(kind, j);
4658
+ case "FuseAll":
4659
+ case "CutAll": return readNaryBool(kind, j);
4660
+ case "Translate":
4661
+ case "Rotate":
4662
+ case "Scale":
4663
+ case "Mirror": return readTransform(kind, j);
4664
+ case "Compound": return readCompound(j);
4665
+ default: return bad(`unknown node kind: ${String(kind)}`);
4666
+ }
4667
+ }
4668
+ function readSingleExpr(j, key, build) {
4669
+ const r = readExpr(j[key]);
4670
+ return r.ok ? require_errors.ok(build(r.value)) : r;
4671
+ }
4672
+ function readPrimitive(kind, j) {
4673
+ switch (kind) {
4674
+ case "Box": return readBox(j);
4675
+ case "Sphere": return readSingleExpr(j, "radius", sphere$1);
4676
+ case "Cylinder": return readCylinder(j);
4677
+ case "Cone": return readCone(j);
4678
+ case "Torus": return readTorus(j);
4679
+ case "Polygon": return readPolygon(j);
4680
+ case "Circle": return readSingleExpr(j, "radius", circle$1);
4681
+ case "Line": return readLine(j);
4682
+ case "Vertex": return readSingleExpr(j, "point", vertex$1);
4683
+ case "Empty": return readEmpty(j);
4684
+ }
4685
+ return bad(`unhandled primitive: ${kind}`);
4686
+ }
4687
+ function readBox(j) {
4688
+ const x = readExpr(j["x"]);
4689
+ if (!x.ok) return x;
4690
+ const y = readExpr(j["y"]);
4691
+ if (!y.ok) return y;
4692
+ const z = readExpr(j["z"]);
4693
+ if (!z.ok) return z;
4694
+ return require_errors.ok(box$1(x.value, y.value, z.value));
4695
+ }
4696
+ function readCylinder(j) {
4697
+ const r = readExpr(j["radius"]);
4698
+ if (!r.ok) return r;
4699
+ const h = readExpr(j["height"]);
4700
+ if (!h.ok) return h;
4701
+ return require_errors.ok(cylinder$1(r.value, h.value));
4702
+ }
4703
+ function readCone(j) {
4704
+ const r1 = readExpr(j["radius1"]);
4705
+ if (!r1.ok) return r1;
4706
+ const r2 = readExpr(j["radius2"]);
4707
+ if (!r2.ok) return r2;
4708
+ const h = readExpr(j["height"]);
4709
+ if (!h.ok) return h;
4710
+ return require_errors.ok(cone$1(r1.value, r2.value, h.value));
4711
+ }
4712
+ function readTorus(j) {
4713
+ const ma = readExpr(j["majorRadius"]);
4714
+ if (!ma.ok) return ma;
4715
+ const mi = readExpr(j["minorRadius"]);
4716
+ if (!mi.ok) return mi;
4717
+ return require_errors.ok(torus$1(ma.value, mi.value));
4718
+ }
4719
+ function readPolygon(j) {
4720
+ const pts = j["points"];
4721
+ if (!Array.isArray(pts)) return bad("Polygon.points: not array");
4722
+ const out = [];
4723
+ for (const p of pts) {
4724
+ const r = readExpr(p);
4725
+ if (!r.ok) return r;
4726
+ out.push(r.value);
4727
+ }
4728
+ return require_errors.ok(polygon$1(out));
4729
+ }
4730
+ function readLine(j) {
4731
+ const f = readExpr(j["from"]);
4732
+ if (!f.ok) return f;
4733
+ const t = readExpr(j["to"]);
4734
+ if (!t.ok) return t;
4735
+ return require_errors.ok(line$1(f.value, t.value));
4736
+ }
4737
+ function readEmpty(j) {
4738
+ const out = j["output"];
4739
+ switch (out) {
4740
+ case "Solid": return require_errors.ok(emptySolid());
4741
+ case "Face": return require_errors.ok(emptyFace());
4742
+ case "Wire": return require_errors.ok(emptyWire());
4743
+ default: return bad(`Empty.output: ${String(out)}`);
4744
+ }
4745
+ }
4746
+ function readBinaryBool(kind, j) {
4747
+ const a = readNode(j["a"]);
4748
+ if (!a.ok) return a;
4749
+ const b = readNode(j["b"]);
4750
+ if (!b.ok) return b;
4751
+ const t = readOptTolerance(j);
4752
+ if (!t.ok) return t;
4753
+ switch (kind) {
4754
+ case "Fuse": return require_errors.ok(fuse$1(a.value, b.value, t.value));
4755
+ case "Cut": return require_errors.ok(cut$1(a.value, b.value, t.value));
4756
+ case "Intersect": return require_errors.ok(intersect$1(a.value, b.value, t.value));
4757
+ }
4758
+ }
4759
+ function readNaryBool(kind, j) {
4760
+ const t = readOptTolerance(j);
4761
+ if (!t.ok) return t;
4762
+ if (kind === "FuseAll") {
4763
+ const shapes = readNodeArray(j["shapes"], "FuseAll.shapes");
4764
+ return shapes.ok ? require_errors.ok(fuseAll$1(shapes.value, t.value)) : shapes;
4765
+ }
4766
+ const base = readNode(j["base"]);
4767
+ if (!base.ok) return base;
4768
+ const tools = readNodeArray(j["tools"], "CutAll.tools");
4769
+ return tools.ok ? require_errors.ok(cutAll$1(base.value, tools.value, t.value)) : tools;
4770
+ }
4771
+ function readTransform(kind, j) {
4772
+ const tgt = readNode(j["target"]);
4773
+ if (!tgt.ok) return tgt;
4774
+ switch (kind) {
4775
+ case "Translate": return readTranslate(j, tgt.value);
4776
+ case "Rotate": return readRotate(j, tgt.value);
4777
+ case "Scale": return readScale(j, tgt.value);
4778
+ case "Mirror": return readMirror(j, tgt.value);
4779
+ }
4780
+ }
4781
+ function readTranslate(j, target) {
4782
+ const v = readExpr(j["vector"]);
4783
+ return v.ok ? require_errors.ok(translate$1(target, v.value)) : v;
4784
+ }
4785
+ function readOptExpr(j, key) {
4786
+ if (j[key] === void 0) return require_errors.ok(void 0);
4787
+ const r = readExpr(j[key]);
4788
+ return r.ok ? require_errors.ok(r.value) : r;
4789
+ }
4790
+ function readRotate(j, target) {
4791
+ const ang = readExpr(j["angle"]);
4792
+ if (!ang.ok) return ang;
4793
+ const axis = readOptExpr(j, "axis");
4794
+ if (!axis.ok) return axis;
4795
+ const at = readOptExpr(j, "at");
4796
+ if (!at.ok) return at;
4797
+ return require_errors.ok(rotate$1(target, ang.value, {
4798
+ axis: axis.value,
4799
+ at: at.value
4800
+ }));
4801
+ }
4802
+ function readScale(j, target) {
4803
+ const f = readExpr(j["factor"]);
4804
+ if (!f.ok) return f;
4805
+ const center = readOptExpr(j, "center");
4806
+ if (!center.ok) return center;
4807
+ return require_errors.ok(scale$1(target, f.value, { center: center.value }));
4808
+ }
4809
+ function readMirror(j, target) {
4810
+ const normal = readOptExpr(j, "normal");
4811
+ if (!normal.ok) return normal;
4812
+ const at = readOptExpr(j, "at");
4813
+ if (!at.ok) return at;
4814
+ return require_errors.ok(mirror$1(target, {
4815
+ normal: normal.value,
4816
+ at: at.value
4817
+ }));
4818
+ }
4819
+ function readCompound(j) {
4820
+ const children = readNodeArray(j["children"], "Compound.children");
4821
+ return children.ok ? require_errors.ok(compound$1(children.value)) : children;
4822
+ }
4823
+ //#endregion
4824
+ //#region src/csg/optimize.ts
4825
+ function optimize(node) {
4826
+ return optimizeNode(node);
4827
+ }
4828
+ function foldExpr(e) {
4829
+ switch (e.kind) {
4830
+ case "NumLit":
4831
+ case "Vec3Lit":
4832
+ case "Vec2Lit":
4833
+ case "Param": return e;
4834
+ case "BinOp": {
4835
+ const a = foldExpr(e.a);
4836
+ const b = foldExpr(e.b);
4837
+ if (a.kind === "NumLit" && b.kind === "NumLit") switch (e.op) {
4838
+ case "+": return numLit(a.value + b.value);
4839
+ case "-": return numLit(a.value - b.value);
4840
+ case "*": return numLit(a.value * b.value);
4841
+ case "/": return numLit(a.value / b.value);
4842
+ }
4843
+ if (a !== e.a || b !== e.b) return binOp(e.op, a, b);
4844
+ return e;
4845
+ }
4846
+ case "UnaryOp": {
4847
+ const arg = foldExpr(e.arg);
4848
+ if (arg.kind === "NumLit") {
4849
+ const n = arg.value;
4850
+ switch (e.op) {
4851
+ case "neg": return numLit(-n);
4852
+ case "sin": return numLit(Math.sin(n));
4853
+ case "cos": return numLit(Math.cos(n));
4854
+ case "sqrt": return numLit(Math.sqrt(n));
4855
+ case "abs": return numLit(Math.abs(n));
4856
+ }
4857
+ }
4858
+ if (arg !== e.arg) return unaryOp(e.op, arg);
4859
+ return e;
4860
+ }
4861
+ case "Component": {
4862
+ const v = foldExpr(e.vec);
4863
+ if (v.kind === "Vec3Lit") return numLit(v.value[e.index]);
4864
+ if (v.kind === "Vec2Lit" && (e.index === 0 || e.index === 1)) return numLit(v.value[e.index]);
4865
+ if (v !== e.vec) return component(v, e.index);
4866
+ return e;
4867
+ }
4868
+ case "BuildVec": {
4869
+ const folded = e.components.map(foldExpr);
4870
+ const collapsed = foldBuildVec(e.dim, folded);
4871
+ if (collapsed) return collapsed;
4872
+ if (folded.some((c, i) => c !== e.components[i])) return buildVec(e.dim, folded);
4873
+ return e;
4874
+ }
4875
+ }
4876
+ }
4877
+ function foldBuildVec(dim, comps) {
4878
+ if (comps.length !== dim) return void 0;
4879
+ const nums = [];
4880
+ for (const c of comps) {
4881
+ if (c.kind !== "NumLit") return void 0;
4882
+ nums.push(c.value);
4883
+ }
4884
+ if (dim === 2) return vec2Lit([nums[0], nums[1]]);
4885
+ return vec3Lit([
4886
+ nums[0],
4887
+ nums[1],
4888
+ nums[2]
4889
+ ]);
4890
+ }
4891
+ function optimizeNode(n) {
4892
+ switch (n.kind) {
4893
+ case "Box": return box$1(foldExpr(n.x), foldExpr(n.y), foldExpr(n.z));
4894
+ case "Sphere": return sphere$1(foldExpr(n.radius));
4895
+ case "Cylinder": return cylinder$1(foldExpr(n.radius), foldExpr(n.height));
4896
+ case "Cone": return cone$1(foldExpr(n.radius1), foldExpr(n.radius2), foldExpr(n.height));
4897
+ case "Torus": return torus$1(foldExpr(n.majorRadius), foldExpr(n.minorRadius));
4898
+ case "Polygon": return polygon$1(n.points.map(foldExpr));
4899
+ case "Circle": return circle$1(foldExpr(n.radius));
4900
+ case "Line": return line$1(foldExpr(n.from), foldExpr(n.to));
4901
+ case "Vertex": return vertex$1(foldExpr(n.point));
4902
+ case "Empty": return n;
4903
+ case "Fuse": return optimizeFuse(n.a, n.b, n.tolerance);
4904
+ case "Cut": return optimizeCut(n.a, n.b, n.tolerance);
4905
+ case "Intersect": return optimizeIntersect(n.a, n.b, n.tolerance);
4906
+ case "FuseAll": return optimizeFuseAll(n.shapes, n.tolerance);
4907
+ case "CutAll": return optimizeCutAll(n.base, n.tools, n.tolerance);
4908
+ case "Translate": return optimizeTranslate(n.target, n.vector);
4909
+ case "Rotate": return rotate$1(optimizeNode(n.target), foldExpr(n.angle), {
4910
+ axis: n.axis ? foldExpr(n.axis) : void 0,
4911
+ at: n.at ? foldExpr(n.at) : void 0
4912
+ });
4913
+ case "Scale": return scale$1(optimizeNode(n.target), foldExpr(n.factor), { center: n.center ? foldExpr(n.center) : void 0 });
4914
+ case "Mirror": return mirror$1(optimizeNode(n.target), {
4915
+ normal: n.normal ? foldExpr(n.normal) : void 0,
4916
+ at: n.at ? foldExpr(n.at) : void 0
4917
+ });
4918
+ case "Compound": return compound$1(n.children.map(optimizeNode).filter((c) => c.kind !== "Empty"));
4919
+ }
4920
+ }
4921
+ function optimizeFuse(a, b, tol) {
4922
+ const oa = optimizeNode(a);
4923
+ const ob = optimizeNode(b);
4924
+ if (oa.kind === "Empty") return ob;
4925
+ if (ob.kind === "Empty") return oa;
4926
+ return fuse$1(oa, ob, tol);
4927
+ }
4928
+ function optimizeCut(a, b, tol) {
4929
+ const oa = optimizeNode(a);
4930
+ const ob = optimizeNode(b);
4931
+ if (ob.kind === "Empty") return oa;
4932
+ if (oa.kind === "Empty") return oa;
4933
+ return cut$1(oa, ob, tol);
4934
+ }
4935
+ function optimizeIntersect(a, b, tol) {
4936
+ const oa = optimizeNode(a);
4937
+ const ob = optimizeNode(b);
4938
+ if (oa.kind === "Empty") return oa;
4939
+ if (ob.kind === "Empty") return ob;
4940
+ return intersect$1(oa, ob, tol);
4941
+ }
4942
+ function optimizeFuseAll(shapes, tol) {
4943
+ const opt = shapes.map(optimizeNode).filter((s) => s.kind !== "Empty");
4944
+ if (opt.length === 0) return emptySolid();
4945
+ if (opt.length === 1) return opt[0];
4946
+ return fuseAll$1(opt, tol);
4947
+ }
4948
+ function optimizeCutAll(base, tools, tol) {
4949
+ const ob = optimizeNode(base);
4950
+ if (ob.kind === "Empty") return ob;
4951
+ const ot = tools.map(optimizeNode).filter((s) => s.kind !== "Empty");
4952
+ if (ot.length === 0) return ob;
4953
+ return cutAll$1(ob, ot, tol);
4954
+ }
4955
+ function optimizeTranslate(target, vector) {
4956
+ const ot = optimizeNode(target);
4957
+ const ov = foldExpr(vector);
4958
+ if (ov.kind !== "Vec3Lit") return translate$1(ot, ov);
4959
+ const [x, y, z] = ov.value;
4960
+ if (x === 0 && y === 0 && z === 0) return ot;
4961
+ if (ot.kind === "Translate") {
4962
+ const inner = foldExpr(ot.vector);
4963
+ if (inner.kind === "Vec3Lit") return translate$1(ot.target, [
4964
+ inner.value[0] + x,
4965
+ inner.value[1] + y,
4966
+ inner.value[2] + z
4967
+ ]);
4968
+ }
4969
+ return translate$1(ot, ov);
4970
+ }
4971
+ //#endregion
4972
+ //#region src/csg/edit.ts
4973
+ function replaceNode(root, pred, replacement) {
4974
+ return walk(root, pred, replacement);
4975
+ }
4976
+ function walk(node, pred, repl) {
4977
+ if (pred(node)) return repl;
4978
+ return rebuildChildren(node, pred, repl);
4979
+ }
4980
+ function rebuildChildren(n, pred, repl) {
4981
+ switch (n.kind) {
4982
+ case "Box":
4983
+ case "Sphere":
4984
+ case "Cylinder":
4985
+ case "Cone":
4986
+ case "Torus":
4987
+ case "Polygon":
4988
+ case "Circle":
4989
+ case "Line":
4990
+ case "Vertex":
4991
+ case "Empty": return n;
4992
+ case "Fuse": return fuse$1(walk(n.a, pred, repl), walk(n.b, pred, repl), n.tolerance);
4993
+ case "Cut": return cut$1(walk(n.a, pred, repl), walk(n.b, pred, repl), n.tolerance);
4994
+ case "Intersect": return intersect$1(walk(n.a, pred, repl), walk(n.b, pred, repl), n.tolerance);
4995
+ case "FuseAll": return fuseAll$1(n.shapes.map((c) => walk(c, pred, repl)), n.tolerance);
4996
+ case "CutAll": return cutAll$1(walk(n.base, pred, repl), n.tools.map((c) => walk(c, pred, repl)), n.tolerance);
4997
+ case "Translate": return translate$1(walk(n.target, pred, repl), n.vector);
4998
+ case "Rotate": return rotate$1(walk(n.target, pred, repl), n.angle, {
4999
+ axis: n.axis,
5000
+ at: n.at
5001
+ });
5002
+ case "Scale": return scale$1(walk(n.target, pred, repl), n.factor, { center: n.center });
5003
+ case "Mirror": return mirror$1(walk(n.target, pred, repl), {
5004
+ normal: n.normal,
5005
+ at: n.at
5006
+ });
5007
+ case "Compound": return compound$1(n.children.map((c) => walk(c, pred, repl)));
5008
+ }
5009
+ }
5010
+ function forEachNode(root, fn) {
5011
+ fn(root);
5012
+ for (const child of childrenOf(root)) forEachNode(child, fn);
5013
+ }
5014
+ function childrenOf(n) {
5015
+ switch (n.kind) {
5016
+ case "Box":
5017
+ case "Sphere":
5018
+ case "Cylinder":
5019
+ case "Cone":
5020
+ case "Torus":
5021
+ case "Polygon":
5022
+ case "Circle":
5023
+ case "Line":
5024
+ case "Vertex":
5025
+ case "Empty": return [];
5026
+ case "Fuse":
5027
+ case "Cut":
5028
+ case "Intersect": return [n.a, n.b];
5029
+ case "FuseAll": return n.shapes;
5030
+ case "CutAll": return [n.base, ...n.tools];
5031
+ case "Translate":
5032
+ case "Rotate":
5033
+ case "Scale":
5034
+ case "Mirror": return [n.target];
5035
+ case "Compound": return n.children;
5036
+ }
5037
+ }
5038
+ function nodeCount(root) {
5039
+ let n = 0;
5040
+ forEachNode(root, () => {
5041
+ n++;
5042
+ });
5043
+ return n;
5044
+ }
5045
+ //#endregion
5046
+ //#region src/ns/csg.ts
5047
+ var csg_exports = /* @__PURE__ */ require_textBlueprints.__exportAll({
5048
+ CSG_VERSION: () => 1,
5049
+ Evaluator: () => Evaluator,
5050
+ add: () => add,
5051
+ asScalarExpr: () => asScalarExpr,
5052
+ asVec2Expr: () => asVec2Expr,
5053
+ asVec3Expr: () => asVec3Expr,
5054
+ binOp: () => binOp,
5055
+ box: () => box$1,
5056
+ buildVec: () => buildVec,
5057
+ circle: () => circle$1,
5058
+ component: () => component,
5059
+ compound: () => compound$1,
5060
+ cone: () => cone$1,
5061
+ cut: () => cut$1,
5062
+ cutAll: () => cutAll$1,
5063
+ cylinder: () => cylinder$1,
5064
+ emptyFace: () => emptyFace,
5065
+ emptySolid: () => emptySolid,
5066
+ emptyWire: () => emptyWire,
5067
+ foldExpr: () => foldExpr,
5068
+ forEachNode: () => forEachNode,
5069
+ fromJSON: () => fromJSON,
5070
+ fuse: () => fuse$1,
5071
+ fuseAll: () => fuseAll$1,
5072
+ intersect: () => intersect$1,
5073
+ line: () => line$1,
5074
+ mirror: () => mirror$1,
5075
+ mul: () => mul,
5076
+ nodeCount: () => nodeCount,
5077
+ numLit: () => numLit,
5078
+ optimize: () => optimize,
5079
+ outputKindOf: () => outputKindOf,
5080
+ param: () => param,
5081
+ polygon: () => polygon$1,
5082
+ replaceNode: () => replaceNode,
5083
+ rotate: () => rotate$1,
5084
+ scale: () => scale$1,
5085
+ sphere: () => sphere$1,
5086
+ toJSON: () => toJSON,
5087
+ torus: () => torus$1,
5088
+ translate: () => translate$1,
5089
+ unaryOp: () => unaryOp,
5090
+ vec2Lit: () => vec2Lit,
5091
+ vec3Lit: () => vec3Lit,
5092
+ vertex: () => vertex$1,
5093
+ withEvaluator: () => withEvaluator
5094
+ });
5095
+ //#endregion
3415
5096
  exports.BaseSketcher2d = require_blueprintSketcher.BaseSketcher2d;
3416
5097
  exports.BlueprintSketcher = require_blueprintSketcher.BlueprintSketcher;
3417
5098
  exports.BrepBugError = require_errors.BrepBugError;
@@ -3523,6 +5204,12 @@ exports.createVertex = require_shapeTypes.createVertex;
3523
5204
  exports.createWire = require_shapeTypes.createWire;
3524
5205
  exports.createWorkerClient = require_workerHandler.createWorkerClient;
3525
5206
  exports.createWorkerHandler = require_workerHandler.createWorkerHandler;
5207
+ Object.defineProperty(exports, "csg", {
5208
+ enumerable: true,
5209
+ get: function() {
5210
+ return csg_exports;
5211
+ }
5212
+ });
3526
5213
  exports.curve2dBoundingBox = require_blueprintFns.curve2dBoundingBox;
3527
5214
  exports.curve2dDistanceFrom = require_blueprintFns.curve2dDistanceFrom;
3528
5215
  exports.curve2dFirstPoint = require_blueprintFns.curve2dFirstPoint;