brepjs 20.1.5 → 20.3.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 (115) hide show
  1. package/dist/2d.cjs +7 -7
  2. package/dist/2d.js +7 -7
  3. package/dist/{adjacencyFns-BrfM5HuO.cjs → adjacencyFns-1rxgJ6Hw.cjs} +3 -3
  4. package/dist/{adjacencyFns-BKNCTFyz.js → adjacencyFns-DeyXahej.js} +3 -3
  5. package/dist/{blueprint-cDEPhHO0.cjs → blueprint-Yyoiz-U1.cjs} +7 -7
  6. package/dist/{blueprint-DQaebcah.js → blueprint-rwJjYPzo.js} +7 -7
  7. package/dist/{blueprintFns-41EvpjiC.cjs → blueprintFns-Ce6OoPSX.cjs} +3 -3
  8. package/dist/{blueprintFns-DdIWHIxE.js → blueprintFns-Q3Sq-Fse.js} +3 -3
  9. package/dist/{blueprintSketcher-DX8NeWqA.cjs → blueprintSketcher-CzKbxeTk.cjs} +4 -4
  10. package/dist/{blueprintSketcher-BnVu9r7p.js → blueprintSketcher-FywUpRiV.js} +4 -4
  11. package/dist/{boolean2D-B0jPhKO1.cjs → boolean2D-BzZ9iBSn.cjs} +5 -5
  12. package/dist/{boolean2D-Dp7Bjzvc.js → boolean2D-D8igCYc9.js} +5 -5
  13. package/dist/brepjs.cjs +305 -81
  14. package/dist/brepjs.js +305 -82
  15. package/dist/{cameraFns-CcgzxZ-9.js → cameraFns-Cs6v3bWQ.js} +4 -4
  16. package/dist/{cameraFns-DUKz-5_d.cjs → cameraFns-RHCb1F1s.cjs} +4 -4
  17. package/dist/core/errors.d.ts +4 -0
  18. package/dist/core.cjs +4 -4
  19. package/dist/core.js +4 -4
  20. package/dist/{cornerFinder-B-eLajMt.cjs → cornerFinder-Cji_BK-R.cjs} +1 -1
  21. package/dist/{cornerFinder-D589drKe.js → cornerFinder-Dlae8IX5.js} +1 -1
  22. package/dist/csg/builders.d.ts +13 -1
  23. package/dist/csg/evaluate.d.ts +10 -1
  24. package/dist/csg/evaluators/context.d.ts +2 -1
  25. package/dist/csg/evaluators/extension.d.ts +5 -0
  26. package/dist/csg/hash.d.ts +1 -0
  27. package/dist/csg/index.d.ts +2 -2
  28. package/dist/csg/jsonData.d.ts +8 -0
  29. package/dist/csg/serialize.d.ts +1 -1
  30. package/dist/csg/types.d.ts +50 -1
  31. package/dist/{curveFns-D-hc0_6t.cjs → curveFns-6-ULFrEB.cjs} +2 -2
  32. package/dist/{curveFns-Q-tL9uNq.js → curveFns-KS1BWGhF.js} +2 -2
  33. package/dist/{drawFns-CrBzPDfw.js → drawFns-BD5OqwLF.js} +14 -14
  34. package/dist/{drawFns-BGW37YtA.cjs → drawFns-Dcvgj3Xg.cjs} +14 -14
  35. package/dist/{errors-CTn8i3lY.js → errors-Zb3jBa0u.js} +4 -0
  36. package/dist/{errors-DWezb9DI.cjs → errors-jwhfQJZK.cjs} +4 -0
  37. package/dist/{faceFns-DQ51W4Eg.js → faceFns-CTlJC5IY.js} +3 -3
  38. package/dist/{faceFns-iyZwpUFe.cjs → faceFns-CZeHWke7.cjs} +3 -3
  39. package/dist/{healingFns-DxEg4twQ.js → healingFns-BDkAwJNy.js} +5 -5
  40. package/dist/{healingFns-DlyPwsRq.cjs → healingFns-DziPRwmh.cjs} +5 -5
  41. package/dist/{helpers-Hna44lMW.js → helpers-BN1mVMuZ.js} +7 -7
  42. package/dist/{helpers-DzuHzyWn.cjs → helpers-NRZVshPb.cjs} +7 -7
  43. package/dist/{importFns-CzX0LzER.js → importFns-0kHGg-b8.js} +3 -3
  44. package/dist/{importFns-BygnKmG8.cjs → importFns-BEi-HsSw.cjs} +3 -3
  45. package/dist/index.d.ts +1 -0
  46. package/dist/io.cjs +2 -2
  47. package/dist/io.js +2 -2
  48. package/dist/kernel/interfaces/measureOps.d.ts +19 -0
  49. package/dist/kernel/occtWasm/measureOps.d.ts +2 -1
  50. package/dist/kernel/occtWasm/occtWasmAdapter.cjs +1 -1
  51. package/dist/kernel/occtWasm/occtWasmAdapter.d.ts +2 -1
  52. package/dist/kernel/occtWasm/occtWasmAdapter.js +1 -1
  53. package/dist/kernel/occtWasm/occtWasmTypes.d.ts +2 -0
  54. package/dist/{loftFns-Bo6ngjcA.js → loftFns-B5mq1WDh.js} +2 -2
  55. package/dist/{loftFns-DfF8LMRm.cjs → loftFns-DL9UsQhd.cjs} +2 -2
  56. package/dist/{measureFns-DnZsoSsE.js → measureFns-CyDVZomf.js} +5 -5
  57. package/dist/{measureFns-Czv8iOd1.cjs → measureFns-D_GpQw5z.cjs} +16 -4
  58. package/dist/measurement/measureCache.d.ts +2 -1
  59. package/dist/measurement/measureTypes.d.ts +9 -0
  60. package/dist/measurement/principalBoxFns.d.ts +33 -0
  61. package/dist/measurement.cjs +3 -1
  62. package/dist/measurement.d.ts +1 -0
  63. package/dist/measurement.js +3 -2
  64. package/dist/{meshFns-82W7072d.cjs → meshFns-CAxkaRTm.cjs} +4 -4
  65. package/dist/{meshFns-DegHraku.js → meshFns-COlno8TY.js} +4 -4
  66. package/dist/ns/measurement.d.ts +1 -0
  67. package/dist/{occtWasmAdapter-D4I0n537.js → occtWasmAdapter-BX10fyla.js} +21 -0
  68. package/dist/{occtWasmAdapter-wCKnmevS.cjs → occtWasmAdapter-CA6PmIIj.cjs} +21 -0
  69. package/dist/operations.cjs +2 -2
  70. package/dist/operations.js +2 -2
  71. package/dist/{originTrackingFns-DP_yN44Z.cjs → originTrackingFns-CWo6NWHK.cjs} +2 -2
  72. package/dist/{originTrackingFns-BbTSRuQj.js → originTrackingFns-DiHy5BZC.js} +2 -2
  73. package/dist/{planeOps-CkpMeheg.js → planeOps-Cxws4Tiu.js} +1 -1
  74. package/dist/{planeOps-CpupTCRM.cjs → planeOps-DJuclNxa.cjs} +1 -1
  75. package/dist/{primitiveFns-D1ayK5yN.js → primitiveFns-CcaoYdzl.js} +5 -5
  76. package/dist/{primitiveFns-_Kid-gYL.cjs → primitiveFns-DayTOw7C.cjs} +5 -5
  77. package/dist/principalBoxFns-5FSbxAj-.cjs +212 -0
  78. package/dist/principalBoxFns-BJgGEoik.js +207 -0
  79. package/dist/projection.cjs +1 -1
  80. package/dist/projection.js +1 -1
  81. package/dist/query.cjs +2 -2
  82. package/dist/query.js +2 -2
  83. package/dist/{refResolveFns-BL_6tDQG.cjs → refResolveFns-BJG5h8ce.cjs} +6 -6
  84. package/dist/{refResolveFns-BujrL8at.js → refResolveFns-C0_Wx7nM.js} +6 -6
  85. package/dist/result.cjs +1 -1
  86. package/dist/result.js +1 -1
  87. package/dist/{shapeFns-sbLSffyZ.js → shapeFns--1wNlcc_.js} +3 -3
  88. package/dist/{shapeFns-SdMLvQ7n.cjs → shapeFns-C2j6oZ2u.cjs} +3 -3
  89. package/dist/shapeRef.cjs +1 -1
  90. package/dist/shapeRef.js +1 -1
  91. package/dist/{shapeTypes-DVpJHhgk.js → shapeTypes-CqNJoSam.js} +1 -1
  92. package/dist/{shapeTypes-BWsKDxzf.cjs → shapeTypes-DH2ShBU_.cjs} +1 -1
  93. package/dist/sketching.cjs +3 -3
  94. package/dist/sketching.js +3 -3
  95. package/dist/{solidBuilders-CZdfdC4S.cjs → solidBuilders-6eLtWBLM.cjs} +7 -7
  96. package/dist/{solidBuilders-BmUEjbhs.js → solidBuilders-BwOF7M-p.js} +7 -7
  97. package/dist/{surfaceBuilders-DW56oYUA.js → surfaceBuilders-8nLk2PWk.js} +4 -4
  98. package/dist/{surfaceBuilders-BujH-WLG.cjs → surfaceBuilders-vYgSvgI6.cjs} +4 -4
  99. package/dist/text.cjs +2 -2
  100. package/dist/text.js +2 -2
  101. package/dist/{textBlueprints-BlTo-FeX.js → textBlueprints-3jLY3G3u.js} +9 -9
  102. package/dist/{textBlueprints-BaRZlz2x.cjs → textBlueprints-BE9lHH5V.cjs} +9 -9
  103. package/dist/{textMetrics-C6AkkXLu.cjs → textMetrics-DMhzyYGs.cjs} +2 -2
  104. package/dist/{textMetrics-KJFOH0hq.js → textMetrics-cyLUdKx1.js} +2 -2
  105. package/dist/{threadFns-D-Qy8nQN.cjs → threadFns-Bc1QOMeh.cjs} +8 -8
  106. package/dist/{threadFns-CRq0YEAj.js → threadFns-CJT2NW3G.js} +8 -8
  107. package/dist/topology.cjs +9 -9
  108. package/dist/topology.js +9 -9
  109. package/dist/{topologyQueryFns-C8Dv3AdW.js → topologyQueryFns-DnfjQgP7.js} +3 -3
  110. package/dist/{topologyQueryFns-DbQBANFg.cjs → topologyQueryFns-q2bGyuEV.cjs} +8 -2
  111. package/dist/{validityTypes-4nhcQAdO.cjs → validityTypes-r0A2YdNq.cjs} +2 -2
  112. package/dist/{validityTypes-D6M4CiEI.js → validityTypes-t7JpS0Ki.js} +2 -2
  113. package/dist/vectors.cjs +1 -1
  114. package/dist/vectors.js +1 -1
  115. package/package.json +1 -1
