brepjs 18.129.0 → 18.131.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.
package/dist/brepjs.cjs CHANGED
@@ -19,7 +19,7 @@ const require_curveFns = require("./curveFns-jmKL1KZp.cjs");
19
19
  const require_meshFns = require("./meshFns-CB7HsxzB.cjs");
20
20
  const require_arrayAccess = require("./arrayAccess-e4H9cBfh.cjs");
21
21
  const require_surfaceBuilders = require("./surfaceBuilders-DUTDN2Ay.cjs");
22
- const require_healingFns = require("./healingFns-DTr6cgTb.cjs");
22
+ const require_healingFns = require("./healingFns-BqmIvfPm.cjs");
23
23
  const require_threadFns = require("./threadFns-BQIE5dO9.cjs");
24
24
  const require_blueprintSketcher = require("./blueprintSketcher-B5UqD0FO.cjs");
25
25
  const require_helpers = require("./helpers-DLZUxawd.cjs");
@@ -32,10 +32,10 @@ const require_blueprintFns = require("./blueprintFns-oatmkSjh.cjs");
32
32
  const require_importFns = require("./importFns-ncp_0vEl.cjs");
33
33
  const require_loftFns = require("./loftFns-u-yPHpJ9.cjs");
34
34
  const require_textBlueprints = require("./textBlueprints-BMvBJ79v.cjs");
35
+ const require_refResolveFns = require("./refResolveFns-c7RWIsZy.cjs");
36
+ const require_adjacencyFns = require("./adjacencyFns-BhdfZany.cjs");
35
37
  const require_cameraFns = require("./cameraFns-i1otOZ0V.cjs");
36
38
  const require_textMetrics = require("./textMetrics-Byfb_37y.cjs");
37
- const require_adjacencyFns = require("./adjacencyFns-BhdfZany.cjs");
38
- const require_refResolveFns = require("./refResolveFns-c7RWIsZy.cjs");
39
39
  const require_workerPool = require("./workerPool-D30NsiIW.cjs");
40
40
  //#region src/kernel/types.ts
41
41
  /** Check if the kernel supports hidden-line-removal projection. */
@@ -1794,6 +1794,44 @@ function extrude$1(profile, vector) {
1794
1794
  freeParams: depsOf(profile, ve)
1795
1795
  };
1796
1796
  }
