brepjs 18.126.0 → 18.127.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
@@ -254,8 +254,8 @@ function repairMesh(mesh, opts, id) {
254
254
  if (require_errors.isErr(engine)) return engine;
255
255
  try {
256
256
  try {
257
- var _usingCtx$10 = require_shapeTypes._usingCtx();
258
- const repaired = _usingCtx$10.u(engine.value.repair_mesh(mesh.vertices, mesh.triangles, resolution, padding));
257
+ var _usingCtx$11 = require_shapeTypes._usingCtx();
258
+ const repaired = _usingCtx$11.u(engine.value.repair_mesh(mesh.vertices, mesh.triangles, resolution, padding));
259
259
  const vertexCount = repaired.positions.length / 3;
260
260
  return require_errors.ok({
261
261
  vertices: repaired.positions,
@@ -269,9 +269,9 @@ function repairMesh(mesh, opts, id) {
269
269
  }]
270
270
  });
271
271
  } catch (_) {
272
- _usingCtx$10.e = _;
272
+ _usingCtx$11.e = _;
273
273
  } finally {
274
- _usingCtx$10.d();
274
+ _usingCtx$11.d();
275
275
  }
276
276
  } catch (cause) {
277
277
  return require_errors.err(require_errors.computationError("VOXEL_REPAIR_FAILED", cause instanceof Error ? cause.message : "voxel repair failed (grid too large?).", cause));
@@ -350,12 +350,12 @@ function offsetMesh(mesh, distance, opts, id) {
350
350
  if (require_errors.isErr(engine)) return engine;
351
351
  try {
352
352
  try {
353
- var _usingCtx$9 = require_shapeTypes._usingCtx();
354
- return meshFromResult(_usingCtx$9.u(engine.value.offset_mesh(mesh.vertices, mesh.triangles, distance, params.value.resolution, params.value.padding)));
353
+ var _usingCtx$10 = require_shapeTypes._usingCtx();
354
+ return meshFromResult(_usingCtx$10.u(engine.value.offset_mesh(mesh.vertices, mesh.triangles, distance, params.value.resolution, params.value.padding)));
355
355
  } catch (_) {
356
- _usingCtx$9.e = _;
356
+ _usingCtx$10.e = _;
357
357
  } finally {
358
- _usingCtx$9.d();
358
+ _usingCtx$10.d();
359
359
  }
360
360
  } catch (cause) {
361
361
  return require_errors.err(require_errors.computationError("VOXEL_OFFSET_FAILED", cause instanceof Error ? cause.message : "voxel offset failed (grid too large?).", cause));
@@ -480,9 +480,9 @@ function resolveGridParams$1(opts) {
480
480
  */
481
481
  function meshFromField(field) {
482
482
  try {
483
- var _usingCtx$8 = require_shapeTypes._usingCtx();
483
+ var _usingCtx$9 = require_shapeTypes._usingCtx();
484
484
  const rawResult = field.contour();
485
- const { positions, normals, indices } = _usingCtx$8.u({
485
+ const { positions, normals, indices } = _usingCtx$9.u({
486
486
  value: rawResult,
487
487
  [Symbol.dispose]() {
488
488
  rawResult.free();
@@ -502,9 +502,9 @@ function meshFromField(field) {
502
502
  }]
503
503
  });
504
504
  } catch (_) {
505
- _usingCtx$8.e = _;
505
+ _usingCtx$9.e = _;
506
506
  } finally {
507
- _usingCtx$8.d();
507
+ _usingCtx$9.d();
508
508
  }
509
509
  }
510
510
  function fieldDeletable(raw) {
@@ -1072,13 +1072,13 @@ function latticeInfill(mesh, opts, id) {
1072
1072
  const { tag, period, thickness, resolution, padding } = resolved.value;
1073
1073
  try {
1074
1074
  try {
1075
- var _usingCtx$7 = require_shapeTypes._usingCtx();
1076
- const repaired = _usingCtx$7.u(engine.value.lattice_infill(mesh.vertices, mesh.triangles, resolution, padding, tag, period, thickness));
1075
+ var _usingCtx$8 = require_shapeTypes._usingCtx();
1076
+ const repaired = _usingCtx$8.u(engine.value.lattice_infill(mesh.vertices, mesh.triangles, resolution, padding, tag, period, thickness));
1077
1077
  return require_errors.ok(toMesh(repaired));
1078
1078
  } catch (_) {
1079
- _usingCtx$7.e = _;
1079
+ _usingCtx$8.e = _;
1080
1080
  } finally {
1081
- _usingCtx$7.d();
1081
+ _usingCtx$8.d();
1082
1082
  }
1083
1083
  } catch (cause) {
1084
1084
  return require_errors.err(require_errors.computationError("LATTICE_INFILL_FAILED", cause instanceof Error ? cause.message : "lattice infill failed (grid too large?).", cause));
@@ -3901,7 +3901,7 @@ function drill(shape, options) {
3901
3901
  */
3902
3902
  function pocket(shape, options) {
3903
3903
  try {
3904
- var _usingCtx$6 = require_shapeTypes._usingCtx();
3904
+ var _usingCtx$7 = require_shapeTypes._usingCtx();
3905
3905
  const s = resolve(shape);
3906
3906
  const { profile, depth } = options;
3907
3907
  if (depth <= 0) return require_errors.err(require_errors.validationError("POCKET_INVALID_DEPTH", "Pocket depth must be positive"));
@@ -3910,7 +3910,7 @@ function pocket(shape, options) {
3910
3910
  const targetFace = targetResult.value;
3911
3911
  const normal = require_faceFns.normalAt(targetFace);
3912
3912
  const center = require_faceFns.faceCenter(targetFace);
3913
- const scope = _usingCtx$6.u(new require_shapeTypes.DisposalScope());
3913
+ const scope = _usingCtx$7.u(new require_shapeTypes.DisposalScope());
3914
3914
  const { wire: w, owned } = toWire(profile);
3915
3915
  if (owned) scope.register(w);
3916
3916
  const faceResult = require_surfaceBuilders.makeFace(w);
@@ -3923,9 +3923,9 @@ function pocket(shape, options) {
3923
3923
  scope.register(toolResult.value);
3924
3924
  return require_solidBuilders.cut(s, toolResult.value, { unsafe: true });
3925
3925
  } catch (_) {
3926
- _usingCtx$6.e = _;
3926
+ _usingCtx$7.e = _;
3927
3927
  } finally {
3928
- _usingCtx$6.d();
3928
+ _usingCtx$7.d();
3929
3929
  }
3930
3930
  }
3931
3931
  /**
@@ -4515,12 +4515,12 @@ function makeInternalGearProfileWire(params) {
4515
4515
  }
4516
4516
  function makeProfileWire(params, isInternal) {
4517
4517
  try {
4518
- var _usingCtx$5 = require_shapeTypes._usingCtx();
4518
+ var _usingCtx$6 = require_shapeTypes._usingCtx();
4519
4519
  const { teeth, moduleSize, pressureAngle, shift, clearance, flankThinning, samples = adaptiveSampleCount(moduleSize) } = params;
4520
4520
  if (teeth < 4) return require_errors.err(require_errors.validationError("GEAR_TEETH_TOO_FEW", `gear needs ≥ 4 teeth, got ${teeth}`));
4521
4521
  if (moduleSize <= 0) return require_errors.err(require_errors.validationError("GEAR_MODULE_NONPOSITIVE", `module must be > 0, got ${moduleSize}`));
4522
4522
  const tm = gearGeometry(teeth, moduleSize, pressureAngle, shift, clearance, flankThinning, isInternal);
4523
- const scope = _usingCtx$5.u(new require_shapeTypes.DisposalScope());
4523
+ const scope = _usingCtx$6.u(new require_shapeTypes.DisposalScope());
4524
4524
  const allEdges = [];
4525
4525
  for (let i = 0; i < teeth; i++) {
4526
4526
  const periodEdges = buildToothPeriodEdges(tm, i, teeth, samples, scope);
@@ -4531,9 +4531,9 @@ function makeProfileWire(params, isInternal) {
4531
4531
  if (require_errors.isErr(wireResult)) return wireResult;
4532
4532
  return require_errors.ok(wireResult.value);
4533
4533
  } catch (_) {
4534
- _usingCtx$5.e = _;
4534
+ _usingCtx$6.e = _;
4535
4535
  } finally {
4536
- _usingCtx$5.d();
4536
+ _usingCtx$6.d();
4537
4537
  }
4538
4538
  }
4539
4539
  //#endregion
@@ -4714,8 +4714,8 @@ function resolvePlanetaryParams(params) {
4714
4714
  }
4715
4715
  function makeOuterCircleWire(radius) {
4716
4716
  try {
4717
- var _usingCtx$4 = require_shapeTypes._usingCtx();
4718
- const circleEdge = _usingCtx$4.u(new require_shapeTypes.DisposalScope()).register(require_surfaceBuilders.makeCircle(radius, [
4717
+ var _usingCtx$5 = require_shapeTypes._usingCtx();
4718
+ const circleEdge = _usingCtx$5.u(new require_shapeTypes.DisposalScope()).register(require_surfaceBuilders.makeCircle(radius, [
4719
4719
  0,
4720
4720
  0,
4721
4721
  0
@@ -4728,9 +4728,9 @@ function makeOuterCircleWire(radius) {
4728
4728
  if (require_errors.isErr(wireResult)) return wireResult;
4729
4729
  return require_errors.ok(wireResult.value);
4730
4730
  } catch (_) {
4731
- _usingCtx$4.e = _;
4731
+ _usingCtx$5.e = _;
4732
4732
  } finally {
4733
- _usingCtx$4.d();
4733
+ _usingCtx$5.d();
4734
4734
  }
4735
4735
  }
4736
4736
  function finalizeExternalSolid(wire, thickness, bore, geom, diagnostics) {
@@ -5702,6 +5702,22 @@ function extrude$1(profile, vector) {
5702
5702
  freeParams: depsOf(profile, ve)
5703
5703
  };
5704
5704
  }
5705
+ /** Sweep a face-producing profile along a Wire/Edge-producing spine.
5706
+ * `frenet` is canonicalized (default false) so the default and explicit
5707
+ * forms share one content address. */
5708
+ function sweep$2(profile, spine, options) {
5709
+ const frenet = options?.frenet ?? false;
5710
+ let h = mix(mix(startHash("Sweep"), profile), spine);
5711
+ h = fnvMixBool(h, frenet);
5712
+ return {
5713
+ kind: "Sweep",
5714
+ profile,
5715
+ spine,
5716
+ frenet,
5717
+ structuralHash: h,
5718
+ freeParams: depsOf(profile, spine)
5719
+ };
5720
+ }
5705
5721
  /** Open (or incidentally closed) planar path in the XY plane at z = 0,
5706
5722
  * producing a Wire. Segments come from `lineTo`/`arcTo`/`bezierTo`/
5707
5723
  * `ellipseArcTo`. */
@@ -5802,7 +5818,8 @@ function outputKindOf(node) {
5802
5818
  case "Mirror": return outputKindOf(node.target);
5803
5819
  case "Extrude":
5804
5820
  case "Revolve":
5805
- case "Loft": return "Solid";
5821
+ case "Loft":
5822
+ case "Sweep": return "Solid";
5806
5823
  case "Path": return "Wire";
5807
5824
  case "Compound": return "Compound";
5808
5825
  case "Instance": return node.fuse ? "Solid" : "Compound";
@@ -6131,9 +6148,9 @@ function evalRevolve(node, ctx) {
6131
6148
  //#region src/csg/evaluators/loft.ts
6132
6149
  function evalLoft(node, ctx) {
6133
6150
  try {
6134
- var _usingCtx$3 = require_shapeTypes._usingCtx();
6151
+ var _usingCtx$4 = require_shapeTypes._usingCtx();
6135
6152
  if (node.sections.length < 2) return require_errors.err(require_errors.validationError("CSG_LOFT_SECTIONS", `Loft requires at least 2 sections, got ${node.sections.length}`));
6136
- const scope = _usingCtx$3.u(new require_shapeTypes.DisposalScope());
6153
+ const scope = _usingCtx$4.u(new require_shapeTypes.DisposalScope());
6137
6154
  const wires = [];
6138
6155
  for (const [i, section] of node.sections.entries()) {
6139
6156
  const face = resolveProfileFace(ctx, section, `Loft.sections[${i}]`);
@@ -6144,9 +6161,9 @@ function evalLoft(node, ctx) {
6144
6161
  }
6145
6162
  return require_loftFns.loft(wires, { ruled: node.ruled });
6146
6163
  } catch (_) {
6147
- _usingCtx$3.e = _;
6164
+ _usingCtx$4.e = _;
6148
6165
  } finally {
6149
- _usingCtx$3.d();
6166
+ _usingCtx$4.d();
6150
6167
  }
6151
6168
  }
6152
6169
  //#endregion
@@ -6257,14 +6274,14 @@ function ellipseEdge(from, seg, ctx) {
6257
6274
  if (!arc.ok) return arc;
6258
6275
  let edge = arc.value;
6259
6276
  if (Math.abs(psi) > EPS) try {
6260
- var _usingCtx$2 = require_shapeTypes._usingCtx();
6261
- const rotated = rotateEdgeAbout(_usingCtx$2.u(edge), psi * 180 / Math.PI, center);
6277
+ var _usingCtx$3 = require_shapeTypes._usingCtx();
6278
+ const rotated = rotateEdgeAbout(_usingCtx$3.u(edge), psi * 180 / Math.PI, center);
6262
6279
  if (!rotated.ok) return rotated;
6263
6280
  edge = rotated.value;
6264
6281
  } catch (_) {
6265
- _usingCtx$2.e = _;
6282
+ _usingCtx$3.e = _;
6266
6283
  } finally {
6267
- _usingCtx$2.d();
6284
+ _usingCtx$3.d();
6268
6285
  }
6269
6286
  if (seg.clockwise) try {
6270
6287
  var _usingCtx3 = require_shapeTypes._usingCtx();
@@ -6368,6 +6385,39 @@ function evalPath(node, ctx) {
6368
6385
  }
6369
6386
  }
6370
6387
  //#endregion
6388
+ //#region src/csg/evaluators/sweep.ts
6389
+ function evalSweep(node, ctx) {
6390
+ try {
6391
+ var _usingCtx$2 = require_shapeTypes._usingCtx();
6392
+ const face = resolveProfileFace(ctx, node.profile, "Sweep.profile");
6393
+ if (!face.ok) return face;
6394
+ const spineShape = ctx.evalNode(node.spine);
6395
+ if (!spineShape.ok) return spineShape;
6396
+ const scope = _usingCtx$2.u(new require_shapeTypes.DisposalScope());
6397
+ let spine;
6398
+ if (require_shapeTypes.isWire(spineShape.value)) spine = spineShape.value;
6399
+ else if (require_shapeTypes.isEdge(spineShape.value)) {
6400
+ const wrapped = require_surfaceBuilders.assembleWire([spineShape.value]);
6401
+ if (!wrapped.ok) return wrapped;
6402
+ scope.register(wrapped.value);
6403
+ spine = wrapped.value;
6404
+ } else return require_errors.err(require_errors.typeCastError("CSG_SWEEP_SPINE", "Sweep.spine: node did not produce a Wire or Edge"));
6405
+ const profileWire = require_faceFns.outerWire(face.value);
6406
+ scope.register(profileWire);
6407
+ const r = require_loftFns.sweep(profileWire, spine, { frenet: node.frenet });
6408
+ if (!r.ok) return r;
6409
+ if (Array.isArray(r.value)) {
6410
+ for (const s of r.value) s[Symbol.dispose]();
6411
+ return require_errors.err(require_errors.typeCastError("CSG_SWEEP_SPINE", "Sweep: unexpected shell-mode result"));
6412
+ }
6413
+ return require_errors.ok(r.value);
6414
+ } catch (_) {
6415
+ _usingCtx$2.e = _;
6416
+ } finally {
6417
+ _usingCtx$2.d();
6418
+ }
6419
+ }
6420
+ //#endregion
6371
6421
  //#region src/csg/evaluate.ts
6372
6422
  function dispatch(node, ctx) {
6373
6423
  switch (node.kind) {
@@ -6396,6 +6446,7 @@ function dispatch(node, ctx) {
6396
6446
  case "Revolve": return evalRevolve(node, ctx);
6397
6447
  case "Loft": return evalLoft(node, ctx);
6398
6448
  case "Path": return evalPath(node, ctx);
6449
+ case "Sweep": return evalSweep(node, ctx);
6399
6450
  }
6400
6451
  }
6401
6452
  function hashExprValue(h, v) {
@@ -6802,9 +6853,10 @@ function withEvaluator(options, fn) {
6802
6853
  _usingCtx$1.d();
6803
6854
  }
6804
6855
  }
6856
+ var MIN_CSG_VERSION = 1;
6805
6857
  function toJSON(node) {
6806
6858
  return {
6807
- csgVersion: 1,
6859
+ csgVersion: 2,
6808
6860
  root: nodeToJson(node)
6809
6861
  };
6810
6862
  }
@@ -7012,6 +7064,12 @@ function nodeToJson(n) {
7012
7064
  start: exprToJson(n.start),
7013
7065
  segments: n.segments.map(segmentToJson)
7014
7066
  };
7067
+ if (n.kind === "Sweep") return {
7068
+ kind: "Sweep",
7069
+ profile: nodeToJson(n.profile),
7070
+ spine: nodeToJson(n.spine),
7071
+ frenet: n.frenet
7072
+ };
7015
7073
  if (n.kind === "Compound") return {
7016
7074
  kind: "Compound",
7017
7075
  children: n.children.map(nodeToJson)
@@ -7055,7 +7113,7 @@ function readVec2(v, where) {
7055
7113
  function fromJSON(envelope) {
7056
7114
  if (!isObj(envelope)) return bad("input is not an object");
7057
7115
  const v = envelope["csgVersion"];
7058
- if (v !== 1) return bad(`unsupported csgVersion ${String(v)} (expected 1)`);
7116
+ if (typeof v !== "number" || !Number.isInteger(v) || v < MIN_CSG_VERSION || v > 2) return bad(`unsupported csgVersion ${String(v)} (expected ${MIN_CSG_VERSION}..2)`);
7059
7117
  const root = envelope["root"];
7060
7118
  return readNode(root);
7061
7119
  }
@@ -7167,6 +7225,7 @@ function readNode(j) {
7167
7225
  case "Revolve": return readRevolve(j);
7168
7226
  case "Loft": return readLoft(j);
7169
7227
  case "Path": return readPath(j);
7228
+ case "Sweep": return readSweep(j);
7170
7229
  default: return bad(`unknown node kind: ${String(kind)}`);
7171
7230
  }
7172
7231
  }
@@ -7402,6 +7461,15 @@ function readSegment(j) {
7402
7461
  default: return bad(`unknown segment kind: ${String(kind)}`);
7403
7462
  }
7404
7463
  }
7464
+ function readSweep(j) {
7465
+ const profile = readNode(j["profile"]);
7466
+ if (!profile.ok) return profile;
7467
+ const spine = readNode(j["spine"]);
7468
+ if (!spine.ok) return spine;
7469
+ const frenet = readFlag(j, "frenet");
7470
+ if (!frenet.ok) return frenet;
7471
+ return require_errors.ok(sweep$2(profile.value, spine.value, { frenet: frenet.value }));
7472
+ }
7405
7473
  function readPath(j) {
7406
7474
  const start = readExpr(j["start"]);
7407
7475
  if (!start.ok) return start;
@@ -7529,6 +7597,7 @@ function optimizeNode(n) {
7529
7597
  case "Extrude":
7530
7598
  case "Revolve":
7531
7599
  case "Loft":
7600
+ case "Sweep":
7532
7601
  case "Path": return optimizeFeature(n);
7533
7602
  }
7534
7603
  }
@@ -7540,6 +7609,7 @@ function optimizeFeature(n) {
7540
7609
  at: n.at ? foldExpr(n.at) : void 0
7541
7610
  });
7542
7611
  case "Loft": return loft$1(n.sections.map(optimizeNode), { ruled: n.ruled });
7612
+ case "Sweep": return sweep$2(optimizeNode(n.profile), optimizeNode(n.spine), { frenet: n.frenet });
7543
7613
  case "Path": return path(foldExpr(n.start), n.segments.map((s) => foldSegment(s, foldExpr)));
7544
7614
  }
7545
7615
  }
@@ -7638,6 +7708,7 @@ function rebuildChildren(n, pred, repl) {
7638
7708
  at: n.at
7639
7709
  });
7640
7710
  case "Loft": return loft$1(n.sections.map((s) => walk(s, pred, repl)), { ruled: n.ruled });
7711
+ case "Sweep": return sweep$2(walk(n.profile, pred, repl), walk(n.spine, pred, repl), { frenet: n.frenet });
7641
7712
  }
7642
7713
  }
7643
7714
  function forEachNode(root, fn) {
@@ -7671,6 +7742,7 @@ function childrenOf(n) {
7671
7742
  case "Extrude":
7672
7743
  case "Revolve": return [n.profile];
7673
7744
  case "Loft": return n.sections;
7745
+ case "Sweep": return [n.profile, n.spine];
7674
7746
  }
7675
7747
  }
7676
7748
  function nodeCount(root) {
@@ -7683,7 +7755,7 @@ function nodeCount(root) {
7683
7755
  //#endregion
7684
7756
  //#region src/ns/csg.ts
7685
7757
  var csg_exports = /* @__PURE__ */ require_rolldown_runtime.__exportAll({
7686
- CSG_VERSION: () => 1,
7758
+ CSG_VERSION: () => 2,
7687
7759
  Evaluator: () => Evaluator,
7688
7760
  add: () => add,
7689
7761
  arcTo: () => arcTo,
@@ -7730,6 +7802,7 @@ var csg_exports = /* @__PURE__ */ require_rolldown_runtime.__exportAll({
7730
7802
  rotate: () => rotate$1,
7731
7803
  scale: () => scale$1,
7732
7804
  sphere: () => sphere$2,
7805
+ sweep: () => sweep$2,
7733
7806
  toJSON: () => toJSON,
7734
7807
  torus: () => torus$2,
7735
7808
  translate: () => translate$1,
package/dist/brepjs.js CHANGED
@@ -264,8 +264,8 @@ function repairMesh(mesh, opts, id) {
264
264
  if (isErr(engine)) return engine;
265
265
  try {
266
266
  try {
267
- var _usingCtx$10 = _usingCtx();
268
- const repaired = _usingCtx$10.u(engine.value.repair_mesh(mesh.vertices, mesh.triangles, resolution, padding));
267
+ var _usingCtx$11 = _usingCtx();
268
+ const repaired = _usingCtx$11.u(engine.value.repair_mesh(mesh.vertices, mesh.triangles, resolution, padding));
269
269
  const vertexCount = repaired.positions.length / 3;
270
270
  return ok({
271
271
  vertices: repaired.positions,
@@ -279,9 +279,9 @@ function repairMesh(mesh, opts, id) {
279
279
  }]
280
280
  });
281
281
  } catch (_) {
282
- _usingCtx$10.e = _;
282
+ _usingCtx$11.e = _;
283
283
  } finally {
284
- _usingCtx$10.d();
284
+ _usingCtx$11.d();
285
285
  }
286
286
  } catch (cause) {
287
287
  return err(computationError("VOXEL_REPAIR_FAILED", cause instanceof Error ? cause.message : "voxel repair failed (grid too large?).", cause));
@@ -360,12 +360,12 @@ function offsetMesh(mesh, distance, opts, id) {
360
360
  if (isErr(engine)) return engine;
361
361
  try {
362
362
  try {
363
- var _usingCtx$9 = _usingCtx();
364
- return meshFromResult(_usingCtx$9.u(engine.value.offset_mesh(mesh.vertices, mesh.triangles, distance, params.value.resolution, params.value.padding)));
363
+ var _usingCtx$10 = _usingCtx();
364
+ return meshFromResult(_usingCtx$10.u(engine.value.offset_mesh(mesh.vertices, mesh.triangles, distance, params.value.resolution, params.value.padding)));
365
365
  } catch (_) {
366
- _usingCtx$9.e = _;
366
+ _usingCtx$10.e = _;
367
367
  } finally {
368
- _usingCtx$9.d();
368
+ _usingCtx$10.d();
369
369
  }
370
370
  } catch (cause) {
371
371
  return err(computationError("VOXEL_OFFSET_FAILED", cause instanceof Error ? cause.message : "voxel offset failed (grid too large?).", cause));
@@ -490,9 +490,9 @@ function resolveGridParams$1(opts) {
490
490
  */
491
491
  function meshFromField(field) {
492
492
  try {
493
- var _usingCtx$8 = _usingCtx();
493
+ var _usingCtx$9 = _usingCtx();
494
494
  const rawResult = field.contour();
495
- const { positions, normals, indices } = _usingCtx$8.u({
495
+ const { positions, normals, indices } = _usingCtx$9.u({
496
496
  value: rawResult,
497
497
  [Symbol.dispose]() {
498
498
  rawResult.free();
@@ -512,9 +512,9 @@ function meshFromField(field) {
512
512
  }]
513
513
  });
514
514
  } catch (_) {
515
- _usingCtx$8.e = _;
515
+ _usingCtx$9.e = _;
516
516
  } finally {
517
- _usingCtx$8.d();
517
+ _usingCtx$9.d();
518
518
  }
519
519
  }
520
520
  function fieldDeletable(raw) {
@@ -1082,13 +1082,13 @@ function latticeInfill(mesh, opts, id) {
1082
1082
  const { tag, period, thickness, resolution, padding } = resolved.value;
1083
1083
  try {
1084
1084
  try {
1085
- var _usingCtx$7 = _usingCtx();
1086
- const repaired = _usingCtx$7.u(engine.value.lattice_infill(mesh.vertices, mesh.triangles, resolution, padding, tag, period, thickness));
1085
+ var _usingCtx$8 = _usingCtx();
1086
+ const repaired = _usingCtx$8.u(engine.value.lattice_infill(mesh.vertices, mesh.triangles, resolution, padding, tag, period, thickness));
1087
1087
  return ok(toMesh(repaired));
1088
1088
  } catch (_) {
1089
- _usingCtx$7.e = _;
1089
+ _usingCtx$8.e = _;
1090
1090
  } finally {
1091
- _usingCtx$7.d();
1091
+ _usingCtx$8.d();
1092
1092
  }
1093
1093
  } catch (cause) {
1094
1094
  return err(computationError("LATTICE_INFILL_FAILED", cause instanceof Error ? cause.message : "lattice infill failed (grid too large?).", cause));
@@ -3910,7 +3910,7 @@ function drill(shape, options) {
3910
3910
  */
3911
3911
  function pocket(shape, options) {
3912
3912
  try {
3913
- var _usingCtx$6 = _usingCtx();
3913
+ var _usingCtx$7 = _usingCtx();
3914
3914
  const s = resolve(shape);
3915
3915
  const { profile, depth } = options;
3916
3916
  if (depth <= 0) return err(validationError("POCKET_INVALID_DEPTH", "Pocket depth must be positive"));
@@ -3919,7 +3919,7 @@ function pocket(shape, options) {
3919
3919
  const targetFace = targetResult.value;
3920
3920
  const normal = normalAt(targetFace);
3921
3921
  const center = faceCenter(targetFace);
3922
- const scope = _usingCtx$6.u(new DisposalScope());
3922
+ const scope = _usingCtx$7.u(new DisposalScope());
3923
3923
  const { wire: w, owned } = toWire(profile);
3924
3924
  if (owned) scope.register(w);
3925
3925
  const faceResult = makeFace(w);
@@ -3932,9 +3932,9 @@ function pocket(shape, options) {
3932
3932
  scope.register(toolResult.value);
3933
3933
  return cut$2(s, toolResult.value, { unsafe: true });
3934
3934
  } catch (_) {
3935
- _usingCtx$6.e = _;
3935
+ _usingCtx$7.e = _;
3936
3936
  } finally {
3937
- _usingCtx$6.d();
3937
+ _usingCtx$7.d();
3938
3938
  }
3939
3939
  }
3940
3940
  /**
@@ -4524,12 +4524,12 @@ function makeInternalGearProfileWire(params) {
4524
4524
  }
4525
4525
  function makeProfileWire(params, isInternal) {
4526
4526
  try {
4527
- var _usingCtx$5 = _usingCtx();
4527
+ var _usingCtx$6 = _usingCtx();
4528
4528
  const { teeth, moduleSize, pressureAngle, shift, clearance, flankThinning, samples = adaptiveSampleCount(moduleSize) } = params;
4529
4529
  if (teeth < 4) return err(validationError("GEAR_TEETH_TOO_FEW", `gear needs ≥ 4 teeth, got ${teeth}`));
4530
4530
  if (moduleSize <= 0) return err(validationError("GEAR_MODULE_NONPOSITIVE", `module must be > 0, got ${moduleSize}`));
4531
4531
  const tm = gearGeometry(teeth, moduleSize, pressureAngle, shift, clearance, flankThinning, isInternal);
4532
- const scope = _usingCtx$5.u(new DisposalScope());
4532
+ const scope = _usingCtx$6.u(new DisposalScope());
4533
4533
  const allEdges = [];
4534
4534
  for (let i = 0; i < teeth; i++) {
4535
4535
  const periodEdges = buildToothPeriodEdges(tm, i, teeth, samples, scope);
@@ -4540,9 +4540,9 @@ function makeProfileWire(params, isInternal) {
4540
4540
  if (isErr(wireResult)) return wireResult;
4541
4541
  return ok(wireResult.value);
4542
4542
  } catch (_) {
4543
- _usingCtx$5.e = _;
4543
+ _usingCtx$6.e = _;
4544
4544
  } finally {
4545
- _usingCtx$5.d();
4545
+ _usingCtx$6.d();
4546
4546
  }
4547
4547
  }
4548
4548
  //#endregion
@@ -4723,8 +4723,8 @@ function resolvePlanetaryParams(params) {
4723
4723
  }
4724
4724
  function makeOuterCircleWire(radius) {
4725
4725
  try {
4726
- var _usingCtx$4 = _usingCtx();
4727
- const circleEdge = _usingCtx$4.u(new DisposalScope()).register(makeCircle(radius, [
4726
+ var _usingCtx$5 = _usingCtx();
4727
+ const circleEdge = _usingCtx$5.u(new DisposalScope()).register(makeCircle(radius, [
4728
4728
  0,
4729
4729
  0,
4730
4730
  0
@@ -4737,9 +4737,9 @@ function makeOuterCircleWire(radius) {
4737
4737
  if (isErr(wireResult)) return wireResult;
4738
4738
  return ok(wireResult.value);
4739
4739
  } catch (_) {
4740
- _usingCtx$4.e = _;
4740
+ _usingCtx$5.e = _;
4741
4741
  } finally {
4742
- _usingCtx$4.d();
4742
+ _usingCtx$5.d();
4743
4743
  }
4744
4744
  }
4745
4745
  function finalizeExternalSolid(wire, thickness, bore, geom, diagnostics) {
@@ -5711,6 +5711,22 @@ function extrude$1(profile, vector) {
5711
5711
  freeParams: depsOf(profile, ve)
5712
5712
  };
5713
5713
  }
5714
+ /** Sweep a face-producing profile along a Wire/Edge-producing spine.
5715
+ * `frenet` is canonicalized (default false) so the default and explicit
5716
+ * forms share one content address. */
5717
+ function sweep$2(profile, spine, options) {
5718
+ const frenet = options?.frenet ?? false;
5719
+ let h = mix(mix(startHash("Sweep"), profile), spine);
5720
+ h = fnvMixBool(h, frenet);
5721
+ return {
5722
+ kind: "Sweep",
5723
+ profile,
5724
+ spine,
5725
+ frenet,
5726
+ structuralHash: h,
5727
+ freeParams: depsOf(profile, spine)
5728
+ };
5729
+ }
5714
5730
  /** Open (or incidentally closed) planar path in the XY plane at z = 0,
5715
5731
  * producing a Wire. Segments come from `lineTo`/`arcTo`/`bezierTo`/
5716
5732
  * `ellipseArcTo`. */
@@ -5811,7 +5827,8 @@ function outputKindOf(node) {
5811
5827
  case "Mirror": return outputKindOf(node.target);
5812
5828
  case "Extrude":
5813
5829
  case "Revolve":
5814
- case "Loft": return "Solid";
5830
+ case "Loft":
5831
+ case "Sweep": return "Solid";
5815
5832
  case "Path": return "Wire";
5816
5833
  case "Compound": return "Compound";
5817
5834
  case "Instance": return node.fuse ? "Solid" : "Compound";
@@ -6140,9 +6157,9 @@ function evalRevolve(node, ctx) {
6140
6157
  //#region src/csg/evaluators/loft.ts
6141
6158
  function evalLoft(node, ctx) {
6142
6159
  try {
6143
- var _usingCtx$3 = _usingCtx();
6160
+ var _usingCtx$4 = _usingCtx();
6144
6161
  if (node.sections.length < 2) return err(validationError("CSG_LOFT_SECTIONS", `Loft requires at least 2 sections, got ${node.sections.length}`));
6145
- const scope = _usingCtx$3.u(new DisposalScope());
6162
+ const scope = _usingCtx$4.u(new DisposalScope());
6146
6163
  const wires = [];
6147
6164
  for (const [i, section] of node.sections.entries()) {
6148
6165
  const face = resolveProfileFace(ctx, section, `Loft.sections[${i}]`);
@@ -6153,9 +6170,9 @@ function evalLoft(node, ctx) {
6153
6170
  }
6154
6171
  return loft$2(wires, { ruled: node.ruled });
6155
6172
  } catch (_) {
6156
- _usingCtx$3.e = _;
6173
+ _usingCtx$4.e = _;
6157
6174
  } finally {
6158
- _usingCtx$3.d();
6175
+ _usingCtx$4.d();
6159
6176
  }
6160
6177
  }
6161
6178
  //#endregion
@@ -6266,14 +6283,14 @@ function ellipseEdge(from, seg, ctx) {
6266
6283
  if (!arc.ok) return arc;
6267
6284
  let edge = arc.value;
6268
6285
  if (Math.abs(psi) > EPS) try {
6269
- var _usingCtx$2 = _usingCtx();
6270
- const rotated = rotateEdgeAbout(_usingCtx$2.u(edge), psi * 180 / Math.PI, center);
6286
+ var _usingCtx$3 = _usingCtx();
6287
+ const rotated = rotateEdgeAbout(_usingCtx$3.u(edge), psi * 180 / Math.PI, center);
6271
6288
  if (!rotated.ok) return rotated;
6272
6289
  edge = rotated.value;
6273
6290
  } catch (_) {
6274
- _usingCtx$2.e = _;
6291
+ _usingCtx$3.e = _;
6275
6292
  } finally {
6276
- _usingCtx$2.d();
6293
+ _usingCtx$3.d();
6277
6294
  }
6278
6295
  if (seg.clockwise) try {
6279
6296
  var _usingCtx3 = _usingCtx();
@@ -6377,6 +6394,39 @@ function evalPath(node, ctx) {
6377
6394
  }
6378
6395
  }
6379
6396
  //#endregion
6397
+ //#region src/csg/evaluators/sweep.ts
6398
+ function evalSweep(node, ctx) {
6399
+ try {
6400
+ var _usingCtx$2 = _usingCtx();
6401
+ const face = resolveProfileFace(ctx, node.profile, "Sweep.profile");
6402
+ if (!face.ok) return face;
6403
+ const spineShape = ctx.evalNode(node.spine);
6404
+ if (!spineShape.ok) return spineShape;
6405
+ const scope = _usingCtx$2.u(new DisposalScope());
6406
+ let spine;
6407
+ if (isWire(spineShape.value)) spine = spineShape.value;
6408
+ else if (isEdge(spineShape.value)) {
6409
+ const wrapped = assembleWire([spineShape.value]);
6410
+ if (!wrapped.ok) return wrapped;
6411
+ scope.register(wrapped.value);
6412
+ spine = wrapped.value;
6413
+ } else return err(typeCastError("CSG_SWEEP_SPINE", "Sweep.spine: node did not produce a Wire or Edge"));
6414
+ const profileWire = outerWire(face.value);
6415
+ scope.register(profileWire);
6416
+ const r = sweep$1(profileWire, spine, { frenet: node.frenet });
6417
+ if (!r.ok) return r;
6418
+ if (Array.isArray(r.value)) {
6419
+ for (const s of r.value) s[Symbol.dispose]();
6420
+ return err(typeCastError("CSG_SWEEP_SPINE", "Sweep: unexpected shell-mode result"));
6421
+ }
6422
+ return ok(r.value);
6423
+ } catch (_) {
6424
+ _usingCtx$2.e = _;
6425
+ } finally {
6426
+ _usingCtx$2.d();
6427
+ }
6428
+ }
6429
+ //#endregion
6380
6430
  //#region src/csg/evaluate.ts
6381
6431
  function dispatch(node, ctx) {
6382
6432
  switch (node.kind) {
@@ -6405,6 +6455,7 @@ function dispatch(node, ctx) {
6405
6455
  case "Revolve": return evalRevolve(node, ctx);
6406
6456
  case "Loft": return evalLoft(node, ctx);
6407
6457
  case "Path": return evalPath(node, ctx);
6458
+ case "Sweep": return evalSweep(node, ctx);
6408
6459
  }
6409
6460
  }
6410
6461
  function hashExprValue(h, v) {
@@ -6811,9 +6862,10 @@ function withEvaluator(options, fn) {
6811
6862
  _usingCtx$1.d();
6812
6863
  }
6813
6864
  }
6865
+ var MIN_CSG_VERSION = 1;
6814
6866
  function toJSON(node) {
6815
6867
  return {
6816
- csgVersion: 1,
6868
+ csgVersion: 2,
6817
6869
  root: nodeToJson(node)
6818
6870
  };
6819
6871
  }
@@ -7021,6 +7073,12 @@ function nodeToJson(n) {
7021
7073
  start: exprToJson(n.start),
7022
7074
  segments: n.segments.map(segmentToJson)
7023
7075
  };
7076
+ if (n.kind === "Sweep") return {
7077
+ kind: "Sweep",
7078
+ profile: nodeToJson(n.profile),
7079
+ spine: nodeToJson(n.spine),
7080
+ frenet: n.frenet
7081
+ };
7024
7082
  if (n.kind === "Compound") return {
7025
7083
  kind: "Compound",
7026
7084
  children: n.children.map(nodeToJson)
@@ -7064,7 +7122,7 @@ function readVec2(v, where) {
7064
7122
  function fromJSON(envelope) {
7065
7123
  if (!isObj(envelope)) return bad("input is not an object");
7066
7124
  const v = envelope["csgVersion"];
7067
- if (v !== 1) return bad(`unsupported csgVersion ${String(v)} (expected 1)`);
7125
+ if (typeof v !== "number" || !Number.isInteger(v) || v < MIN_CSG_VERSION || v > 2) return bad(`unsupported csgVersion ${String(v)} (expected ${MIN_CSG_VERSION}..2)`);
7068
7126
  const root = envelope["root"];
7069
7127
  return readNode(root);
7070
7128
  }
@@ -7176,6 +7234,7 @@ function readNode(j) {
7176
7234
  case "Revolve": return readRevolve(j);
7177
7235
  case "Loft": return readLoft(j);
7178
7236
  case "Path": return readPath(j);
7237
+ case "Sweep": return readSweep(j);
7179
7238
  default: return bad(`unknown node kind: ${String(kind)}`);
7180
7239
  }
7181
7240
  }
@@ -7411,6 +7470,15 @@ function readSegment(j) {
7411
7470
  default: return bad(`unknown segment kind: ${String(kind)}`);
7412
7471
  }
7413
7472
  }
7473
+ function readSweep(j) {
7474
+ const profile = readNode(j["profile"]);
7475
+ if (!profile.ok) return profile;
7476
+ const spine = readNode(j["spine"]);
7477
+ if (!spine.ok) return spine;
7478
+ const frenet = readFlag(j, "frenet");
7479
+ if (!frenet.ok) return frenet;
7480
+ return ok(sweep$2(profile.value, spine.value, { frenet: frenet.value }));
7481
+ }
7414
7482
  function readPath(j) {
7415
7483
  const start = readExpr(j["start"]);
7416
7484
  if (!start.ok) return start;
@@ -7538,6 +7606,7 @@ function optimizeNode(n) {
7538
7606
  case "Extrude":
7539
7607
  case "Revolve":
7540
7608
  case "Loft":
7609
+ case "Sweep":
7541
7610
  case "Path": return optimizeFeature(n);
7542
7611
  }
7543
7612
  }
@@ -7549,6 +7618,7 @@ function optimizeFeature(n) {
7549
7618
  at: n.at ? foldExpr(n.at) : void 0
7550
7619
  });
7551
7620
  case "Loft": return loft$1(n.sections.map(optimizeNode), { ruled: n.ruled });
7621
+ case "Sweep": return sweep$2(optimizeNode(n.profile), optimizeNode(n.spine), { frenet: n.frenet });
7552
7622
  case "Path": return path(foldExpr(n.start), n.segments.map((s) => foldSegment(s, foldExpr)));
7553
7623
  }
7554
7624
  }
@@ -7647,6 +7717,7 @@ function rebuildChildren(n, pred, repl) {
7647
7717
  at: n.at
7648
7718
  });
7649
7719
  case "Loft": return loft$1(n.sections.map((s) => walk(s, pred, repl)), { ruled: n.ruled });
7720
+ case "Sweep": return sweep$2(walk(n.profile, pred, repl), walk(n.spine, pred, repl), { frenet: n.frenet });
7650
7721
  }
7651
7722
  }
7652
7723
  function forEachNode(root, fn) {
@@ -7680,6 +7751,7 @@ function childrenOf(n) {
7680
7751
  case "Extrude":
7681
7752
  case "Revolve": return [n.profile];
7682
7753
  case "Loft": return n.sections;
7754
+ case "Sweep": return [n.profile, n.spine];
7683
7755
  }
7684
7756
  }
7685
7757
  function nodeCount(root) {
@@ -7692,7 +7764,7 @@ function nodeCount(root) {
7692
7764
  //#endregion
7693
7765
  //#region src/ns/csg.ts
7694
7766
  var csg_exports = /* @__PURE__ */ __exportAll({
7695
- CSG_VERSION: () => 1,
7767
+ CSG_VERSION: () => 2,
7696
7768
  Evaluator: () => Evaluator,
7697
7769
  add: () => add,
7698
7770
  arcTo: () => arcTo,
@@ -7739,6 +7811,7 @@ var csg_exports = /* @__PURE__ */ __exportAll({
7739
7811
  rotate: () => rotate$1,
7740
7812
  scale: () => scale$1,
7741
7813
  sphere: () => sphere$2,
7814
+ sweep: () => sweep$2,
7742
7815
  toJSON: () => toJSON,
7743
7816
  torus: () => torus$2,
7744
7817
  translate: () => translate$1,
@@ -1,7 +1,7 @@
1
1
  import { ScalarInput, Vec2Input, Vec3Input } from './expressions.js';
2
2
  import { Segment2D } from './segments.js';
3
3
  import { Matrix4x4 } from '../core/types.js';
4
- import { BoxNode, SphereNode, CylinderNode, ConeNode, TorusNode, PolygonNode, CircleNode, LineNode, VertexLitNode, EmptyNode, FuseNode, CutNode, IntersectNode, FuseAllNode, CutAllNode, TranslateNode, RotateNode, ScaleNode, MirrorNode, ExtrudeNode, RevolveNode, LoftNode, PathNode, CompoundNode, InstanceNode, IRNode, SolidNode, FaceNode, EdgeNode, VertexNode } from './types.js';
4
+ import { BoxNode, SphereNode, CylinderNode, ConeNode, TorusNode, PolygonNode, CircleNode, LineNode, VertexLitNode, EmptyNode, FuseNode, CutNode, IntersectNode, FuseAllNode, CutAllNode, TranslateNode, RotateNode, ScaleNode, MirrorNode, ExtrudeNode, RevolveNode, LoftNode, SweepNode, PathNode, CompoundNode, InstanceNode, IRNode, SolidNode, FaceNode, EdgeNode, VertexNode } from './types.js';
5
5
  export declare function box(x: ScalarInput, y: ScalarInput, z: ScalarInput): BoxNode;
6
6
  export declare function sphere(radius: ScalarInput): SphereNode;
7
7
  export declare function cylinder(radius: ScalarInput, height: ScalarInput): CylinderNode;
@@ -35,6 +35,13 @@ export interface MirrorOptions {
35
35
  }
36
36
  export declare function mirror(target: IRNode, options?: MirrorOptions): MirrorNode;
37
37
  export declare function extrude(profile: FaceNode, vector: Vec3Input): ExtrudeNode;
38
+ export interface SweepNodeOptions {
39
+ readonly frenet?: boolean | undefined;
40
+ }
41
+ /** Sweep a face-producing profile along a Wire/Edge-producing spine.
42
+ * `frenet` is canonicalized (default false) so the default and explicit
43
+ * forms share one content address. */
44
+ export declare function sweep(profile: FaceNode, spine: IRNode, options?: SweepNodeOptions): SweepNode;
38
45
  /** Open (or incidentally closed) planar path in the XY plane at z = 0,
39
46
  * producing a Wire. Segments come from `lineTo`/`arcTo`/`bezierTo`/
40
47
  * `ellipseArcTo`. */
@@ -0,0 +1,5 @@
1
+ import { Result } from '../../core/result.js';
2
+ import { AnyShape, Dimension } from '../../core/shapeTypes.js';
3
+ import { SweepNode } from '../types.js';
4
+ import { EvalContext } from './context.js';
5
+ export declare function evalSweep(node: SweepNode, 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, path, compound, instance, type RevolveOptions, type LoftOptions, 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, path, 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, PathNode, InstanceNode, SolidNode, FaceNode, EdgeNode, VertexNode, AnyNode, } from './types.js';
10
+ export type { IRNode, NodeKind, OutputKind, PrimitiveNode, BooleanNode, TransformIRNode, ExtrudeNode, RevolveNode, LoftNode, SweepNode, PathNode, InstanceNode, SolidNode, FaceNode, EdgeNode, VertexNode, AnyNode, } from './types.js';
11
11
  export { outputKindOf } from './types.js';
12
12
  export { lineTo, arcTo, bezierTo, ellipseArcTo, type Segment2D, type SegmentOptions, type EllipseArcOptions, } from './segments.js';
13
13
  export { Evaluator, withEvaluator, type EvaluatorOptions, type StepInfo, type CacheStats, } from './evaluate.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 = 1;
3
+ export declare const CSG_VERSION = 2;
4
4
  export interface CsgEnvelope {
5
5
  readonly csgVersion: number;
6
6
  readonly root: unknown;
@@ -124,6 +124,15 @@ export interface RevolveNode extends IRNodeBase {
124
124
  readonly axis?: Expr | undefined;
125
125
  readonly at?: Expr | undefined;
126
126
  }
127
+ export interface SweepNode extends IRNodeBase {
128
+ readonly kind: 'Sweep';
129
+ /** Must produce OutputKind 'Face'. */
130
+ readonly profile: IRNode;
131
+ /** Must produce OutputKind 'Wire' or 'Edge' (Line, Circle, Path). */
132
+ readonly spine: IRNode;
133
+ /** Canonicalized by the builder (default false). */
134
+ readonly frenet: boolean;
135
+ }
127
136
  export interface PathNode extends IRNodeBase {
128
137
  readonly kind: 'Path';
129
138
  /** Vec2 start point; the path lies in the XY plane (z = 0) and is lifted
@@ -154,7 +163,7 @@ export interface InstanceNode extends IRNodeBase {
154
163
  export type PrimitiveNode = BoxNode | SphereNode | CylinderNode | ConeNode | TorusNode | PolygonNode | CircleNode | LineNode | VertexLitNode | EmptyNode;
155
164
  export type BooleanNode = FuseNode | CutNode | IntersectNode | FuseAllNode | CutAllNode;
156
165
  export type TransformIRNode = TranslateNode | RotateNode | ScaleNode | MirrorNode;
157
- export type IRNode = PrimitiveNode | BooleanNode | TransformIRNode | ExtrudeNode | RevolveNode | LoftNode | PathNode | CompoundNode | InstanceNode;
166
+ export type IRNode = PrimitiveNode | BooleanNode | TransformIRNode | ExtrudeNode | RevolveNode | LoftNode | SweepNode | PathNode | CompoundNode | InstanceNode;
158
167
  export type NodeKind = IRNode['kind'];
159
168
  export type AnyNode = IRNode;
160
169
  /** Nodes that produce a 3D solid. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "brepjs",
3
- "version": "18.126.0",
3
+ "version": "18.127.0",
4
4
  "description": "Web CAD library with pluggable geometry kernel",
5
5
  "keywords": [
6
6
  "cad",