package/dist/brepjs.cjs CHANGED
@@ -1,41 +1,42 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_rolldown_runtime = require("./rolldown-runtime-C0BPl7ul.cjs");
3
- const require_shapeTypes = require("./shapeTypes-BWsKDxzf.cjs");
4
- const require_occtWasmAdapter = require("./occtWasmAdapter-wCKnmevS.cjs");
3
+ const require_shapeTypes = require("./shapeTypes-DH2ShBU_.cjs");
4
+ const require_occtWasmAdapter = require("./occtWasmAdapter-CA6PmIIj.cjs");
5
5
  const require_bug = require("./bug-O02CsAmt.cjs");
6
- const require_errors = require("./errors-DWezb9DI.cjs");
7
- const require_topologyQueryFns = require("./topologyQueryFns-DbQBANFg.cjs");
8
- const require_validityTypes = require("./validityTypes-4nhcQAdO.cjs");
6
+ const require_errors = require("./errors-jwhfQJZK.cjs");
7
+ const require_topologyQueryFns = require("./topologyQueryFns-q2bGyuEV.cjs");
8
+ const require_validityTypes = require("./validityTypes-r0A2YdNq.cjs");
9
9
  const require_constants = require("./constants-BOVyEYGH.cjs");
10
10
  const require_types = require("./types-KjA8tY4Y.cjs");