1797
+ function hashEdgeRef(h0, ref) {
1798
+ let h = fnvMixString(h0, ref.origin);
1799
+ h = fnvMixString(h, ref.faceRoles[0]);
1800
+ h = fnvMixString(h, ref.faceRoles[1]);
1801
+ const hint = ref.hint;
1802
+ h = fnvMixBool(h, hint.length !== void 0);
1803
+ if (hint.length !== void 0) h = fnvMixNumber(h, hint.length);
1804
+ h = fnvMixBool(h, hint.midpoint !== void 0);
1805
+ if (hint.midpoint) for (const c of hint.midpoint) h = fnvMixNumber(h, c);
1806
+ return h;
1807
+ }
1808
+ /** Fillet the edge named by a lineage ref on the evaluated target. The ref is
1809
+ * serializable node data (the cache key stays purely structural); it
1810
+ * resolves against the materialized target at evaluation, so an upstream
1811
+ * parameter edit re-targets the same edge by its face roles. */
1812
+ function fillet$1(target, ref, radius) {
1813
+ const copied = {
1814
+ origin: ref.origin,
1815
+ faceRoles: [ref.faceRoles[0], ref.faceRoles[1]],
1816
+ hint: {
1817
+ entityType: "edge",
1818
+ length: ref.hint.length,
1819
+ midpoint: ref.hint.midpoint ? [...ref.hint.midpoint] : void 0
1820
+ }
1821
+ };
1822
+ const re = asScalarExpr(radius);
1823
+ let h = mix(startHash("Fillet"), target);
1824
+ h = hashEdgeRef(h, copied);
1825
+ h = mix(h, re);
1826
+ return {
1827
+ kind: "Fillet",
1828
+ target,
1829
+ ref: copied,
1830
+ radius: re,
1831
+ structuralHash: h,
1832
+ freeParams: depsOf(target, re)
1833
+ };
1834
+ }
1797
1835
  /** Attach a color (hex string or RGB/RGBA tuple, canonicalized to RGBA) to
1798
1836
  * the evaluated result of `target`. Metadata rides beside the geometry: the
1799
1837
  * evaluator re-tags the shared target materialization with an independent
@@ -1945,7 +1983,8 @@ function outputKindOf(node) {
1945
1983
  case "Extrude":
1946
1984
  case "Revolve":
1947
1985
  case "Loft":
1948
- case "Sweep": return "Solid";
1986
+ case "Sweep":
1987
+ case "Fillet": return "Solid";
1949
1988
  case "Profile": return "Face";
1950
1989
  case "Path": return "Wire";
1951
1990
  case "Compound": return "Compound";
@@ -2952,6 +2991,22 @@ function evalColor(node, ctx) {
2952
2991
  return require_errors.ok(require_solidBuilders.colorShape(moved, [...node.color]));
2953
2992
  }
2954
2993
  //#endregion
2994
+ //#region src/csg/evaluators/fillet.ts
2995
+ function evalFillet(node, ctx) {
2996
+ const radius = evalScalar(node.radius, ctx.env, "Fillet.radius");
2997
+ if (!radius.ok) return radius;
2998
+ if (radius.value <= 0) return require_errors.err(require_errors.validationError("CSG_FILLET_RADIUS", `Fillet.radius must be positive, got ${radius.value}`));
2999
+ const t = ctx.evalNode(node.target);
3000
+ if (!t.ok) return t;
3001
+ if (!require_shapeTypes.isSolid(t.value)) return require_errors.err(require_errors.validationError("CSG_FILLET_TARGET", "Fillet.target did not produce a Solid"));
3002
+ const solid = require_validityTypes.validSolid(t.value);
3003
+ if (!solid.ok) return require_errors.err(require_errors.validationError("CSG_FILLET_TARGET", solid.error));
3004
+ const resolved = require_refResolveFns.resolveRefIn(node.ref, t.value);
3005
+ if (!resolved.ok) return require_errors.err(require_errors.validationError("CSG_FILLET_REF", `Fillet.ref did not resolve: ${resolved.reason}`));
3006
+ if (!require_shapeTypes.isEdge(resolved.entity)) return require_errors.err(require_errors.validationError("CSG_FILLET_REF", "Fillet.ref resolved to a non-edge"));
3007
+ return require_healingFns.fillet(solid.value, [resolved.entity], radius.value);
3008
+ }
3009
+ //#endregion
2955
3010
  //#region src/csg/evaluate.ts
2956
3011
  function dispatch(node, ctx) {
2957
3012
  switch (node.kind) {
@@ -2983,6 +3038,7 @@ function dispatch(node, ctx) {
2983
3038
  case "Sweep": return evalSweep(node, ctx);
2984
3039
  case "Profile": return evalProfile(node, ctx);
2985
3040
  case "Color": return evalColor(node, ctx);
3041
+ case "Fillet": return evalFillet(node, ctx);
2986
3042
  }
2987
3043
  }
2988
3044
  function hashExprValue(h, v) {
@@ -3392,7 +3448,7 @@ function withEvaluator(options, fn) {
3392
3448
  var MIN_CSG_VERSION = 1;
3393
3449
  function toJSON(node) {
3394
3450
  return {
3395
- csgVersion: 4,
3451
+ csgVersion: 5,
3396
3452
  root: nodeToJson(node)
3397
3453
  };
3398
3454
  }
@@ -3622,6 +3678,20 @@ function nodeToJson(n) {
3622
3678
  target: nodeToJson(n.target),
3623
3679
  color: [...n.color]
3624
3680
  };
3681
+ if (n.kind === "Fillet") return {
3682
+ kind: "Fillet",
3683
+ target: nodeToJson(n.target),
3684
+ ref: {
3685
+ origin: n.ref.origin,
3686
+ faceRoles: [...n.ref.faceRoles],
3687
+ hint: {
3688
+ entityType: "edge",
3689
+ length: n.ref.hint.length,
3690
+ midpoint: n.ref.hint.midpoint ? [...n.ref.hint.midpoint] : void 0
3691
+ }
3692
+ },
3693
+ radius: exprToJson(n.radius)
3694
+ };
3625
3695
  if (n.kind === "Compound") return {
3626
3696
  kind: "Compound",
3627
3697
  children: n.children.map(nodeToJson)
@@ -3665,7 +3735,7 @@ function readVec2(v, where) {
3665
3735
  function fromJSON(envelope) {
3666
3736
  if (!isObj(envelope)) return bad("input is not an object");
3667
3737
  const v = envelope["csgVersion"];
3668
- if (typeof v !== "number" || !Number.isInteger(v) || v < MIN_CSG_VERSION || v > 4) return bad(`unsupported csgVersion ${String(v)} (expected ${MIN_CSG_VERSION}..4)`);
3738
+ if (typeof v !== "number" || !Number.isInteger(v) || v < MIN_CSG_VERSION || v > 5) return bad(`unsupported csgVersion ${String(v)} (expected ${MIN_CSG_VERSION}..5)`);
3669
3739
  const root = envelope["root"];
3670
3740
  return readNode(root);
3671
3741
  }
@@ -3780,6 +3850,7 @@ function readNode(j) {
3780
3850
  case "Sweep": return readSweep(j);
3781
3851
  case "Profile": return readProfile(j);
3782
3852
  case "Color": return readColor(j);
3853
+ case "Fillet": return readFillet(j);
3783
3854
  default: return bad(`unknown node kind: ${String(kind)}`);
3784
3855
  }
3785
3856
  }
@@ -4029,6 +4100,37 @@ function readContour(j, where) {
4029
4100
  }
4030
4101
  return require_errors.ok(contour(start.value, segments));
4031
4102
  }
4103
+ function readFillet(j) {
4104
+ const target = readNode(j["target"]);
4105
+ if (!target.ok) return target;
4106
+ const radius = readExpr(j["radius"]);
4107
+ if (!radius.ok) return radius;
4108
+ const ref = j["ref"];
4109
+ if (!isObj(ref)) return bad("Fillet.ref: not an object");
4110
+ const origin = ref["origin"];
4111
+ if (!isString(origin)) return bad("Fillet.ref.origin: not a string");
4112
+ const roles = ref["faceRoles"];
4113
+ if (!Array.isArray(roles) || roles.length !== 2 || !roles.every(isString)) return bad("Fillet.ref.faceRoles: expected two role strings");
4114
+ const hintRaw = ref["hint"];
4115
+ if (!isObj(hintRaw)) return bad("Fillet.ref.hint: not an object");
4116
+ const length = hintRaw["length"];
4117
+ if (length !== void 0 && !isNumber$1(length)) return bad("Fillet.ref.hint.length");
4118
+ let midpoint;
4119
+ if (hintRaw["midpoint"] !== void 0) {
4120
+ const m = readVec3(hintRaw["midpoint"], "Fillet.ref.hint.midpoint");
4121
+ if (!m.ok) return m;
4122
+ midpoint = m.value;
4123
+ }
4124
+ return require_errors.ok(fillet$1(target.value, {
4125
+ origin,
4126
+ faceRoles: [roles[0], roles[1]],
4127
+ hint: {
4128
+ entityType: "edge",
4129
+ length,
4130
+ midpoint
4131
+ }
4132
+ }, radius.value));
4133
+ }
4032
4134
  function readColor(j) {
4033
4135
  const target = readNode(j["target"]);
4034
4136
  if (!target.ok) return target;
@@ -4176,15 +4278,9 @@ function optimizeNode(n) {
4176
4278
  case "FuseAll": return optimizeFuseAll(n.shapes, n.tolerance);
4177
4279
  case "CutAll": return optimizeCutAll(n.base, n.tools, n.tolerance);
4178
4280
  case "Translate": return optimizeTranslate(n.target, n.vector);
4179
- case "Rotate": return rotate$1(optimizeNode(n.target), foldExpr(n.angle), {
4180
- axis: n.axis ? foldExpr(n.axis) : void 0,
4181
- at: n.at ? foldExpr(n.at) : void 0
4182
- });
4183
- case "Scale": return scale$2(optimizeNode(n.target), foldExpr(n.factor), { center: n.center ? foldExpr(n.center) : void 0 });
4184
- case "Mirror": return mirror$1(optimizeNode(n.target), {
4185
- normal: n.normal ? foldExpr(n.normal) : void 0,
4186
- at: n.at ? foldExpr(n.at) : void 0
4187
- });
4281
+ case "Rotate":
4282
+ case "Scale":
4283
+ case "Mirror": return optimizeTransform(n);
4188
4284
  case "Compound": return compound$1(n.children.map(optimizeNode).filter((c) => c.kind !== "Empty"));
4189
4285
  case "Instance": return instance$1(optimizeNode(n.source), n.placements, n.fuse);
4190
4286
  case "Extrude":
@@ -4193,7 +4289,8 @@ function optimizeNode(n) {
4193
4289
  case "Sweep":
4194
4290
  case "Profile":
4195
4291
  case "Path":
4196
- case "Color": return optimizeFeature(n);
4292
+ case "Color":
4293
+ case "Fillet": return optimizeFeature(n);
4197
4294
  }
4198
4295
  }
4199
4296
  function optimizeFeature(n) {
@@ -4208,6 +4305,20 @@ function optimizeFeature(n) {
4208
4305
  case "Profile": return profile(foldContour(n.outline, foldExpr), n.holes.map((hole) => foldContour(hole, foldExpr)));
4209
4306
  case "Path": return path(foldExpr(n.start), n.segments.map((s) => foldSegment(s, foldExpr)));
4210
4307
  case "Color": return color(optimizeNode(n.target), [...n.color]);
4308
+ case "Fillet": return fillet$1(optimizeNode(n.target), n.ref, foldExpr(n.radius));
4309
+ }
4310
+ }
4311
+ function optimizeTransform(n) {
4312
+ switch (n.kind) {
4313
+ case "Rotate": return rotate$1(optimizeNode(n.target), foldExpr(n.angle), {
4314
+ axis: n.axis ? foldExpr(n.axis) : void 0,
4315
+ at: n.at ? foldExpr(n.at) : void 0
4316
+ });
4317
+ case "Scale": return scale$2(optimizeNode(n.target), foldExpr(n.factor), { center: n.center ? foldExpr(n.center) : void 0 });
4318
+ case "Mirror": return mirror$1(optimizeNode(n.target), {
4319
+ normal: n.normal ? foldExpr(n.normal) : void 0,
4320
+ at: n.at ? foldExpr(n.at) : void 0
4321
+ });
4211
4322
  }
4212
4323
  }
4213
4324
  function optimizeFuse(a, b, tol) {
@@ -4300,6 +4411,16 @@ function rebuildChildren(n, pred, repl) {
4300
4411
  });
4301
4412
  case "Compound": return compound$1(n.children.map((c) => walk(c, pred, repl)));
4302
4413
  case "Instance": return instance$1(walk(n.source, pred, repl), n.placements, n.fuse);
4414
+ case "Extrude":
4415
+ case "Revolve":
4416
+ case "Loft":
4417
+ case "Sweep":
4418
+ case "Color":
4419
+ case "Fillet": return rebuildFeature(n, pred, repl);
4420
+ }
4421
+ }
4422
+ function rebuildFeature(n, pred, repl) {
4423
+ switch (n.kind) {
4303
4424
  case "Extrude": return extrude$1(walk(n.profile, pred, repl), n.vector);
4304
4425
  case "Revolve": return revolve$1(walk(n.profile, pred, repl), n.angle, {
4305
4426
  axis: n.axis,
@@ -4308,6 +4429,7 @@ function rebuildChildren(n, pred, repl) {
4308
4429
  case "Loft": return loft$1(n.sections.map((s) => walk(s, pred, repl)), { ruled: n.ruled });
4309
4430
  case "Sweep": return sweep$2(walk(n.profile, pred, repl), walk(n.spine, pred, repl), { frenet: n.frenet });
4310
4431
  case "Color": return color(walk(n.target, pred, repl), [...n.color]);
4432
+ case "Fillet": return fillet$1(walk(n.target, pred, repl), n.ref, n.radius);
4311
4433
  }
4312
4434
  }
4313
4435
  function forEachNode(root, fn) {
@@ -4337,7 +4459,8 @@ function childrenOf(n) {
4337
4459
  case "Rotate":
4338
4460
  case "Scale":
4339
4461
  case "Mirror":
4340
- case "Color": return [n.target];
4462
+ case "Color":
4463
+ case "Fillet": return [n.target];
4341
4464
  case "Compound": return n.children;
4342
4465
  case "Instance": return [n.source];
4343
4466
  case "Extrude":
@@ -8348,7 +8471,7 @@ var patterns_exports = /* @__PURE__ */ require_rolldown_runtime.__exportAll({
8348
8471
  //#endregion
8349
8472
  //#region src/ns/csg.ts
8350
8473
  var csg_exports = /* @__PURE__ */ require_rolldown_runtime.__exportAll({
8351
- CSG_VERSION: () => 4,
8474
+ CSG_VERSION: () => 5,
8352
8475
  Evaluator: () => Evaluator,
8353
8476
  add: () => add$1,
8354
8477
  arbitraryClosedProfile: () => arbitraryClosedProfile,
@@ -8380,6 +8503,7 @@ var csg_exports = /* @__PURE__ */ require_rolldown_runtime.__exportAll({
8380
8503
  emptySolid: () => emptySolid,
8381
8504
  emptyWire: () => emptyWire,
8382
8505
  extrude: () => extrude$1,
8506
+ fillet: () => fillet$1,
8383
8507
  foldExpr: () => foldExpr,
8384
8508
  forEachNode: () => forEachNode,
8385
8509
  fromJSON: () => fromJSON,
package/dist/brepjs.js CHANGED
@@ -17,7 +17,7 @@ import { a as curveIsPeriodic, c as curvePointAt, d as flipOrientation, f as get
17
17
  import { a as meshEdges$1, c as meshMultiLOD, d as createMeshCache, i as mesh$1, l as buildMeshCacheKey, n as exportSTEP, o as meshLODs, r as exportSTL, s as meshLODsProgressive, t as exportIGES, u as clearMeshCache } from "./meshFns-CpfeEN1b.js";
18
18
  import { n as getAtOrThrow, r as lastOrThrow, t as firstOrThrow } from "./arrayAccess-DrUGPADn.js";
19
19
  import { _ as makeThreePointArc, d as makeCircle, h as makeLine, l as makeBSplineInterpolation, n as fill, p as makeEllipseArc, r as makeFace, s as assembleWire, u as makeBezierCurve } from "./surfaceBuilders-B7WlmoVr.js";
20
- import { A as toBufferGeometryData, C as shellWithEvolution, D as getNurbsCurveData, E as fuseAllBisect, M as toLODGeometryData, N as toLODGeometryLevels, O as getNurbsSurfaceData, P as toLineGeometryData, S as intersectWithEvolution, T as cutAllBisect, _ as positionOnCurve, a as healFace, b as filletWithEvolution, c as isValid$1, d as draft$1, f as fillet$1, g as variableFillet, h as thicken$1, i as heal$1, j as toGroupedBufferGeometryData, k as chamferDistAngle, l as solidFromShell, m as shell$1, n as fixSelfIntersection, o as healSolid, p as offset$1, r as fixShape, s as healWire, t as autoHeal, u as chamfer$1, v as chamferWithEvolution, w as checkBoolean, x as fuseWithEvolution, y as cutWithEvolution } from "./healingFns-BptGY1Th.js";
20
+ import { A as toBufferGeometryData, C as chamfer$1, D as shell$1, E as offset$1, M as toLODGeometryData, N as toLODGeometryLevels, O as thicken$1, P as toLineGeometryData, S as chamferDistAngle, T as fillet$2, _ as checkBoolean, a as healFace, b as getNurbsCurveData, c as isValid$1, d as chamferWithEvolution, f as cutWithEvolution, g as shellWithEvolution, h as intersectWithEvolution, i as heal$1, j as toGroupedBufferGeometryData, k as variableFillet, l as solidFromShell, m as fuseWithEvolution, n as fixSelfIntersection, o as healSolid, p as filletWithEvolution, r as fixShape, s as healWire, t as autoHeal, u as positionOnCurve, v as cutAllBisect, w as draft$1, x as getNurbsSurfaceData, y as fuseAllBisect } from "./healingFns-BrrTpxjI.js";
21
21
  import { A as setJointValue, B as walkAssembly, C as cylindricalJoint, D as planarJoint, E as mechanismDOF, F as countNodes, G as quatFromAxisAngle, H as circularPattern, I as createAssemblyNode, J as quatRotate, K as quatFromTo, L as findNode, M as sphericalJoint, N as addChild, O as prismaticJoint, P as collectShapes, R as removeChild, S as addJoint, T as jointTransform, U as gridPattern, V as exportAssemblySTEP, W as linearPattern, Y as createAssembly, _ as exportURDF, a as deserializeHistory, b as inverseKinematics, c as modifyStep, d as replayFrom, f as replayHistory, g as undoLast, h as stepsFrom, i as createRegistry, j as setJointValues, k as revoluteJoint, l as registerOperation, m as stepCount, n as addStep, o as findStep, p as serializeHistory, q as quatMultiply, r as createHistory, s as getShape, t as thread, u as registerShape, v as importURDF, w as forwardKinematics, x as jointTrajectory, y as jointsFromDH, z as updateNode } from "./threadFns-B6-3UeCZ.js";
22
22
  import { n as BaseSketcher2d, r as organiseBlueprints, t as BlueprintSketcher } from "./blueprintSketcher-yZiAeqft.js";
23
23
  import { a as createTypedFinder, i as wireFinder, n as edgeFinder, r as faceFinder, t as getSingleFace } from "./helpers-BiqV-wPK.js";
@@ -30,10 +30,10 @@ import { S as reverseCurve, _ as curve2dIsOnCurve, a as isInside2D, b as curve2d
30
30
  import { a as importSVG, c as blueprintToDXF, d as exportGltf, f as exportOBJ, i as exportSTEPConfigured, l as exportDXF, n as importSTEP, o as importSVGPathD, r as importSTL, s as exportThreeMF, t as importIGES, u as exportGlb } from "./importFns-BId6d2pt.js";
31
31
  import { a as multiSectionSweep, c as twistExtrude, i as guidedSweep, n as loftAll, o as supportExtrude, r as complexExtrude, s as sweep$1, t as loft$2 } from "./loftFns-m7LoJWE2.js";
32
32
  import { a as Sketch, b as extrudeAll, c as compoundSketchLoft, d as sketchFace, f as sketchLoft, h as sketchWires, i as Sketches, l as compoundSketchRevolve, m as sketchSweep, n as getFont, o as compoundSketchExtrude, p as sketchRevolve, r as loadFont, s as compoundSketchFace, t as textBlueprints, u as sketchExtrude, v as CompoundSketch, x as revolve$2, y as extrude$2 } from "./textBlueprints-myJW6Fzl.js";
33
+ import { _ as createRef, a as isVertexRef, b as defaultScorer, c as resolveRefParams, d as createVertexRef, f as resolveVertexRef, g as captureHint, h as assignRoles, i as isLineageRef, l as createDerivedFaceRef, m as resolveEdgeRef, n as isEdgeRef, o as resolveLineageRef, p as createEdgeRef, r as isFaceRef, s as resolveRefIn, t as isDerivedFaceRef, u as resolveDerivedFaceRef, v as resolveRef, y as updateRoles } from "./refResolveFns-DcyIQSDi.js";
34
+ import { a as facesOfVertex, c as verticesOfFace, i as facesOfEdge, l as wiresOfFace, n as adjacentFaces, o as sharedEdges, r as edgesOfFace, s as verticesOfEdge } from "./adjacencyFns-CwcdjOsT.js";
33
35
  import { a as makeProjectedEdges, i as projectEdges, n as cameraLookAt, r as createCamera, s as isProjectionPlane, t as cameraFromPlane } from "./cameraFns-VVI0cWLa.js";
34
36
  import { n as textMetrics, r as sketchText, t as fontMetrics } from "./textMetrics-CPFqh2a1.js";
35
- import { a as facesOfVertex, c as verticesOfFace, i as facesOfEdge, l as wiresOfFace, n as adjacentFaces, o as sharedEdges, r as edgesOfFace, s as verticesOfEdge } from "./adjacencyFns-CwcdjOsT.js";
36
- import { _ as createRef, a as isVertexRef, b as defaultScorer, c as resolveRefParams, d as createVertexRef, f as resolveVertexRef, g as captureHint, h as assignRoles, i as isLineageRef, l as createDerivedFaceRef, m as resolveEdgeRef, n as isEdgeRef, o as resolveLineageRef, p as createEdgeRef, r as isFaceRef, s as resolveRefIn, t as isDerivedFaceRef, u as resolveDerivedFaceRef, v as resolveRef, y as updateRoles } from "./refResolveFns-DcyIQSDi.js";
37
37
  import { _ as isSuccessResponse, a as createWorkerClient, c as enqueueTask, d as rejectAll, f as isBatchRequest, g as isOperationRequest, h as isInitRequest, i as registerHandler, l as isEmpty$1, m as isErrorResponse, n as createOperationRegistry, o as createTaskQueue, p as isDisposeRequest, r as createWorkerHandler, s as dequeueTask, t as createWorkerPool, u as pendingCount } from "./workerPool-XcYX2UZ0.js";
38
38
  //#region \0rolldown/runtime.js
39
39
  var __defProp = Object.defineProperty;
@@ -1804,6 +1804,44 @@ function extrude$1(profile, vector) {
1804
1804
  freeParams: depsOf(profile, ve)
1805
1805
  };
1806
1806
  }
1807
+ function hashEdgeRef(h0, ref) {
1808
+ let h = fnvMixString(h0, ref.origin);
1809
+ h = fnvMixString(h, ref.faceRoles[0]);
1810
+ h = fnvMixString(h, ref.faceRoles[1]);
1811
+ const hint = ref.hint;
1812
+ h = fnvMixBool(h, hint.length !== void 0);
1813
+ if (hint.length !== void 0) h = fnvMixNumber(h, hint.length);
1814
+ h = fnvMixBool(h, hint.midpoint !== void 0);
1815
+ if (hint.midpoint) for (const c of hint.midpoint) h = fnvMixNumber(h, c);
1816
+ return h;
1817
+ }
1818
+ /** Fillet the edge named by a lineage ref on the evaluated target. The ref is
1819
+ * serializable node data (the cache key stays purely structural); it
1820
+ * resolves against the materialized target at evaluation, so an upstream
1821
+ * parameter edit re-targets the same edge by its face roles. */
1822
+ function fillet$1(target, ref, radius) {
1823
+ const copied = {
1824
+ origin: ref.origin,
1825
+ faceRoles: [ref.faceRoles[0], ref.faceRoles[1]],
1826
+ hint: {
1827
+ entityType: "edge",
1828
+ length: ref.hint.length,
1829
+ midpoint: ref.hint.midpoint ? [...ref.hint.midpoint] : void 0
1830
+ }
1831
+ };
1832
+ const re = asScalarExpr(radius);
1833
+ let h = mix(startHash("Fillet"), target);
1834
+ h = hashEdgeRef(h, copied);
1835
+ h = mix(h, re);
1836
+ return {
1837
+ kind: "Fillet",
1838
+ target,
1839
+ ref: copied,
1840
+ radius: re,
1841
+ structuralHash: h,
1842
+ freeParams: depsOf(target, re)
1843
+ };
1844
+ }
1807
1845
  /** Attach a color (hex string or RGB/RGBA tuple, canonicalized to RGBA) to
1808
1846
  * the evaluated result of `target`. Metadata rides beside the geometry: the
1809
1847
  * evaluator re-tags the shared target materialization with an independent
@@ -1955,7 +1993,8 @@ function outputKindOf(node) {
1955
1993
  case "Extrude":
1956
1994
  case "Revolve":
1957
1995
  case "Loft":
1958
- case "Sweep": return "Solid";
1996
+ case "Sweep":
1997
+ case "Fillet": return "Solid";
1959
1998
  case "Profile": return "Face";
1960
1999
  case "Path": return "Wire";
1961
2000
  case "Compound": return "Compound";
@@ -2962,6 +3001,22 @@ function evalColor(node, ctx) {
2962
3001
  return ok(colorShape(moved, [...node.color]));
2963
3002
  }
2964
3003
  //#endregion
3004
+ //#region src/csg/evaluators/fillet.ts
3005
+ function evalFillet(node, ctx) {
3006
+ const radius = evalScalar(node.radius, ctx.env, "Fillet.radius");
3007
+ if (!radius.ok) return radius;
3008
+ if (radius.value <= 0) return err(validationError("CSG_FILLET_RADIUS", `Fillet.radius must be positive, got ${radius.value}`));
3009
+ const t = ctx.evalNode(node.target);
3010
+ if (!t.ok) return t;
3011
+ if (!isSolid(t.value)) return err(validationError("CSG_FILLET_TARGET", "Fillet.target did not produce a Solid"));
3012
+ const solid = validSolid(t.value);
3013
+ if (!solid.ok) return err(validationError("CSG_FILLET_TARGET", solid.error));
3014
+ const resolved = resolveRefIn(node.ref, t.value);
3015
+ if (!resolved.ok) return err(validationError("CSG_FILLET_REF", `Fillet.ref did not resolve: ${resolved.reason}`));
3016
+ if (!isEdge(resolved.entity)) return err(validationError("CSG_FILLET_REF", "Fillet.ref resolved to a non-edge"));
3017
+ return fillet$2(solid.value, [resolved.entity], radius.value);
3018
+ }
3019
+ //#endregion
2965
3020
  //#region src/csg/evaluate.ts
2966
3021
  function dispatch(node, ctx) {
2967
3022
  switch (node.kind) {
@@ -2993,6 +3048,7 @@ function dispatch(node, ctx) {
2993
3048
  case "Sweep": return evalSweep(node, ctx);
2994
3049
  case "Profile": return evalProfile(node, ctx);
2995
3050
  case "Color": return evalColor(node, ctx);
3051
+ case "Fillet": return evalFillet(node, ctx);
2996
3052
  }
2997
3053
  }
2998
3054
  function hashExprValue(h, v) {
@@ -3402,7 +3458,7 @@ function withEvaluator(options, fn) {
3402
3458
  var MIN_CSG_VERSION = 1;
3403
3459
  function toJSON(node) {
3404
3460
  return {
3405
- csgVersion: 4,
3461
+ csgVersion: 5,
3406
3462
  root: nodeToJson(node)
3407
3463
  };
3408
3464
  }
@@ -3632,6 +3688,20 @@ function nodeToJson(n) {
3632
3688
  target: nodeToJson(n.target),
3633
3689
  color: [...n.color]
3634
3690
  };
3691
+ if (n.kind === "Fillet") return {
3692
+ kind: "Fillet",
3693
+ target: nodeToJson(n.target),
3694
+ ref: {
3695
+ origin: n.ref.origin,
3696
+ faceRoles: [...n.ref.faceRoles],
3697
+ hint: {
3698
+ entityType: "edge",
3699
+ length: n.ref.hint.length,
3700
+ midpoint: n.ref.hint.midpoint ? [...n.ref.hint.midpoint] : void 0
3701
+ }
3702
+ },
3703
+ radius: exprToJson(n.radius)
3704
+ };
3635
3705
  if (n.kind === "Compound") return {
3636
3706
  kind: "Compound",
3637
3707
  children: n.children.map(nodeToJson)
@@ -3675,7 +3745,7 @@ function readVec2(v, where) {
3675
3745
  function fromJSON(envelope) {
3676
3746
  if (!isObj(envelope)) return bad("input is not an object");
3677
3747
  const v = envelope["csgVersion"];
3678
- if (typeof v !== "number" || !Number.isInteger(v) || v < MIN_CSG_VERSION || v > 4) return bad(`unsupported csgVersion ${String(v)} (expected ${MIN_CSG_VERSION}..4)`);
3748
+ if (typeof v !== "number" || !Number.isInteger(v) || v < MIN_CSG_VERSION || v > 5) return bad(`unsupported csgVersion ${String(v)} (expected ${MIN_CSG_VERSION}..5)`);
3679
3749
  const root = envelope["root"];
3680
3750
  return readNode(root);
3681
3751
  }
@@ -3790,6 +3860,7 @@ function readNode(j) {
3790
3860
  case "Sweep": return readSweep(j);
3791
3861
  case "Profile": return readProfile(j);
3792
3862
  case "Color": return readColor(j);
3863
+ case "Fillet": return readFillet(j);
3793
3864
  default: return bad(`unknown node kind: ${String(kind)}`);
3794
3865
  }
3795
3866
  }
@@ -4039,6 +4110,37 @@ function readContour(j, where) {
4039
4110
  }
4040
4111
  return ok(contour(start.value, segments));
4041
4112
  }
4113
+ function readFillet(j) {
4114
+ const target = readNode(j["target"]);
4115
+ if (!target.ok) return target;
4116
+ const radius = readExpr(j["radius"]);
4117
+ if (!radius.ok) return radius;
4118
+ const ref = j["ref"];
4119
+ if (!isObj(ref)) return bad("Fillet.ref: not an object");
4120
+ const origin = ref["origin"];
4121
+ if (!isString(origin)) return bad("Fillet.ref.origin: not a string");
4122
+ const roles = ref["faceRoles"];
4123
+ if (!Array.isArray(roles) || roles.length !== 2 || !roles.every(isString)) return bad("Fillet.ref.faceRoles: expected two role strings");
4124
+ const hintRaw = ref["hint"];
4125
+ if (!isObj(hintRaw)) return bad("Fillet.ref.hint: not an object");
4126
+ const length = hintRaw["length"];
4127
+ if (length !== void 0 && !isNumber$1(length)) return bad("Fillet.ref.hint.length");
4128
+ let midpoint;
4129
+ if (hintRaw["midpoint"] !== void 0) {
4130
+ const m = readVec3(hintRaw["midpoint"], "Fillet.ref.hint.midpoint");
4131
+ if (!m.ok) return m;
4132
+ midpoint = m.value;
4133
+ }
4134
+ return ok(fillet$1(target.value, {
4135
+ origin,
4136
+ faceRoles: [roles[0], roles[1]],
4137
+ hint: {
4138
+ entityType: "edge",
4139
+ length,
4140
+ midpoint
4141
+ }
4142
+ }, radius.value));
4143
+ }
4042
4144
  function readColor(j) {
4043
4145
  const target = readNode(j["target"]);
4044
4146
  if (!target.ok) return target;
@@ -4186,15 +4288,9 @@ function optimizeNode(n) {
4186
4288
  case "FuseAll": return optimizeFuseAll(n.shapes, n.tolerance);
4187
4289
  case "CutAll": return optimizeCutAll(n.base, n.tools, n.tolerance);
4188
4290
  case "Translate": return optimizeTranslate(n.target, n.vector);
4189
- case "Rotate": return rotate$1(optimizeNode(n.target), foldExpr(n.angle), {
4190
- axis: n.axis ? foldExpr(n.axis) : void 0,
4191
- at: n.at ? foldExpr(n.at) : void 0
4192
- });
4193
- case "Scale": return scale$2(optimizeNode(n.target), foldExpr(n.factor), { center: n.center ? foldExpr(n.center) : void 0 });
4194
- case "Mirror": return mirror$1(optimizeNode(n.target), {
4195
- normal: n.normal ? foldExpr(n.normal) : void 0,
4196
- at: n.at ? foldExpr(n.at) : void 0
4197
- });
4291
+ case "Rotate":
4292
+ case "Scale":
4293
+ case "Mirror": return optimizeTransform(n);
4198
4294
  case "Compound": return compound$1(n.children.map(optimizeNode).filter((c) => c.kind !== "Empty"));
4199
4295
  case "Instance": return instance$1(optimizeNode(n.source), n.placements, n.fuse);
4200
4296
  case "Extrude":
@@ -4203,7 +4299,8 @@ function optimizeNode(n) {
4203
4299
  case "Sweep":
4204
4300
  case "Profile":
4205
4301
  case "Path":
4206
- case "Color": return optimizeFeature(n);
4302
+ case "Color":
4303
+ case "Fillet": return optimizeFeature(n);
4207
4304
  }
4208
4305
  }
4209
4306
  function optimizeFeature(n) {
@@ -4218,6 +4315,20 @@ function optimizeFeature(n) {
4218
4315
  case "Profile": return profile(foldContour(n.outline, foldExpr), n.holes.map((hole) => foldContour(hole, foldExpr)));
4219
4316
  case "Path": return path(foldExpr(n.start), n.segments.map((s) => foldSegment(s, foldExpr)));
4220
4317
  case "Color": return color(optimizeNode(n.target), [...n.color]);
4318
+ case "Fillet": return fillet$1(optimizeNode(n.target), n.ref, foldExpr(n.radius));
4319
+ }
4320
+ }
4321
+ function optimizeTransform(n) {
4322
+ switch (n.kind) {
4323
+ case "Rotate": return rotate$1(optimizeNode(n.target), foldExpr(n.angle), {
4324
+ axis: n.axis ? foldExpr(n.axis) : void 0,
4325
+ at: n.at ? foldExpr(n.at) : void 0
4326
+ });
4327
+ case "Scale": return scale$2(optimizeNode(n.target), foldExpr(n.factor), { center: n.center ? foldExpr(n.center) : void 0 });
4328
+ case "Mirror": return mirror$1(optimizeNode(n.target), {
4329
+ normal: n.normal ? foldExpr(n.normal) : void 0,
4330
+ at: n.at ? foldExpr(n.at) : void 0
4331
+ });
4221
4332
  }
4222
4333
  }
4223
4334
  function optimizeFuse(a, b, tol) {
@@ -4310,6 +4421,16 @@ function rebuildChildren(n, pred, repl) {
4310
4421
  });
4311
4422
  case "Compound": return compound$1(n.children.map((c) => walk(c, pred, repl)));
4312
4423
  case "Instance": return instance$1(walk(n.source, pred, repl), n.placements, n.fuse);
4424
+ case "Extrude":
4425
+ case "Revolve":
4426
+ case "Loft":
4427
+ case "Sweep":
4428
+ case "Color":
4429
+ case "Fillet": return rebuildFeature(n, pred, repl);
4430
+ }
4431
+ }
4432
+ function rebuildFeature(n, pred, repl) {
4433
+ switch (n.kind) {
4313
4434
  case "Extrude": return extrude$1(walk(n.profile, pred, repl), n.vector);
4314
4435
  case "Revolve": return revolve$1(walk(n.profile, pred, repl), n.angle, {
4315
4436
  axis: n.axis,
@@ -4318,6 +4439,7 @@ function rebuildChildren(n, pred, repl) {
4318
4439
  case "Loft": return loft$1(n.sections.map((s) => walk(s, pred, repl)), { ruled: n.ruled });
4319
4440
  case "Sweep": return sweep$2(walk(n.profile, pred, repl), walk(n.spine, pred, repl), { frenet: n.frenet });
4320
4441
  case "Color": return color(walk(n.target, pred, repl), [...n.color]);
4442
+ case "Fillet": return fillet$1(walk(n.target, pred, repl), n.ref, n.radius);
4321
4443
  }
4322
4444
  }
4323
4445
  function forEachNode(root, fn) {
@@ -4347,7 +4469,8 @@ function childrenOf(n) {
4347
4469
  case "Rotate":
4348
4470
  case "Scale":
4349
4471
  case "Mirror":
4350
- case "Color": return [n.target];
4472
+ case "Color":
4473
+ case "Fillet": return [n.target];
4351
4474
  case "Compound": return n.children;
4352
4475
  case "Instance": return [n.source];
4353
4476
  case "Extrude":
@@ -6934,7 +7057,7 @@ function fillet(shape, edgesOrRadius, maybeRadius) {
6934
7057
  edges = void 0;
6935
7058
  radius = edgesOrRadius;
6936
7059
  }
6937
- return fillet$1(s, edges, radius);
7060
+ return fillet$2(s, edges, radius);
6938
7061
  }
6939
7062
  function chamfer(shape, edgesOrDistance, maybeDistance) {
6940
7063
  const s = resolve(shape);
@@ -8357,7 +8480,7 @@ var patterns_exports = /* @__PURE__ */ __exportAll({
8357
8480
  //#endregion
8358
8481
  //#region src/ns/csg.ts
8359
8482
  var csg_exports = /* @__PURE__ */ __exportAll({
8360
- CSG_VERSION: () => 4,
8483
+ CSG_VERSION: () => 5,
8361
8484
  Evaluator: () => Evaluator,
8362
8485
  add: () => add$1,
8363
8486
  arbitraryClosedProfile: () => arbitraryClosedProfile,
@@ -8389,6 +8512,7 @@ var csg_exports = /* @__PURE__ */ __exportAll({
8389
8512
  emptySolid: () => emptySolid,
8390
8513
  emptyWire: () => emptyWire,
8391
8514
  extrude: () => extrude$1,
8515
+ fillet: () => fillet$1,
8392
8516
  foldExpr: () => foldExpr,
8393
8517
  forEachNode: () => forEachNode,
8394
8518
  fromJSON: () => fromJSON,
@@ -2,7 +2,8 @@ import { ScalarInput, Vec2Input, Vec3Input } from './expressions.js';
2
2
  import { Contour, Segment2D } from './segments.js';
3
3
  import { Matrix4x4 } from '../core/types.js';
4
4
  import { ColorInput } from '../topology/metadata/colorFns.js';
5
- import { BoxNode, SphereNode, CylinderNode, ConeNode, TorusNode, PolygonNode, CircleNode, LineNode, VertexLitNode, EmptyNode, FuseNode, CutNode, IntersectNode, FuseAllNode, CutAllNode, TranslateNode, RotateNode, ScaleNode, MirrorNode, ExtrudeNode, RevolveNode, LoftNode, SweepNode, ProfileNode, PathNode, ColorNode, CompoundNode, InstanceNode, IRNode, SolidNode, FaceNode, EdgeNode, VertexNode } from './types.js';
5
+ import { EdgeRef } from '../topology/shapeRef/shapeRefTypes.js';
6
+ import { BoxNode, SphereNode, CylinderNode, ConeNode, TorusNode, PolygonNode, CircleNode, LineNode, VertexLitNode, EmptyNode, FuseNode, CutNode, IntersectNode, FuseAllNode, CutAllNode, TranslateNode, RotateNode, ScaleNode, MirrorNode, ExtrudeNode, RevolveNode, LoftNode, SweepNode, ProfileNode, PathNode, ColorNode, FilletNode, CompoundNode, InstanceNode, IRNode, SolidNode, FaceNode, EdgeNode, VertexNode } from './types.js';
6
7
  export declare function box(x: ScalarInput, y: ScalarInput, z: ScalarInput): BoxNode;
7
8
  export declare function sphere(radius: ScalarInput): SphereNode;
8
9
  export declare function cylinder(radius: ScalarInput, height: ScalarInput): CylinderNode;
@@ -36,6 +37,11 @@ export interface MirrorOptions {
36
37
  }
37
38
  export declare function mirror(target: IRNode, options?: MirrorOptions): MirrorNode;
38
39
  export declare function extrude(profile: FaceNode, vector: Vec3Input): ExtrudeNode;
40
+ /** Fillet the edge named by a lineage ref on the evaluated target. The ref is
41
+ * serializable node data (the cache key stays purely structural); it
42
+ * resolves against the materialized target at evaluation, so an upstream
43
+ * parameter edit re-targets the same edge by its face roles. */
44
+ export declare function fillet(target: IRNode, ref: EdgeRef, radius: ScalarInput): FilletNode;
39
45
  /** Attach a color (hex string or RGB/RGBA tuple, canonicalized to RGBA) to
40
46
  * the evaluated result of `target`. Metadata rides beside the geometry: the
41
47
  * evaluator re-tags the shared target materialization with an independent
@@ -0,0 +1,5 @@
1
+ import { Result } from '../../core/result.js';
2
+ import { AnyShape, Dimension } from '../../core/shapeTypes.js';
3
+ import { FilletNode } from '../types.js';
4
+ import { EvalContext } from './context.js';
5
+ export declare function evalFillet(node: FilletNode, ctx: EvalContext): Result<AnyShape<Dimension>>;
@@ -5,9 +5,9 @@
5
5
  * parameterize via named expression bindings; evaluate against the active
6
6
  * kernel with subtree-level cache reuse for incremental parametric edits.
7
7
  */
8
- export { box, sphere, cylinder, cone, torus, polygon, circle, line, vertex, emptySolid, emptyFace, emptyWire, fuse, cut, intersect, fuseAll, cutAll, translate, rotate, scale, mirror, extrude, revolve, loft, sweep, profile, path, color, compound, instance, type RevolveOptions, type LoftOptions, type SweepNodeOptions, type RotateOptions, type ScaleOptions, type MirrorOptions, } from './builders.js';
8
+ export { box, sphere, cylinder, cone, torus, polygon, circle, line, vertex, emptySolid, emptyFace, emptyWire, fuse, cut, intersect, fuseAll, cutAll, translate, rotate, scale, mirror, extrude, revolve, loft, sweep, profile, path, color, fillet, compound, instance, type RevolveOptions, type LoftOptions, type SweepNodeOptions, type RotateOptions, type ScaleOptions, type MirrorOptions, } from './builders.js';
9
9
  export { numLit, vec3Lit, vec2Lit, param, binOp, unaryOp, component, buildVec, add, mul, asScalarExpr, asVec3Expr, asVec2Expr, type Expr, type ExprValue, type Env, type ScalarInput, type Vec3Input, type Vec2Input, type BinaryOp, type UnaryOp, } from './expressions.js';
10
- export type { IRNode, NodeKind, OutputKind, PrimitiveNode, BooleanNode, TransformIRNode, ExtrudeNode, RevolveNode, LoftNode, SweepNode, ProfileNode, PathNode, ColorNode, InstanceNode, SolidNode, FaceNode, EdgeNode, VertexNode, AnyNode, } from './types.js';
10
+ export type { IRNode, NodeKind, OutputKind, PrimitiveNode, BooleanNode, TransformIRNode, ExtrudeNode, RevolveNode, LoftNode, SweepNode, ProfileNode, PathNode, ColorNode, FilletNode, InstanceNode, SolidNode, FaceNode, EdgeNode, VertexNode, AnyNode, } from './types.js';
11
11
  export { outputKindOf } from './types.js';
12
12
  export { lineTo, arcTo, bezierTo, ellipseArcTo, contour, type Contour, type Segment2D, type SegmentOptions, type EllipseArcOptions, } from './segments.js';
13
13
  export { rectangularProfile, circularProfile, iBeamProfile, asymmetricIProfile, lShapeProfile, tShapeProfile, uShapeProfile, zShapeProfile, cShapeProfile, ellipseProfile, trapeziumProfile, rectangleHollowProfile, circleHollowProfile, arbitraryClosedProfile, arbitraryProfileWithVoids, type IBeamParams, type AsymmetricIParams, type LShapeParams, type TShapeParams, type UShapeParams, type ZShapeParams, type CShapeParams, type TrapeziumParams, type RectangleHollowParams, type CircleHollowParams, } from './profiles.js';
@@ -1,6 +1,6 @@
1
1
  import { Result } from '../core/result.js';
2
2
  import { IRNode } from './types.js';
3
- export declare const CSG_VERSION = 4;
3
+ export declare const CSG_VERSION = 5;
4
4
  export interface CsgEnvelope {
5
5
  readonly csgVersion: number;
6
6
  readonly root: unknown;