forgecad 0.9.8 → 0.9.9

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.
@@ -806,11 +806,11 @@ function isFinitePositive$3(value) {
806
806
  function isFiniteNonNegative(value) {
807
807
  return Number.isFinite(value) && value >= 0;
808
808
  }
809
- function cloneVec3$5(vec2) {
809
+ function cloneVec3$6(vec2) {
810
810
  return [vec2[0], vec2[1], vec2[2]];
811
811
  }
812
812
  function cloneFaceAxis(vec2) {
813
- return vec2 ? cloneVec3$5(vec2) : void 0;
813
+ return vec2 ? cloneVec3$6(vec2) : void 0;
814
814
  }
815
815
  function cloneSheetMetalModel(model) {
816
816
  if (!model) return null;
@@ -1120,8 +1120,8 @@ function lowerSheetMetalBasePlan(model, output) {
1120
1120
  function descriptor(name, center, normal, planar, uAxis, vAxis, semantic = "face", memberNames = [name], coplanar = planar) {
1121
1121
  return {
1122
1122
  name,
1123
- center: cloneVec3$5(center),
1124
- normal: cloneVec3$5(normal),
1123
+ center: cloneVec3$6(center),
1124
+ normal: cloneVec3$6(normal),
1125
1125
  planar,
1126
1126
  uAxis: cloneFaceAxis(uAxis),
1127
1127
  vAxis: cloneFaceAxis(vAxis),
@@ -1374,10 +1374,10 @@ function describeSheetMetalPlanarRegionFrames(model, output) {
1374
1374
  const size = sheetMetalPlanarRegionSize(derived, face.name);
1375
1375
  return {
1376
1376
  name: face.name,
1377
- center: cloneVec3$5(face.center),
1378
- normal: cloneVec3$5(face.normal),
1379
- uAxis: cloneVec3$5(face.uAxis),
1380
- vAxis: cloneVec3$5(face.vAxis),
1377
+ center: cloneVec3$6(face.center),
1378
+ normal: cloneVec3$6(face.normal),
1379
+ uAxis: cloneVec3$6(face.uAxis),
1380
+ vAxis: cloneVec3$6(face.vAxis),
1381
1381
  width: size.width,
1382
1382
  height: size.height,
1383
1383
  thickness: derived.thickness
@@ -8367,7 +8367,7 @@ function sub$7(a2, b) {
8367
8367
  function cross$8(a2, b) {
8368
8368
  return [a2[1] * b[2] - a2[2] * b[1], a2[2] * b[0] - a2[0] * b[2], a2[0] * b[1] - a2[1] * b[0]];
8369
8369
  }
8370
- function makeEdge(name, start, end, faceName, curve) {
8370
+ function makeEdge$1(name, start, end, faceName, curve) {
8371
8371
  return {
8372
8372
  name,
8373
8373
  start,
@@ -8411,10 +8411,10 @@ function buildSurfaceSheetTopology(boundaries, options = {}) {
8411
8411
  surface: options.surface
8412
8412
  });
8413
8413
  const edges = /* @__PURE__ */ new Map();
8414
- edges.set("u0", makeEdge("u0", u0Start, u0End, faceName, (_a3 = options.edgeCurves) == null ? void 0 : _a3.u0));
8415
- edges.set("u1", makeEdge("u1", u1Start, u1End, faceName, (_b3 = options.edgeCurves) == null ? void 0 : _b3.u1));
8416
- edges.set("v0", makeEdge("v0", v0Start, v0End, faceName, (_c2 = options.edgeCurves) == null ? void 0 : _c2.v0));
8417
- edges.set("v1", makeEdge("v1", v1Start, v1End, faceName, (_d2 = options.edgeCurves) == null ? void 0 : _d2.v1));
8414
+ edges.set("u0", makeEdge$1("u0", u0Start, u0End, faceName, (_a3 = options.edgeCurves) == null ? void 0 : _a3.u0));
8415
+ edges.set("u1", makeEdge$1("u1", u1Start, u1End, faceName, (_b3 = options.edgeCurves) == null ? void 0 : _b3.u1));
8416
+ edges.set("v0", makeEdge$1("v0", v0Start, v0End, faceName, (_c2 = options.edgeCurves) == null ? void 0 : _c2.v0));
8417
+ edges.set("v1", makeEdge$1("v1", v1Start, v1End, faceName, (_d2 = options.edgeCurves) == null ? void 0 : _d2.v1));
8418
8418
  return { faces, edges };
8419
8419
  }
8420
8420
  function attachSurfaceSheetTopology(shape, boundaries, options = {}) {
@@ -8432,7 +8432,7 @@ function attachSurfaceSheetTopology(shape, boundaries, options = {}) {
8432
8432
  });
8433
8433
  return shape;
8434
8434
  }
8435
- function cloneVec3$4(value) {
8435
+ function cloneVec3$5(value) {
8436
8436
  return [value[0], value[1], value[2]];
8437
8437
  }
8438
8438
  function cloneNurbsFaceTrimLoop(loop) {
@@ -8454,38 +8454,38 @@ function cloneFaceSurface(surface) {
8454
8454
  if (!surface) return void 0;
8455
8455
  switch (surface.kind) {
8456
8456
  case "plane":
8457
- return { kind: "plane", normal: cloneVec3$4(surface.normal) };
8457
+ return { kind: "plane", normal: cloneVec3$5(surface.normal) };
8458
8458
  case "cylinder":
8459
8459
  return {
8460
8460
  kind: "cylinder",
8461
- origin: cloneVec3$4(surface.origin),
8462
- axis: cloneVec3$4(surface.axis),
8461
+ origin: cloneVec3$5(surface.origin),
8462
+ axis: cloneVec3$5(surface.axis),
8463
8463
  radius: surface.radius,
8464
8464
  height: surface.height
8465
8465
  };
8466
8466
  case "cone":
8467
8467
  return {
8468
8468
  kind: "cone",
8469
- origin: cloneVec3$4(surface.origin),
8470
- axis: cloneVec3$4(surface.axis),
8469
+ origin: cloneVec3$5(surface.origin),
8470
+ axis: cloneVec3$5(surface.axis),
8471
8471
  radiusBottom: surface.radiusBottom,
8472
8472
  radiusTop: surface.radiusTop,
8473
8473
  height: surface.height
8474
8474
  };
8475
8475
  case "sphere":
8476
- return { kind: "sphere", center: cloneVec3$4(surface.center), radius: surface.radius };
8476
+ return { kind: "sphere", center: cloneVec3$5(surface.center), radius: surface.radius };
8477
8477
  case "torus":
8478
8478
  return {
8479
8479
  kind: "torus",
8480
- center: cloneVec3$4(surface.center),
8481
- axis: cloneVec3$4(surface.axis),
8480
+ center: cloneVec3$5(surface.center),
8481
+ axis: cloneVec3$5(surface.axis),
8482
8482
  majorRadius: surface.majorRadius,
8483
8483
  minorRadius: surface.minorRadius
8484
8484
  };
8485
8485
  case "ruled":
8486
8486
  return {
8487
8487
  kind: "ruled",
8488
- rails: surface.rails.map((rail2) => rail2.map(cloneVec3$4))
8488
+ rails: surface.rails.map((rail2) => rail2.map(cloneVec3$5))
8489
8489
  };
8490
8490
  case "nurbs":
8491
8491
  return {
@@ -8498,9 +8498,9 @@ function cloneEdgeCurve(curve) {
8498
8498
  if (!curve) return void 0;
8499
8499
  switch (curve.kind) {
8500
8500
  case "line":
8501
- return { ...curve, start: cloneVec3$4(curve.start), end: cloneVec3$4(curve.end) };
8501
+ return { ...curve, start: cloneVec3$5(curve.start), end: cloneVec3$5(curve.end) };
8502
8502
  case "circle":
8503
- return { ...curve, center: cloneVec3$4(curve.center), axis: cloneVec3$4(curve.axis) };
8503
+ return { ...curve, center: cloneVec3$5(curve.center), axis: cloneVec3$5(curve.axis) };
8504
8504
  case "surfaceIso":
8505
8505
  return { ...curve, parameterRange: [curve.parameterRange[0], curve.parameterRange[1]] };
8506
8506
  case "nurbsUv":
@@ -8518,7 +8518,7 @@ function cloneEdgeCurve(curve) {
8518
8518
  }
8519
8519
  }
8520
8520
  function makeLineEdgeCurve(start, end, faceName) {
8521
- return faceName ? { kind: "line", start: cloneVec3$4(start), end: cloneVec3$4(end), faceName } : { kind: "line", start: cloneVec3$4(start), end: cloneVec3$4(end) };
8521
+ return faceName ? { kind: "line", start: cloneVec3$5(start), end: cloneVec3$5(end), faceName } : { kind: "line", start: cloneVec3$5(start), end: cloneVec3$5(end) };
8522
8522
  }
8523
8523
  function edgeCurveFaceName(curve) {
8524
8524
  switch (curve.kind) {
@@ -10605,7 +10605,7 @@ async function initManifoldWasm() {
10605
10605
  if (_wasm$1) return _wasm$1;
10606
10606
  performance.mark("manifold:start");
10607
10607
  const Module = (await __vitePreload(async () => {
10608
- const { default: __vite_default__ } = await import("./manifold-C6-sZYQN.js");
10608
+ const { default: __vite_default__ } = await import("./manifold-BRdhoQy5.js");
10609
10609
  return { default: __vite_default__ };
10610
10610
  }, true ? [] : void 0)).default;
10611
10611
  performance.mark("manifold:imported");
@@ -22489,7 +22489,7 @@ function marchingTetrahedra(sdfFn, bounds, edgeLength2) {
22489
22489
  };
22490
22490
  }
22491
22491
  const EPS$8 = 1e-9;
22492
- function finitePositive(value) {
22492
+ function finitePositive$1(value) {
22493
22493
  return Number.isFinite(value) && value > EPS$8;
22494
22494
  }
22495
22495
  function clampNonNegative(value) {
@@ -22508,7 +22508,7 @@ function distancePreservingMatrixScale(matrix) {
22508
22508
  const sx = length4(col0);
22509
22509
  const sy = length4(col1);
22510
22510
  const sz = length4(col2);
22511
- if (!finitePositive(sx) || !finitePositive(sy) || !finitePositive(sz)) return null;
22511
+ if (!finitePositive$1(sx) || !finitePositive$1(sy) || !finitePositive$1(sz)) return null;
22512
22512
  if (Math.abs(sx - sy) > EPS$8 || Math.abs(sx - sz) > EPS$8) return null;
22513
22513
  if (Math.abs(dot2(col0, col1)) > EPS$8 || Math.abs(dot2(col0, col2)) > EPS$8 || Math.abs(dot2(col1, col2)) > EPS$8) return null;
22514
22514
  return sx;
@@ -22525,7 +22525,7 @@ function transformStepDistanceScale(step) {
22525
22525
  const sx = Math.abs(step.x);
22526
22526
  const sy = Math.abs(step.y);
22527
22527
  const sz = Math.abs(step.z);
22528
- if (!finitePositive(sx) || !finitePositive(sy) || !finitePositive(sz)) return null;
22528
+ if (!finitePositive$1(sx) || !finitePositive$1(sy) || !finitePositive$1(sz)) return null;
22529
22529
  return Math.abs(sx - sy) <= EPS$8 && Math.abs(sx - sz) <= EPS$8 ? sx : null;
22530
22530
  }
22531
22531
  }
@@ -22565,7 +22565,7 @@ function translatedPlan(base, z2) {
22565
22565
  };
22566
22566
  }
22567
22567
  function offsetCylinderDimensions(plan, thickness) {
22568
- if (!finitePositive(plan.height)) return null;
22568
+ if (!finitePositive$1(plan.height)) return null;
22569
22569
  const radiusTop = plan.radiusTop ?? plan.radius;
22570
22570
  const slope = (radiusTop - plan.radius) / plan.height;
22571
22571
  const normalScale = Math.hypot(1, slope);
@@ -22574,7 +22574,7 @@ function offsetCylinderDimensions(plan, thickness) {
22574
22574
  const height = zMax - zMin;
22575
22575
  const radiusBottom = plan.radius + thickness * (normalScale - slope);
22576
22576
  const offsetRadiusTop = radiusTop + thickness * (normalScale + slope);
22577
- if (!finitePositive(height) || radiusBottom < -EPS$8 || offsetRadiusTop < -EPS$8) return null;
22577
+ if (!finitePositive$1(height) || radiusBottom < -EPS$8 || offsetRadiusTop < -EPS$8) return null;
22578
22578
  return {
22579
22579
  zMin,
22580
22580
  height,
@@ -22632,7 +22632,7 @@ function rectangleCandidatePointsFromProfile(plan) {
22632
22632
  case "rect": {
22633
22633
  const width = Math.abs(plan.width);
22634
22634
  const height = Math.abs(plan.height);
22635
- if (!finitePositive(width) || !finitePositive(height)) return null;
22635
+ if (!finitePositive$1(width) || !finitePositive$1(height)) return null;
22636
22636
  const halfWidth = width / 2;
22637
22637
  const halfHeight = height / 2;
22638
22638
  const points = [
@@ -22666,7 +22666,7 @@ function rectangleFootprintFromProfile(plan) {
22666
22666
  const [xMin, xMax] = xs;
22667
22667
  const [zMin, zMax] = zs;
22668
22668
  if (xMin == null || xMax == null || zMin == null || zMax == null) return null;
22669
- if (xMin < -EPS$8 || !finitePositive(xMax) || !finitePositive(zMax - zMin)) return null;
22669
+ if (xMin < -EPS$8 || !finitePositive$1(xMax) || !finitePositive$1(zMax - zMin)) return null;
22670
22670
  const hasCorner = (x2, z2) => points.some(([px2, pz2]) => sameScalar$1(px2, x2) && sameScalar$1(pz2, z2));
22671
22671
  if (!hasCorner(xMin, zMin) || !hasCorner(xMax, zMin) || !hasCorner(xMax, zMax) || !hasCorner(xMin, zMax)) return null;
22672
22672
  return {
@@ -22679,7 +22679,7 @@ function rectangleFootprintFromProfile(plan) {
22679
22679
  function circleFootprintFromProfile(plan) {
22680
22680
  if (plan.kind !== "circle") return null;
22681
22681
  const radius = Math.abs(plan.radius);
22682
- if (!finitePositive(radius)) return null;
22682
+ if (!finitePositive$1(radius)) return null;
22683
22683
  const center = transformProfilePointThrough$1([0, 0], plan.transforms);
22684
22684
  const xPoint = transformProfilePointThrough$1([1, 0], plan.transforms);
22685
22685
  const yPoint = transformProfilePointThrough$1([0, 1], plan.transforms);
@@ -22688,7 +22688,7 @@ function circleFootprintFromProfile(plan) {
22688
22688
  const xScale = Math.hypot(xAxis[0], xAxis[1]);
22689
22689
  const yScale = Math.hypot(yAxis[0], yAxis[1]);
22690
22690
  const dot2 = xAxis[0] * yAxis[0] + xAxis[1] * yAxis[1];
22691
- if (!finitePositive(xScale) || !finitePositive(yScale)) return null;
22691
+ if (!finitePositive$1(xScale) || !finitePositive$1(yScale)) return null;
22692
22692
  if (Math.abs(xScale - yScale) > EPS$8 || Math.abs(dot2) > EPS$8 * xScale * yScale) return null;
22693
22693
  return {
22694
22694
  center,
@@ -22701,7 +22701,7 @@ function fullCircleRevolveTorusPlan(plan, minorRadiusOffset = 0) {
22701
22701
  const circle2 = circleFootprintFromProfile(plan.profile);
22702
22702
  if (!circle2 || circle2.center[0] <= EPS$8) return null;
22703
22703
  const minorRadius = circle2.radius + minorRadiusOffset;
22704
- if (!finitePositive(minorRadius) || minorRadius >= circle2.center[0] - EPS$8) return null;
22704
+ if (!finitePositive$1(minorRadius) || minorRadius >= circle2.center[0] - EPS$8) return null;
22705
22705
  return translatedPlan(
22706
22706
  {
22707
22707
  kind: "torus",
@@ -22748,7 +22748,7 @@ function offsetFullRectRevolvePlan(plan, thickness) {
22748
22748
  const innerRadius = rectangle.innerRadius - thickness;
22749
22749
  const outerRadius = rectangle.outerRadius + thickness;
22750
22750
  const height = rectangle.zMax - rectangle.zMin + 2 * thickness;
22751
- if (innerRadius < -EPS$8 || !finitePositive(outerRadius) || !finitePositive(height) || outerRadius <= innerRadius + EPS$8) return null;
22751
+ if (innerRadius < -EPS$8 || !finitePositive$1(outerRadius) || !finitePositive$1(height) || outerRadius <= innerRadius + EPS$8) return null;
22752
22752
  const zCenter = (rectangle.zMin + rectangle.zMax) / 2;
22753
22753
  if (innerRadius <= EPS$8) {
22754
22754
  return translatedPlan(
@@ -22789,11 +22789,11 @@ function offsetSolidAnalyticPrimitivePlan(base, thickness) {
22789
22789
  };
22790
22790
  }
22791
22791
  case "box": {
22792
- if (!finitePositive(base.z)) return null;
22792
+ if (!finitePositive$1(base.z)) return null;
22793
22793
  const x2 = Math.abs(base.x) + 2 * thickness;
22794
22794
  const y2 = Math.abs(base.y) + 2 * thickness;
22795
22795
  const z2 = base.z + 2 * thickness;
22796
- if (!finitePositive(x2) || !finitePositive(y2) || !finitePositive(z2)) return null;
22796
+ if (!finitePositive$1(x2) || !finitePositive$1(y2) || !finitePositive$1(z2)) return null;
22797
22797
  return translatedPlan(
22798
22798
  {
22799
22799
  kind: "box",
@@ -22820,7 +22820,7 @@ function offsetSolidAnalyticPrimitivePlan(base, thickness) {
22820
22820
  }
22821
22821
  case "sphere": {
22822
22822
  const radius = base.radius + thickness;
22823
- if (!finitePositive(radius)) return null;
22823
+ if (!finitePositive$1(radius)) return null;
22824
22824
  return {
22825
22825
  kind: "sphere",
22826
22826
  radius,
@@ -22829,7 +22829,7 @@ function offsetSolidAnalyticPrimitivePlan(base, thickness) {
22829
22829
  }
22830
22830
  case "torus": {
22831
22831
  const minorRadius = base.minorRadius + thickness;
22832
- if (!finitePositive(minorRadius) || minorRadius >= base.majorRadius - EPS$8) return null;
22832
+ if (!finitePositive$1(minorRadius) || minorRadius >= base.majorRadius - EPS$8) return null;
22833
22833
  return {
22834
22834
  kind: "torus",
22835
22835
  majorRadius: base.majorRadius,
@@ -30683,17 +30683,17 @@ function emptyFaceTable() {
30683
30683
  blockedQueries: []
30684
30684
  };
30685
30685
  }
30686
- function cloneVec3$3(vec2) {
30686
+ function cloneVec3$4(vec2) {
30687
30687
  return [vec2[0], vec2[1], vec2[2]];
30688
30688
  }
30689
30689
  function cloneFaceRefValue(face) {
30690
30690
  return {
30691
30691
  ...face,
30692
- normal: cloneVec3$3(face.normal),
30693
- center: cloneVec3$3(face.center),
30692
+ normal: cloneVec3$4(face.normal),
30693
+ center: cloneVec3$4(face.center),
30694
30694
  query: cloneFaceQueryRef(face.query),
30695
- uAxis: face.uAxis ? cloneVec3$3(face.uAxis) : void 0,
30696
- vAxis: face.vAxis ? cloneVec3$3(face.vAxis) : void 0,
30695
+ uAxis: face.uAxis ? cloneVec3$4(face.uAxis) : void 0,
30696
+ vAxis: face.vAxis ? cloneVec3$4(face.vAxis) : void 0,
30697
30697
  surface: cloneFaceSurface(face.surface),
30698
30698
  descendant: face.descendant ? cloneFaceDescendantMetadata(face.descendant) : void 0
30699
30699
  };
@@ -31548,11 +31548,11 @@ function resolveShapeFaceTableInternal(plan, owner) {
31548
31548
  for (const descriptor2 of describeSheetMetalFaces(plan.model, plan.output)) {
31549
31549
  registerFace(table2, {
31550
31550
  name: descriptor2.name,
31551
- normal: cloneVec3$3(descriptor2.normal),
31552
- center: cloneVec3$3(descriptor2.center),
31551
+ normal: cloneVec3$4(descriptor2.normal),
31552
+ center: cloneVec3$4(descriptor2.center),
31553
31553
  planar: descriptor2.planar,
31554
- uAxis: descriptor2.uAxis ? cloneVec3$3(descriptor2.uAxis) : void 0,
31555
- vAxis: descriptor2.vAxis ? cloneVec3$3(descriptor2.vAxis) : void 0,
31554
+ uAxis: descriptor2.uAxis ? cloneVec3$4(descriptor2.uAxis) : void 0,
31555
+ vAxis: descriptor2.vAxis ? cloneVec3$4(descriptor2.vAxis) : void 0,
31556
31556
  query: createTrackedFaceQuery(descriptor2.name, owner),
31557
31557
  descendant: createFaceDescendantMetadata(descriptor2.semantic, descriptor2.memberNames, descriptor2.coplanar)
31558
31558
  });
@@ -31579,7 +31579,7 @@ function resolveShapeFaceTableInternal(plan, owner) {
31579
31579
  baseFace.center[2] - baseFace.normal[2] * plan.thickness
31580
31580
  ],
31581
31581
  normal: [-baseFace.normal[0], -baseFace.normal[1], -baseFace.normal[2]],
31582
- uAxis: baseFace.uAxis ? cloneVec3$3(baseFace.uAxis) : void 0,
31582
+ uAxis: baseFace.uAxis ? cloneVec3$4(baseFace.uAxis) : void 0,
31583
31583
  vAxis: baseFace.vAxis ? [-baseFace.vAxis[0], -baseFace.vAxis[1], -baseFace.vAxis[2]] : void 0,
31584
31584
  query: createdQuery
31585
31585
  });
@@ -31645,15 +31645,15 @@ function resolveShapeFaceTableInternal(plan, owner) {
31645
31645
  if (counterboreFloorQuery && plan.hole.counterbore) {
31646
31646
  registerFace(table2, {
31647
31647
  name: "counterbore-floor",
31648
- normal: cloneVec3$3(workplane.normal),
31648
+ normal: cloneVec3$4(workplane.normal),
31649
31649
  center: [
31650
31650
  origin[0] + inward[0] * plan.hole.counterbore.depth,
31651
31651
  origin[1] + inward[1] * plan.hole.counterbore.depth,
31652
31652
  origin[2] + inward[2] * plan.hole.counterbore.depth
31653
31653
  ],
31654
31654
  planar: true,
31655
- uAxis: cloneVec3$3(workplane.u),
31656
- vAxis: cloneVec3$3(workplane.v),
31655
+ uAxis: cloneVec3$4(workplane.u),
31656
+ vAxis: cloneVec3$4(workplane.v),
31657
31657
  query: counterboreFloorQuery
31658
31658
  });
31659
31659
  }
@@ -31677,11 +31677,11 @@ function resolveShapeFaceTableInternal(plan, owner) {
31677
31677
  if (floorQuery) {
31678
31678
  registerFace(table2, {
31679
31679
  name: "floor",
31680
- normal: cloneVec3$3(workplane.normal),
31680
+ normal: cloneVec3$4(workplane.normal),
31681
31681
  center: [origin[0] + inward[0] * forward.depth, origin[1] + inward[1] * forward.depth, origin[2] + inward[2] * forward.depth],
31682
31682
  planar: true,
31683
- uAxis: cloneVec3$3(workplane.u),
31684
- vAxis: cloneVec3$3(workplane.v),
31683
+ uAxis: cloneVec3$4(workplane.u),
31684
+ vAxis: cloneVec3$4(workplane.v),
31685
31685
  query: floorQuery
31686
31686
  });
31687
31687
  }
@@ -31692,7 +31692,7 @@ function resolveShapeFaceTableInternal(plan, owner) {
31692
31692
  normal: [-workplane.normal[0], -workplane.normal[1], -workplane.normal[2]],
31693
31693
  center: [origin[0] - inward[0] * reverse.depth, origin[1] - inward[1] * reverse.depth, origin[2] - inward[2] * reverse.depth],
31694
31694
  planar: true,
31695
- uAxis: cloneVec3$3(workplane.u),
31695
+ uAxis: cloneVec3$4(workplane.u),
31696
31696
  vAxis: [-workplane.v[0], -workplane.v[1], -workplane.v[2]],
31697
31697
  query: capQuery
31698
31698
  });
@@ -31871,11 +31871,11 @@ function resolveShapeFaceTableInternal(plan, owner) {
31871
31871
  })();
31872
31872
  registerFace(table2, {
31873
31873
  name: "floor",
31874
- normal: cloneVec3$3(placement.workplane.normal),
31874
+ normal: cloneVec3$4(placement.workplane.normal),
31875
31875
  center: floorCenter,
31876
31876
  planar: true,
31877
- uAxis: cloneVec3$3(placement.workplane.u),
31878
- vAxis: cloneVec3$3(placement.workplane.v),
31877
+ uAxis: cloneVec3$4(placement.workplane.u),
31878
+ vAxis: cloneVec3$4(placement.workplane.v),
31879
31879
  query: floorQuery
31880
31880
  });
31881
31881
  }
@@ -31890,7 +31890,7 @@ function resolveShapeFaceTableInternal(plan, owner) {
31890
31890
  origin[2] - depthDir[2] * reverse.depth
31891
31891
  ],
31892
31892
  planar: true,
31893
- uAxis: cloneVec3$3(placement.workplane.u),
31893
+ uAxis: cloneVec3$4(placement.workplane.u),
31894
31894
  vAxis: [-placement.workplane.v[0], -placement.workplane.v[1], -placement.workplane.v[2]],
31895
31895
  query: capQuery
31896
31896
  });
@@ -32076,7 +32076,7 @@ function preservedShapeFaceQueries(basePlan) {
32076
32076
  return listShapeFaceQueries(basePlan);
32077
32077
  }
32078
32078
  const PLACEMENT_REFERENCE_KINDS = ["points", "edges", "surfaces", "objects"];
32079
- function cloneVec3$2(value, label) {
32079
+ function cloneVec3$3(value, label) {
32080
32080
  if (!Array.isArray(value) || value.length < 3) {
32081
32081
  throw new Error(`${label} must be a [x, y, z] tuple`);
32082
32082
  }
@@ -32102,23 +32102,23 @@ function isBoundsObject(value) {
32102
32102
  function toObjectBounds(value, label) {
32103
32103
  if (isBoundsObject(value)) {
32104
32104
  return {
32105
- min: cloneVec3$2(value.min, `${label}.min`),
32106
- max: cloneVec3$2(value.max, `${label}.max`)
32105
+ min: cloneVec3$3(value.min, `${label}.min`),
32106
+ max: cloneVec3$3(value.max, `${label}.max`)
32107
32107
  };
32108
32108
  }
32109
32109
  if (typeof value === "object" && value != null) {
32110
32110
  if ("boundingBox" in value && typeof value.boundingBox === "function") {
32111
32111
  const bounds = value.boundingBox();
32112
32112
  return {
32113
- min: cloneVec3$2(bounds.min, `${label}.min`),
32114
- max: cloneVec3$2(bounds.max, `${label}.max`)
32113
+ min: cloneVec3$3(bounds.min, `${label}.min`),
32114
+ max: cloneVec3$3(bounds.max, `${label}.max`)
32115
32115
  };
32116
32116
  }
32117
32117
  if ("_bbox" in value && typeof value._bbox === "function") {
32118
32118
  const bounds = value._bbox();
32119
32119
  return {
32120
- min: cloneVec3$2(bounds.min, `${label}.min`),
32121
- max: cloneVec3$2(bounds.max, `${label}.max`)
32120
+ min: cloneVec3$3(bounds.min, `${label}.min`),
32121
+ max: cloneVec3$3(bounds.max, `${label}.max`)
32122
32122
  };
32123
32123
  }
32124
32124
  }
@@ -32162,24 +32162,24 @@ function createPlacementReferences() {
32162
32162
  function clonePlacementReferences(refs) {
32163
32163
  const out = createPlacementReferences();
32164
32164
  for (const [name, point2] of Object.entries(refs.points)) {
32165
- out.points[name] = cloneVec3$2(point2, `points.${name}`);
32165
+ out.points[name] = cloneVec3$3(point2, `points.${name}`);
32166
32166
  }
32167
32167
  for (const [name, edge] of Object.entries(refs.edges)) {
32168
32168
  out.edges[name] = {
32169
- start: cloneVec3$2(edge.start, `edges.${name}.start`),
32170
- end: cloneVec3$2(edge.end, `edges.${name}.end`)
32169
+ start: cloneVec3$3(edge.start, `edges.${name}.start`),
32170
+ end: cloneVec3$3(edge.end, `edges.${name}.end`)
32171
32171
  };
32172
32172
  }
32173
32173
  for (const [name, surface] of Object.entries(refs.surfaces)) {
32174
32174
  out.surfaces[name] = {
32175
- center: cloneVec3$2(surface.center, `surfaces.${name}.center`),
32176
- normal: cloneVec3$2(surface.normal, `surfaces.${name}.normal`)
32175
+ center: cloneVec3$3(surface.center, `surfaces.${name}.center`),
32176
+ normal: cloneVec3$3(surface.normal, `surfaces.${name}.normal`)
32177
32177
  };
32178
32178
  }
32179
32179
  for (const [name, objectRef] of Object.entries(refs.objects)) {
32180
32180
  out.objects[name] = {
32181
- min: cloneVec3$2(objectRef.min, `objects.${name}.min`),
32182
- max: cloneVec3$2(objectRef.max, `objects.${name}.max`)
32181
+ min: cloneVec3$3(objectRef.min, `objects.${name}.min`),
32182
+ max: cloneVec3$3(objectRef.max, `objects.${name}.max`)
32183
32183
  };
32184
32184
  }
32185
32185
  return out;
@@ -32187,18 +32187,18 @@ function clonePlacementReferences(refs) {
32187
32187
  function normalizePlacementReferenceInput(input = {}) {
32188
32188
  const out = createPlacementReferences();
32189
32189
  for (const [name, point2] of Object.entries(input.points ?? {})) {
32190
- out.points[name] = cloneVec3$2(point2, `points.${name}`);
32190
+ out.points[name] = cloneVec3$3(point2, `points.${name}`);
32191
32191
  }
32192
32192
  for (const [name, edge] of Object.entries(input.edges ?? {})) {
32193
32193
  out.edges[name] = {
32194
- start: cloneVec3$2(edge.start, `edges.${name}.start`),
32195
- end: cloneVec3$2(edge.end, `edges.${name}.end`)
32194
+ start: cloneVec3$3(edge.start, `edges.${name}.start`),
32195
+ end: cloneVec3$3(edge.end, `edges.${name}.end`)
32196
32196
  };
32197
32197
  }
32198
32198
  for (const [name, surface] of Object.entries(input.surfaces ?? {})) {
32199
32199
  out.surfaces[name] = {
32200
- center: cloneVec3$2(surface.center, `surfaces.${name}.center`),
32201
- normal: normalizeVector$1(cloneVec3$2(surface.normal, `surfaces.${name}.normal`))
32200
+ center: cloneVec3$3(surface.center, `surfaces.${name}.center`),
32201
+ normal: normalizeVector$1(cloneVec3$3(surface.normal, `surfaces.${name}.normal`))
32202
32202
  };
32203
32203
  }
32204
32204
  for (const [name, objectRef] of Object.entries(input.objects ?? {})) {
@@ -32209,23 +32209,23 @@ function normalizePlacementReferenceInput(input = {}) {
32209
32209
  function mergePlacementReferences(...refsList) {
32210
32210
  const out = createPlacementReferences();
32211
32211
  for (const refs of refsList) {
32212
- for (const [name, point2] of Object.entries(refs.points)) out.points[name] = cloneVec3$2(point2, `points.${name}`);
32212
+ for (const [name, point2] of Object.entries(refs.points)) out.points[name] = cloneVec3$3(point2, `points.${name}`);
32213
32213
  for (const [name, edge] of Object.entries(refs.edges)) {
32214
32214
  out.edges[name] = {
32215
- start: cloneVec3$2(edge.start, `edges.${name}.start`),
32216
- end: cloneVec3$2(edge.end, `edges.${name}.end`)
32215
+ start: cloneVec3$3(edge.start, `edges.${name}.start`),
32216
+ end: cloneVec3$3(edge.end, `edges.${name}.end`)
32217
32217
  };
32218
32218
  }
32219
32219
  for (const [name, surface] of Object.entries(refs.surfaces)) {
32220
32220
  out.surfaces[name] = {
32221
- center: cloneVec3$2(surface.center, `surfaces.${name}.center`),
32222
- normal: cloneVec3$2(surface.normal, `surfaces.${name}.normal`)
32221
+ center: cloneVec3$3(surface.center, `surfaces.${name}.center`),
32222
+ normal: cloneVec3$3(surface.normal, `surfaces.${name}.normal`)
32223
32223
  };
32224
32224
  }
32225
32225
  for (const [name, objectRef] of Object.entries(refs.objects)) {
32226
32226
  out.objects[name] = {
32227
- min: cloneVec3$2(objectRef.min, `objects.${name}.min`),
32228
- max: cloneVec3$2(objectRef.max, `objects.${name}.max`)
32227
+ min: cloneVec3$3(objectRef.min, `objects.${name}.min`),
32228
+ max: cloneVec3$3(objectRef.max, `objects.${name}.max`)
32229
32229
  };
32230
32230
  }
32231
32231
  }
@@ -32269,7 +32269,7 @@ function resolvePointFromKind(refs, kind, name, selector, originalRef) {
32269
32269
  const point2 = refs.points[name];
32270
32270
  if (!point2) return null;
32271
32271
  if (selector != null) placementRefSelectorError(originalRef, "does not support selectors");
32272
- return cloneVec3$2(point2, `points.${name}`);
32272
+ return cloneVec3$3(point2, `points.${name}`);
32273
32273
  }
32274
32274
  case "edges": {
32275
32275
  const edge = refs.edges[name];
@@ -32277,8 +32277,8 @@ function resolvePointFromKind(refs, kind, name, selector, originalRef) {
32277
32277
  if (selector == null || selector === "midpoint" || selector === "center") {
32278
32278
  return midpoint$2(edge.start, edge.end);
32279
32279
  }
32280
- if (selector === "start") return cloneVec3$2(edge.start, `edges.${name}.start`);
32281
- if (selector === "end") return cloneVec3$2(edge.end, `edges.${name}.end`);
32280
+ if (selector === "start") return cloneVec3$3(edge.start, `edges.${name}.start`);
32281
+ if (selector === "end") return cloneVec3$3(edge.end, `edges.${name}.end`);
32282
32282
  placementRefSelectorError(originalRef, "supports only .start, .end, or .midpoint");
32283
32283
  }
32284
32284
  case "surfaces": {
@@ -32287,7 +32287,7 @@ function resolvePointFromKind(refs, kind, name, selector, originalRef) {
32287
32287
  if (selector != null && selector !== "center") {
32288
32288
  placementRefSelectorError(originalRef, "supports only .center");
32289
32289
  }
32290
- return cloneVec3$2(surface.center, `surfaces.${name}.center`);
32290
+ return cloneVec3$3(surface.center, `surfaces.${name}.center`);
32291
32291
  }
32292
32292
  case "objects": {
32293
32293
  const objectRef = refs.objects[name];
@@ -35372,7 +35372,7 @@ function attachTopologyRewritePropagation(plan, propagation) {
35372
35372
  }
35373
35373
  const DEFAULT_TOLERANCE$2 = 1;
35374
35374
  const DEFAULT_ANGLE_TOLERANCE = 10;
35375
- function distSq(a2, b) {
35375
+ function distSq$1(a2, b) {
35376
35376
  const dx = a2[0] - b[0], dy = a2[1] - b[1], dz = a2[2] - b[2];
35377
35377
  return dx * dx + dy * dy + dz * dz;
35378
35378
  }
@@ -35464,7 +35464,7 @@ function applyFilters(edges, query) {
35464
35464
  }
35465
35465
  if (query.near) {
35466
35466
  const pt = query.near;
35467
- result = result.slice().sort((a2, b) => distSq(a2.midpoint, pt) - distSq(b.midpoint, pt));
35467
+ result = result.slice().sort((a2, b) => distSq$1(a2.midpoint, pt) - distSq$1(b.midpoint, pt));
35468
35468
  }
35469
35469
  return result;
35470
35470
  }
@@ -35528,10 +35528,10 @@ function coalesceEdges(segments, tolerance = 0.01) {
35528
35528
  }
35529
35529
  function minEndpointGap(a2, b) {
35530
35530
  return Math.min(
35531
- Math.sqrt(distSq(a2.start, b.start)),
35532
- Math.sqrt(distSq(a2.start, b.end)),
35533
- Math.sqrt(distSq(a2.end, b.start)),
35534
- Math.sqrt(distSq(a2.end, b.end))
35531
+ Math.sqrt(distSq$1(a2.start, b.start)),
35532
+ Math.sqrt(distSq$1(a2.start, b.end)),
35533
+ Math.sqrt(distSq$1(a2.end, b.start)),
35534
+ Math.sqrt(distSq$1(a2.end, b.end))
35535
35535
  );
35536
35536
  }
35537
35537
  function mergeCollinearGroup(group2, index2) {
@@ -53237,11 +53237,11 @@ function inverseLerp(x2, y2, value) {
53237
53237
  return 0;
53238
53238
  }
53239
53239
  }
53240
- function lerp$5(x2, y2, t) {
53240
+ function lerp$6(x2, y2, t) {
53241
53241
  return (1 - t) * x2 + t * y2;
53242
53242
  }
53243
53243
  function damp(x2, y2, lambda, dt) {
53244
- return lerp$5(x2, y2, 1 - Math.exp(-lambda * dt));
53244
+ return lerp$6(x2, y2, 1 - Math.exp(-lambda * dt));
53245
53245
  }
53246
53246
  function pingpong(x2, length4 = 1) {
53247
53247
  return length4 - Math.abs(euclideanModulo(x2, length4 * 2) - length4);
@@ -53434,7 +53434,7 @@ const MathUtils = {
53434
53434
  * @param {number} t - The interpolation factor in the closed interval `[0, 1]`.
53435
53435
  * @return {number} The interpolated value.
53436
53436
  */
53437
- lerp: lerp$5,
53437
+ lerp: lerp$6,
53438
53438
  /**
53439
53439
  * Smoothly interpolate a number from `x` to `y` in a spring-like manner using a delta
53440
53440
  * time to maintain frame rate independent movement. For details, see
@@ -62388,9 +62388,9 @@ class Color {
62388
62388
  lerpHSL(color, alpha) {
62389
62389
  this.getHSL(_hslA);
62390
62390
  color.getHSL(_hslB);
62391
- const h = lerp$5(_hslA.h, _hslB.h, alpha);
62392
- const s = lerp$5(_hslA.s, _hslB.s, alpha);
62393
- const l = lerp$5(_hslA.l, _hslB.l, alpha);
62391
+ const h = lerp$6(_hslA.h, _hslB.h, alpha);
62392
+ const s = lerp$6(_hslA.s, _hslB.s, alpha);
62393
+ const l = lerp$6(_hslA.l, _hslB.l, alpha);
62394
62394
  this.setHSL(h, s, l);
62395
62395
  return this;
62396
62396
  }
@@ -96725,7 +96725,7 @@ function scale$1(v, s) {
96725
96725
  function dot$2(a2, b) {
96726
96726
  return a2[0] * b[0] + a2[1] * b[1] + a2[2] * b[2];
96727
96727
  }
96728
- function lerp$4(a2, b, t) {
96728
+ function lerp$5(a2, b, t) {
96729
96729
  return a2 + (b - a2) * t;
96730
96730
  }
96731
96731
  function frameMatrix$1(x2, y2, z2, p2) {
@@ -96801,9 +96801,9 @@ function interpolateQuery(a2, b, t) {
96801
96801
  }
96802
96802
  return {
96803
96803
  side: sideA,
96804
- u: lerp$4(a2.u ?? 0.5, b.u ?? 0.5, t),
96805
- v: lerp$4(a2.v ?? 0.5, b.v ?? 0.5, t),
96806
- offset: lerp$4(a2.offset ?? 0, b.offset ?? 0, t)
96804
+ u: lerp$5(a2.u ?? 0.5, b.u ?? 0.5, t),
96805
+ v: lerp$5(a2.v ?? 0.5, b.v ?? 0.5, t),
96806
+ offset: lerp$5(a2.offset ?? 0, b.offset ?? 0, t)
96807
96807
  };
96808
96808
  }
96809
96809
  function resolvePathQueries(points) {
@@ -96928,7 +96928,7 @@ class ProductSkin {
96928
96928
  }
96929
96929
  /** Interpolate center, width, and depth at a normalized v or absolute axis value. */
96930
96930
  stationAt(vOrAxis) {
96931
- const axisValue = vOrAxis >= 0 && vOrAxis <= 1 ? lerp$4(this.axisMin, this.axisMax, vOrAxis) : clamp$5(vOrAxis, this.axisMin, this.axisMax);
96931
+ const axisValue = vOrAxis >= 0 && vOrAxis <= 1 ? lerp$5(this.axisMin, this.axisMax, vOrAxis) : clamp$5(vOrAxis, this.axisMin, this.axisMax);
96932
96932
  const sorted = this.stations;
96933
96933
  for (let index2 = 0; index2 < sorted.length - 1; index2 += 1) {
96934
96934
  const a2 = sorted[index2];
@@ -96940,12 +96940,12 @@ class ProductSkin {
96940
96940
  const t = clamp$5((axisValue - aAxis) / span, 0, 1);
96941
96941
  return {
96942
96942
  axisValue,
96943
- center: [lerp$4(a2.center[0], b.center[0], t), lerp$4(a2.center[1], b.center[1], t), lerp$4(a2.center[2], b.center[2], t)],
96944
- width: lerp$4(a2.profile.width, b.profile.width, t),
96945
- depth: lerp$4(a2.profile.depth, b.profile.depth, t),
96943
+ center: [lerp$5(a2.center[0], b.center[0], t), lerp$5(a2.center[1], b.center[1], t), lerp$5(a2.center[2], b.center[2], t)],
96944
+ width: lerp$5(a2.profile.width, b.profile.width, t),
96945
+ depth: lerp$5(a2.profile.depth, b.profile.depth, t),
96946
96946
  dWidth: (b.profile.width - a2.profile.width) / span,
96947
96947
  dDepth: (b.profile.depth - a2.profile.depth) / span,
96948
- exponent: lerp$4(profileExponent(a2), profileExponent(b), t),
96948
+ exponent: lerp$5(profileExponent(a2), profileExponent(b), t),
96949
96949
  kind: a2.profile.kind === b.profile.kind ? a2.profile.kind : "custom"
96950
96950
  };
96951
96951
  }
@@ -97778,7 +97778,7 @@ function requirePositive$3(value, label) {
97778
97778
  function clamp$4(value, min2, max2) {
97779
97779
  return Math.max(min2, Math.min(max2, value));
97780
97780
  }
97781
- function lerp$3(a2, b, t) {
97781
+ function lerp$4(a2, b, t) {
97782
97782
  return a2 + (b - a2) * t;
97783
97783
  }
97784
97784
  function add(a2, b) {
@@ -97828,19 +97828,19 @@ function transformLocal(point2, tangentAcross, normal, tangentAlong, x2, y2, z2
97828
97828
  function interpolateCylinder(a2, b, t, mode) {
97829
97829
  let delta = b.angle - a2.angle;
97830
97830
  if (mode === "shortest" && Math.abs(delta) > 180) delta -= Math.sign(delta) * 360;
97831
- return { kind: "cylinder", angle: a2.angle + delta * t, z: lerp$3(a2.z, b.z, t), offset: lerp$3(a2.offset ?? 0, b.offset ?? 0, t) };
97831
+ return { kind: "cylinder", angle: a2.angle + delta * t, z: lerp$4(a2.z, b.z, t), offset: lerp$4(a2.offset ?? 0, b.offset ?? 0, t) };
97832
97832
  }
97833
97833
  function interpolatePlane(a2, b, t) {
97834
- return { kind: "plane", x: lerp$3(a2.x, b.x, t), y: lerp$3(a2.y, b.y, t), offset: lerp$3(a2.offset ?? 0, b.offset ?? 0, t) };
97834
+ return { kind: "plane", x: lerp$4(a2.x, b.x, t), y: lerp$4(a2.y, b.y, t), offset: lerp$4(a2.offset ?? 0, b.offset ?? 0, t) };
97835
97835
  }
97836
97836
  function interpolateProductSkin(a2, b, t) {
97837
97837
  if ((a2.side ?? b.side) !== (b.side ?? a2.side)) throw new Error("SurfacePath on ProductSkin currently supports one side per path; split side transitions into separate members.");
97838
97838
  return {
97839
97839
  kind: "productSkin",
97840
97840
  side: a2.side ?? b.side,
97841
- u: lerp$3(a2.u ?? 0.5, b.u ?? 0.5, t),
97842
- v: lerp$3(a2.v ?? 0.5, b.v ?? 0.5, t),
97843
- offset: lerp$3(a2.offset ?? 0, b.offset ?? 0, t)
97841
+ u: lerp$4(a2.u ?? 0.5, b.u ?? 0.5, t),
97842
+ v: lerp$4(a2.v ?? 0.5, b.v ?? 0.5, t),
97843
+ offset: lerp$4(a2.offset ?? 0, b.offset ?? 0, t)
97844
97844
  };
97845
97845
  }
97846
97846
  class SurfacePath {
@@ -98938,7 +98938,7 @@ function counterboresForPlate(spec2, width, height, thickness, diagnostics) {
98938
98938
  function minWidthAcrossAlongRange(widthAtT, length4, minAlong, maxAlong) {
98939
98939
  let minWidth = Number.POSITIVE_INFINITY;
98940
98940
  for (let index2 = 0; index2 <= 8; index2 += 1) {
98941
- const along = lerp$3(minAlong, maxAlong, index2 / 8);
98941
+ const along = lerp$4(minAlong, maxAlong, index2 / 8);
98942
98942
  const t = Math.max(0, Math.min(1, (along + length4 / 2) / Math.max(length4, 1e-8)));
98943
98943
  minWidth = Math.min(minWidth, widthAtT(t));
98944
98944
  }
@@ -99238,7 +99238,7 @@ function pathParameterAtDistance(samples, distance2) {
99238
99238
  const segmentLength = Math.hypot(b.point[0] - a2.point[0], b.point[1] - a2.point[1], b.point[2] - a2.point[2]);
99239
99239
  if (traveled + segmentLength >= distance2) {
99240
99240
  const localT = segmentLength <= 1e-8 ? 0 : (distance2 - traveled) / segmentLength;
99241
- return lerp$3(a2.t, b.t, localT);
99241
+ return lerp$4(a2.t, b.t, localT);
99242
99242
  }
99243
99243
  traveled += segmentLength;
99244
99244
  }
@@ -99291,7 +99291,7 @@ function compileBandFootprintMesh(path2, input) {
99291
99291
  const width = input.widthAt(t);
99292
99292
  const along = distance2 - length4 / 2;
99293
99293
  for (let acrossIndex = 0; acrossIndex <= acrossSegments; acrossIndex += 1) {
99294
- const across = lerp$3(-width / 2, width / 2, acrossIndex / acrossSegments);
99294
+ const across = lerp$4(-width / 2, width / 2, acrossIndex / acrossSegments);
99295
99295
  mesh.vertices.push(pointAtProfile([across, along], false));
99296
99296
  }
99297
99297
  }
@@ -99301,7 +99301,7 @@ function compileBandFootprintMesh(path2, input) {
99301
99301
  const width = input.widthAt(t);
99302
99302
  const along = distance2 - length4 / 2;
99303
99303
  for (let acrossIndex = 0; acrossIndex <= acrossSegments; acrossIndex += 1) {
99304
- const across = lerp$3(-width / 2, width / 2, acrossIndex / acrossSegments);
99304
+ const across = lerp$4(-width / 2, width / 2, acrossIndex / acrossSegments);
99305
99305
  mesh.vertices.push(pointAtProfile([across, along], true));
99306
99306
  }
99307
99307
  }
@@ -99313,7 +99313,7 @@ function compileBandFootprintMesh(path2, input) {
99313
99313
  const width = input.widthAt(t);
99314
99314
  const along = distance2 - length4 / 2;
99315
99315
  for (let acrossIndex = 0; acrossIndex < acrossSegments; acrossIndex += 1) {
99316
- const across = lerp$3(-width / 2, width / 2, (acrossIndex + 0.5) / acrossSegments);
99316
+ const across = lerp$4(-width / 2, width / 2, (acrossIndex + 0.5) / acrossSegments);
99317
99317
  filled[alongIndex][acrossIndex] = !holes.some((hole2) => pointInProfileLoop([across, along], hole2));
99318
99318
  }
99319
99319
  }
@@ -101513,7 +101513,7 @@ function midpoint$1(a2, b) {
101513
101513
  requireVec3$1(b, "b");
101514
101514
  return [(a2[0] + b[0]) / 2, (a2[1] + b[1]) / 2, (a2[2] + b[2]) / 2];
101515
101515
  }
101516
- function lerp$2(a2, b, t) {
101516
+ function lerp$3(a2, b, t) {
101517
101517
  requireVec3$1(a2, "a");
101518
101518
  requireVec3$1(b, "b");
101519
101519
  requireFiniteNumber(t, "t");
@@ -101543,7 +101543,7 @@ const Points2 = {
101543
101543
  /** Center point between two 3D points. */
101544
101544
  midpoint: midpoint$1,
101545
101545
  /** Linearly interpolate between two 3D points. t=0 returns a, t=1 returns b. */
101546
- lerp: lerp$2,
101546
+ lerp: lerp$3,
101547
101547
  /** Unit direction vector from a to b. Throws if a and b are the same point. */
101548
101548
  direction,
101549
101549
  /** Move a point along a direction vector by a given amount. */
@@ -122079,7 +122079,7 @@ function railCrossAt(rail2, position) {
122079
122079
  const b = points[index2 + 1];
122080
122080
  if (position >= a2.position - LOFT_GUIDE_EPS && position <= b.position + LOFT_GUIDE_EPS) {
122081
122081
  const t = (position - a2.position) / (b.position - a2.position);
122082
- return [lerp$1(a2.cross[0], b.cross[0], t), lerp$1(a2.cross[1], b.cross[1], t)];
122082
+ return [lerp$2(a2.cross[0], b.cross[0], t), lerp$2(a2.cross[1], b.cross[1], t)];
122083
122083
  }
122084
122084
  }
122085
122085
  throw new Error("Loft guide rail does not cover requested station position");
@@ -122117,7 +122117,7 @@ function crossPointForAxis(axis, point2) {
122117
122117
  if (axis === "Y") return [point2[0], -point2[2]];
122118
122118
  return [point2[0], point2[1]];
122119
122119
  }
122120
- function lerp$1(a2, b, t) {
122120
+ function lerp$2(a2, b, t) {
122121
122121
  return a2 + (b - a2) * t;
122122
122122
  }
122123
122123
  function loftWithGuideRails(stations, rails, options = {}) {
@@ -122241,13 +122241,13 @@ function sketchBounds(profile) {
122241
122241
  }
122242
122242
  function lerpBounds(a2, b, t) {
122243
122243
  return {
122244
- minX: lerp(a2.minX, b.minX, t),
122245
- maxX: lerp(a2.maxX, b.maxX, t),
122246
- minY: lerp(a2.minY, b.minY, t),
122247
- maxY: lerp(a2.maxY, b.maxY, t)
122244
+ minX: lerp$1(a2.minX, b.minX, t),
122245
+ maxX: lerp$1(a2.maxX, b.maxX, t),
122246
+ minY: lerp$1(a2.minY, b.minY, t),
122247
+ maxY: lerp$1(a2.maxY, b.maxY, t)
122248
122248
  };
122249
122249
  }
122250
- function lerp(a2, b, t) {
122250
+ function lerp$1(a2, b, t) {
122251
122251
  return a2 + (b - a2) * t;
122252
122252
  }
122253
122253
  function mapLoftPath2D(path2, label, mapper) {
@@ -341732,7 +341732,7 @@ function runScript(code, fileName = "main.forge.js", allFiles = {}, options = {}
341732
341732
  }
341733
341733
  }
341734
341734
  const DEFAULT_LEAF_SIZE = 8;
341735
- function cloneVec3$1(value) {
341735
+ function cloneVec3$2(value) {
341736
341736
  return [value[0], value[1], value[2]];
341737
341737
  }
341738
341738
  function emptyBounds() {
@@ -341800,14 +341800,14 @@ class AabbSpatialIndex {
341800
341800
  nodeCount += 1;
341801
341801
  const bounds = boundsFor(entries, indexes);
341802
341802
  if (indexes.length <= this.leafSize) {
341803
- return { min: cloneVec3$1(bounds.min), max: cloneVec3$1(bounds.max), left: null, right: null, indexes };
341803
+ return { min: cloneVec3$2(bounds.min), max: cloneVec3$2(bounds.max), left: null, right: null, indexes };
341804
341804
  }
341805
341805
  const axis = longestAxis(bounds);
341806
341806
  indexes.sort((a2, b) => centerOnAxis(entries[a2], axis) - centerOnAxis(entries[b], axis) || a2 - b);
341807
341807
  const mid = Math.max(1, Math.floor(indexes.length / 2));
341808
341808
  return {
341809
- min: cloneVec3$1(bounds.min),
341810
- max: cloneVec3$1(bounds.max),
341809
+ min: cloneVec3$2(bounds.min),
341810
+ max: cloneVec3$2(bounds.max),
341811
341811
  left: build(indexes.slice(0, mid)),
341812
341812
  right: build(indexes.slice(mid)),
341813
341813
  indexes: null
@@ -341873,7 +341873,7 @@ class AabbSpatialIndex {
341873
341873
  const DEFAULT_COLLISION_INSPECTION_OPTIONS = {
341874
341874
  minOverlapVolume: 0.1
341875
341875
  };
341876
- function cloneVec3(value) {
341876
+ function cloneVec3$1(value) {
341877
341877
  return [value[0], value[1], value[2]];
341878
341878
  }
341879
341879
  function isIdentityTransform(matrix) {
@@ -341915,8 +341915,8 @@ function prepareEntry(entry) {
341915
341915
  if (isIdentityTransform(entry.transform)) {
341916
341916
  return {
341917
341917
  ...entry,
341918
- min: cloneVec3(entry.min),
341919
- max: cloneVec3(entry.max)
341918
+ min: cloneVec3$1(entry.min),
341919
+ max: cloneVec3$1(entry.max)
341920
341920
  };
341921
341921
  }
341922
341922
  const bbox = transformBBox(entry.min, entry.max, entry.transform);
@@ -341935,7 +341935,7 @@ function shouldSkipPair(a2, b, options) {
341935
341935
  if (options.skipMockPairs && a2.mock && b.mock) return true;
341936
341936
  return false;
341937
341937
  }
341938
- function collectCandidatePairs(entries, options) {
341938
+ function collectCandidatePairs$1(entries, options) {
341939
341939
  const index2 = new AabbSpatialIndex(entries, 1);
341940
341940
  const result = index2.overlapPairs({
341941
341941
  padding: options.bboxPadding,
@@ -341976,7 +341976,7 @@ function analyzeCollisionIntersections(entries, rawOptions = {}) {
341976
341976
  const warnings = [];
341977
341977
  const collisions = [];
341978
341978
  const preparedEntries = entries.map((entry) => prepareEntry(entry));
341979
- const { pairs: candidatePairs, bboxPairChecks } = collectCandidatePairs(preparedEntries, options);
341979
+ const { pairs: candidatePairs, bboxPairChecks } = collectCandidatePairs$1(preparedEntries, options);
341980
341980
  const exactCandidatePairs = candidatePairs.filter((pair) => pair.bboxOverlapVolume > options.minOverlapVolume);
341981
341981
  const bboxVolumePrunedPairCount = candidatePairs.length - exactCandidatePairs.length;
341982
341982
  const limitedCandidatePairs = options.maxCandidatePairs === null ? exactCandidatePairs : exactCandidatePairs.slice(0, options.maxCandidatePairs);
@@ -342062,8 +342062,8 @@ function analyzeCollisionIntersections(entries, rawOptions = {}) {
342062
342062
  treePath: entry.treePath,
342063
342063
  mock: entry.mock === true,
342064
342064
  bbox: {
342065
- min: cloneVec3(entry.min),
342066
- max: cloneVec3(entry.max)
342065
+ min: cloneVec3$1(entry.min),
342066
+ max: cloneVec3$1(entry.max)
342067
342067
  }
342068
342068
  }));
342069
342069
  return {
@@ -342277,6 +342277,706 @@ function geometryWithVisibleVertexColors(geometry, colors) {
342277
342277
  out.setAttribute("color", colorAttribute);
342278
342278
  return out;
342279
342279
  }
342280
+ const DEFAULT_ROUGHNESS_INSPECTION_OPTIONS = {
342281
+ smoothAngleDeg: 5,
342282
+ sharpAngleDeg: 30,
342283
+ harshAngleDeg: 90,
342284
+ maxSamplesPerObject: 5e3
342285
+ };
342286
+ const ROUGHNESS_COLORS = {
342287
+ smooth: [62, 72, 84],
342288
+ moderate: [255, 214, 0],
342289
+ sharp: [255, 124, 34],
342290
+ harsh: [255, 42, 96]
342291
+ };
342292
+ function resolveRoughnessInspectionOptions(raw = {}) {
342293
+ const options = {
342294
+ smoothAngleDeg: raw.smoothAngleDeg ?? DEFAULT_ROUGHNESS_INSPECTION_OPTIONS.smoothAngleDeg,
342295
+ sharpAngleDeg: raw.sharpAngleDeg ?? DEFAULT_ROUGHNESS_INSPECTION_OPTIONS.sharpAngleDeg,
342296
+ harshAngleDeg: raw.harshAngleDeg ?? DEFAULT_ROUGHNESS_INSPECTION_OPTIONS.harshAngleDeg,
342297
+ maxSamplesPerObject: raw.maxSamplesPerObject ?? DEFAULT_ROUGHNESS_INSPECTION_OPTIONS.maxSamplesPerObject
342298
+ };
342299
+ if (!Number.isFinite(options.smoothAngleDeg) || options.smoothAngleDeg < 0) {
342300
+ throw new Error(`smoothAngleDeg must be a finite non-negative angle (got ${options.smoothAngleDeg}).`);
342301
+ }
342302
+ if (!Number.isFinite(options.sharpAngleDeg) || options.sharpAngleDeg <= options.smoothAngleDeg) {
342303
+ throw new Error(`sharpAngleDeg must be greater than smoothAngleDeg (got ${options.sharpAngleDeg}).`);
342304
+ }
342305
+ if (!Number.isFinite(options.harshAngleDeg) || options.harshAngleDeg <= options.sharpAngleDeg || options.harshAngleDeg > 180) {
342306
+ throw new Error(`harshAngleDeg must be greater than sharpAngleDeg and <= 180 (got ${options.harshAngleDeg}).`);
342307
+ }
342308
+ if (!Number.isFinite(options.maxSamplesPerObject) || options.maxSamplesPerObject <= 0) {
342309
+ throw new Error(`maxSamplesPerObject must be a positive finite number (got ${options.maxSamplesPerObject}).`);
342310
+ }
342311
+ return {
342312
+ ...options,
342313
+ maxSamplesPerObject: Math.max(1, Math.floor(options.maxSamplesPerObject))
342314
+ };
342315
+ }
342316
+ function roughnessClassForAngle(angleDeg, options) {
342317
+ if (angleDeg >= options.harshAngleDeg) return "harsh";
342318
+ if (angleDeg >= options.sharpAngleDeg) return "sharp";
342319
+ if (angleDeg >= options.smoothAngleDeg) return "moderate";
342320
+ return "smooth";
342321
+ }
342322
+ function roughnessScoreForAngle(angleDeg, options) {
342323
+ if (angleDeg < options.sharpAngleDeg) return 0;
342324
+ if (angleDeg < options.harshAngleDeg) {
342325
+ return MathUtils.lerp(0.48, 0.82, (angleDeg - options.sharpAngleDeg) / (options.harshAngleDeg - options.sharpAngleDeg));
342326
+ }
342327
+ return 1;
342328
+ }
342329
+ function roughnessColorForAngle(angleDeg, options) {
342330
+ const cls = roughnessClassForAngle(angleDeg, options);
342331
+ if (cls === "smooth" || cls === "harsh") return ROUGHNESS_COLORS[cls];
342332
+ if (cls === "moderate") {
342333
+ return lerpRgb(
342334
+ ROUGHNESS_COLORS.moderate,
342335
+ ROUGHNESS_COLORS.sharp,
342336
+ (angleDeg - options.smoothAngleDeg) / (options.sharpAngleDeg - options.smoothAngleDeg)
342337
+ );
342338
+ }
342339
+ return lerpRgb(
342340
+ ROUGHNESS_COLORS.sharp,
342341
+ ROUGHNESS_COLORS.harsh,
342342
+ (angleDeg - options.sharpAngleDeg) / (options.harshAngleDeg - options.sharpAngleDeg)
342343
+ );
342344
+ }
342345
+ function lerpRgb(a2, b, t) {
342346
+ const clamped = MathUtils.clamp(t, 0, 1);
342347
+ return [
342348
+ Math.round(MathUtils.lerp(a2[0], b[0], clamped)),
342349
+ Math.round(MathUtils.lerp(a2[1], b[1], clamped)),
342350
+ Math.round(MathUtils.lerp(a2[2], b[2], clamped))
342351
+ ];
342352
+ }
342353
+ const AXIS_NAMES = ["x", "y", "z"];
342354
+ function nearestBoundaryGap(a2, b, axis) {
342355
+ return Math.min(Math.abs(a2.max[axis] - b.min[axis]), Math.abs(b.max[axis] - a2.min[axis]));
342356
+ }
342357
+ function hasPositiveGap(gaps) {
342358
+ return gaps[0] > 0 || gaps[1] > 0 || gaps[2] > 0;
342359
+ }
342360
+ function contactFromBBoxes(a2, b, tolerance) {
342361
+ const gaps = aabbGaps(a2, b);
342362
+ const largestGap = Math.max(gaps[0], gaps[1], gaps[2]);
342363
+ if (largestGap > tolerance) return { touching: false, gap: largestGap };
342364
+ const separatedAxes = gaps.map((gap, axis) => ({ gap, axis })).filter((entry) => entry.gap > 0);
342365
+ if (separatedAxes.length > 0) {
342366
+ const nearest2 = separatedAxes.reduce((best, entry) => entry.gap > best.gap ? entry : best, separatedAxes[0]);
342367
+ return { touching: true, gap: nearest2.gap, axis: AXIS_NAMES[nearest2.axis] };
342368
+ }
342369
+ const boundaryAxes = AXIS_NAMES.map((axisName, axis) => ({
342370
+ axis,
342371
+ axisName,
342372
+ gap: nearestBoundaryGap(a2, b, axis)
342373
+ })).filter((entry) => entry.gap <= tolerance);
342374
+ if (boundaryAxes.length === 0) return { touching: false, gap: 0 };
342375
+ const nearest = boundaryAxes.reduce((best, entry) => entry.gap < best.gap ? entry : best, boundaryAxes[0]);
342376
+ return { touching: true, gap: nearest.gap, axis: nearest.axisName };
342377
+ }
342378
+ function isFiniteTriangle(positions, offset2) {
342379
+ for (let index2 = 0; index2 < 9; index2 += 1) {
342380
+ if (!Number.isFinite(positions[offset2 + index2])) return false;
342381
+ }
342382
+ return true;
342383
+ }
342384
+ function triangleRef(positions, offset2) {
342385
+ if (!isFiniteTriangle(positions, offset2)) return null;
342386
+ const ax = positions[offset2];
342387
+ const ay = positions[offset2 + 1];
342388
+ const az = positions[offset2 + 2];
342389
+ const bx = positions[offset2 + 3];
342390
+ const by = positions[offset2 + 4];
342391
+ const bz = positions[offset2 + 5];
342392
+ const cx = positions[offset2 + 6];
342393
+ const cy = positions[offset2 + 7];
342394
+ const cz = positions[offset2 + 8];
342395
+ return {
342396
+ offset: offset2,
342397
+ min: [Math.min(ax, bx, cx), Math.min(ay, by, cy), Math.min(az, bz, cz)],
342398
+ max: [Math.max(ax, bx, cx), Math.max(ay, by, cy), Math.max(az, bz, cz)]
342399
+ };
342400
+ }
342401
+ function meshContactDataFor(entry) {
342402
+ const positions = entry.positions;
342403
+ if (!positions || positions.length < 9) return null;
342404
+ const triangleCount = Math.floor(positions.length / 9);
342405
+ const triangles = [];
342406
+ for (let triangleIndex = 0; triangleIndex < triangleCount; triangleIndex += 1) {
342407
+ const triangle = triangleRef(positions, triangleIndex * 9);
342408
+ if (triangle) triangles.push(triangle);
342409
+ }
342410
+ if (triangles.length === 0) return null;
342411
+ return {
342412
+ positions,
342413
+ vertexCount: triangleCount * 3,
342414
+ triangles
342415
+ };
342416
+ }
342417
+ function distSq(px2, py2, pz2, qx, qy, qz) {
342418
+ const dx = px2 - qx;
342419
+ const dy = py2 - qy;
342420
+ const dz = pz2 - qz;
342421
+ return dx * dx + dy * dy + dz * dz;
342422
+ }
342423
+ function pointSegmentDistanceSq(point2, start, end) {
342424
+ const dx = end[0] - start[0];
342425
+ const dy = end[1] - start[1];
342426
+ const dz = end[2] - start[2];
342427
+ const lengthSq = dx * dx + dy * dy + dz * dz;
342428
+ if (lengthSq <= 1e-20) return distSq(point2[0], point2[1], point2[2], start[0], start[1], start[2]);
342429
+ const t = Math.max(0, Math.min(1, ((point2[0] - start[0]) * dx + (point2[1] - start[1]) * dy + (point2[2] - start[2]) * dz) / lengthSq));
342430
+ return distSq(point2[0], point2[1], point2[2], start[0] + t * dx, start[1] + t * dy, start[2] + t * dz);
342431
+ }
342432
+ function pointTriangleDistanceSq(px2, py2, pz2, ax, ay, az, bx, by, bz, cx, cy, cz) {
342433
+ const abx = bx - ax;
342434
+ const aby = by - ay;
342435
+ const abz = bz - az;
342436
+ const acx = cx - ax;
342437
+ const acy = cy - ay;
342438
+ const acz = cz - az;
342439
+ const apx = px2 - ax;
342440
+ const apy = py2 - ay;
342441
+ const apz = pz2 - az;
342442
+ const d1 = abx * apx + aby * apy + abz * apz;
342443
+ const d2 = acx * apx + acy * apy + acz * apz;
342444
+ if (d1 <= 0 && d2 <= 0) return distSq(px2, py2, pz2, ax, ay, az);
342445
+ const bpx = px2 - bx;
342446
+ const bpy = py2 - by;
342447
+ const bpz = pz2 - bz;
342448
+ const d3 = abx * bpx + aby * bpy + abz * bpz;
342449
+ const d4 = acx * bpx + acy * bpy + acz * bpz;
342450
+ if (d3 >= 0 && d4 <= d3) return distSq(px2, py2, pz2, bx, by, bz);
342451
+ const vc = d1 * d4 - d3 * d2;
342452
+ if (vc <= 0 && d1 >= 0 && d3 <= 0) {
342453
+ const v22 = d1 / (d1 - d3);
342454
+ return distSq(px2, py2, pz2, ax + v22 * abx, ay + v22 * aby, az + v22 * abz);
342455
+ }
342456
+ const cpx = px2 - cx;
342457
+ const cpy = py2 - cy;
342458
+ const cpz = pz2 - cz;
342459
+ const d5 = abx * cpx + aby * cpy + abz * cpz;
342460
+ const d6 = acx * cpx + acy * cpy + acz * cpz;
342461
+ if (d6 >= 0 && d5 <= d6) return distSq(px2, py2, pz2, cx, cy, cz);
342462
+ const vb = d5 * d2 - d1 * d6;
342463
+ if (vb <= 0 && d2 >= 0 && d6 <= 0) {
342464
+ const w22 = d2 / (d2 - d6);
342465
+ return distSq(px2, py2, pz2, ax + w22 * acx, ay + w22 * acy, az + w22 * acz);
342466
+ }
342467
+ const va = d3 * d6 - d5 * d4;
342468
+ if (va <= 0 && d4 - d3 >= 0 && d5 - d6 >= 0) {
342469
+ const bcx = cx - bx;
342470
+ const bcy = cy - by;
342471
+ const bcz = cz - bz;
342472
+ const w22 = (d4 - d3) / (d4 - d3 + d5 - d6);
342473
+ return distSq(px2, py2, pz2, bx + w22 * bcx, by + w22 * bcy, bz + w22 * bcz);
342474
+ }
342475
+ const barycentricTotal = va + vb + vc;
342476
+ if (!Number.isFinite(barycentricTotal) || Math.abs(barycentricTotal) < 1e-20) {
342477
+ return Math.min(distSq(px2, py2, pz2, ax, ay, az), distSq(px2, py2, pz2, bx, by, bz), distSq(px2, py2, pz2, cx, cy, cz));
342478
+ }
342479
+ const denom = 1 / barycentricTotal;
342480
+ const v = vb * denom;
342481
+ const w2 = vc * denom;
342482
+ return distSq(px2, py2, pz2, ax + abx * v + acx * w2, ay + aby * v + acy * w2, az + abz * v + acz * w2);
342483
+ }
342484
+ function segmentSegmentDistanceSq(a0, a1, b0, b1) {
342485
+ const ux = a1[0] - a0[0];
342486
+ const uy = a1[1] - a0[1];
342487
+ const uz = a1[2] - a0[2];
342488
+ const vx = b1[0] - b0[0];
342489
+ const vy = b1[1] - b0[1];
342490
+ const vz = b1[2] - b0[2];
342491
+ const wx = a0[0] - b0[0];
342492
+ const wy = a0[1] - b0[1];
342493
+ const wz = a0[2] - b0[2];
342494
+ const a2 = ux * ux + uy * uy + uz * uz;
342495
+ const b = ux * vx + uy * vy + uz * vz;
342496
+ const c2 = vx * vx + vy * vy + vz * vz;
342497
+ const d2 = ux * wx + uy * wy + uz * wz;
342498
+ const e = vx * wx + vy * wy + vz * wz;
342499
+ const denom = a2 * c2 - b * b;
342500
+ let sNumerator = denom;
342501
+ let sDenominator = denom;
342502
+ let tNumerator = denom;
342503
+ let tDenominator = denom;
342504
+ if (a2 <= 1e-20) return pointSegmentDistanceSq(a0, b0, b1);
342505
+ if (c2 <= 1e-20) return pointSegmentDistanceSq(b0, a0, a1);
342506
+ if (denom < 1e-20) {
342507
+ sNumerator = 0;
342508
+ sDenominator = 1;
342509
+ tNumerator = e;
342510
+ tDenominator = c2;
342511
+ } else {
342512
+ sNumerator = b * e - c2 * d2;
342513
+ tNumerator = a2 * e - b * d2;
342514
+ if (sNumerator < 0) {
342515
+ sNumerator = 0;
342516
+ tNumerator = e;
342517
+ tDenominator = c2;
342518
+ } else if (sNumerator > sDenominator) {
342519
+ sNumerator = sDenominator;
342520
+ tNumerator = e + b;
342521
+ tDenominator = c2;
342522
+ }
342523
+ }
342524
+ if (tNumerator < 0) {
342525
+ tNumerator = 0;
342526
+ if (-d2 < 0) {
342527
+ sNumerator = 0;
342528
+ } else if (-d2 > a2) {
342529
+ sNumerator = sDenominator;
342530
+ } else {
342531
+ sNumerator = -d2;
342532
+ sDenominator = a2;
342533
+ }
342534
+ } else if (tNumerator > tDenominator) {
342535
+ tNumerator = tDenominator;
342536
+ if (-d2 + b < 0) {
342537
+ sNumerator = 0;
342538
+ } else if (-d2 + b > a2) {
342539
+ sNumerator = sDenominator;
342540
+ } else {
342541
+ sNumerator = -d2 + b;
342542
+ sDenominator = a2;
342543
+ }
342544
+ }
342545
+ const s = Math.abs(sNumerator) < 1e-20 ? 0 : sNumerator / sDenominator;
342546
+ const t = Math.abs(tNumerator) < 1e-20 ? 0 : tNumerator / tDenominator;
342547
+ const dx = wx + s * ux - t * vx;
342548
+ const dy = wy + s * uy - t * vy;
342549
+ const dz = wz + s * uz - t * vz;
342550
+ return dx * dx + dy * dy + dz * dz;
342551
+ }
342552
+ function trianglePoint(positions, triangle, corner) {
342553
+ const offset2 = triangle.offset + corner * 3;
342554
+ return [positions[offset2], positions[offset2 + 1], positions[offset2 + 2]];
342555
+ }
342556
+ function bboxDistanceSq(a2, b) {
342557
+ let total = 0;
342558
+ for (let axis = 0; axis < 3; axis += 1) {
342559
+ const gap = Math.max(0, a2.min[axis] - b.max[axis], b.min[axis] - a2.max[axis]);
342560
+ total += gap * gap;
342561
+ }
342562
+ return total;
342563
+ }
342564
+ function triangleDistanceSq(aPositions, a2, bPositions, b) {
342565
+ const a0 = trianglePoint(aPositions, a2, 0);
342566
+ const a1 = trianglePoint(aPositions, a2, 1);
342567
+ const a22 = trianglePoint(aPositions, a2, 2);
342568
+ const b0 = trianglePoint(bPositions, b, 0);
342569
+ const b1 = trianglePoint(bPositions, b, 1);
342570
+ const b22 = trianglePoint(bPositions, b, 2);
342571
+ return Math.min(
342572
+ pointTriangleDistanceSq(a0[0], a0[1], a0[2], b0[0], b0[1], b0[2], b1[0], b1[1], b1[2], b22[0], b22[1], b22[2]),
342573
+ pointTriangleDistanceSq(a1[0], a1[1], a1[2], b0[0], b0[1], b0[2], b1[0], b1[1], b1[2], b22[0], b22[1], b22[2]),
342574
+ pointTriangleDistanceSq(a22[0], a22[1], a22[2], b0[0], b0[1], b0[2], b1[0], b1[1], b1[2], b22[0], b22[1], b22[2]),
342575
+ pointTriangleDistanceSq(b0[0], b0[1], b0[2], a0[0], a0[1], a0[2], a1[0], a1[1], a1[2], a22[0], a22[1], a22[2]),
342576
+ pointTriangleDistanceSq(b1[0], b1[1], b1[2], a0[0], a0[1], a0[2], a1[0], a1[1], a1[2], a22[0], a22[1], a22[2]),
342577
+ pointTriangleDistanceSq(b22[0], b22[1], b22[2], a0[0], a0[1], a0[2], a1[0], a1[1], a1[2], a22[0], a22[1], a22[2]),
342578
+ segmentSegmentDistanceSq(a0, a1, b0, b1),
342579
+ segmentSegmentDistanceSq(a0, a1, b1, b22),
342580
+ segmentSegmentDistanceSq(a0, a1, b22, b0),
342581
+ segmentSegmentDistanceSq(a1, a22, b0, b1),
342582
+ segmentSegmentDistanceSq(a1, a22, b1, b22),
342583
+ segmentSegmentDistanceSq(a1, a22, b22, b0),
342584
+ segmentSegmentDistanceSq(a22, a0, b0, b1),
342585
+ segmentSegmentDistanceSq(a22, a0, b1, b22),
342586
+ segmentSegmentDistanceSq(a22, a0, b22, b0)
342587
+ );
342588
+ }
342589
+ function meshEntriesContactDistance(a2, b, tolerance) {
342590
+ const toleranceSq = tolerance * tolerance;
342591
+ let bestDistanceSq = Infinity;
342592
+ for (const aTriangle of a2.triangles) {
342593
+ for (const bTriangle of b.triangles) {
342594
+ if (bboxDistanceSq(aTriangle, bTriangle) > toleranceSq) continue;
342595
+ const distanceSq = triangleDistanceSq(a2.positions, aTriangle, b.positions, bTriangle);
342596
+ if (distanceSq > toleranceSq) continue;
342597
+ if (distanceSq <= 1e-20) return 0;
342598
+ bestDistanceSq = Math.min(bestDistanceSq, distanceSq);
342599
+ }
342600
+ }
342601
+ return Number.isFinite(bestDistanceSq) ? Math.sqrt(bestDistanceSq) : null;
342602
+ }
342603
+ function intersectionVolume(a2, b) {
342604
+ try {
342605
+ const hit = a2.shape.intersect(b.shape);
342606
+ if (hit.isEmpty()) return { volume: 0 };
342607
+ const volume = hit.volume();
342608
+ return { volume: Number.isFinite(volume) ? volume : 0 };
342609
+ } catch (err2) {
342610
+ const message = err2 instanceof Error ? err2.message : String(err2);
342611
+ return { volume: null, warning: `Could not boolean-test ${a2.name} against ${b.name}: ${message}` };
342612
+ }
342613
+ }
342614
+ function detectPhysicalContact(a2, b, options, meshCache = {}) {
342615
+ const gaps = aabbGaps(a2, b);
342616
+ const largestGap = Math.max(gaps[0], gaps[1], gaps[2]);
342617
+ if (largestGap > options.contactTolerance) return { contact: null };
342618
+ const sourceMesh = meshCache.sourceMesh !== void 0 ? meshCache.sourceMesh : meshContactDataFor(a2);
342619
+ const targetMesh = meshCache.targetMesh !== void 0 ? meshCache.targetMesh : meshContactDataFor(b);
342620
+ if (sourceMesh && targetMesh) {
342621
+ const distance2 = meshEntriesContactDistance(sourceMesh, targetMesh, options.contactTolerance);
342622
+ if (distance2 != null) {
342623
+ return {
342624
+ contact: {
342625
+ kind: "touching",
342626
+ method: "mesh-surface-distance",
342627
+ gap: distance2
342628
+ }
342629
+ };
342630
+ }
342631
+ }
342632
+ const bboxOverlaps = !hasPositiveGap(gaps) && aabbInteriorOverlaps(a2, b);
342633
+ if (options.exactGeometry && bboxOverlaps) {
342634
+ if (aabbOverlapVolume(a2, b) <= options.minOverlapVolume) return { contact: null };
342635
+ const overlap = intersectionVolume(a2, b);
342636
+ if (overlap.volume != null && overlap.volume > options.minOverlapVolume) {
342637
+ return {
342638
+ contact: {
342639
+ kind: "overlap",
342640
+ method: "boolean-intersection",
342641
+ gap: 0,
342642
+ overlapVolume: overlap.volume
342643
+ },
342644
+ warning: overlap.warning
342645
+ };
342646
+ }
342647
+ return { contact: null, warning: overlap.warning };
342648
+ }
342649
+ if (bboxOverlaps && options.mergeOverlappingBBoxes) {
342650
+ return {
342651
+ contact: {
342652
+ kind: "overlap",
342653
+ method: "bbox-overlap",
342654
+ gap: 0,
342655
+ overlapVolume: aabbOverlapVolume(a2, b)
342656
+ }
342657
+ };
342658
+ }
342659
+ if (options.mergeTouchingBBoxes) {
342660
+ const contact = contactFromBBoxes(a2, b, options.contactTolerance);
342661
+ if (contact.touching) {
342662
+ return {
342663
+ contact: {
342664
+ kind: "touching",
342665
+ method: "bbox-contact",
342666
+ gap: contact.gap,
342667
+ axis: contact.axis
342668
+ }
342669
+ };
342670
+ }
342671
+ }
342672
+ return { contact: null };
342673
+ }
342674
+ const DEFAULT_PHYSICAL_CONNECTIVITY_OPTIONS = {
342675
+ contactTolerance: 0.05,
342676
+ minOverlapVolume: 0.1,
342677
+ exactGeometry: true
342678
+ };
342679
+ class UnionFind {
342680
+ constructor(size) {
342681
+ __publicField(this, "parent");
342682
+ __publicField(this, "rank");
342683
+ this.parent = Array.from({ length: size }, (_2, index2) => index2);
342684
+ this.rank = Array.from({ length: size }, () => 0);
342685
+ }
342686
+ find(value) {
342687
+ const parent = this.parent[value];
342688
+ if (parent === value) return value;
342689
+ const root = this.find(parent);
342690
+ this.parent[value] = root;
342691
+ return root;
342692
+ }
342693
+ union(a2, b) {
342694
+ const rootA = this.find(a2);
342695
+ const rootB = this.find(b);
342696
+ if (rootA === rootB) return;
342697
+ if (this.rank[rootA] < this.rank[rootB]) {
342698
+ this.parent[rootA] = rootB;
342699
+ return;
342700
+ }
342701
+ if (this.rank[rootA] > this.rank[rootB]) {
342702
+ this.parent[rootB] = rootA;
342703
+ return;
342704
+ }
342705
+ this.parent[rootB] = rootA;
342706
+ this.rank[rootA] += 1;
342707
+ }
342708
+ }
342709
+ function cloneVec3(value) {
342710
+ return [value[0], value[1], value[2]];
342711
+ }
342712
+ function emptyBBox() {
342713
+ return {
342714
+ min: [Infinity, Infinity, Infinity],
342715
+ max: [-Infinity, -Infinity, -Infinity]
342716
+ };
342717
+ }
342718
+ function expandBBox(target, min2, max2) {
342719
+ for (let axis = 0; axis < 3; axis += 1) {
342720
+ target.min[axis] = Math.min(target.min[axis], min2[axis]);
342721
+ target.max[axis] = Math.max(target.max[axis], max2[axis]);
342722
+ }
342723
+ }
342724
+ function collectCandidatePairs(entries, tolerance) {
342725
+ if (entries.length < 2) return [];
342726
+ const index2 = new AabbSpatialIndex(entries);
342727
+ const pairs = index2.overlapPairs({ padding: tolerance }).pairs.map((pair) => ({
342728
+ sourceIndex: pair.sourceIndex,
342729
+ targetIndex: pair.targetIndex,
342730
+ gaps: aabbGaps(entries[pair.sourceIndex], entries[pair.targetIndex])
342731
+ })).filter((pair) => Math.max(pair.gaps[0], pair.gaps[1], pair.gaps[2]) <= tolerance);
342732
+ pairs.sort((a2, b) => a2.sourceIndex - b.sourceIndex || a2.targetIndex - b.targetIndex);
342733
+ return pairs;
342734
+ }
342735
+ function bodyCountForEntry(entry) {
342736
+ if (typeof entry.bodyCount === "number" && Number.isFinite(entry.bodyCount)) {
342737
+ return Math.max(0, Math.round(entry.bodyCount));
342738
+ }
342739
+ return 1;
342740
+ }
342741
+ function makeEdge(entries, sourceIndex, targetIndex, edge) {
342742
+ const source = entries[sourceIndex];
342743
+ const target = entries[targetIndex];
342744
+ return {
342745
+ sourceIndex,
342746
+ targetIndex,
342747
+ sourceId: source.id,
342748
+ targetId: target.id,
342749
+ sourceName: source.name,
342750
+ targetName: target.name,
342751
+ ...edge
342752
+ };
342753
+ }
342754
+ function analyzePhysicalConnectivity(entries, rawOptions = {}) {
342755
+ const exactGeometry = rawOptions.exactGeometry ?? DEFAULT_PHYSICAL_CONNECTIVITY_OPTIONS.exactGeometry;
342756
+ const options = {
342757
+ contactTolerance: rawOptions.contactTolerance ?? DEFAULT_PHYSICAL_CONNECTIVITY_OPTIONS.contactTolerance,
342758
+ minOverlapVolume: rawOptions.minOverlapVolume ?? DEFAULT_PHYSICAL_CONNECTIVITY_OPTIONS.minOverlapVolume,
342759
+ exactGeometry,
342760
+ mergeOverlappingBBoxes: rawOptions.mergeOverlappingBBoxes ?? !exactGeometry,
342761
+ mergeTouchingBBoxes: rawOptions.mergeTouchingBBoxes ?? !exactGeometry
342762
+ };
342763
+ const warnings = [];
342764
+ const edges = [];
342765
+ const unionFind = new UnionFind(entries.length);
342766
+ const meshDataByIndex = /* @__PURE__ */ new Map();
342767
+ entries.forEach((entry, index2) => {
342768
+ const meshData = meshContactDataFor(entry);
342769
+ if (meshData) meshDataByIndex.set(index2, meshData);
342770
+ });
342771
+ for (const pair of collectCandidatePairs(entries, options.contactTolerance)) {
342772
+ const i = pair.sourceIndex;
342773
+ const j = pair.targetIndex;
342774
+ const detection = detectPhysicalContact(entries[i], entries[j], options, {
342775
+ sourceMesh: meshDataByIndex.get(i) ?? null,
342776
+ targetMesh: meshDataByIndex.get(j) ?? null
342777
+ });
342778
+ if (detection.warning) warnings.push(detection.warning);
342779
+ if (!detection.contact) continue;
342780
+ unionFind.union(i, j);
342781
+ edges.push(makeEdge(entries, i, j, detection.contact));
342782
+ }
342783
+ const objects = entries.map((entry, index2) => ({
342784
+ index: index2,
342785
+ id: entry.id,
342786
+ name: entry.name,
342787
+ groupName: entry.groupName,
342788
+ treePath: entry.treePath,
342789
+ mock: entry.mock === true,
342790
+ bodyCount: bodyCountForEntry(entry),
342791
+ bbox: {
342792
+ min: cloneVec3(entry.min),
342793
+ max: cloneVec3(entry.max)
342794
+ },
342795
+ componentIndex: 0
342796
+ }));
342797
+ const componentByRoot = /* @__PURE__ */ new Map();
342798
+ const rootToComponentIndex = /* @__PURE__ */ new Map();
342799
+ for (let objectIndex = 0; objectIndex < objects.length; objectIndex += 1) {
342800
+ const root = unionFind.find(objectIndex);
342801
+ let component = componentByRoot.get(root);
342802
+ if (!component) {
342803
+ component = {
342804
+ index: componentByRoot.size + 1,
342805
+ objectIndexes: [],
342806
+ objectIds: [],
342807
+ objectNames: [],
342808
+ objectCount: 0,
342809
+ bodyCount: 0,
342810
+ bbox: emptyBBox()
342811
+ };
342812
+ componentByRoot.set(root, component);
342813
+ rootToComponentIndex.set(root, component.index);
342814
+ }
342815
+ const object = objects[objectIndex];
342816
+ object.componentIndex = rootToComponentIndex.get(root) ?? component.index;
342817
+ component.objectIndexes.push(object.index);
342818
+ component.objectIds.push(object.id);
342819
+ component.objectNames.push(object.name);
342820
+ component.objectCount += 1;
342821
+ component.bodyCount += object.bodyCount;
342822
+ expandBBox(component.bbox, object.bbox.min, object.bbox.max);
342823
+ }
342824
+ const components = [...componentByRoot.values()];
342825
+ return {
342826
+ method: options.exactGeometry ? "mesh-contact-plus-boolean-overlap" : "bbox-neighborhood",
342827
+ options,
342828
+ objectCount: objects.length,
342829
+ componentCount: components.length,
342830
+ objects,
342831
+ components,
342832
+ edges,
342833
+ warnings
342834
+ };
342835
+ }
342836
+ const DEFAULT_THICKNESS_INSPECTION_OPTIONS = {
342837
+ minThickness: 1.2,
342838
+ warnThickness: 2,
342839
+ maxThickness: 6,
342840
+ maxSamplesPerObject: 5e3,
342841
+ contactTolerance: DEFAULT_PHYSICAL_CONNECTIVITY_OPTIONS.contactTolerance
342842
+ };
342843
+ const THICKNESS_COLORS = {
342844
+ critical: [255, 28, 28],
342845
+ warning: [255, 150, 0],
342846
+ ok: [60, 220, 90],
342847
+ thick: [70, 145, 255],
342848
+ unknown: [90, 90, 90]
342849
+ };
342850
+ function finitePositive(value, fallback, label) {
342851
+ if (value === void 0) return fallback;
342852
+ if (!Number.isFinite(value) || value <= 0) {
342853
+ throw new Error(`${label} must be a positive finite number.`);
342854
+ }
342855
+ return value;
342856
+ }
342857
+ function finiteNonNegative(value, fallback, label) {
342858
+ if (value === void 0) return fallback;
342859
+ if (!Number.isFinite(value) || value < 0) {
342860
+ throw new Error(`${label} must be a non-negative finite number.`);
342861
+ }
342862
+ return value;
342863
+ }
342864
+ function resolveThicknessInspectionOptions(raw = {}) {
342865
+ const minThickness = finitePositive(raw.minThickness, DEFAULT_THICKNESS_INSPECTION_OPTIONS.minThickness, "minThickness");
342866
+ const warnThickness = finitePositive(raw.warnThickness, DEFAULT_THICKNESS_INSPECTION_OPTIONS.warnThickness, "warnThickness");
342867
+ const maxThickness = finitePositive(raw.maxThickness, DEFAULT_THICKNESS_INSPECTION_OPTIONS.maxThickness, "maxThickness");
342868
+ const maxSamplesPerObject = finitePositive(
342869
+ raw.maxSamplesPerObject,
342870
+ DEFAULT_THICKNESS_INSPECTION_OPTIONS.maxSamplesPerObject,
342871
+ "maxSamplesPerObject"
342872
+ );
342873
+ const contactTolerance = finiteNonNegative(
342874
+ raw.contactTolerance,
342875
+ DEFAULT_THICKNESS_INSPECTION_OPTIONS.contactTolerance,
342876
+ "contactTolerance"
342877
+ );
342878
+ if (minThickness > warnThickness) {
342879
+ throw new Error("minThickness must be less than or equal to warnThickness.");
342880
+ }
342881
+ if (warnThickness > maxThickness) {
342882
+ throw new Error("warnThickness must be less than or equal to maxThickness.");
342883
+ }
342884
+ return {
342885
+ minThickness,
342886
+ warnThickness,
342887
+ maxThickness,
342888
+ maxSamplesPerObject: Math.max(1, Math.floor(maxSamplesPerObject)),
342889
+ contactTolerance
342890
+ };
342891
+ }
342892
+ function lerp(a2, b, t) {
342893
+ return a2 + (b - a2) * Math.max(0, Math.min(1, t));
342894
+ }
342895
+ function lerpColor(a2, b, t) {
342896
+ return [Math.round(lerp(a2[0], b[0], t)), Math.round(lerp(a2[1], b[1], t)), Math.round(lerp(a2[2], b[2], t))];
342897
+ }
342898
+ function thicknessClass(thickness, options) {
342899
+ if (thickness == null || !Number.isFinite(thickness) || thickness <= 0) return "unknown";
342900
+ if (thickness <= options.minThickness) return "critical";
342901
+ if (thickness <= options.warnThickness) return "warning";
342902
+ if (thickness <= options.maxThickness) return "ok";
342903
+ return "thick";
342904
+ }
342905
+ function thicknessColor(thickness, options) {
342906
+ const cls = thicknessClass(thickness, options);
342907
+ if (cls === "unknown") return THICKNESS_COLORS.unknown;
342908
+ if (cls === "critical") return THICKNESS_COLORS.critical;
342909
+ if (cls === "warning") {
342910
+ const span = Math.max(1e-9, options.warnThickness - options.minThickness);
342911
+ return lerpColor(THICKNESS_COLORS.critical, THICKNESS_COLORS.warning, ((thickness ?? 0) - options.minThickness) / span);
342912
+ }
342913
+ if (cls === "ok") {
342914
+ const span = Math.max(1e-9, options.maxThickness - options.warnThickness);
342915
+ return lerpColor(THICKNESS_COLORS.ok, THICKNESS_COLORS.thick, ((thickness ?? 0) - options.warnThickness) / span);
342916
+ }
342917
+ return THICKNESS_COLORS.thick;
342918
+ }
342919
+ function sampleArea(sample) {
342920
+ const area2 = sample.area ?? 1;
342921
+ return Number.isFinite(area2) && area2 > 0 ? area2 : 1;
342922
+ }
342923
+ function weightedQuantile(samples, q) {
342924
+ if (samples.length === 0) return null;
342925
+ const sorted = [...samples].sort((a2, b) => a2.thickness - b.thickness);
342926
+ const totalArea = sorted.reduce((sum2, sample) => sum2 + sample.area, 0);
342927
+ const target = totalArea * Math.max(0, Math.min(1, q));
342928
+ let cumulative = 0;
342929
+ for (const sample of sorted) {
342930
+ cumulative += sample.area;
342931
+ if (cumulative >= target) return sample.thickness;
342932
+ }
342933
+ return sorted[sorted.length - 1].thickness;
342934
+ }
342935
+ function percent(part, total) {
342936
+ if (total <= 0) return 0;
342937
+ return part / total * 100;
342938
+ }
342939
+ function summarizeThicknessSamples(samples, options) {
342940
+ const resolved = [];
342941
+ let totalArea = 0;
342942
+ let resolvedArea = 0;
342943
+ let unresolvedArea = 0;
342944
+ let criticalArea = 0;
342945
+ let warningArea = 0;
342946
+ let weightedSum = 0;
342947
+ for (const sample of samples) {
342948
+ const area2 = sampleArea(sample);
342949
+ totalArea += area2;
342950
+ const value = sample.thickness;
342951
+ if (value == null || !Number.isFinite(value) || value <= 0) {
342952
+ unresolvedArea += area2;
342953
+ continue;
342954
+ }
342955
+ resolved.push({ thickness: value, area: area2 });
342956
+ resolvedArea += area2;
342957
+ weightedSum += value * area2;
342958
+ if (value <= options.minThickness) {
342959
+ criticalArea += area2;
342960
+ } else if (value <= options.warnThickness) {
342961
+ warningArea += area2;
342962
+ }
342963
+ }
342964
+ const values = resolved.map((sample) => sample.thickness);
342965
+ return {
342966
+ sampleCount: samples.length,
342967
+ resolvedCount: resolved.length,
342968
+ unresolvedCount: samples.length - resolved.length,
342969
+ minThickness: values.length > 0 ? Math.min(...values) : null,
342970
+ p05Thickness: weightedQuantile(resolved, 0.05),
342971
+ medianThickness: weightedQuantile(resolved, 0.5),
342972
+ meanThickness: resolvedArea > 0 ? weightedSum / resolvedArea : null,
342973
+ maxThickness: values.length > 0 ? Math.max(...values) : null,
342974
+ criticalAreaPercent: percent(criticalArea, resolvedArea),
342975
+ warningAreaPercent: percent(warningArea, resolvedArea),
342976
+ belowWarnAreaPercent: percent(criticalArea + warningArea, resolvedArea),
342977
+ unresolvedAreaPercent: percent(unresolvedArea, totalArea)
342978
+ };
342979
+ }
342280
342980
  const VECTOR_KEYS = /* @__PURE__ */ new Set(["pos", "position", "target", "lookat", "aim", "up"]);
342281
342981
  const roundNumber = (value, digits) => {
342282
342982
  const scale2 = 10 ** digits;
@@ -342565,7 +343265,7 @@ export {
342565
343265
  DEFAULT_ACTIVE_BACKEND as ay,
342566
343266
  isConstraintSketch as az,
342567
343267
  PCFShadowMap as b,
342568
- Group as b$,
343268
+ analyzePhysicalConnectivity as b$,
342569
343269
  PointLight as b0,
342570
343270
  DirectionalLight as b1,
342571
343271
  analyzeCollisionIntersections as b2,
@@ -342576,33 +343276,33 @@ export {
342576
343276
  runScript as b7,
342577
343277
  MeshPhysicalMaterial as b8,
342578
343278
  LineSegments as b9,
342579
- resolveExplodeDirective as bA,
342580
- computeExplodeMotion as bB,
342581
- getSketchWorldMatrix as bC,
342582
- explodeAdd as bD,
342583
- hasExplodeOverride as bE,
342584
- resolveExplodeLocalFanDirection as bF,
342585
- explodeMul as bG,
342586
- explodeLeafFanStage as bH,
342587
- normalizeCutPlane as bI,
342588
- toClippingPlane as bJ,
342589
- findJointAnimationClip as bK,
342590
- resolveJointAnimation as bL,
342591
- resolveJointViewValues as bM,
342592
- getShapePorts as bN,
342593
- getShapeUsedPorts as bO,
342594
- DEFAULT_VIEW_CONFIG as bP,
342595
- getKernelFaceNameForTriangle as bQ,
342596
- resolveScalarSceneSampleBudget as bR,
342597
- initKernel as bS,
342598
- initSolverWasm as bT,
342599
- BoxGeometry as bU,
342600
- localAabbPlaneRelation as bV,
342601
- ShapeUtils as bW,
342602
- aabbGaps as bX,
342603
- aabbInteriorOverlaps as bY,
342604
- aabbOverlapVolume as bZ,
342605
- AabbSpatialIndex as b_,
343279
+ parseViewportCameraState as bA,
343280
+ createResolvedExplodeConfig as bB,
343281
+ explodeBoundsCenter as bC,
343282
+ explodeMergeBounds as bD,
343283
+ resolveExplodeDirective as bE,
343284
+ computeExplodeMotion as bF,
343285
+ getSketchWorldMatrix as bG,
343286
+ explodeAdd as bH,
343287
+ hasExplodeOverride as bI,
343288
+ resolveExplodeLocalFanDirection as bJ,
343289
+ explodeMul as bK,
343290
+ explodeLeafFanStage as bL,
343291
+ normalizeCutPlane as bM,
343292
+ toClippingPlane as bN,
343293
+ findJointAnimationClip as bO,
343294
+ resolveJointAnimation as bP,
343295
+ resolveJointViewValues as bQ,
343296
+ getShapePorts as bR,
343297
+ getShapeUsedPorts as bS,
343298
+ DEFAULT_VIEW_CONFIG as bT,
343299
+ getKernelFaceNameForTriangle as bU,
343300
+ resolveScalarSceneSampleBudget as bV,
343301
+ initKernel as bW,
343302
+ initSolverWasm as bX,
343303
+ BoxGeometry as bY,
343304
+ localAabbPlaneRelation as bZ,
343305
+ ShapeUtils as b_,
342606
343306
  geometryWithVisibleVertexColors as ba,
342607
343307
  getRenderStylePreset as bb,
342608
343308
  AdditiveBlending as bc,
@@ -342617,32 +343317,44 @@ export {
342617
343317
  SURFACE_FIELD_VERTEX_SHADER as bl,
342618
343318
  CatmullRomCurve3 as bm,
342619
343319
  TubeGeometry as bn,
342620
- MeshStandardMaterial as bo,
342621
- compileSdfNode3 as bp,
342622
- buildSdfRaymarchFragmentShader as bq,
342623
- SDF_RAYMARCH_PROXY_VERTEX_SHADER as br,
342624
- Shape2 as bs,
342625
- ShapeGeometry as bt,
342626
- ShaderLib as bu,
342627
- CylinderGeometry as bv,
342628
- parseViewportCameraState as bw,
342629
- createResolvedExplodeConfig as bx,
342630
- explodeBoundsCenter as by,
342631
- explodeMergeBounds as bz,
343320
+ ROUGHNESS_COLORS as bo,
343321
+ DEFAULT_ROUGHNESS_INSPECTION_OPTIONS as bp,
343322
+ DEFAULT_THICKNESS_INSPECTION_OPTIONS as bq,
343323
+ THICKNESS_COLORS as br,
343324
+ MeshStandardMaterial as bs,
343325
+ compileSdfNode3 as bt,
343326
+ buildSdfRaymarchFragmentShader as bu,
343327
+ SDF_RAYMARCH_PROXY_VERTEX_SHADER as bv,
343328
+ Shape2 as bw,
343329
+ ShapeGeometry as bx,
343330
+ ShaderLib as by,
343331
+ CylinderGeometry as bz,
342632
343332
  SRGBColorSpace as c,
342633
- intersectWithPlane as c0,
342634
- setActiveBackend as c1,
342635
- parseCameraCliSpec as c2,
342636
- PMREMGenerator as c3,
342637
- PointsMaterial as c4,
342638
- Points$1 as c5,
342639
- serializeCollisionFinding as c6,
342640
- worldAuthorPlaneToLocal as c7,
342641
- generateCuttingLayoutPdf as c8,
342642
- getCameraForwardVector as c9,
342643
- RENDER_STYLE_OPTIONS as ca,
342644
- initKernelManifoldOnly as cb,
342645
- __viteBrowserExternal$1 as cc,
343333
+ meshContactDataFor as c0,
343334
+ AabbSpatialIndex as c1,
343335
+ detectPhysicalContact as c2,
343336
+ resolveThicknessInspectionOptions as c3,
343337
+ thicknessColor as c4,
343338
+ thicknessClass as c5,
343339
+ roughnessClassForAngle as c6,
343340
+ resolveRoughnessInspectionOptions as c7,
343341
+ roughnessColorForAngle as c8,
343342
+ roughnessScoreForAngle as c9,
343343
+ Group as ca,
343344
+ intersectWithPlane as cb,
343345
+ setActiveBackend as cc,
343346
+ parseCameraCliSpec as cd,
343347
+ PMREMGenerator as ce,
343348
+ PointsMaterial as cf,
343349
+ Points$1 as cg,
343350
+ serializeCollisionFinding as ch,
343351
+ summarizeThicknessSamples as ci,
343352
+ worldAuthorPlaneToLocal as cj,
343353
+ generateCuttingLayoutPdf as ck,
343354
+ getCameraForwardVector as cl,
343355
+ RENDER_STYLE_OPTIONS as cm,
343356
+ initKernelManifoldOnly as cn,
343357
+ __viteBrowserExternal$1 as co,
342646
343358
  Layers as d,
342647
343359
  Color as e,
342648
343360
  RGBAFormat as f,