11
11
  const require_vecOps = require("./vecOps-CCnJt-yH.cjs");
12
- const require_planeOps = require("./planeOps-CpupTCRM.cjs");
13
- const require_faceFns = require("./faceFns-iyZwpUFe.cjs");
14
- const require_originTrackingFns = require("./originTrackingFns-DP_yN44Z.cjs");
15
- const require_solidBuilders = require("./solidBuilders-CZdfdC4S.cjs");
16
- const require_primitiveFns = require("./primitiveFns-_Kid-gYL.cjs");
17
- const require_shapeFns = require("./shapeFns-SdMLvQ7n.cjs");
18
- const require_curveFns = require("./curveFns-D-hc0_6t.cjs");
19
- const require_meshFns = require("./meshFns-82W7072d.cjs");
12
+ const require_planeOps = require("./planeOps-DJuclNxa.cjs");
13
+ const require_faceFns = require("./faceFns-CZeHWke7.cjs");
14
+ const require_originTrackingFns = require("./originTrackingFns-CWo6NWHK.cjs");
15
+ const require_solidBuilders = require("./solidBuilders-6eLtWBLM.cjs");
16
+ const require_primitiveFns = require("./primitiveFns-DayTOw7C.cjs");
17
+ const require_shapeFns = require("./shapeFns-C2j6oZ2u.cjs");
18
+ const require_curveFns = require("./curveFns-6-ULFrEB.cjs");
19
+ const require_meshFns = require("./meshFns-CAxkaRTm.cjs");
20
20
  const require_arrayAccess = require("./arrayAccess-e4H9cBfh.cjs");
21
- const require_surfaceBuilders = require("./surfaceBuilders-BujH-WLG.cjs");
22
- const require_healingFns = require("./healingFns-DlyPwsRq.cjs");
23
- const require_threadFns = require("./threadFns-D-Qy8nQN.cjs");
24
- const require_blueprintSketcher = require("./blueprintSketcher-DX8NeWqA.cjs");
25
- const require_helpers = require("./helpers-DzuHzyWn.cjs");
26
- const require_blueprint = require("./blueprint-cDEPhHO0.cjs");
27
- const require_drawFns = require("./drawFns-BGW37YtA.cjs");
28
- const require_measureFns = require("./measureFns-Czv8iOd1.cjs");
29
- const require_cornerFinder = require("./cornerFinder-B-eLajMt.cjs");
30
- const require_boolean2D = require("./boolean2D-B0jPhKO1.cjs");
31
- const require_blueprintFns = require("./blueprintFns-41EvpjiC.cjs");
32
- const require_importFns = require("./importFns-BygnKmG8.cjs");
33
- const require_loftFns = require("./loftFns-DfF8LMRm.cjs");
34
- const require_textBlueprints = require("./textBlueprints-BaRZlz2x.cjs");
35
- const require_refResolveFns = require("./refResolveFns-BL_6tDQG.cjs");
36
- const require_adjacencyFns = require("./adjacencyFns-BrfM5HuO.cjs");
37
- const require_cameraFns = require("./cameraFns-DUKz-5_d.cjs");
38
- const require_textMetrics = require("./textMetrics-C6AkkXLu.cjs");
21
+ const require_surfaceBuilders = require("./surfaceBuilders-vYgSvgI6.cjs");
22
+ const require_healingFns = require("./healingFns-DziPRwmh.cjs");
23
+ const require_threadFns = require("./threadFns-Bc1QOMeh.cjs");
24
+ const require_blueprintSketcher = require("./blueprintSketcher-CzKbxeTk.cjs");
25
+ const require_helpers = require("./helpers-NRZVshPb.cjs");
26
+ const require_blueprint = require("./blueprint-Yyoiz-U1.cjs");
27
+ const require_drawFns = require("./drawFns-Dcvgj3Xg.cjs");
28
+ const require_measureFns = require("./measureFns-D_GpQw5z.cjs");
29
+ const require_cornerFinder = require("./cornerFinder-Cji_BK-R.cjs");
30
+ const require_boolean2D = require("./boolean2D-BzZ9iBSn.cjs");
31
+ const require_blueprintFns = require("./blueprintFns-Ce6OoPSX.cjs");
32
+ const require_importFns = require("./importFns-BEi-HsSw.cjs");
33
+ const require_loftFns = require("./loftFns-DL9UsQhd.cjs");
34
+ const require_textBlueprints = require("./textBlueprints-BE9lHH5V.cjs");
35
+ const require_refResolveFns = require("./refResolveFns-BJG5h8ce.cjs");
36
+ const require_adjacencyFns = require("./adjacencyFns-1rxgJ6Hw.cjs");
37
+ const require_cameraFns = require("./cameraFns-RHCb1F1s.cjs");
38
+ const require_textMetrics = require("./textMetrics-DMhzyYGs.cjs");
39
+ const require_principalBoxFns = require("./principalBoxFns-5FSbxAj-.cjs");
39
40
  const require_workerPool = require("./workerPool-D30NsiIW.cjs");
40
41
  //#region src/kernel/types.ts
41
42
  /** Check if the kernel supports hidden-line-removal projection. */
@@ -1174,6 +1175,14 @@ function fnvMixInt32(h, n) {
1174
1175
  }
1175
1176
  return r;
1176
1177
  }
1178
+ function fnvMixText(h, s) {
1179
+ let r = fnvMixInt32(h, s.length);
1180
+ for (let i = 0; i < s.length; i++) {
1181
+ const c = s.charCodeAt(i);
1182
+ r = fnvMixByte(fnvMixByte(r, c), c >>> 8);
1183
+ }
1184
+ return r;
1185
+ }
1177
1186
  function fnvMixBool(h, b) {
1178
1187
  return fnvMixByte(h, b ? 1 : 0);
1179
1188
  }
@@ -1522,6 +1531,130 @@ function foldSegment(s, foldExpr) {
1522
1531
  }
1523
1532
  }
1524
1533
  //#endregion
1534
+ //#region src/csg/jsonData.ts
1535
+ /** Validate `value` as JSON-safe and return its canonical frozen copy, or a
1536
+ * message naming the first offending path (rooted at `path`). */
1537
+ function canonicalJson(value, path) {
1538
+ return copyJson(value, path, /* @__PURE__ */ new Set());
1539
+ }
1540
+ function copyJson(v, path, ancestors) {
1541
+ if (v === null || typeof v === "boolean" || typeof v === "string") return require_errors.ok(v);
1542
+ if (typeof v === "number") {
1543
+ if (!Number.isFinite(v)) return require_errors.err(`${path}: ${String(v)} is not JSON-safe`);
1544
+ return require_errors.ok(v === 0 ? 0 : v);
1545
+ }
1546
+ if (typeof v !== "object") return require_errors.err(`${path}: ${typeof v} is not JSON-safe`);
1547
+ if (ancestors.has(v)) return require_errors.err(`${path}: circular reference is not JSON-safe`);
1548
+ ancestors.add(v);
1549
+ const out = Array.isArray(v) ? copyArray(v, path, ancestors) : copyObject(v, path, ancestors);
1550
+ ancestors.delete(v);
1551
+ return out;
1552
+ }
1553
+ function copyArray(v, path, ancestors) {
1554
+ const out = [];
1555
+ for (let i = 0; i < v.length; i++) {
1556
+ const r = copyJson(v[i], `${path}[${i}]`, ancestors);
1557
+ if (!r.ok) return r;
1558
+ out.push(r.value);
1559
+ }
1560
+ return require_errors.ok(Object.freeze(out));
1561
+ }
1562
+ function copyObject(v, path, ancestors) {
1563
+ const proto = Object.getPrototypeOf(v);
1564
+ if (proto !== Object.prototype && proto !== null) {
1565
+ const ctor = v.constructor;
1566
+ const what = typeof ctor === "function" && ctor.name ? `${ctor.name} instance` : "object";
1567
+ return require_errors.err(`${path}: ${what} is not JSON-safe (use a plain object)`);
1568
+ }
1569
+ const record = v;
1570
+ const entries = [];
1571
+ for (const key of Object.keys(record).sort()) {
1572
+ const r = copyJson(record[key], `${path}.${key}`, ancestors);
1573
+ if (!r.ok) return r;
1574
+ entries.push([key, r.value]);
1575
+ }
1576
+ return require_errors.ok(Object.freeze(Object.fromEntries(entries)));
1577
+ }
1578
+ var TAG_NULL = 0;
1579
+ var TAG_FALSE = 1;
1580
+ var TAG_TRUE = 2;
1581
+ var TAG_NUMBER = 3;
1582
+ var TAG_STRING = 4;
1583
+ var TAG_ARRAY = 5;
1584
+ var TAG_OBJECT = 6;
1585
+ /** Type-tagged, length-prefixed Merkle mix of a JSON value; object keys are
1586
+ * hashed in sorted order, so key order never changes the result. */
1587
+ function hashJson(h, v) {
1588
+ if (v === null) return fnvMixByte(h, TAG_NULL);
1589
+ if (typeof v === "boolean") return fnvMixByte(h, v ? TAG_TRUE : TAG_FALSE);
1590
+ if (typeof v === "number") return fnvMixNumber(fnvMixByte(h, TAG_NUMBER), v);
1591
+ if (typeof v === "string") return fnvMixText(fnvMixByte(h, TAG_STRING), v);
1592
+ if (isJsonArray(v)) {
1593
+ let r = fnvMixInt32(fnvMixByte(h, TAG_ARRAY), v.length);
1594
+ for (const item of v) r = hashJson(r, item);
1595
+ return r;
1596
+ }
1597
+ const keys = Object.keys(v).sort();
1598
+ let r = fnvMixInt32(fnvMixByte(h, TAG_OBJECT), keys.length);
1599
+ for (const key of keys) {
1600
+ r = fnvMixText(r, key);
1601
+ r = hashJson(r, v[key] ?? null);
1602
+ }
1603
+ return r;
1604
+ }
1605
+ function isJsonArray(v) {
1606
+ return Array.isArray(v);
1607
+ }
1608
+ //#endregion
1609
+ //#region src/csg/types.ts
1610
+ var OUTPUT_KINDS = {
1611
+ Solid: true,
1612
+ Face: true,
1613
+ Wire: true,
1614
+ Edge: true,
1615
+ Vertex: true,
1616
+ Compound: true
1617
+ };
1618
+ function isOutputKind(v) {
1619
+ return typeof v === "string" && Object.hasOwn(OUTPUT_KINDS, v);
1620
+ }
1621
+ function outputKindOf(node) {
1622
+ switch (node.kind) {
1623
+ case "Box":
1624
+ case "Sphere":
1625
+ case "Cylinder":
1626
+ case "Cone":
1627
+ case "Torus": return "Solid";
1628
+ case "Polygon": return "Face";
1629
+ case "Circle":
1630
+ case "Line": return "Edge";
1631
+ case "Vertex": return "Vertex";
1632
+ case "Empty": return node.output;
1633
+ case "Fuse":
1634
+ case "Cut":
1635
+ case "Intersect": return outputKindOf(node.a);
1636
+ case "FuseAll": return node.shapes[0] ? outputKindOf(node.shapes[0]) : "Solid";
1637
+ case "CutAll": return outputKindOf(node.base);
1638
+ case "Translate":
1639
+ case "Rotate":
1640
+ case "Scale":
1641
+ case "Mirror":
1642
+ case "Color": return outputKindOf(node.target);
1643
+ case "Extrude":
1644
+ case "Revolve":
1645
+ case "Loft":
1646
+ case "Sweep":
1647
+ case "Fillet":
1648
+ case "Chamfer":
1649
+ case "Shell": return "Solid";
1650
+ case "Profile": return "Face";
1651
+ case "Path": return "Wire";
1652
+ case "Compound": return "Compound";
1653
+ case "Instance": return node.fuse ? "Solid" : "Compound";
1654
+ case "Extension": return node.output;
1655
+ }
1656
+ }
1657
+ //#endregion
1525
1658
  //#region src/csg/builders.ts
1526
1659
  var EMPTY_DEPS = /* @__PURE__ */ new Set();
1527
1660
  function startHash(tag) {
@@ -2025,42 +2158,47 @@ function instance$1(source, placements, fuse = false) {
2025
2158
  freeParams: depsOf(source)
2026
2159
  };
2027
2160
  }
2028
- //#endregion
2029
- //#region src/csg/types.ts
2030
- function outputKindOf(node) {
2031
- switch (node.kind) {
2032
- case "Box":
2033
- case "Sphere":
2034
- case "Cylinder":
2035
- case "Cone":
2036
- case "Torus": return "Solid";
2037
- case "Polygon": return "Face";
2038
- case "Circle":
2039
- case "Line": return "Edge";
2040
- case "Vertex": return "Vertex";
2041
- case "Empty": return node.output;
2042
- case "Fuse":
2043
- case "Cut":
2044
- case "Intersect": return outputKindOf(node.a);
2045
- case "FuseAll": return node.shapes[0] ? outputKindOf(node.shapes[0]) : "Solid";
2046
- case "CutAll": return outputKindOf(node.base);
2047
- case "Translate":
2048
- case "Rotate":
2049
- case "Scale":
2050
- case "Mirror":
2051
- case "Color": return outputKindOf(node.target);
2052
- case "Extrude":
2053
- case "Revolve":
2054
- case "Loft":
2055
- case "Sweep":
2056
- case "Fillet":
2057
- case "Chamfer":
2058
- case "Shell": return "Solid";
2059
- case "Profile": return "Face";
2060
- case "Path": return "Wire";
2061
- case "Compound": return "Compound";
2062
- case "Instance": return node.fuse ? "Solid" : "Compound";
2063
- }
2161
+ function isExpr(v) {
2162
+ return typeof v === "object" && v !== null && typeof v.structuralHash === "bigint";
2163
+ }
2164
+ function extensionParams(name, input) {
2165
+ const entries = [];
2166
+ for (const key of Object.keys(input).sort()) {
2167
+ const v = input[key];
2168
+ if (typeof v !== "number" && !isExpr(v)) throw new TypeError(`csg.extension(${name}): params.${key} must be a number or an Expr`);
2169
+ entries.push([key, asScalarExpr(v)]);
2170
+ }
2171
+ return entries;
2172
+ }
2173
+ /** A caller-defined operation, materialized at evaluation by the
2174
+ * `ExtensionEvaluator` registered under `name` in
2175
+ * `EvaluatorOptions.extensions`. Unlike the other builders this one validates
2176
+ * eagerly and throws a TypeError: a node whose data cannot be hashed
2177
+ * canonically has no content address. */
2178
+ function extension(name, output, options) {
2179
+ if (typeof name !== "string" || name.length === 0) throw new TypeError("csg.extension: name must be a non-empty string");
2180
+ if (!isOutputKind(output)) throw new TypeError(`csg.extension(${name}): unknown output kind ${String(output)}`);
2181
+ const data = canonicalJson(options?.data ?? null, "data");
2182
+ if (!data.ok) throw new TypeError(`csg.extension(${name}): ${data.error}`);
2183
+ const children = [...options?.children ?? []];
2184
+ const params = extensionParams(name, options?.params ?? {});
2185
+ let h = fnvMixText(startHash("Extension"), name);
2186
+ h = fnvMixText(h, output);
2187
+ h = fnvMixInt32(h, children.length);
2188
+ for (const c of children) h = mix(h, c);
2189
+ h = fnvMixInt32(h, params.length);
2190
+ for (const [key, e] of params) h = mix(fnvMixText(h, key), e);
2191
+ h = hashJson(h, data.value);
2192
+ return {
2193
+ kind: "Extension",
2194
+ name,
2195
+ output,
2196
+ children,
2197
+ params: Object.fromEntries(params),
2198
+ data: data.value,
2199
+ structuralHash: h,
2200
+ freeParams: depsOf(...children, ...params.map(([, e]) => e))
2201
+ };
2064
2202
  }
2065
2203
  //#endregion
2066
2204
  //#region src/csg/profiles.ts
@@ -3115,6 +3253,29 @@ function evalShell(node, ctx) {
3115
3253
  return require_healingFns.shell(solid.value, faces, thickness.value);
3116
3254
  }
3117
3255
  //#endregion
3256
+ //#region src/csg/evaluators/extension.ts
3257
+ function evalExtension(node, ctx) {
3258
+ const evaluator = ctx.extensions.get(node.name);
3259
+ if (evaluator === void 0) return require_errors.err(require_errors.validationError(require_errors.BrepErrorCode.CSG_EXTENSION_UNKNOWN, `Extension: no evaluator registered for '${node.name}'`, void 0, { name: node.name }, `Register one with new csg.Evaluator({ extensions: { '${node.name}': fn } })`));
3260
+ const params = [];
3261
+ for (const [key, expr] of Object.entries(node.params)) {
3262
+ const v = evalScalar(expr, ctx.env, `Extension(${node.name}).params.${key}`);
3263
+ if (!v.ok) return v;
3264
+ params.push([key, v.value]);
3265
+ }
3266
+ const children = [];
3267
+ for (const child of node.children) {
3268
+ const r = ctx.evalNode(child);
3269
+ if (!r.ok) return r;
3270
+ children.push(r.value);
3271
+ }
3272
+ return evaluator({
3273
+ params: Object.fromEntries(params),
3274
+ data: node.data,
3275
+ children
3276
+ });
3277
+ }
3278
+ //#endregion
3118
3279
  //#region src/csg/evaluate.ts
3119
3280
  function dispatch(node, ctx) {
3120
3281
  switch (node.kind) {
@@ -3139,6 +3300,7 @@ function dispatch(node, ctx) {
3139
3300
  case "Mirror": return evalMirror(node, ctx);
3140
3301
  case "Compound": return evalCompound(node, ctx);
3141
3302
  case "Instance": return evalInstance(node, ctx);
3303
+ case "Extension": return evalExtension(node, ctx);
3142
3304
  case "Extrude":
3143
3305
  case "Revolve":
3144
3306
  case "Loft":
@@ -3366,6 +3528,7 @@ var Evaluator = class {
3366
3528
  maxMeshCacheEntries;
3367
3529
  meshCache = /* @__PURE__ */ new Map();
3368
3530
  onStep;
3531
+ extensions;
3369
3532
  hits = 0;
3370
3533
  misses = 0;
3371
3534
  evictions = 0;
@@ -3379,6 +3542,9 @@ var Evaluator = class {
3379
3542
  const meshMax = options.maxMeshCacheEntries;
3380
3543
  if (meshMax !== void 0 && (!Number.isInteger(meshMax) || meshMax < 1)) throw new RangeError(`Evaluator: maxMeshCacheEntries must be a positive integer, got ${String(meshMax)}`);
3381
3544
  this.maxMeshCacheEntries = meshMax;
3545
+ const extensions = new Map(Object.entries(options.extensions ?? {}));
3546
+ for (const [name, fn] of extensions) if (typeof fn !== "function") throw new TypeError(`Evaluator: extensions['${name}'] must be a function`);
3547
+ this.extensions = extensions;
3382
3548
  }
3383
3549
  /**
3384
3550
  * Materialize a CSG IR tree against the given parameter environment.
@@ -3507,7 +3673,8 @@ var Evaluator = class {
3507
3673
  const result = dispatch(node, {
3508
3674
  env,
3509
3675
  tolerance: this.defaultTolerance,
3510
- evalNode: (child) => this.evaluateInner(child, env)
3676
+ evalNode: (child) => this.evaluateInner(child, env),
3677
+ extensions: this.extensions
3511
3678
  });
3512
3679
  if (!result.ok) return result;
3513
3680
  const shape = result.value;
@@ -3635,6 +3802,11 @@ function rebuildChildren(n, pred, repl, memo) {
3635
3802
  });
3636
3803
  case "Compound": return compound$1(n.children.map((c) => walk(c, pred, repl, memo)));
3637
3804
  case "Instance": return instance$1(walk(n.source, pred, repl, memo), n.placements, n.fuse);
3805
+ case "Extension": return extension(n.name, n.output, {
3806
+ children: n.children.map((c) => walk(c, pred, repl, memo)),
3807
+ params: n.params,
3808
+ data: n.data
3809
+ });
3638
3810
  case "Extrude":
3639
3811
  case "Revolve":
3640
3812
  case "Loft":
@@ -3699,7 +3871,8 @@ function childrenOf(n) {
3699
3871
  case "Fillet":
3700
3872
  case "Chamfer":
3701
3873
  case "Shell": return [n.target];
3702
- case "Compound": return n.children;
3874
+ case "Compound":
3875
+ case "Extension": return n.children;
3703
3876
  case "Instance": return [n.source];
3704
3877
  case "Extrude":
3705
3878
  case "Revolve": return [n.profile];
@@ -3723,11 +3896,11 @@ function toJSON(node) {
3723
3896
  };
3724
3897
  const root = emitNode(node, ctx);
3725
3898
  return ctx.defs.length > 0 ? {
3726
- csgVersion: 8,
3899
+ csgVersion: 9,
3727
3900
  defs: ctx.defs,
3728
3901
  root
3729
3902
  } : {
3730
- csgVersion: 8,
3903
+ csgVersion: 9,
3731
3904
  root
3732
3905
  };
3733
3906
  }
@@ -4000,7 +4173,18 @@ function featureToJson(n, ctx) {
4000
4173
  default: return;
4001
4174
  }
4002
4175
  }
4176
+ function extensionToJson(n, ctx) {
4177
+ return {
4178
+ kind: "Extension",
4179
+ name: n.name,
4180
+ output: n.output,
4181
+ children: n.children.map((c) => emitNode(c, ctx)),
4182
+ params: Object.fromEntries(Object.entries(n.params).map(([k, e]) => [k, exprToJson(e)])),
4183
+ data: n.data
4184
+ };
4185
+ }
4003
4186
  function nodeToJson(n, ctx) {
4187
+ if (n.kind === "Extension") return extensionToJson(n, ctx);
4004
4188
  if (n.kind === "Color") return {
4005
4189
  kind: "Color",
4006
4190
  target: emitNode(n.target, ctx),
@@ -4067,7 +4251,7 @@ function readVec2(v, where) {
4067
4251
  function fromJSON(envelope) {
4068
4252
  if (!isObj(envelope)) return bad("input is not an object");
4069
4253
  const v = envelope["csgVersion"];
4070
- if (typeof v !== "number" || !Number.isInteger(v) || v < MIN_CSG_VERSION || v > 8) return bad(`unsupported csgVersion ${String(v)} (expected ${MIN_CSG_VERSION}..8)`);
4254
+ if (typeof v !== "number" || !Number.isInteger(v) || v < MIN_CSG_VERSION || v > 9) return bad(`unsupported csgVersion ${String(v)} (expected ${MIN_CSG_VERSION}..9)`);
4071
4255
  const rawDefs = envelope["defs"];
4072
4256
  const defs = [];
4073
4257
  if (rawDefs !== void 0) {
@@ -4159,15 +4343,15 @@ function readOptTolerance(j) {
4159
4343
  if (t === void 0 || t === null) return require_errors.ok(void 0);
4160
4344
  return isNumber$1(t) ? require_errors.ok(t) : bad("tolerance: not a finite number");
4161
4345
  }
4346
+ function readRef(ref, defs) {
4347
+ if (!isNumber$1(ref) || !Number.isInteger(ref) || ref < 0) return bad("$ref: expected a non-negative integer def index");
4348
+ const node = defs[ref];
4349
+ if (node === void 0) return bad(`$ref: ${ref} is out of range (forward refs are rejected)`);
4350
+ return require_errors.ok(node);
4351
+ }
4162
4352
  function readNode(j, defs) {
4163
4353
  if (!isObj(j)) return bad("node: not an object");
4164
- const ref = j["$ref"];
4165
- if (ref !== void 0) {
4166
- if (!isNumber$1(ref) || !Number.isInteger(ref) || ref < 0) return bad("$ref: expected a non-negative integer def index");
4167
- const node = defs[ref];
4168
- if (node === void 0) return bad(`$ref: ${ref} is out of range (forward refs are rejected)`);
4169
- return require_errors.ok(node);
4170
- }
4354
+ if (j["$ref"] !== void 0) return readRef(j["$ref"], defs);
4171
4355
  const kind = j["kind"];
4172
4356
  switch (kind) {
4173
4357
  case "Box":
@@ -4201,6 +4385,7 @@ function readNode(j, defs) {
4201
4385
  case "Fillet": return readFillet(j, defs);
4202
4386
  case "Chamfer": return readChamfer(j, defs);
4203
4387
  case "Shell": return readShell(j, defs);
4388
+ case "Extension": return readExtension(j, defs);
4204
4389
  default: return bad(`unknown node kind: ${String(kind)}`);
4205
4390
  }
4206
4391
  }
@@ -4612,6 +4797,34 @@ function readCompound(j, defs) {
4612
4797
  function isMatrix4x4(v) {
4613
4798
  return Array.isArray(v) && v.length === 4 && v.every((row) => Array.isArray(row) && row.length === 4 && row.every(isNumber$1));
4614
4799
  }
4800
+ function readExtensionParams(j) {
4801
+ if (j === void 0) return require_errors.ok({});
4802
+ if (!isObj(j)) return bad("Extension.params: not an object");
4803
+ const entries = [];
4804
+ for (const [key, raw] of Object.entries(j)) {
4805
+ const e = readExpr(raw);
4806
+ if (!e.ok) return e;
4807
+ entries.push([key, e.value]);
4808
+ }
4809
+ return require_errors.ok(Object.fromEntries(entries));
4810
+ }
4811
+ function readExtension(j, defs) {
4812
+ const name = j["name"];
4813
+ if (!isString(name) || name.length === 0) return bad("Extension.name: expected a non-empty string");
4814
+ const output = j["output"];
4815
+ if (!isOutputKind(output)) return bad(`Extension.output: ${String(output)}`);
4816
+ const children = j["children"] === void 0 ? require_errors.ok([]) : readNodeArray(j["children"], "Extension.children", defs);
4817
+ if (!children.ok) return children;
4818
+ const params = readExtensionParams(j["params"]);
4819
+ if (!params.ok) return params;
4820
+ const data = canonicalJson(j["data"] ?? null, "Extension.data");
4821
+ if (!data.ok) return bad(data.error);
4822
+ return require_errors.ok(extension(name, output, {
4823
+ children: children.value,
4824
+ params: params.value,
4825
+ data: data.value
4826
+ }));
4827
+ }
4615
4828
  function readInstance(j, defs) {
4616
4829
  const source = readNode(j["source"], defs);
4617
4830
  if (!source.ok) return source;
@@ -4718,6 +4931,7 @@ function rewriteNode(n) {
4718
4931
  case "Mirror": return optimizeTransform(n);
4719
4932
  case "Compound": return compound$1(n.children.map(optimizeNode).filter((c) => c.kind !== "Empty"));
4720
4933
  case "Instance": return instance$1(optimizeNode(n.source), n.placements, n.fuse);
4934
+ case "Extension": return optimizeExtension(n);
4721
4935
  case "Extrude":
4722
4936
  case "Revolve":
4723
4937
  case "Loft":
@@ -4747,6 +4961,13 @@ function optimizeFeature(n) {
4747
4961
  case "Shell": return shell$1(optimizeNode(n.target), n.refs, foldExpr(n.thickness));
4748
4962
  }
4749
4963
  }
4964
+ function optimizeExtension(n) {
4965
+ return extension(n.name, n.output, {
4966
+ children: n.children.map(optimizeNode),
4967
+ params: Object.fromEntries(Object.entries(n.params).map(([k, e]) => [k, foldExpr(e)])),
4968
+ data: n.data
4969
+ });
4970
+ }
4750
4971
  function optimizeTransform(n) {
4751
4972
  switch (n.kind) {
4752
4973
  case "Rotate": return rotate$1(optimizeNode(n.target), foldExpr(n.angle), {
@@ -8709,7 +8930,8 @@ var measurement_exports = /* @__PURE__ */ require_rolldown_runtime.__exportAll({
8709
8930
  measureLinearProps: () => require_measureFns.measureLinearProps,
8710
8931
  measureSurfaceProps: () => require_measureFns.measureSurfaceProps,
8711
8932
  measureVolume: () => require_measureFns.measureVolume,
8712
- measureVolumeProps: () => require_measureFns.measureVolumeProps
8933
+ measureVolumeProps: () => require_measureFns.measureVolumeProps,
8934
+ principalBoundingBox: () => require_principalBoxFns.principalBoundingBox
8713
8935
  });
8714
8936
  //#endregion
8715
8937
  //#region src/ns/ioNs.ts
@@ -8770,7 +8992,7 @@ var patterns_exports = /* @__PURE__ */ require_rolldown_runtime.__exportAll({
8770
8992
  //#endregion
8771
8993
  //#region src/ns/csg.ts
8772
8994
  var csg_exports = /* @__PURE__ */ require_rolldown_runtime.__exportAll({
8773
- CSG_VERSION: () => 8,
8995
+ CSG_VERSION: () => 9,
8774
8996
  Evaluator: () => Evaluator,
8775
8997
  add: () => add$1,
8776
8998
  arbitraryClosedProfile: () => arbitraryClosedProfile,
@@ -8802,6 +9024,7 @@ var csg_exports = /* @__PURE__ */ require_rolldown_runtime.__exportAll({
8802
9024
  emptyFace: () => emptyFace,
8803
9025
  emptySolid: () => emptySolid,
8804
9026
  emptyWire: () => emptyWire,
9027
+ extension: () => extension,
8805
9028
  extrude: () => extrude$1,
8806
9029
  fillet: () => fillet$1,
8807
9030
  foldExpr: () => foldExpr,
@@ -9317,6 +9540,7 @@ Object.defineProperty(exports, "primitives", {
9317
9540
  return primitives_exports;
9318
9541
  }
9319
9542
  });
9543
+ exports.principalBoundingBox = require_principalBoxFns.principalBoundingBox;
9320
9544
  exports.prismaticJoint = require_threadFns.prismaticJoint;
9321
9545
  exports.projectEdges = require_cameraFns.projectEdges;
9322
9546
  exports.projectPointOnFace = require_faceFns.projectPointOnFace;