@tscircuit/3d-viewer 0.0.469 → 0.0.471

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/index.d.ts +4 -0
  2. package/dist/index.js +1171 -1057
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1053,7 +1053,7 @@ var require_rotateY = __commonJS({
1053
1053
  var require_rotateZ = __commonJS({
1054
1054
  "node_modules/@jscad/modeling/src/maths/vec3/rotateZ.js"(exports, module) {
1055
1055
  "use strict";
1056
- var rotateZ4 = (out, vector, origin, radians) => {
1056
+ var rotateZ3 = (out, vector, origin, radians) => {
1057
1057
  const p = [];
1058
1058
  const r = [];
1059
1059
  p[0] = vector[0] - origin[0];
@@ -1065,7 +1065,7 @@ var require_rotateZ = __commonJS({
1065
1065
  out[2] = vector[2];
1066
1066
  return out;
1067
1067
  };
1068
- module.exports = rotateZ4;
1068
+ module.exports = rotateZ3;
1069
1069
  }
1070
1070
  });
1071
1071
 
@@ -1129,13 +1129,13 @@ var require_squaredLength = __commonJS({
1129
1129
  var require_subtract = __commonJS({
1130
1130
  "node_modules/@jscad/modeling/src/maths/vec3/subtract.js"(exports, module) {
1131
1131
  "use strict";
1132
- var subtract7 = (out, a, b) => {
1132
+ var subtract5 = (out, a, b) => {
1133
1133
  out[0] = a[0] - b[0];
1134
1134
  out[1] = a[1] - b[1];
1135
1135
  out[2] = a[2] - b[2];
1136
1136
  return out;
1137
1137
  };
1138
- module.exports = subtract7;
1138
+ module.exports = subtract5;
1139
1139
  }
1140
1140
  });
1141
1141
 
@@ -1607,7 +1607,7 @@ var require_rotateZ2 = __commonJS({
1607
1607
  "node_modules/@jscad/modeling/src/maths/mat4/rotateZ.js"(exports, module) {
1608
1608
  "use strict";
1609
1609
  var { sin: sin2, cos: cos2 } = require_trigonometry();
1610
- var rotateZ4 = (out, matrix, radians) => {
1610
+ var rotateZ3 = (out, matrix, radians) => {
1611
1611
  const s = sin2(radians);
1612
1612
  const c = cos2(radians);
1613
1613
  const a00 = matrix[0];
@@ -1638,7 +1638,7 @@ var require_rotateZ2 = __commonJS({
1638
1638
  out[7] = a13 * c - a03 * s;
1639
1639
  return out;
1640
1640
  };
1641
- module.exports = rotateZ4;
1641
+ module.exports = rotateZ3;
1642
1642
  }
1643
1643
  });
1644
1644
 
@@ -1676,7 +1676,7 @@ var require_scale2 = __commonJS({
1676
1676
  var require_subtract2 = __commonJS({
1677
1677
  "node_modules/@jscad/modeling/src/maths/mat4/subtract.js"(exports, module) {
1678
1678
  "use strict";
1679
- var subtract7 = (out, a, b) => {
1679
+ var subtract5 = (out, a, b) => {
1680
1680
  out[0] = a[0] - b[0];
1681
1681
  out[1] = a[1] - b[1];
1682
1682
  out[2] = a[2] - b[2];
@@ -1695,7 +1695,7 @@ var require_subtract2 = __commonJS({
1695
1695
  out[15] = a[15] - b[15];
1696
1696
  return out;
1697
1697
  };
1698
- module.exports = subtract7;
1698
+ module.exports = subtract5;
1699
1699
  }
1700
1700
  });
1701
1701
 
@@ -1712,7 +1712,7 @@ var require_toString2 = __commonJS({
1712
1712
  var require_translate = __commonJS({
1713
1713
  "node_modules/@jscad/modeling/src/maths/mat4/translate.js"(exports, module) {
1714
1714
  "use strict";
1715
- var translate11 = (out, matrix, offsets) => {
1715
+ var translate7 = (out, matrix, offsets) => {
1716
1716
  const x = offsets[0];
1717
1717
  const y = offsets[1];
1718
1718
  const z135 = offsets[2];
@@ -1765,7 +1765,7 @@ var require_translate = __commonJS({
1765
1765
  }
1766
1766
  return out;
1767
1767
  };
1768
- module.exports = translate11;
1768
+ module.exports = translate7;
1769
1769
  }
1770
1770
  });
1771
1771
 
@@ -2205,12 +2205,12 @@ var require_squaredLength2 = __commonJS({
2205
2205
  var require_subtract3 = __commonJS({
2206
2206
  "node_modules/@jscad/modeling/src/maths/vec2/subtract.js"(exports, module) {
2207
2207
  "use strict";
2208
- var subtract7 = (out, a, b) => {
2208
+ var subtract5 = (out, a, b) => {
2209
2209
  out[0] = a[0] - b[0];
2210
2210
  out[1] = a[1] - b[1];
2211
2211
  return out;
2212
2212
  };
2213
- module.exports = subtract7;
2213
+ module.exports = subtract5;
2214
2214
  }
2215
2215
  });
2216
2216
 
@@ -2671,14 +2671,14 @@ var require_point_line_distance = __commonJS({
2671
2671
  "node_modules/@jscad/modeling/src/operations/hulls/quickhull/point-line-distance.js"(exports, module) {
2672
2672
  "use strict";
2673
2673
  var cross = require_cross();
2674
- var subtract7 = require_subtract();
2674
+ var subtract5 = require_subtract();
2675
2675
  var squaredLength = require_squaredLength();
2676
2676
  var distanceSquared = (p, a, b) => {
2677
2677
  const ab = [];
2678
2678
  const ap = [];
2679
2679
  const cr = [];
2680
- subtract7(ab, b, a);
2681
- subtract7(ap, p, a);
2680
+ subtract5(ab, b, a);
2681
+ subtract5(ap, p, a);
2682
2682
  const area = squaredLength(cross(cr, ap, ab));
2683
2683
  const s = squaredLength(ab);
2684
2684
  if (s === 0) {
@@ -2697,11 +2697,11 @@ var require_get_plane_normal = __commonJS({
2697
2697
  "use strict";
2698
2698
  var cross = require_cross();
2699
2699
  var normalize = require_normalize();
2700
- var subtract7 = require_subtract();
2700
+ var subtract5 = require_subtract();
2701
2701
  var planeNormal = (out, point1, point2, point32) => {
2702
2702
  const tmp = [0, 0, 0];
2703
- subtract7(out, point1, point2);
2704
- subtract7(tmp, point2, point32);
2703
+ subtract5(out, point1, point2);
2704
+ subtract5(tmp, point2, point32);
2705
2705
  cross(out, out, tmp);
2706
2706
  return normalize(out, out);
2707
2707
  };
@@ -2915,7 +2915,7 @@ var require_Face = __commonJS({
2915
2915
  var length2 = require_length();
2916
2916
  var normalize = require_normalize();
2917
2917
  var scale3 = require_scale();
2918
- var subtract7 = require_subtract();
2918
+ var subtract5 = require_subtract();
2919
2919
  var HalfEdge = require_HalfEdge();
2920
2920
  var VISIBLE = 0;
2921
2921
  var NON_CONVEX = 1;
@@ -2949,14 +2949,14 @@ var require_Face = __commonJS({
2949
2949
  const e0 = this.edge;
2950
2950
  const e1 = e0.next;
2951
2951
  let e2 = e1.next;
2952
- const v2 = subtract7([], e1.head().point, e0.head().point);
2952
+ const v2 = subtract5([], e1.head().point, e0.head().point);
2953
2953
  const t = [];
2954
2954
  const v1 = [];
2955
2955
  this.nVertices = 2;
2956
2956
  this.normal = [0, 0, 0];
2957
2957
  while (e2 !== e0) {
2958
2958
  copy(v1, v2);
2959
- subtract7(v2, e2.head().point, e0.head().point);
2959
+ subtract5(v2, e2.head().point, e0.head().point);
2960
2960
  add(this.normal, this.normal, cross(t, v1, v2));
2961
2961
  e2 = e2.next;
2962
2962
  this.nVertices += 1;
@@ -2980,7 +2980,7 @@ var require_Face = __commonJS({
2980
2980
  } while (edge !== this.edge);
2981
2981
  const p1 = maxEdge.tail().point;
2982
2982
  const p2 = maxEdge.head().point;
2983
- const maxVector = subtract7([], p2, p1);
2983
+ const maxVector = subtract5([], p2, p1);
2984
2984
  const maxLength = Math.sqrt(maxSquaredLength);
2985
2985
  scale3(maxVector, maxVector, 1 / maxLength);
2986
2986
  const maxProjection = dot(this.normal, maxVector);
@@ -5426,7 +5426,7 @@ var require_colorize = __commonJS({
5426
5426
  newpoly.color = color;
5427
5427
  return newpoly;
5428
5428
  };
5429
- var colorize8 = (color, ...objects) => {
5429
+ var colorize4 = (color, ...objects) => {
5430
5430
  if (!Array.isArray(color)) throw new Error("color must be an array");
5431
5431
  if (color.length < 3) throw new Error("color must contain R, G and B values");
5432
5432
  if (color.length === 3) color = [color[0], color[1], color[2], 1];
@@ -5442,7 +5442,7 @@ var require_colorize = __commonJS({
5442
5442
  });
5443
5443
  return results.length === 1 ? results[0] : results;
5444
5444
  };
5445
- module.exports = colorize8;
5445
+ module.exports = colorize4;
5446
5446
  }
5447
5447
  });
5448
5448
 
@@ -6267,11 +6267,11 @@ var require_clone9 = __commonJS({
6267
6267
  "node_modules/@jscad/modeling/src/maths/line2/clone.js"(exports, module) {
6268
6268
  "use strict";
6269
6269
  var create = require_create11();
6270
- var clone = (line4) => {
6270
+ var clone = (line2) => {
6271
6271
  const out = create();
6272
- out[0] = line4[0];
6273
- out[1] = line4[1];
6274
- out[2] = line4[2];
6272
+ out[0] = line2[0];
6273
+ out[1] = line2[1];
6274
+ out[2] = line2[2];
6275
6275
  return out;
6276
6276
  };
6277
6277
  module.exports = clone;
@@ -6283,8 +6283,8 @@ var require_direction = __commonJS({
6283
6283
  "node_modules/@jscad/modeling/src/maths/line2/direction.js"(exports, module) {
6284
6284
  "use strict";
6285
6285
  var vec2 = require_vec2();
6286
- var direction = (line4) => {
6287
- const vector = vec2.normal(vec2.create(), line4);
6286
+ var direction = (line2) => {
6287
+ const vector = vec2.normal(vec2.create(), line2);
6288
6288
  vec2.negate(vector, vector);
6289
6289
  return vector;
6290
6290
  };
@@ -6297,7 +6297,7 @@ var require_origin = __commonJS({
6297
6297
  "node_modules/@jscad/modeling/src/maths/line2/origin.js"(exports, module) {
6298
6298
  "use strict";
6299
6299
  var vec2 = require_vec2();
6300
- var origin = (line4) => vec2.scale(vec2.create(), line4, line4[2]);
6300
+ var origin = (line2) => vec2.scale(vec2.create(), line2, line2[2]);
6301
6301
  module.exports = origin;
6302
6302
  }
6303
6303
  });
@@ -6309,9 +6309,9 @@ var require_closestPoint = __commonJS({
6309
6309
  var vec2 = require_vec2();
6310
6310
  var direction = require_direction();
6311
6311
  var origin = require_origin();
6312
- var closestPoint = (line4, point2) => {
6313
- const orig = origin(line4);
6314
- const dir = direction(line4);
6312
+ var closestPoint = (line2, point2) => {
6313
+ const orig = origin(line2);
6314
+ const dir = direction(line2);
6315
6315
  const v = vec2.subtract(vec2.create(), point2, orig);
6316
6316
  const dist = vec2.dot(v, dir);
6317
6317
  vec2.scale(v, dir, dist);
@@ -6326,10 +6326,10 @@ var require_closestPoint = __commonJS({
6326
6326
  var require_copy5 = __commonJS({
6327
6327
  "node_modules/@jscad/modeling/src/maths/line2/copy.js"(exports, module) {
6328
6328
  "use strict";
6329
- var copy = (out, line4) => {
6330
- out[0] = line4[0];
6331
- out[1] = line4[1];
6332
- out[2] = line4[2];
6329
+ var copy = (out, line2) => {
6330
+ out[0] = line2[0];
6331
+ out[1] = line2[1];
6332
+ out[2] = line2[2];
6333
6333
  return out;
6334
6334
  };
6335
6335
  module.exports = copy;
@@ -6341,9 +6341,9 @@ var require_distanceToPoint = __commonJS({
6341
6341
  "node_modules/@jscad/modeling/src/maths/line2/distanceToPoint.js"(exports, module) {
6342
6342
  "use strict";
6343
6343
  var vec2 = require_vec2();
6344
- var distanceToPoint = (line4, point2) => {
6345
- let distance2 = vec2.dot(point2, line4);
6346
- distance2 = Math.abs(distance2 - line4[2]);
6344
+ var distanceToPoint = (line2, point2) => {
6345
+ let distance2 = vec2.dot(point2, line2);
6346
+ distance2 = Math.abs(distance2 - line2[2]);
6347
6347
  return distance2;
6348
6348
  };
6349
6349
  module.exports = distanceToPoint;
@@ -6354,7 +6354,7 @@ var require_distanceToPoint = __commonJS({
6354
6354
  var require_equals6 = __commonJS({
6355
6355
  "node_modules/@jscad/modeling/src/maths/line2/equals.js"(exports, module) {
6356
6356
  "use strict";
6357
- var equals = (line1, line22) => line1[0] === line22[0] && (line1[1] === line22[1] && line1[2] === line22[2]);
6357
+ var equals = (line1, line2) => line1[0] === line2[0] && (line1[1] === line2[1] && line1[2] === line2[2]);
6358
6358
  module.exports = equals;
6359
6359
  }
6360
6360
  });
@@ -6496,8 +6496,8 @@ var require_intersectPointOfLines = __commonJS({
6496
6496
  "use strict";
6497
6497
  var vec2 = require_vec2();
6498
6498
  var { solve2Linear } = require_utils();
6499
- var intersectToLine = (line1, line22) => {
6500
- const point2 = solve2Linear(line1[0], line1[1], line22[0], line22[1], line1[2], line22[2]);
6499
+ var intersectToLine = (line1, line2) => {
6500
+ const point2 = solve2Linear(line1[0], line1[1], line2[0], line2[1], line1[2], line2[2]);
6501
6501
  return vec2.clone(point2);
6502
6502
  };
6503
6503
  module.exports = intersectToLine;
@@ -6511,9 +6511,9 @@ var require_reverse3 = __commonJS({
6511
6511
  var vec2 = require_vec2();
6512
6512
  var copy = require_copy5();
6513
6513
  var fromValues = require_fromValues5();
6514
- var reverse = (out, line4) => {
6515
- const normal = vec2.negate(vec2.create(), line4);
6516
- const distance2 = -line4[2];
6514
+ var reverse = (out, line2) => {
6515
+ const normal = vec2.negate(vec2.create(), line2);
6516
+ const distance2 = -line2[2];
6517
6517
  return copy(out, fromValues(normal[0], normal[1], distance2));
6518
6518
  };
6519
6519
  module.exports = reverse;
@@ -6524,7 +6524,7 @@ var require_reverse3 = __commonJS({
6524
6524
  var require_toString9 = __commonJS({
6525
6525
  "node_modules/@jscad/modeling/src/maths/line2/toString.js"(exports, module) {
6526
6526
  "use strict";
6527
- var toString = (line4) => `line2: (${line4[0].toFixed(7)}, ${line4[1].toFixed(7)}, ${line4[2].toFixed(7)})`;
6527
+ var toString = (line2) => `line2: (${line2[0].toFixed(7)}, ${line2[1].toFixed(7)}, ${line2[2].toFixed(7)})`;
6528
6528
  module.exports = toString;
6529
6529
  }
6530
6530
  });
@@ -6537,9 +6537,9 @@ var require_transform9 = __commonJS({
6537
6537
  var fromPoints = require_fromPoints6();
6538
6538
  var origin = require_origin();
6539
6539
  var direction = require_direction();
6540
- var transform2 = (out, line4, matrix) => {
6541
- const org = origin(line4);
6542
- const dir = direction(line4);
6540
+ var transform2 = (out, line2, matrix) => {
6541
+ const org = origin(line2);
6542
+ const dir = direction(line2);
6543
6543
  vec2.transform(org, org, matrix);
6544
6544
  vec2.transform(dir, dir, matrix);
6545
6545
  return fromPoints(out, org, dir);
@@ -6553,10 +6553,10 @@ var require_xAtY = __commonJS({
6553
6553
  "node_modules/@jscad/modeling/src/maths/line2/xAtY.js"(exports, module) {
6554
6554
  "use strict";
6555
6555
  var origin = require_origin();
6556
- var xAtY = (line4, y) => {
6557
- let x = (line4[2] - line4[1] * y) / line4[0];
6556
+ var xAtY = (line2, y) => {
6557
+ let x = (line2[2] - line2[1] * y) / line2[0];
6558
6558
  if (Number.isNaN(x)) {
6559
- const org = origin(line4);
6559
+ const org = origin(line2);
6560
6560
  x = org[0];
6561
6561
  }
6562
6562
  return x;
@@ -6610,10 +6610,10 @@ var require_clone10 = __commonJS({
6610
6610
  "use strict";
6611
6611
  var vec3 = require_vec3();
6612
6612
  var create = require_create12();
6613
- var clone = (line4) => {
6613
+ var clone = (line2) => {
6614
6614
  const out = create();
6615
- vec3.copy(out[0], line4[0]);
6616
- vec3.copy(out[1], line4[1]);
6615
+ vec3.copy(out[0], line2[0]);
6616
+ vec3.copy(out[1], line2[1]);
6617
6617
  return out;
6618
6618
  };
6619
6619
  module.exports = clone;
@@ -6625,9 +6625,9 @@ var require_closestPoint2 = __commonJS({
6625
6625
  "node_modules/@jscad/modeling/src/maths/line3/closestPoint.js"(exports, module) {
6626
6626
  "use strict";
6627
6627
  var vec3 = require_vec3();
6628
- var closestPoint = (line4, point2) => {
6629
- const lpoint = line4[0];
6630
- const ldirection = line4[1];
6628
+ var closestPoint = (line2, point2) => {
6629
+ const lpoint = line2[0];
6630
+ const ldirection = line2[1];
6631
6631
  const a = vec3.dot(vec3.subtract(vec3.create(), point2, lpoint), ldirection);
6632
6632
  const b = vec3.dot(ldirection, ldirection);
6633
6633
  const t = a / b;
@@ -6644,9 +6644,9 @@ var require_copy6 = __commonJS({
6644
6644
  "node_modules/@jscad/modeling/src/maths/line3/copy.js"(exports, module) {
6645
6645
  "use strict";
6646
6646
  var vec3 = require_vec3();
6647
- var copy = (out, line4) => {
6648
- vec3.copy(out[0], line4[0]);
6649
- vec3.copy(out[1], line4[1]);
6647
+ var copy = (out, line2) => {
6648
+ vec3.copy(out[0], line2[0]);
6649
+ vec3.copy(out[1], line2[1]);
6650
6650
  return out;
6651
6651
  };
6652
6652
  module.exports = copy;
@@ -6657,7 +6657,7 @@ var require_copy6 = __commonJS({
6657
6657
  var require_direction2 = __commonJS({
6658
6658
  "node_modules/@jscad/modeling/src/maths/line3/direction.js"(exports, module) {
6659
6659
  "use strict";
6660
- var direction = (line4) => line4[1];
6660
+ var direction = (line2) => line2[1];
6661
6661
  module.exports = direction;
6662
6662
  }
6663
6663
  });
@@ -6668,8 +6668,8 @@ var require_distanceToPoint2 = __commonJS({
6668
6668
  "use strict";
6669
6669
  var vec3 = require_vec3();
6670
6670
  var closestPoint = require_closestPoint2();
6671
- var distanceToPoint = (line4, point2) => {
6672
- const closest = closestPoint(line4, point2);
6671
+ var distanceToPoint = (line2, point2) => {
6672
+ const closest = closestPoint(line2, point2);
6673
6673
  const distancevector = vec3.subtract(vec3.create(), point2, closest);
6674
6674
  return vec3.length(distancevector);
6675
6675
  };
@@ -6682,9 +6682,9 @@ var require_equals7 = __commonJS({
6682
6682
  "node_modules/@jscad/modeling/src/maths/line3/equals.js"(exports, module) {
6683
6683
  "use strict";
6684
6684
  var vec3 = require_vec3();
6685
- var equals = (line1, line22) => {
6686
- if (!vec3.equals(line1[1], line22[1])) return false;
6687
- if (!vec3.equals(line1[0], line22[0])) return false;
6685
+ var equals = (line1, line2) => {
6686
+ if (!vec3.equals(line1[1], line2[1])) return false;
6687
+ if (!vec3.equals(line1[0], line2[0])) return false;
6688
6688
  return true;
6689
6689
  };
6690
6690
  module.exports = equals;
@@ -6762,11 +6762,11 @@ var require_intersectPointOfLineAndPlane = __commonJS({
6762
6762
  "node_modules/@jscad/modeling/src/maths/line3/intersectPointOfLineAndPlane.js"(exports, module) {
6763
6763
  "use strict";
6764
6764
  var vec3 = require_vec3();
6765
- var intersectToPlane = (line4, plane) => {
6765
+ var intersectToPlane = (line2, plane) => {
6766
6766
  const pnormal = plane;
6767
6767
  const pw = plane[3];
6768
- const lpoint = line4[0];
6769
- const ldirection = line4[1];
6768
+ const lpoint = line2[0];
6769
+ const ldirection = line2[1];
6770
6770
  const labda = (pw - vec3.dot(pnormal, lpoint)) / vec3.dot(pnormal, ldirection);
6771
6771
  const point2 = vec3.add(vec3.create(), lpoint, vec3.scale(vec3.create(), ldirection, labda));
6772
6772
  return point2;
@@ -6779,7 +6779,7 @@ var require_intersectPointOfLineAndPlane = __commonJS({
6779
6779
  var require_origin2 = __commonJS({
6780
6780
  "node_modules/@jscad/modeling/src/maths/line3/origin.js"(exports, module) {
6781
6781
  "use strict";
6782
- var origin = (line4) => line4[0];
6782
+ var origin = (line2) => line2[0];
6783
6783
  module.exports = origin;
6784
6784
  }
6785
6785
  });
@@ -6790,9 +6790,9 @@ var require_reverse4 = __commonJS({
6790
6790
  "use strict";
6791
6791
  var vec3 = require_vec3();
6792
6792
  var fromPointAndDirection = require_fromPointAndDirection();
6793
- var reverse = (out, line4) => {
6794
- const point2 = vec3.clone(line4[0]);
6795
- const direction = vec3.negate(vec3.create(), line4[1]);
6793
+ var reverse = (out, line2) => {
6794
+ const point2 = vec3.clone(line2[0]);
6795
+ const direction = vec3.negate(vec3.create(), line2[1]);
6796
6796
  return fromPointAndDirection(out, point2, direction);
6797
6797
  };
6798
6798
  module.exports = reverse;
@@ -6803,9 +6803,9 @@ var require_reverse4 = __commonJS({
6803
6803
  var require_toString10 = __commonJS({
6804
6804
  "node_modules/@jscad/modeling/src/maths/line3/toString.js"(exports, module) {
6805
6805
  "use strict";
6806
- var toString = (line4) => {
6807
- const point2 = line4[0];
6808
- const direction = line4[1];
6806
+ var toString = (line2) => {
6807
+ const point2 = line2[0];
6808
+ const direction = line2[1];
6809
6809
  return `line3: point: (${point2[0].toFixed(7)}, ${point2[1].toFixed(7)}, ${point2[2].toFixed(7)}) direction: (${direction[0].toFixed(7)}, ${direction[1].toFixed(7)}, ${direction[2].toFixed(7)})`;
6810
6810
  };
6811
6811
  module.exports = toString;
@@ -6818,9 +6818,9 @@ var require_transform10 = __commonJS({
6818
6818
  "use strict";
6819
6819
  var vec3 = require_vec3();
6820
6820
  var fromPointAndDirection = require_fromPointAndDirection();
6821
- var transform2 = (out, line4, matrix) => {
6822
- const point2 = line4[0];
6823
- const direction = line4[1];
6821
+ var transform2 = (out, line2, matrix) => {
6822
+ const point2 = line2[0];
6823
+ const direction = line2[1];
6824
6824
  const pointPlusDirection = vec3.add(vec3.create(), point2, direction);
6825
6825
  const newpoint = vec3.transform(vec3.create(), point2, matrix);
6826
6826
  const newPointPlusDirection = vec3.transform(pointPlusDirection, pointPlusDirection, matrix);
@@ -7555,7 +7555,7 @@ var require_circle = __commonJS({
7555
7555
  var { TAU } = require_constants();
7556
7556
  var ellipse2 = require_ellipse();
7557
7557
  var { isGTE } = require_commonChecks();
7558
- var circle2 = (options) => {
7558
+ var circle = (options) => {
7559
7559
  const defaults = {
7560
7560
  center: [0, 0],
7561
7561
  radius: 1,
@@ -7568,7 +7568,7 @@ var require_circle = __commonJS({
7568
7568
  radius = [radius, radius];
7569
7569
  return ellipse2({ center, radius, startAngle, endAngle, segments });
7570
7570
  };
7571
- module.exports = circle2;
7571
+ module.exports = circle;
7572
7572
  }
7573
7573
  });
7574
7574
 
@@ -8033,11 +8033,11 @@ var require_line = __commonJS({
8033
8033
  "node_modules/@jscad/modeling/src/primitives/line.js"(exports, module) {
8034
8034
  "use strict";
8035
8035
  var path2 = require_path2();
8036
- var line4 = (points) => {
8036
+ var line2 = (points) => {
8037
8037
  if (!Array.isArray(points)) throw new Error("points must be an array");
8038
8038
  return path2.fromPoints({}, points);
8039
8039
  };
8040
- module.exports = line4;
8040
+ module.exports = line2;
8041
8041
  }
8042
8042
  });
8043
8043
 
@@ -8397,7 +8397,7 @@ var require_roundedRectangle = __commonJS({
8397
8397
  var geom2 = require_geom2();
8398
8398
  var { isGTE, isNumberArray } = require_commonChecks();
8399
8399
  var rectangle = require_rectangle();
8400
- var roundedRectangle4 = (options) => {
8400
+ var roundedRectangle3 = (options) => {
8401
8401
  const defaults = {
8402
8402
  center: [0, 0],
8403
8403
  size: [2, 2],
@@ -8437,7 +8437,7 @@ var require_roundedRectangle = __commonJS({
8437
8437
  }
8438
8438
  return geom2.fromPoints(corner0Points.concat(corner1Points, corner2Points, corner3Points));
8439
8439
  };
8440
- module.exports = roundedRectangle4;
8440
+ module.exports = roundedRectangle3;
8441
8441
  }
8442
8442
  });
8443
8443
 
@@ -9727,12 +9727,12 @@ var require_rotate3 = __commonJS({
9727
9727
  };
9728
9728
  var rotateX = (angle, ...objects) => rotate3([angle, 0, 0], objects);
9729
9729
  var rotateY = (angle, ...objects) => rotate3([0, angle, 0], objects);
9730
- var rotateZ4 = (angle, ...objects) => rotate3([0, 0, angle], objects);
9730
+ var rotateZ3 = (angle, ...objects) => rotate3([0, 0, angle], objects);
9731
9731
  module.exports = {
9732
9732
  rotate: rotate3,
9733
9733
  rotateX,
9734
9734
  rotateY,
9735
- rotateZ: rotateZ4
9735
+ rotateZ: rotateZ3
9736
9736
  };
9737
9737
  }
9738
9738
  });
@@ -9746,7 +9746,7 @@ var require_translate2 = __commonJS({
9746
9746
  var geom2 = require_geom2();
9747
9747
  var geom3 = require_geom3();
9748
9748
  var path2 = require_path2();
9749
- var translate11 = (offset4, ...objects) => {
9749
+ var translate7 = (offset4, ...objects) => {
9750
9750
  if (!Array.isArray(offset4)) throw new Error("offset must be an array");
9751
9751
  objects = flatten(objects);
9752
9752
  if (objects.length === 0) throw new Error("wrong number of arguments");
@@ -9761,11 +9761,11 @@ var require_translate2 = __commonJS({
9761
9761
  });
9762
9762
  return results.length === 1 ? results[0] : results;
9763
9763
  };
9764
- var translateX = (offset4, ...objects) => translate11([offset4, 0, 0], objects);
9765
- var translateY = (offset4, ...objects) => translate11([0, offset4, 0], objects);
9766
- var translateZ = (offset4, ...objects) => translate11([0, 0, offset4], objects);
9764
+ var translateX = (offset4, ...objects) => translate7([offset4, 0, 0], objects);
9765
+ var translateY = (offset4, ...objects) => translate7([0, offset4, 0], objects);
9766
+ var translateZ = (offset4, ...objects) => translate7([0, 0, offset4], objects);
9767
9767
  module.exports = {
9768
- translate: translate11,
9768
+ translate: translate7,
9769
9769
  translateX,
9770
9770
  translateY,
9771
9771
  translateZ
@@ -9780,8 +9780,8 @@ var require_torus = __commonJS({
9780
9780
  var { TAU } = require_constants();
9781
9781
  var extrudeRotate = require_extrudeRotate();
9782
9782
  var { rotate: rotate3 } = require_rotate3();
9783
- var { translate: translate11 } = require_translate2();
9784
- var circle2 = require_circle();
9783
+ var { translate: translate7 } = require_translate2();
9784
+ var circle = require_circle();
9785
9785
  var { isGT, isGTE } = require_commonChecks();
9786
9786
  var torus = (options) => {
9787
9787
  const defaults = {
@@ -9801,11 +9801,11 @@ var require_torus = __commonJS({
9801
9801
  if (!isGTE(startAngle, 0)) throw new Error("startAngle must be positive");
9802
9802
  if (!isGT(outerRotation, 0)) throw new Error("outerRotation must be greater than zero");
9803
9803
  if (innerRadius >= outerRadius) throw new Error("inner circle is too large to rotate about the outer circle");
9804
- let innerCircle = circle2({ radius: innerRadius, segments: innerSegments });
9804
+ let innerCircle = circle({ radius: innerRadius, segments: innerSegments });
9805
9805
  if (innerRotation !== 0) {
9806
9806
  innerCircle = rotate3([0, 0, innerRotation], innerCircle);
9807
9807
  }
9808
- innerCircle = translate11([outerRadius, 0], innerCircle);
9808
+ innerCircle = translate7([outerRadius, 0], innerCircle);
9809
9809
  const extrudeOptions = {
9810
9810
  startAngle,
9811
9811
  angle: outerRotation,
@@ -10148,9 +10148,9 @@ var require_vectorText = __commonJS({
10148
10148
  "use strict";
10149
10149
  var vectorChar = require_vectorChar();
10150
10150
  var vectorParams = require_vectorParams();
10151
- var translateLine = (options, line4) => {
10151
+ var translateLine = (options, line2) => {
10152
10152
  const { x, y } = Object.assign({ x: 0, y: 0 }, options || {});
10153
- const segments = line4.segments;
10153
+ const segments = line2.segments;
10154
10154
  let segment = null;
10155
10155
  let point2 = null;
10156
10156
  for (let i = 0, il = segments.length; i < il; i++) {
@@ -10160,7 +10160,7 @@ var require_vectorText = __commonJS({
10160
10160
  segment[j] = [point2[0] + x, point2[1] + y];
10161
10161
  }
10162
10162
  }
10163
- return line4;
10163
+ return line2;
10164
10164
  };
10165
10165
  var vectorText3 = (options, text) => {
10166
10166
  const {
@@ -10176,15 +10176,15 @@ var require_vectorText = __commonJS({
10176
10176
  } = vectorParams(options, text);
10177
10177
  let [x, y] = [xOffset, yOffset];
10178
10178
  let i, il, char, vect, width10, diff;
10179
- let line4 = { width: 0, segments: [] };
10179
+ let line2 = { width: 0, segments: [] };
10180
10180
  const lines = [];
10181
10181
  let output = [];
10182
10182
  let maxWidth = 0;
10183
10183
  const lineStart = x;
10184
10184
  const pushLine = () => {
10185
- lines.push(line4);
10186
- maxWidth = Math.max(maxWidth, line4.width);
10187
- line4 = { width: 0, segments: [] };
10185
+ lines.push(line2);
10186
+ maxWidth = Math.max(maxWidth, line2.width);
10187
+ line2 = { width: 0, segments: [] };
10188
10188
  };
10189
10189
  for (i = 0, il = input.length; i < il; i++) {
10190
10190
  char = input[i];
@@ -10196,26 +10196,26 @@ var require_vectorText = __commonJS({
10196
10196
  continue;
10197
10197
  }
10198
10198
  width10 = vect.width * letterSpacing;
10199
- line4.width += width10;
10199
+ line2.width += width10;
10200
10200
  x += width10;
10201
10201
  if (char !== " ") {
10202
- line4.segments = line4.segments.concat(vect.segments);
10202
+ line2.segments = line2.segments.concat(vect.segments);
10203
10203
  }
10204
10204
  }
10205
- if (line4.segments.length) {
10205
+ if (line2.segments.length) {
10206
10206
  pushLine();
10207
10207
  }
10208
10208
  for (i = 0, il = lines.length; i < il; i++) {
10209
- line4 = lines[i];
10210
- if (maxWidth > line4.width) {
10211
- diff = maxWidth - line4.width;
10209
+ line2 = lines[i];
10210
+ if (maxWidth > line2.width) {
10211
+ diff = maxWidth - line2.width;
10212
10212
  if (align === "right") {
10213
- line4 = translateLine({ x: diff }, line4);
10213
+ line2 = translateLine({ x: diff }, line2);
10214
10214
  } else if (align === "center") {
10215
- line4 = translateLine({ x: diff / 2 }, line4);
10215
+ line2 = translateLine({ x: diff / 2 }, line2);
10216
10216
  }
10217
10217
  }
10218
- output = output.concat(line4.segments);
10218
+ output = output.concat(line2.segments);
10219
10219
  }
10220
10220
  return output;
10221
10221
  };
@@ -10487,7 +10487,7 @@ var require_reTesselateCoplanarPolygons = __commonJS({
10487
10487
  "node_modules/@jscad/modeling/src/operations/modifiers/reTesselateCoplanarPolygons.js"(exports, module) {
10488
10488
  "use strict";
10489
10489
  var { EPS } = require_constants();
10490
- var line22 = require_line2();
10490
+ var line2 = require_line2();
10491
10491
  var vec2 = require_vec2();
10492
10492
  var OrthoNormalBasis = require_OrthoNormalBasis();
10493
10493
  var interpolateBetween2DPointsForY = require_interpolateBetween2DPointsForY();
@@ -10673,8 +10673,8 @@ var require_reTesselateCoplanarPolygons = __commonJS({
10673
10673
  topright,
10674
10674
  bottomleft,
10675
10675
  bottomright,
10676
- leftline: line22.fromPoints(line22.create(), topleft, bottomleft),
10677
- rightline: line22.fromPoints(line22.create(), bottomright, topright)
10676
+ leftline: line2.fromPoints(line2.create(), topleft, bottomleft),
10677
+ rightline: line2.fromPoints(line2.create(), bottomright, topright)
10678
10678
  };
10679
10679
  if (newoutpolygonrow.length > 0) {
10680
10680
  const prevoutpolygon = newoutpolygonrow[newoutpolygonrow.length - 1];
@@ -10700,11 +10700,11 @@ var require_reTesselateCoplanarPolygons = __commonJS({
10700
10700
  if (vec2.distance(prevpolygon.bottomleft, thispolygon.topleft) < EPS) {
10701
10701
  if (vec2.distance(prevpolygon.bottomright, thispolygon.topright) < EPS) {
10702
10702
  matchedindexes.add(ii);
10703
- const v1 = line22.direction(thispolygon.leftline);
10704
- const v2 = line22.direction(prevpolygon.leftline);
10703
+ const v1 = line2.direction(thispolygon.leftline);
10704
+ const v2 = line2.direction(prevpolygon.leftline);
10705
10705
  const d1 = v1[0] - v2[0];
10706
- const v3 = line22.direction(thispolygon.rightline);
10707
- const v4 = line22.direction(prevpolygon.rightline);
10706
+ const v3 = line2.direction(thispolygon.rightline);
10707
+ const v4 = line2.direction(prevpolygon.rightline);
10708
10708
  const d2 = v3[0] - v4[0];
10709
10709
  const leftlinecontinues = Math.abs(d1) < EPS;
10710
10710
  const rightlinecontinues = Math.abs(d2) < EPS;
@@ -11612,7 +11612,7 @@ var require_subtractGeom3 = __commonJS({
11612
11612
  var flatten = require_flatten();
11613
11613
  var retessellate = require_retessellate();
11614
11614
  var subtractSub = require_subtractGeom3Sub();
11615
- var subtract7 = (...geometries) => {
11615
+ var subtract5 = (...geometries) => {
11616
11616
  geometries = flatten(geometries);
11617
11617
  let newgeometry = geometries.shift();
11618
11618
  geometries.forEach((geometry) => {
@@ -11621,7 +11621,7 @@ var require_subtractGeom3 = __commonJS({
11621
11621
  newgeometry = retessellate(newgeometry);
11622
11622
  return newgeometry;
11623
11623
  };
11624
- module.exports = subtract7;
11624
+ module.exports = subtract5;
11625
11625
  }
11626
11626
  });
11627
11627
 
@@ -11635,14 +11635,14 @@ var require_subtractGeom2 = __commonJS({
11635
11635
  var fromFakePolygons = require_fromFakePolygons();
11636
11636
  var to3DWalls = require_to3DWalls();
11637
11637
  var subtractGeom3 = require_subtractGeom3();
11638
- var subtract7 = (...geometries) => {
11638
+ var subtract5 = (...geometries) => {
11639
11639
  geometries = flatten(geometries);
11640
11640
  const newgeometries = geometries.map((geometry) => to3DWalls({ z0: -1, z1: 1 }, geometry));
11641
11641
  const newgeom3 = subtractGeom3(newgeometries);
11642
11642
  const epsilon = measureEpsilon(newgeom3);
11643
11643
  return fromFakePolygons(epsilon, geom3.toPolygons(newgeom3));
11644
11644
  };
11645
- module.exports = subtract7;
11645
+ module.exports = subtract5;
11646
11646
  }
11647
11647
  });
11648
11648
 
@@ -11656,7 +11656,7 @@ var require_subtract4 = __commonJS({
11656
11656
  var geom3 = require_geom3();
11657
11657
  var subtractGeom2 = require_subtractGeom2();
11658
11658
  var subtractGeom3 = require_subtractGeom3();
11659
- var subtract7 = (...geometries) => {
11659
+ var subtract5 = (...geometries) => {
11660
11660
  geometries = flatten(geometries);
11661
11661
  if (geometries.length === 0) throw new Error("wrong number of arguments");
11662
11662
  if (!areAllShapesTheSameType(geometries)) {
@@ -11667,7 +11667,7 @@ var require_subtract4 = __commonJS({
11667
11667
  if (geom3.isA(geometry)) return subtractGeom3(geometries);
11668
11668
  return geometry;
11669
11669
  };
11670
- module.exports = subtract7;
11670
+ module.exports = subtract5;
11671
11671
  }
11672
11672
  });
11673
11673
 
@@ -11709,7 +11709,7 @@ var require_unionGeom3 = __commonJS({
11709
11709
  var flatten = require_flatten();
11710
11710
  var retessellate = require_retessellate();
11711
11711
  var unionSub = require_unionGeom3Sub();
11712
- var union6 = (...geometries) => {
11712
+ var union5 = (...geometries) => {
11713
11713
  geometries = flatten(geometries);
11714
11714
  let i;
11715
11715
  for (i = 1; i < geometries.length; i += 2) {
@@ -11719,7 +11719,7 @@ var require_unionGeom3 = __commonJS({
11719
11719
  newgeometry = retessellate(newgeometry);
11720
11720
  return newgeometry;
11721
11721
  };
11722
- module.exports = union6;
11722
+ module.exports = union5;
11723
11723
  }
11724
11724
  });
11725
11725
 
@@ -11733,14 +11733,14 @@ var require_unionGeom2 = __commonJS({
11733
11733
  var fromFakePolygons = require_fromFakePolygons();
11734
11734
  var to3DWalls = require_to3DWalls();
11735
11735
  var unionGeom3 = require_unionGeom3();
11736
- var union6 = (...geometries) => {
11736
+ var union5 = (...geometries) => {
11737
11737
  geometries = flatten(geometries);
11738
11738
  const newgeometries = geometries.map((geometry) => to3DWalls({ z0: -1, z1: 1 }, geometry));
11739
11739
  const newgeom3 = unionGeom3(newgeometries);
11740
11740
  const epsilon = measureEpsilon(newgeom3);
11741
11741
  return fromFakePolygons(epsilon, geom3.toPolygons(newgeom3));
11742
11742
  };
11743
- module.exports = union6;
11743
+ module.exports = union5;
11744
11744
  }
11745
11745
  });
11746
11746
 
@@ -11754,7 +11754,7 @@ var require_union = __commonJS({
11754
11754
  var geom3 = require_geom3();
11755
11755
  var unionGeom2 = require_unionGeom2();
11756
11756
  var unionGeom3 = require_unionGeom3();
11757
- var union6 = (...geometries) => {
11757
+ var union5 = (...geometries) => {
11758
11758
  geometries = flatten(geometries);
11759
11759
  if (geometries.length === 0) throw new Error("wrong number of arguments");
11760
11760
  if (!areAllShapesTheSameType(geometries)) {
@@ -11765,7 +11765,7 @@ var require_union = __commonJS({
11765
11765
  if (geom3.isA(geometry)) return unionGeom3(geometries);
11766
11766
  return geometry;
11767
11767
  };
11768
- module.exports = union6;
11768
+ module.exports = union5;
11769
11769
  }
11770
11770
  });
11771
11771
 
@@ -11788,7 +11788,7 @@ var require_offsetFromPoints = __commonJS({
11788
11788
  "use strict";
11789
11789
  var { EPS, TAU } = require_constants();
11790
11790
  var intersect3 = require_intersect();
11791
- var line22 = require_line2();
11791
+ var line2 = require_line2();
11792
11792
  var vec2 = require_vec2();
11793
11793
  var area = require_area();
11794
11794
  var offsetFromPoints = (options, points) => {
@@ -11852,12 +11852,12 @@ var require_offsetFromPoints = __commonJS({
11852
11852
  if (corners === "edge") {
11853
11853
  const pointIndex = /* @__PURE__ */ new Map();
11854
11854
  newPoints.forEach((point2, index2) => pointIndex.set(point2, index2));
11855
- const line0 = line22.create();
11856
- const line1 = line22.create();
11855
+ const line0 = line2.create();
11856
+ const line1 = line2.create();
11857
11857
  newCorners.forEach((corner) => {
11858
- line22.fromPoints(line0, corner.s0[0], corner.s0[1]);
11859
- line22.fromPoints(line1, corner.s1[0], corner.s1[1]);
11860
- const ip = line22.intersectPointOfLines(line0, line1);
11858
+ line2.fromPoints(line0, corner.s0[0], corner.s0[1]);
11859
+ line2.fromPoints(line1, corner.s1[0], corner.s1[1]);
11860
+ const ip = line2.intersectPointOfLines(line0, line1);
11861
11861
  if (Number.isFinite(ip[0]) && Number.isFinite(ip[1])) {
11862
11862
  const p0 = corner.s0[1];
11863
11863
  const i = pointIndex.get(p0);
@@ -12155,7 +12155,7 @@ var require_expandGeom3 = __commonJS({
12155
12155
  "node_modules/@jscad/modeling/src/operations/expansions/expandGeom3.js"(exports, module) {
12156
12156
  "use strict";
12157
12157
  var geom3 = require_geom3();
12158
- var union6 = require_union();
12158
+ var union5 = require_union();
12159
12159
  var expandShell = require_expandShell();
12160
12160
  var expandGeom3 = (options, geometry) => {
12161
12161
  const defaults = {
@@ -12171,7 +12171,7 @@ var require_expandGeom3 = __commonJS({
12171
12171
  if (polygons.length === 0) throw new Error("the given geometry cannot be empty");
12172
12172
  options = { delta, corners, segments };
12173
12173
  const expanded = expandShell(options, geometry);
12174
- return union6(geometry, expanded);
12174
+ return union5(geometry, expanded);
12175
12175
  };
12176
12176
  module.exports = expandGeom3;
12177
12177
  }
@@ -12269,7 +12269,7 @@ var require_expand = __commonJS({
12269
12269
  var expandGeom2 = require_expandGeom2();
12270
12270
  var expandGeom3 = require_expandGeom3();
12271
12271
  var expandPath2 = require_expandPath2();
12272
- var expand5 = (options, ...objects) => {
12272
+ var expand3 = (options, ...objects) => {
12273
12273
  objects = flatten(objects);
12274
12274
  if (objects.length === 0) throw new Error("wrong number of arguments");
12275
12275
  const results = objects.map((object) => {
@@ -12280,7 +12280,7 @@ var require_expand = __commonJS({
12280
12280
  });
12281
12281
  return results.length === 1 ? results[0] : results;
12282
12282
  };
12283
- module.exports = expand5;
12283
+ module.exports = expand3;
12284
12284
  }
12285
12285
  });
12286
12286
 
@@ -12451,7 +12451,7 @@ var require_extrudeLinear = __commonJS({
12451
12451
  var path2 = require_path2();
12452
12452
  var extrudeLinearGeom2 = require_extrudeLinearGeom2();
12453
12453
  var extrudeLinearPath2 = require_extrudeLinearPath2();
12454
- var extrudeLinear9 = (options, ...objects) => {
12454
+ var extrudeLinear5 = (options, ...objects) => {
12455
12455
  const defaults = {
12456
12456
  height: 1,
12457
12457
  twistAngle: 0,
@@ -12469,7 +12469,7 @@ var require_extrudeLinear = __commonJS({
12469
12469
  });
12470
12470
  return results.length === 1 ? results[0] : results;
12471
12471
  };
12472
- module.exports = extrudeLinear9;
12472
+ module.exports = extrudeLinear5;
12473
12473
  }
12474
12474
  });
12475
12475
 
@@ -12478,7 +12478,7 @@ var require_extrudeRectangularPath2 = __commonJS({
12478
12478
  "node_modules/@jscad/modeling/src/operations/extrusions/extrudeRectangularPath2.js"(exports, module) {
12479
12479
  "use strict";
12480
12480
  var path2 = require_path2();
12481
- var expand5 = require_expand();
12481
+ var expand3 = require_expand();
12482
12482
  var extrudeLinearGeom2 = require_extrudeLinearGeom2();
12483
12483
  var extrudeRectangularPath2 = (options, geometry) => {
12484
12484
  const defaults = {
@@ -12490,7 +12490,7 @@ var require_extrudeRectangularPath2 = __commonJS({
12490
12490
  options.offset = [0, 0, height10];
12491
12491
  const points = path2.toPoints(geometry);
12492
12492
  if (points.length === 0) throw new Error("the given geometry cannot be empty");
12493
- const newgeometry = expand5(options, geometry);
12493
+ const newgeometry = expand3(options, geometry);
12494
12494
  return extrudeLinearGeom2(options, newgeometry);
12495
12495
  };
12496
12496
  module.exports = extrudeRectangularPath2;
@@ -12504,7 +12504,7 @@ var require_extrudeRectangularGeom2 = __commonJS({
12504
12504
  var { area } = require_utils();
12505
12505
  var geom2 = require_geom2();
12506
12506
  var path2 = require_path2();
12507
- var expand5 = require_expand();
12507
+ var expand3 = require_expand();
12508
12508
  var extrudeLinearGeom2 = require_extrudeLinearGeom2();
12509
12509
  var extrudeRectangularGeom2 = (options, geometry) => {
12510
12510
  const defaults = {
@@ -12518,7 +12518,7 @@ var require_extrudeRectangularGeom2 = __commonJS({
12518
12518
  if (outlines.length === 0) throw new Error("the given geometry cannot be empty");
12519
12519
  const newparts = outlines.map((outline) => {
12520
12520
  if (area(outline) < 0) outline.reverse();
12521
- return expand5(options, path2.fromPoints({ closed: true }, outline));
12521
+ return expand3(options, path2.fromPoints({ closed: true }, outline));
12522
12522
  });
12523
12523
  const allsides = newparts.reduce((sides2, part) => sides2.concat(geom2.toSides(part)), []);
12524
12524
  const newgeometry = geom2.create(allsides);
@@ -12886,7 +12886,7 @@ var require_hullChain = __commonJS({
12886
12886
  "node_modules/@jscad/modeling/src/operations/hulls/hullChain.js"(exports, module) {
12887
12887
  "use strict";
12888
12888
  var flatten = require_flatten();
12889
- var union6 = require_union();
12889
+ var union5 = require_union();
12890
12890
  var hull = require_hull();
12891
12891
  var hullChain = (...geometries) => {
12892
12892
  geometries = flatten(geometries);
@@ -12895,7 +12895,7 @@ var require_hullChain = __commonJS({
12895
12895
  for (let i = 1; i < geometries.length; i++) {
12896
12896
  hulls.push(hull(geometries[i - 1], geometries[i]));
12897
12897
  }
12898
- return union6(hulls);
12898
+ return union5(hulls);
12899
12899
  };
12900
12900
  module.exports = hullChain;
12901
12901
  }
@@ -13528,7 +13528,7 @@ var require_align = __commonJS({
13528
13528
  var flatten = require_flatten();
13529
13529
  var padArrayToLength = require_padArrayToLength();
13530
13530
  var measureAggregateBoundingBox = require_measureAggregateBoundingBox();
13531
- var { translate: translate11 } = require_translate2();
13531
+ var { translate: translate7 } = require_translate2();
13532
13532
  var validateOptions = (options) => {
13533
13533
  if (!Array.isArray(options.modes) || options.modes.length > 3) throw new Error("align(): modes must be an array of length <= 3");
13534
13534
  options.modes = padArrayToLength(options.modes, "none", 3);
@@ -13565,7 +13565,7 @@ var require_align = __commonJS({
13565
13565
  translation[i] = relativeTo[i] - bounds[0][i];
13566
13566
  }
13567
13567
  }
13568
- return translate11(translation, geometry);
13568
+ return translate7(translation, geometry);
13569
13569
  };
13570
13570
  var align = (options, ...geometries) => {
13571
13571
  const defaults = {
@@ -13602,7 +13602,7 @@ var require_center = __commonJS({
13602
13602
  var geom3 = require_geom3();
13603
13603
  var path2 = require_path2();
13604
13604
  var measureBoundingBox = require_measureBoundingBox2();
13605
- var { translate: translate11 } = require_translate2();
13605
+ var { translate: translate7 } = require_translate2();
13606
13606
  var centerGeometry = (options, object) => {
13607
13607
  const defaults = {
13608
13608
  axes: [true, true, true],
@@ -13614,7 +13614,7 @@ var require_center = __commonJS({
13614
13614
  if (axes[0]) offset4[0] = relativeTo[0] - (bounds[0][0] + (bounds[1][0] - bounds[0][0]) / 2);
13615
13615
  if (axes[1]) offset4[1] = relativeTo[1] - (bounds[0][1] + (bounds[1][1] - bounds[0][1]) / 2);
13616
13616
  if (axes[2]) offset4[2] = relativeTo[2] - (bounds[0][2] + (bounds[1][2] - bounds[0][2]) / 2);
13617
- return translate11(offset4, object);
13617
+ return translate7(offset4, object);
13618
13618
  };
13619
13619
  var center = (options, ...objects) => {
13620
13620
  const defaults = {
@@ -14229,10 +14229,10 @@ var require_browser = __commonJS({
14229
14229
 
14230
14230
  // src/CadViewer.tsx
14231
14231
  import { useState as useState35, useCallback as useCallback21, useRef as useRef26, useEffect as useEffect43 } from "react";
14232
- import * as THREE31 from "three";
14232
+ import * as THREE33 from "three";
14233
14233
 
14234
14234
  // src/CadViewerJscad.tsx
14235
- import { su as su11 } from "@tscircuit/circuit-json-util";
14235
+ import { su as su12 } from "@tscircuit/circuit-json-util";
14236
14236
  import { forwardRef as forwardRef3, useMemo as useMemo20 } from "react";
14237
14237
 
14238
14238
  // src/AnyCadComponent.tsx
@@ -24526,7 +24526,7 @@ var m2host = (raw_params) => {
24526
24526
  }
24527
24527
  const centerX = (minX + maxX) / 2;
24528
24528
  const centerY = (minY + maxY) / 2;
24529
- const translate11 = (el) => {
24529
+ const translate7 = (el) => {
24530
24530
  if (typeof el.x === "number") el.x -= centerX;
24531
24531
  if (typeof el.y === "number") el.y -= centerY;
24532
24532
  if (el.center) {
@@ -24540,9 +24540,9 @@ var m2host = (raw_params) => {
24540
24540
  }));
24541
24541
  }
24542
24542
  };
24543
- for (const pad2 of pads) translate11(pad2);
24544
- translate11(cutout);
24545
- translate11(pin1Marker);
24543
+ for (const pad2 of pads) translate7(pad2);
24544
+ translate7(cutout);
24545
+ translate7(pin1Marker);
24546
24546
  return {
24547
24547
  circuitJson: [
24548
24548
  ...pads,
@@ -28509,7 +28509,7 @@ import * as THREE15 from "three";
28509
28509
  // package.json
28510
28510
  var package_default = {
28511
28511
  name: "@tscircuit/3d-viewer",
28512
- version: "0.0.468",
28512
+ version: "0.0.470",
28513
28513
  main: "./dist/index.js",
28514
28514
  module: "./dist/index.js",
28515
28515
  type: "module",
@@ -29727,7 +29727,7 @@ var colors = {
29727
29727
  var MANIFOLD_Z_OFFSET = 1e-3;
29728
29728
  var SMOOTH_CIRCLE_SEGMENTS = 32;
29729
29729
  var DEFAULT_SMT_PAD_THICKNESS = 0.035;
29730
- var TRACE_TEXTURE_RESOLUTION = 50;
29730
+ var TRACE_TEXTURE_RESOLUTION = 150;
29731
29731
  var boardMaterialColors = {
29732
29732
  fr1: colors.fr1Tan,
29733
29733
  fr4: colors.fr4Tan
@@ -29782,6 +29782,10 @@ var createSimplifiedBoardGeom = (circuitJson) => {
29782
29782
  let pcbThickness = 1.2;
29783
29783
  if (panels.length > 0) {
29784
29784
  boardOrPanel = panels[0];
29785
+ const firstBoardInPanel = boards.find(
29786
+ (b) => b.pcb_panel_id === boardOrPanel.pcb_panel_id
29787
+ );
29788
+ pcbThickness = firstBoardInPanel?.thickness ?? 1.2;
29785
29789
  } else {
29786
29790
  const boardsNotInPanel = boards.filter(
29787
29791
  (b) => !b.pcb_panel_id
@@ -29807,7 +29811,10 @@ var createSimplifiedBoardGeom = (circuitJson) => {
29807
29811
  center: [boardOrPanel.center.x, boardOrPanel.center.y, 0]
29808
29812
  });
29809
29813
  }
29810
- const material = boardMaterialColors["material" in boardOrPanel ? boardOrPanel.material ?? "fr4" : "fr4"] ?? colors.fr4Tan;
29814
+ const materialName = "material" in boardOrPanel && boardOrPanel.material ? boardOrPanel.material : panels.length > 0 ? boards.find(
29815
+ (b) => b.pcb_panel_id === boardOrPanel.pcb_panel_id
29816
+ )?.material ?? "fr4" : "fr4";
29817
+ const material = boardMaterialColors[materialName] ?? colors.fr4Tan;
29811
29818
  return [(0, import_colors.colorize)(material, boardGeom)];
29812
29819
  };
29813
29820
  var createBoardGeomFromCircuitJson = (circuitJson, opts = {}) => {
@@ -29821,10 +29828,10 @@ var createBoardGeomFromCircuitJson = (circuitJson, opts = {}) => {
29821
29828
  };
29822
29829
 
29823
29830
  // src/BoardGeomBuilder.ts
29824
- var import_transforms10 = __toESM(require_transforms(), 1);
29825
- var import_primitives11 = __toESM(require_primitives(), 1);
29826
- var import_colors7 = __toESM(require_colors(), 1);
29827
- var import_booleans7 = __toESM(require_booleans(), 1);
29831
+ var import_transforms6 = __toESM(require_transforms(), 1);
29832
+ var import_primitives7 = __toESM(require_primitives(), 1);
29833
+ var import_colors3 = __toESM(require_colors(), 1);
29834
+ var import_booleans5 = __toESM(require_booleans(), 1);
29828
29835
  import { su as su3 } from "@tscircuit/circuit-json-util";
29829
29836
 
29830
29837
  // src/geoms/plated-hole.ts
@@ -29996,19 +30003,19 @@ var platedHole = (plated_hole, ctx, options = {}) => {
29996
30003
  const holeWidth = plated_hole.hole_width || 0;
29997
30004
  const holeHeight = plated_hole.hole_height || 0;
29998
30005
  const copperBody = (() => {
29999
- const circle2 = (0, import_primitives4.cylinder)({
30006
+ const circle = (0, import_primitives4.cylinder)({
30000
30007
  center: [0, 0, 0],
30001
30008
  radius: 1,
30002
30009
  height: copperSpan + 0.01,
30003
30010
  segments: 64
30004
30011
  // High segment count for smooth ellipse
30005
30012
  });
30006
- const scaled = (0, import_transforms3.scale)([outerWidth / 2, outerHeight / 2, 1], circle2);
30013
+ const scaled = (0, import_transforms3.scale)([outerWidth / 2, outerHeight / 2, 1], circle);
30007
30014
  return (0, import_transforms4.translate)([plated_hole.x, plated_hole.y, 0], scaled);
30008
30015
  })();
30009
30016
  const copperSolid = maybeClip(copperBody, clipGeom);
30010
30017
  const drill = (() => {
30011
- const circle2 = (0, import_primitives4.cylinder)({
30018
+ const circle = (0, import_primitives4.cylinder)({
30012
30019
  center: [0, 0, 0],
30013
30020
  radius: 1,
30014
30021
  height: throughDrillHeight,
@@ -30017,7 +30024,7 @@ var platedHole = (plated_hole, ctx, options = {}) => {
30017
30024
  });
30018
30025
  const scaled = (0, import_transforms3.scale)(
30019
30026
  [Math.max(holeWidth / 2, 0.01), Math.max(holeHeight / 2, 0.01), 1],
30020
- circle2
30027
+ circle
30021
30028
  );
30022
30029
  return (0, import_transforms4.translate)([plated_hole.x, plated_hole.y, 0], scaled);
30023
30030
  })();
@@ -30379,526 +30386,12 @@ var platedHole = (plated_hole, ctx, options = {}) => {
30379
30386
  };
30380
30387
 
30381
30388
  // src/BoardGeomBuilder.ts
30382
- var import_extrusions8 = __toESM(require_extrusions(), 1);
30383
- var import_expansions4 = __toESM(require_expansions(), 1);
30384
-
30385
- // src/geoms/create-geoms-for-silkscreen-text.ts
30386
- var import_text = __toESM(require_text(), 1);
30387
-
30388
- // node_modules/transformation-matrix/src/applyToPoint.js
30389
- function applyToPoint(matrix, point2) {
30390
- return Array.isArray(point2) ? [
30391
- matrix.a * point2[0] + matrix.c * point2[1] + matrix.e,
30392
- matrix.b * point2[0] + matrix.d * point2[1] + matrix.f
30393
- ] : {
30394
- x: matrix.a * point2.x + matrix.c * point2.y + matrix.e,
30395
- y: matrix.b * point2.x + matrix.d * point2.y + matrix.f
30396
- };
30397
- }
30398
-
30399
- // node_modules/transformation-matrix/src/utils.js
30400
- function isUndefined(val) {
30401
- return typeof val === "undefined";
30402
- }
30403
-
30404
- // node_modules/transformation-matrix/src/translate.js
30405
- function translate4(tx, ty = 0) {
30406
- return {
30407
- a: 1,
30408
- c: 0,
30409
- e: tx,
30410
- b: 0,
30411
- d: 1,
30412
- f: ty
30413
- };
30414
- }
30415
-
30416
- // node_modules/transformation-matrix/src/transform.js
30417
- function transform(...matrices) {
30418
- matrices = Array.isArray(matrices[0]) ? matrices[0] : matrices;
30419
- const multiply = (m1, m2) => {
30420
- return {
30421
- a: m1.a * m2.a + m1.c * m2.b,
30422
- c: m1.a * m2.c + m1.c * m2.d,
30423
- e: m1.a * m2.e + m1.c * m2.f + m1.e,
30424
- b: m1.b * m2.a + m1.d * m2.b,
30425
- d: m1.b * m2.c + m1.d * m2.d,
30426
- f: m1.b * m2.e + m1.d * m2.f + m1.f
30427
- };
30428
- };
30429
- switch (matrices.length) {
30430
- case 0:
30431
- throw new Error("no matrices provided");
30432
- case 1:
30433
- return matrices[0];
30434
- case 2:
30435
- return multiply(matrices[0], matrices[1]);
30436
- default: {
30437
- const [m1, m2, ...rest] = matrices;
30438
- const m = multiply(m1, m2);
30439
- return transform(m, ...rest);
30440
- }
30441
- }
30442
- }
30443
- function compose(...matrices) {
30444
- return transform(...matrices);
30445
- }
30446
-
30447
- // node_modules/transformation-matrix/src/rotate.js
30448
- var { cos, sin, PI } = Math;
30449
- function rotate2(angle, cx, cy) {
30450
- const cosAngle = cos(angle);
30451
- const sinAngle = sin(angle);
30452
- const rotationMatrix = {
30453
- a: cosAngle,
30454
- c: -sinAngle,
30455
- e: 0,
30456
- b: sinAngle,
30457
- d: cosAngle,
30458
- f: 0
30459
- };
30460
- if (isUndefined(cx) || isUndefined(cy)) {
30461
- return rotationMatrix;
30462
- }
30463
- return transform([
30464
- translate4(cx, cy),
30465
- rotationMatrix,
30466
- translate4(-cx, -cy)
30467
- ]);
30468
- }
30469
-
30470
- // node_modules/transformation-matrix/src/skew.js
30471
- var { tan } = Math;
30472
-
30473
- // node_modules/transformation-matrix/src/fromTransformAttribute.autogenerated.js
30474
- function peg$subclass(child, parent) {
30475
- function C() {
30476
- this.constructor = child;
30477
- }
30478
- C.prototype = parent.prototype;
30479
- child.prototype = new C();
30480
- }
30481
- function peg$SyntaxError(message, expected, found, location) {
30482
- var self = Error.call(this, message);
30483
- if (Object.setPrototypeOf) {
30484
- Object.setPrototypeOf(self, peg$SyntaxError.prototype);
30485
- }
30486
- self.expected = expected;
30487
- self.found = found;
30488
- self.location = location;
30489
- self.name = "SyntaxError";
30490
- return self;
30491
- }
30492
- peg$subclass(peg$SyntaxError, Error);
30493
- function peg$padEnd(str, targetLength, padString) {
30494
- padString = padString || " ";
30495
- if (str.length > targetLength) {
30496
- return str;
30497
- }
30498
- targetLength -= str.length;
30499
- padString += padString.repeat(targetLength);
30500
- return str + padString.slice(0, targetLength);
30501
- }
30502
- peg$SyntaxError.prototype.format = function(sources) {
30503
- var str = "Error: " + this.message;
30504
- if (this.location) {
30505
- var src = null;
30506
- var k;
30507
- for (k = 0; k < sources.length; k++) {
30508
- if (sources[k].source === this.location.source) {
30509
- src = sources[k].text.split(/\r\n|\n|\r/g);
30510
- break;
30511
- }
30512
- }
30513
- var s = this.location.start;
30514
- var offset_s = this.location.source && typeof this.location.source.offset === "function" ? this.location.source.offset(s) : s;
30515
- var loc = this.location.source + ":" + offset_s.line + ":" + offset_s.column;
30516
- if (src) {
30517
- var e = this.location.end;
30518
- var filler = peg$padEnd("", offset_s.line.toString().length, " ");
30519
- var line4 = src[s.line - 1];
30520
- var last = s.line === e.line ? e.column : line4.length + 1;
30521
- var hatLen = last - s.column || 1;
30522
- str += "\n --> " + loc + "\n" + filler + " |\n" + offset_s.line + " | " + line4 + "\n" + filler + " | " + peg$padEnd("", s.column - 1, " ") + peg$padEnd("", hatLen, "^");
30523
- } else {
30524
- str += "\n at " + loc;
30525
- }
30526
- }
30527
- return str;
30528
- };
30529
- peg$SyntaxError.buildMessage = function(expected, found) {
30530
- var DESCRIBE_EXPECTATION_FNS = {
30531
- literal: function(expectation) {
30532
- return '"' + literalEscape(expectation.text) + '"';
30533
- },
30534
- class: function(expectation) {
30535
- var escapedParts = expectation.parts.map(function(part) {
30536
- return Array.isArray(part) ? classEscape(part[0]) + "-" + classEscape(part[1]) : classEscape(part);
30537
- });
30538
- return "[" + (expectation.inverted ? "^" : "") + escapedParts.join("") + "]";
30539
- },
30540
- any: function() {
30541
- return "any character";
30542
- },
30543
- end: function() {
30544
- return "end of input";
30545
- },
30546
- other: function(expectation) {
30547
- return expectation.description;
30548
- }
30549
- };
30550
- function hex(ch) {
30551
- return ch.charCodeAt(0).toString(16).toUpperCase();
30552
- }
30553
- function literalEscape(s) {
30554
- return s.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\0/g, "\\0").replace(/\t/g, "\\t").replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/[\x00-\x0F]/g, function(ch) {
30555
- return "\\x0" + hex(ch);
30556
- }).replace(/[\x10-\x1F\x7F-\x9F]/g, function(ch) {
30557
- return "\\x" + hex(ch);
30558
- });
30559
- }
30560
- function classEscape(s) {
30561
- return s.replace(/\\/g, "\\\\").replace(/\]/g, "\\]").replace(/\^/g, "\\^").replace(/-/g, "\\-").replace(/\0/g, "\\0").replace(/\t/g, "\\t").replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/[\x00-\x0F]/g, function(ch) {
30562
- return "\\x0" + hex(ch);
30563
- }).replace(/[\x10-\x1F\x7F-\x9F]/g, function(ch) {
30564
- return "\\x" + hex(ch);
30565
- });
30566
- }
30567
- function describeExpectation(expectation) {
30568
- return DESCRIBE_EXPECTATION_FNS[expectation.type](expectation);
30569
- }
30570
- function describeExpected(expected2) {
30571
- var descriptions = expected2.map(describeExpectation);
30572
- var i, j;
30573
- descriptions.sort();
30574
- if (descriptions.length > 0) {
30575
- for (i = 1, j = 1; i < descriptions.length; i++) {
30576
- if (descriptions[i - 1] !== descriptions[i]) {
30577
- descriptions[j] = descriptions[i];
30578
- j++;
30579
- }
30580
- }
30581
- descriptions.length = j;
30582
- }
30583
- switch (descriptions.length) {
30584
- case 1:
30585
- return descriptions[0];
30586
- case 2:
30587
- return descriptions[0] + " or " + descriptions[1];
30588
- default:
30589
- return descriptions.slice(0, -1).join(", ") + ", or " + descriptions[descriptions.length - 1];
30590
- }
30591
- }
30592
- function describeFound(found2) {
30593
- return found2 ? '"' + literalEscape(found2) + '"' : "end of input";
30594
- }
30595
- return "Expected " + describeExpected(expected) + " but " + describeFound(found) + " found.";
30596
- };
30597
-
30598
- // src/geoms/create-geoms-for-silkscreen-text.ts
30599
- function createSilkscreenTextGeoms(silkscreenText) {
30600
- const textOutlines = (0, import_text.vectorText)({
30601
- height: silkscreenText.font_size * 0.45,
30602
- input: silkscreenText.text
30603
- });
30604
- let rotationDegrees = silkscreenText.ccw_rotation ?? 0;
30605
- textOutlines.forEach((outline) => {
30606
- if (outline.length === 29) {
30607
- textOutlines.splice(
30608
- textOutlines.indexOf(outline),
30609
- 1,
30610
- outline.slice(0, 15)
30611
- );
30612
- textOutlines.splice(
30613
- textOutlines.indexOf(outline),
30614
- 0,
30615
- outline.slice(14, 29)
30616
- );
30617
- } else if (outline.length === 17) {
30618
- textOutlines.splice(
30619
- textOutlines.indexOf(outline),
30620
- 1,
30621
- outline.slice(0, 10)
30622
- );
30623
- textOutlines.splice(
30624
- textOutlines.indexOf(outline),
30625
- 0,
30626
- outline.slice(9, 17)
30627
- );
30628
- }
30629
- });
30630
- const points = textOutlines.flatMap((o) => o);
30631
- const textBounds = {
30632
- minX: Math.min(...points.map((p) => p[0])),
30633
- maxX: Math.max(...points.map((p) => p[0])),
30634
- minY: Math.min(...points.map((p) => p[1])),
30635
- maxY: Math.max(...points.map((p) => p[1]))
30636
- };
30637
- const centerX = (textBounds.minX + textBounds.maxX) / 2;
30638
- const centerY = (textBounds.minY + textBounds.maxY) / 2;
30639
- let xOffset = -centerX;
30640
- let yOffset = -centerY;
30641
- if (silkscreenText.anchor_alignment?.includes("right")) {
30642
- xOffset = -textBounds.maxX;
30643
- } else if (silkscreenText.anchor_alignment?.includes("left")) {
30644
- xOffset = -textBounds.minX;
30645
- }
30646
- if (silkscreenText.anchor_alignment?.includes("top")) {
30647
- yOffset = -textBounds.maxY;
30648
- } else if (silkscreenText.anchor_alignment?.includes("bottom")) {
30649
- yOffset = -textBounds.minY;
30650
- }
30651
- const transforms = [];
30652
- if (silkscreenText.layer === "bottom") {
30653
- transforms.push(
30654
- translate4(centerX, centerY),
30655
- { a: -1, b: 0, c: 0, d: 1, e: 0, f: 0 },
30656
- // horizontal flip matrix
30657
- translate4(-centerX, -centerY)
30658
- );
30659
- rotationDegrees = -rotationDegrees;
30660
- }
30661
- if (rotationDegrees) {
30662
- const rad = rotationDegrees * Math.PI / 180;
30663
- transforms.push(
30664
- translate4(centerX, centerY),
30665
- rotate2(rad),
30666
- translate4(-centerX, -centerY)
30667
- );
30668
- }
30669
- let transformedOutlines = textOutlines;
30670
- if (transforms.length > 0) {
30671
- const matrix = compose(...transforms);
30672
- transformedOutlines = textOutlines.map(
30673
- (outline) => outline.map(([x, y]) => {
30674
- const { x: nx, y: ny } = applyToPoint(matrix, { x, y });
30675
- return [nx, ny];
30676
- })
30677
- );
30678
- }
30679
- return {
30680
- textOutlines: transformedOutlines,
30681
- xOffset,
30682
- yOffset
30683
- };
30684
- }
30685
-
30686
- // src/geoms/create-geoms-for-silkscreen-path.ts
30687
- var import_primitives5 = __toESM(require_primitives(), 1);
30688
- var import_expansions2 = __toESM(require_expansions(), 1);
30689
30389
  var import_extrusions4 = __toESM(require_extrusions(), 1);
30690
- var import_transforms5 = __toESM(require_transforms(), 1);
30691
- var import_colors3 = __toESM(require_colors(), 1);
30692
-
30693
- // src/utils/units.ts
30694
- var MM_PER_INCH = 25.4;
30695
- var MM_PER_MIL = MM_PER_INCH / 1e3;
30696
- var dimensionRegex = /^\s*(-?\d*(?:\.\d+)?)(?:\s*(mm|mil|inch|in|"))?\s*$/i;
30697
- function normalizeUnit(unit) {
30698
- if (!unit) return void 0;
30699
- const normalized = unit.trim().toLowerCase();
30700
- if (normalized === '"') return "in";
30701
- if (normalized === "inch") return "in";
30702
- return normalized;
30703
- }
30704
- function parseDimensionToMm(value) {
30705
- if (value === null || value === void 0) return void 0;
30706
- if (typeof value === "number") {
30707
- return Number.isFinite(value) ? value : void 0;
30708
- }
30709
- if (typeof value !== "string") return void 0;
30710
- const trimmed = value.trim();
30711
- if (trimmed.length === 0) return void 0;
30712
- const match = trimmed.match(dimensionRegex);
30713
- if (!match) {
30714
- const numeric = Number.parseFloat(trimmed);
30715
- return Number.isFinite(numeric) ? numeric : void 0;
30716
- }
30717
- const [, magnitudeRaw, unitRaw] = match;
30718
- const magnitude = Number.parseFloat(magnitudeRaw || "0");
30719
- if (!Number.isFinite(magnitude)) return void 0;
30720
- const unit = normalizeUnit(unitRaw);
30721
- switch (unit) {
30722
- case "mil":
30723
- return magnitude * MM_PER_MIL;
30724
- case "in":
30725
- return magnitude * MM_PER_INCH;
30726
- case "mm":
30727
- case void 0:
30728
- return magnitude;
30729
- default:
30730
- return magnitude;
30731
- }
30732
- }
30733
- function coerceDimensionToMm(value, fallback) {
30734
- const parsed = parseDimensionToMm(value);
30735
- return parsed === void 0 ? fallback : parsed;
30736
- }
30737
-
30738
- // src/geoms/create-geoms-for-silkscreen-path.ts
30739
- function createSilkscreenPathGeom(sp, ctx) {
30740
- if (sp.route.length < 2) return void 0;
30741
- const routePoints = sp.route.map((p) => [
30742
- parseDimensionToMm(p.x) ?? 0,
30743
- parseDimensionToMm(p.y) ?? 0
30744
- ]);
30745
- const pathLine = (0, import_primitives5.line)(routePoints);
30746
- const strokeWidth = coerceDimensionToMm(sp.stroke_width, 0.1);
30747
- const expandedPath = (0, import_expansions2.expand)(
30748
- { delta: strokeWidth / 2, corners: "round" },
30749
- pathLine
30750
- );
30751
- const layerSign = sp.layer === "bottom" ? -1 : 1;
30752
- const zPos = layerSign * ctx.pcbThickness / 2 + layerSign * M * 1.5;
30753
- let pathGeom = (0, import_transforms5.translate)(
30754
- [0, 0, zPos],
30755
- (0, import_extrusions4.extrudeLinear)({ height: 0.012 }, expandedPath)
30756
- // Standard silkscreen thickness
30757
- );
30758
- pathGeom = (0, import_colors3.colorize)([1, 1, 1], pathGeom);
30759
- return pathGeom;
30760
- }
30761
-
30762
- // src/geoms/create-geoms-for-silkscreen-line.ts
30763
- var import_primitives6 = __toESM(require_primitives(), 1);
30764
- var import_expansions3 = __toESM(require_expansions(), 1);
30765
- var import_extrusions5 = __toESM(require_extrusions(), 1);
30766
- var import_transforms6 = __toESM(require_transforms(), 1);
30767
- var import_colors4 = __toESM(require_colors(), 1);
30768
- function createSilkscreenLineGeom(sl, ctx) {
30769
- const x1 = parseDimensionToMm(sl.x1) ?? 0;
30770
- const y1 = parseDimensionToMm(sl.y1) ?? 0;
30771
- const x2 = parseDimensionToMm(sl.x2) ?? 0;
30772
- const y2 = parseDimensionToMm(sl.y2) ?? 0;
30773
- if (x1 === x2 && y1 === y2) return void 0;
30774
- const routePoints = [
30775
- [x1, y1],
30776
- [x2, y2]
30777
- ];
30778
- const baseLine = (0, import_primitives6.line)(routePoints);
30779
- const strokeWidth = coerceDimensionToMm(sl.stroke_width, 0.1);
30780
- const expandedLine = (0, import_expansions3.expand)(
30781
- { delta: strokeWidth / 2, corners: "round" },
30782
- baseLine
30783
- );
30784
- const layerSign = sl.layer === "bottom" ? -1 : 1;
30785
- const zPos = layerSign * ctx.pcbThickness / 2 + layerSign * M * 1.5;
30786
- let lineGeom = (0, import_transforms6.translate)(
30787
- [0, 0, zPos],
30788
- (0, import_extrusions5.extrudeLinear)({ height: 0.012 }, expandedLine)
30789
- );
30790
- lineGeom = (0, import_colors4.colorize)([1, 1, 1], lineGeom);
30791
- return lineGeom;
30792
- }
30793
-
30794
- // src/geoms/create-geoms-for-silkscreen-rect.ts
30795
- var import_primitives7 = __toESM(require_primitives(), 1);
30796
- var import_extrusions6 = __toESM(require_extrusions(), 1);
30797
- var import_transforms7 = __toESM(require_transforms(), 1);
30798
- var import_colors5 = __toESM(require_colors(), 1);
30799
- var import_booleans3 = __toESM(require_booleans(), 1);
30800
- var RECT_SEGMENTS = 64;
30801
- function createSilkscreenRectGeom(rect, ctx) {
30802
- const width10 = coerceDimensionToMm(rect.width, 0);
30803
- const height10 = coerceDimensionToMm(rect.height, 0);
30804
- if (width10 <= 0 || height10 <= 0) return void 0;
30805
- const centerX = parseDimensionToMm(rect.center?.x) ?? 0;
30806
- const centerY = parseDimensionToMm(rect.center?.y) ?? 0;
30807
- const rawBorderRadius = extractRectBorderRadius(rect);
30808
- const borderRadius = clampRectBorderRadius(
30809
- width10,
30810
- height10,
30811
- typeof rawBorderRadius === "string" ? parseDimensionToMm(rawBorderRadius) : rawBorderRadius
30812
- );
30813
- const createRectGeom = (rectWidth, rectHeight, radius) => (0, import_extrusions6.extrudeLinear)(
30814
- { height: 0.012 },
30815
- (0, import_primitives7.roundedRectangle)({
30816
- size: [rectWidth, rectHeight],
30817
- roundRadius: radius,
30818
- segments: RECT_SEGMENTS
30819
- })
30820
- );
30821
- const isFilled = rect.is_filled ?? true;
30822
- const hasStroke = rect.has_stroke ?? false;
30823
- const strokeWidth = hasStroke ? coerceDimensionToMm(rect.stroke_width, 0.1) : 0;
30824
- let fillGeom;
30825
- if (isFilled) {
30826
- fillGeom = createRectGeom(width10, height10, borderRadius);
30827
- }
30828
- let strokeGeom;
30829
- if (hasStroke && strokeWidth > 0) {
30830
- const outerGeom = createRectGeom(width10, height10, borderRadius);
30831
- const innerWidth = width10 - strokeWidth * 2;
30832
- const innerHeight = height10 - strokeWidth * 2;
30833
- if (innerWidth > 0 && innerHeight > 0) {
30834
- const innerRadius = clampRectBorderRadius(
30835
- innerWidth,
30836
- innerHeight,
30837
- Math.max(borderRadius - strokeWidth, 0)
30838
- );
30839
- const innerGeom = createRectGeom(innerWidth, innerHeight, innerRadius);
30840
- strokeGeom = (0, import_booleans3.subtract)(outerGeom, innerGeom);
30841
- } else {
30842
- strokeGeom = outerGeom;
30843
- }
30844
- }
30845
- let rectGeom = fillGeom;
30846
- if (strokeGeom) {
30847
- rectGeom = rectGeom ? (0, import_booleans3.union)(rectGeom, strokeGeom) : strokeGeom;
30848
- }
30849
- if (!rectGeom) return void 0;
30850
- const layerSign = rect.layer === "bottom" ? -1 : 1;
30851
- const zPos = layerSign * ctx.pcbThickness / 2 + layerSign * M * 1.5;
30852
- rectGeom = (0, import_transforms7.translate)([centerX, centerY, zPos], rectGeom);
30853
- return (0, import_colors5.colorize)([1, 1, 1], rectGeom);
30854
- }
30855
-
30856
- // src/geoms/create-geoms-for-silkscreen-circle.ts
30857
- var import_primitives8 = __toESM(require_primitives(), 1);
30858
- var import_extrusions7 = __toESM(require_extrusions(), 1);
30859
- var import_transforms8 = __toESM(require_transforms(), 1);
30860
- var import_colors6 = __toESM(require_colors(), 1);
30861
- var import_booleans4 = __toESM(require_booleans(), 1);
30862
- var CIRCLE_SEGMENTS = 64;
30863
- function createSilkscreenCircleGeom(circleEl, ctx) {
30864
- const radius = coerceDimensionToMm(circleEl.radius, 0);
30865
- if (radius <= 0) return void 0;
30866
- const strokeWidth = coerceDimensionToMm(circleEl.stroke_width, 0.12);
30867
- const hasStroke = strokeWidth > 0;
30868
- const centerX = parseDimensionToMm(circleEl.center?.x) ?? 0;
30869
- const centerY = parseDimensionToMm(circleEl.center?.y) ?? 0;
30870
- const layerSign = circleEl.layer === "bottom" ? -1 : 1;
30871
- const zPos = layerSign * ctx.pcbThickness / 2 + layerSign * M * 1.5;
30872
- const baseHeight = 0.012;
30873
- let circleGeom;
30874
- if (hasStroke) {
30875
- const outerRadius = radius + strokeWidth / 2;
30876
- const innerRadius = radius - strokeWidth / 2;
30877
- const outerCircle2d = (0, import_primitives8.circle)({
30878
- radius: outerRadius,
30879
- segments: CIRCLE_SEGMENTS
30880
- });
30881
- let ring3d = (0, import_extrusions7.extrudeLinear)({ height: baseHeight }, outerCircle2d);
30882
- if (innerRadius > 0) {
30883
- const innerCircle2d = (0, import_primitives8.circle)({
30884
- radius: innerRadius,
30885
- segments: CIRCLE_SEGMENTS
30886
- });
30887
- const inner3d = (0, import_extrusions7.extrudeLinear)({ height: baseHeight }, innerCircle2d);
30888
- ring3d = (0, import_booleans4.subtract)(ring3d, inner3d);
30889
- }
30890
- circleGeom = ring3d;
30891
- } else {
30892
- const filledCircle2d = (0, import_primitives8.circle)({ radius, segments: CIRCLE_SEGMENTS });
30893
- circleGeom = (0, import_extrusions7.extrudeLinear)({ height: baseHeight }, filledCircle2d);
30894
- }
30895
- const translatedGeom = (0, import_transforms8.translate)([centerX, centerY, zPos], circleGeom);
30896
- return (0, import_colors6.colorize)([1, 1, 1], translatedGeom);
30897
- }
30390
+ var import_expansions2 = __toESM(require_expansions(), 1);
30898
30391
 
30899
30392
  // src/geoms/brep-converter.ts
30900
- var import_primitives9 = __toESM(require_primitives(), 1);
30901
- var import_booleans5 = __toESM(require_booleans(), 1);
30393
+ var import_primitives5 = __toESM(require_primitives(), 1);
30394
+ var import_booleans3 = __toESM(require_booleans(), 1);
30902
30395
  function segmentToPoints(p1, p2, bulge, arcSegments) {
30903
30396
  if (!bulge || Math.abs(bulge) < 1e-9) {
30904
30397
  return [];
@@ -30966,7 +30459,7 @@ function createGeom2FromBRep(brep, arcSegments = 16) {
30966
30459
  if (arePointsClockwise2(outerPoints)) {
30967
30460
  outerPoints.reverse();
30968
30461
  }
30969
- const outerGeom = (0, import_primitives9.polygon)({ points: outerPoints });
30462
+ const outerGeom = (0, import_primitives5.polygon)({ points: outerPoints });
30970
30463
  if (!brep.inner_rings || brep.inner_rings.length === 0) {
30971
30464
  return outerGeom;
30972
30465
  }
@@ -30975,16 +30468,16 @@ function createGeom2FromBRep(brep, arcSegments = 16) {
30975
30468
  if (arePointsClockwise2(innerPoints)) {
30976
30469
  innerPoints.reverse();
30977
30470
  }
30978
- return (0, import_primitives9.polygon)({ points: innerPoints });
30471
+ return (0, import_primitives5.polygon)({ points: innerPoints });
30979
30472
  });
30980
30473
  if (innerGeoms.length === 0) return outerGeom;
30981
- return (0, import_booleans5.subtract)(outerGeom, innerGeoms);
30474
+ return (0, import_booleans3.subtract)(outerGeom, innerGeoms);
30982
30475
  }
30983
30476
 
30984
30477
  // src/geoms/via-geoms.ts
30985
- var import_booleans6 = __toESM(require_booleans(), 1);
30986
- var import_transforms9 = __toESM(require_transforms(), 1);
30987
- var import_primitives10 = __toESM(require_primitives(), 1);
30478
+ var import_booleans4 = __toESM(require_booleans(), 1);
30479
+ var import_transforms5 = __toESM(require_transforms(), 1);
30480
+ var import_primitives6 = __toESM(require_primitives(), 1);
30988
30481
  function createViaCopper({
30989
30482
  x,
30990
30483
  y,
@@ -31003,34 +30496,34 @@ function createViaCopper({
31003
30496
  outerDiameter / 2,
31004
30497
  holeDiameter / 2 + platingThickness
31005
30498
  );
31006
- const barrel = (0, import_primitives10.cylinder)({
30499
+ const barrel = (0, import_primitives6.cylinder)({
31007
30500
  center: [0, 0, 0],
31008
30501
  radius: barrelRadius,
31009
30502
  height: thickness,
31010
30503
  segments: SMOOTH_CIRCLE_SEGMENTS
31011
30504
  });
31012
- const topPad = (0, import_primitives10.cylinder)({
30505
+ const topPad = (0, import_primitives6.cylinder)({
31013
30506
  center: [0, 0, thickness / 2],
31014
30507
  radius: outerDiameter / 2,
31015
30508
  height: padThickness,
31016
30509
  segments: SMOOTH_CIRCLE_SEGMENTS
31017
30510
  });
31018
- const bottomPad = (0, import_primitives10.cylinder)({
30511
+ const bottomPad = (0, import_primitives6.cylinder)({
31019
30512
  center: [0, 0, -thickness / 2],
31020
30513
  radius: outerDiameter / 2,
31021
30514
  height: padThickness,
31022
30515
  segments: SMOOTH_CIRCLE_SEGMENTS
31023
30516
  });
31024
- const viaSolid = (0, import_booleans6.union)([barrel, topPad, bottomPad]);
30517
+ const viaSolid = (0, import_booleans4.union)([barrel, topPad, bottomPad]);
31025
30518
  const drillHeight = thickness + padThickness * 2;
31026
- const drill = (0, import_primitives10.cylinder)({
30519
+ const drill = (0, import_primitives6.cylinder)({
31027
30520
  center: [0, 0, 0],
31028
30521
  radius: holeDiameter / 2,
31029
30522
  height: drillHeight,
31030
30523
  segments: SMOOTH_CIRCLE_SEGMENTS
31031
30524
  });
31032
- const finalViaCopper = (0, import_booleans6.subtract)(viaSolid, drill);
31033
- const positionedVia = (0, import_transforms9.translate)([x, y, 0], finalViaCopper);
30525
+ const finalViaCopper = (0, import_booleans4.subtract)(viaSolid, drill);
30526
+ const positionedVia = (0, import_transforms5.translate)([x, y, 0], finalViaCopper);
31034
30527
  return positionedVia;
31035
30528
  }
31036
30529
  function createViaBoardDrill({
@@ -31041,7 +30534,7 @@ function createViaBoardDrill({
31041
30534
  }) {
31042
30535
  const drillHeight = thickness * 1.5;
31043
30536
  const drillRadius = holeDiameter / 2 + M;
31044
- const drill = (0, import_primitives10.cylinder)({
30537
+ const drill = (0, import_primitives6.cylinder)({
31045
30538
  center: [x, y, 0],
31046
30539
  radius: drillRadius,
31047
30540
  height: drillHeight,
@@ -31057,15 +30550,15 @@ var BOARD_CLIP_XY_OUTSET = 0.05;
31057
30550
  var createCenteredRectPadGeom = (width10, height10, thickness, rectBorderRadius) => {
31058
30551
  const clampedRadius = clampRectBorderRadius(width10, height10, rectBorderRadius);
31059
30552
  if (clampedRadius <= 0) {
31060
- return (0, import_primitives11.cuboid)({ center: [0, 0, 0], size: [width10, height10, thickness] });
30553
+ return (0, import_primitives7.cuboid)({ center: [0, 0, 0], size: [width10, height10, thickness] });
31061
30554
  }
31062
- const rect2d = (0, import_primitives11.roundedRectangle)({
30555
+ const rect2d = (0, import_primitives7.roundedRectangle)({
31063
30556
  size: [width10, height10],
31064
30557
  roundRadius: clampedRadius,
31065
30558
  segments: PAD_ROUNDED_SEGMENTS
31066
30559
  });
31067
- const extruded = (0, import_extrusions8.extrudeLinear)({ height: thickness }, rect2d);
31068
- return (0, import_transforms10.translate)([0, 0, -thickness / 2], extruded);
30560
+ const extruded = (0, import_extrusions4.extrudeLinear)({ height: thickness }, rect2d);
30561
+ return (0, import_transforms6.translate)([0, 0, -thickness / 2], extruded);
31069
30562
  };
31070
30563
  var buildStateOrder = [
31071
30564
  "initializing",
@@ -31076,11 +30569,6 @@ var buildStateOrder = [
31076
30569
  "processing_cutouts",
31077
30570
  "processing_traces",
31078
30571
  "processing_vias",
31079
- "processing_silkscreen_text",
31080
- "processing_silkscreen_lines",
31081
- "processing_silkscreen_circles",
31082
- "processing_silkscreen_rects",
31083
- "processing_silkscreen_paths",
31084
30572
  "finalizing",
31085
30573
  "done"
31086
30574
  ];
@@ -31092,11 +30580,6 @@ var BoardGeomBuilder = class {
31092
30580
  pads;
31093
30581
  traces;
31094
30582
  pcb_vias;
31095
- silkscreenTexts;
31096
- silkscreenPaths;
31097
- silkscreenLines;
31098
- silkscreenCircles;
31099
- silkscreenRects;
31100
30583
  pcb_cutouts;
31101
30584
  pcb_copper_pours;
31102
30585
  boardGeom = null;
@@ -31105,11 +30588,6 @@ var BoardGeomBuilder = class {
31105
30588
  traceGeoms = [];
31106
30589
  viaGeoms = [];
31107
30590
  // Combined with platedHoleGeoms
31108
- silkscreenTextGeoms = [];
31109
- silkscreenPathGeoms = [];
31110
- silkscreenLineGeoms = [];
31111
- silkscreenCircleGeoms = [];
31112
- silkscreenRectGeoms = [];
31113
30591
  copperPourGeoms = [];
31114
30592
  boardClipGeom = null;
31115
30593
  state = "initializing";
@@ -31141,16 +30619,18 @@ var BoardGeomBuilder = class {
31141
30619
  const boards = su3(circuitJson).pcb_board.list();
31142
30620
  if (panels.length > 0) {
31143
30621
  const panel = panels[0];
30622
+ const firstBoardInPanel = boards.find(
30623
+ (b) => b.pcb_panel_id === panel.pcb_panel_id
30624
+ );
31144
30625
  this.board = {
31145
30626
  type: "pcb_board",
31146
30627
  pcb_board_id: panel.pcb_panel_id,
31147
30628
  center: panel.center,
31148
30629
  width: panel.width,
31149
30630
  height: panel.height,
31150
- thickness: 1.6,
31151
- // Default thickness
31152
- material: "fr4",
31153
- num_layers: 2
30631
+ thickness: firstBoardInPanel?.thickness ?? 1.6,
30632
+ material: firstBoardInPanel?.material ?? "fr4",
30633
+ num_layers: firstBoardInPanel?.num_layers ?? 2
31154
30634
  };
31155
30635
  } else {
31156
30636
  const boardsNotInPanel = boards.filter((b) => !b.pcb_panel_id);
@@ -31161,11 +30641,6 @@ var BoardGeomBuilder = class {
31161
30641
  this.pads = su3(circuitJson).pcb_smtpad.list();
31162
30642
  this.traces = su3(circuitJson).pcb_trace.list();
31163
30643
  this.pcb_vias = su3(circuitJson).pcb_via.list();
31164
- this.silkscreenTexts = su3(circuitJson).pcb_silkscreen_text.list();
31165
- this.silkscreenPaths = su3(circuitJson).pcb_silkscreen_path.list();
31166
- this.silkscreenLines = su3(circuitJson).pcb_silkscreen_line.list();
31167
- this.silkscreenCircles = su3(circuitJson).pcb_silkscreen_circle.list();
31168
- this.silkscreenRects = su3(circuitJson).pcb_silkscreen_rect.list();
31169
30644
  this.pcb_cutouts = su3(circuitJson).pcb_cutout.list();
31170
30645
  this.pcb_copper_pours = circuitJson.filter(
31171
30646
  (e) => e.type === "pcb_copper_pour"
@@ -31190,11 +30665,11 @@ var BoardGeomBuilder = class {
31190
30665
  { xyOutset: BOARD_CLIP_XY_OUTSET }
31191
30666
  );
31192
30667
  } else {
31193
- this.boardGeom = (0, import_primitives11.cuboid)({
30668
+ this.boardGeom = (0, import_primitives7.cuboid)({
31194
30669
  size: [this.board.width, this.board.height, this.ctx.pcbThickness],
31195
30670
  center: [this.board.center.x, this.board.center.y, 0]
31196
30671
  });
31197
- this.boardClipGeom = (0, import_primitives11.cuboid)({
30672
+ this.boardClipGeom = (0, import_primitives7.cuboid)({
31198
30673
  size: [
31199
30674
  this.board.width + 2 * BOARD_CLIP_XY_OUTSET,
31200
30675
  this.board.height + 2 * BOARD_CLIP_XY_OUTSET,
@@ -31258,48 +30733,6 @@ var BoardGeomBuilder = class {
31258
30733
  this.goToNextState();
31259
30734
  }
31260
30735
  break;
31261
- case "processing_silkscreen_text":
31262
- if (this.currentIndex < this.silkscreenTexts.length) {
31263
- this.processSilkscreenText(this.silkscreenTexts[this.currentIndex]);
31264
- this.currentIndex++;
31265
- } else {
31266
- this.goToNextState();
31267
- }
31268
- break;
31269
- case "processing_silkscreen_lines":
31270
- if (this.currentIndex < this.silkscreenLines.length) {
31271
- this.processSilkscreenLine(this.silkscreenLines[this.currentIndex]);
31272
- this.currentIndex++;
31273
- } else {
31274
- this.goToNextState();
31275
- }
31276
- break;
31277
- case "processing_silkscreen_circles":
31278
- if (this.currentIndex < this.silkscreenCircles.length) {
31279
- this.processSilkscreenCircle(
31280
- this.silkscreenCircles[this.currentIndex]
31281
- );
31282
- this.currentIndex++;
31283
- } else {
31284
- this.goToNextState();
31285
- }
31286
- break;
31287
- case "processing_silkscreen_rects":
31288
- if (this.currentIndex < this.silkscreenRects.length) {
31289
- this.processSilkscreenRect(this.silkscreenRects[this.currentIndex]);
31290
- this.currentIndex++;
31291
- } else {
31292
- this.goToNextState();
31293
- }
31294
- break;
31295
- case "processing_silkscreen_paths":
31296
- if (this.currentIndex < this.silkscreenPaths.length) {
31297
- this.processSilkscreenPath(this.silkscreenPaths[this.currentIndex]);
31298
- this.currentIndex++;
31299
- } else {
31300
- this.goToNextState();
31301
- }
31302
- break;
31303
30736
  case "processing_cutouts":
31304
30737
  if (this.currentIndex < this.pcb_cutouts.length) {
31305
30738
  this.processCutout(this.pcb_cutouts[this.currentIndex]);
@@ -31336,31 +30769,31 @@ var BoardGeomBuilder = class {
31336
30769
  extractRectBorderRadius(cutout)
31337
30770
  );
31338
30771
  if (rectCornerRadius > 0) {
31339
- const rect2d = (0, import_primitives11.roundedRectangle)({
30772
+ const rect2d = (0, import_primitives7.roundedRectangle)({
31340
30773
  size: [cutout.width, cutout.height],
31341
30774
  roundRadius: rectCornerRadius,
31342
30775
  segments: PAD_ROUNDED_SEGMENTS
31343
30776
  });
31344
- cutoutGeom = (0, import_extrusions8.extrudeLinear)({ height: cutoutHeight }, rect2d);
31345
- cutoutGeom = (0, import_transforms10.translate)([0, 0, -cutoutHeight / 2], cutoutGeom);
30777
+ cutoutGeom = (0, import_extrusions4.extrudeLinear)({ height: cutoutHeight }, rect2d);
30778
+ cutoutGeom = (0, import_transforms6.translate)([0, 0, -cutoutHeight / 2], cutoutGeom);
31346
30779
  } else {
31347
- cutoutGeom = (0, import_primitives11.cuboid)({
30780
+ cutoutGeom = (0, import_primitives7.cuboid)({
31348
30781
  center: [0, 0, 0],
31349
30782
  size: [cutout.width, cutout.height, cutoutHeight]
31350
30783
  });
31351
30784
  }
31352
30785
  if (cutout.rotation) {
31353
30786
  const rotationRadians = cutout.rotation * Math.PI / 180;
31354
- cutoutGeom = (0, import_transforms10.rotateZ)(rotationRadians, cutoutGeom);
30787
+ cutoutGeom = (0, import_transforms6.rotateZ)(rotationRadians, cutoutGeom);
31355
30788
  }
31356
- cutoutGeom = (0, import_transforms10.translate)(
30789
+ cutoutGeom = (0, import_transforms6.translate)(
31357
30790
  [cutout.center.x, cutout.center.y, 0],
31358
30791
  cutoutGeom
31359
30792
  );
31360
30793
  break;
31361
30794
  }
31362
30795
  case "circle":
31363
- cutoutGeom = (0, import_primitives11.cylinder)({
30796
+ cutoutGeom = (0, import_primitives7.cylinder)({
31364
30797
  center: [cutout.center.x, cutout.center.y, 0],
31365
30798
  radius: cutout.radius,
31366
30799
  height: cutoutHeight
@@ -31377,14 +30810,14 @@ var BoardGeomBuilder = class {
31377
30810
  if (arePointsClockwise(pointsVec2)) {
31378
30811
  pointsVec2 = pointsVec2.reverse();
31379
30812
  }
31380
- const polygon2d = (0, import_primitives11.polygon)({ points: pointsVec2 });
31381
- cutoutGeom = (0, import_extrusions8.extrudeLinear)({ height: cutoutHeight }, polygon2d);
31382
- cutoutGeom = (0, import_transforms10.translate)([0, 0, -cutoutHeight / 2], cutoutGeom);
30813
+ const polygon2d = (0, import_primitives7.polygon)({ points: pointsVec2 });
30814
+ cutoutGeom = (0, import_extrusions4.extrudeLinear)({ height: cutoutHeight }, polygon2d);
30815
+ cutoutGeom = (0, import_transforms6.translate)([0, 0, -cutoutHeight / 2], cutoutGeom);
31383
30816
  break;
31384
30817
  }
31385
30818
  }
31386
30819
  if (cutoutGeom) {
31387
- this.boardGeom = (0, import_booleans7.subtract)(this.boardGeom, cutoutGeom);
30820
+ this.boardGeom = (0, import_booleans5.subtract)(this.boardGeom, cutoutGeom);
31388
30821
  }
31389
30822
  }
31390
30823
  processCopperPour(pour) {
@@ -31392,22 +30825,22 @@ var BoardGeomBuilder = class {
31392
30825
  const zPos = layerSign * this.ctx.pcbThickness / 2 + layerSign * BOARD_SURFACE_OFFSET.copper;
31393
30826
  let pourGeom = null;
31394
30827
  if (pour.shape === "rect") {
31395
- let baseGeom = (0, import_primitives11.cuboid)({
30828
+ let baseGeom = (0, import_primitives7.cuboid)({
31396
30829
  center: [0, 0, 0],
31397
30830
  // Create at origin for rotation
31398
30831
  size: [pour.width, pour.height, M]
31399
30832
  });
31400
30833
  if ("rotation" in pour && pour.rotation) {
31401
30834
  const rotationRadians = pour.rotation * Math.PI / 180;
31402
- baseGeom = (0, import_transforms10.rotateZ)(rotationRadians, baseGeom);
30835
+ baseGeom = (0, import_transforms6.rotateZ)(rotationRadians, baseGeom);
31403
30836
  }
31404
- pourGeom = (0, import_transforms10.translate)([pour.center.x, pour.center.y, zPos], baseGeom);
30837
+ pourGeom = (0, import_transforms6.translate)([pour.center.x, pour.center.y, zPos], baseGeom);
31405
30838
  } else if (pour.shape === "brep") {
31406
30839
  const brepShape = pour.brep_shape;
31407
30840
  if (brepShape?.outer_ring) {
31408
30841
  const pourGeom2 = createGeom2FromBRep(brepShape);
31409
- pourGeom = (0, import_extrusions8.extrudeLinear)({ height: M }, pourGeom2);
31410
- pourGeom = (0, import_transforms10.translate)([0, 0, zPos], pourGeom);
30842
+ pourGeom = (0, import_extrusions4.extrudeLinear)({ height: M }, pourGeom2);
30843
+ pourGeom = (0, import_transforms6.translate)([0, 0, zPos], pourGeom);
31411
30844
  }
31412
30845
  } else if (pour.shape === "polygon") {
31413
30846
  let pointsVec2 = pour.points.map((p) => [p.x, p.y]);
@@ -31420,17 +30853,17 @@ var BoardGeomBuilder = class {
31420
30853
  if (arePointsClockwise(pointsVec2)) {
31421
30854
  pointsVec2 = pointsVec2.reverse();
31422
30855
  }
31423
- const polygon2d = (0, import_primitives11.polygon)({ points: pointsVec2 });
31424
- pourGeom = (0, import_extrusions8.extrudeLinear)({ height: M }, polygon2d);
31425
- pourGeom = (0, import_transforms10.translate)([0, 0, zPos], pourGeom);
30856
+ const polygon2d = (0, import_primitives7.polygon)({ points: pointsVec2 });
30857
+ pourGeom = (0, import_extrusions4.extrudeLinear)({ height: M }, polygon2d);
30858
+ pourGeom = (0, import_transforms6.translate)([0, 0, zPos], pourGeom);
31426
30859
  }
31427
30860
  if (pourGeom) {
31428
30861
  if (this.boardClipGeom) {
31429
- pourGeom = (0, import_booleans7.intersect)(this.boardClipGeom, pourGeom);
30862
+ pourGeom = (0, import_booleans5.intersect)(this.boardClipGeom, pourGeom);
31430
30863
  }
31431
30864
  const covered = pour.covered_with_solder_mask !== false;
31432
30865
  const pourMaterialColor = covered ? tracesMaterialColors[this.board.material] ?? colors.fr4TracesWithoutMaskTan : colors.copper;
31433
- const coloredPourGeom = (0, import_colors7.colorize)(pourMaterialColor, pourGeom);
30866
+ const coloredPourGeom = (0, import_colors3.colorize)(pourMaterialColor, pourGeom);
31434
30867
  this.copperPourGeoms.push(coloredPourGeom);
31435
30868
  }
31436
30869
  }
@@ -31439,7 +30872,7 @@ var BoardGeomBuilder = class {
31439
30872
  if (ph.shape === "circle" || ph.shape === "circular_hole_with_rect_pad") {
31440
30873
  let cyGeom = null;
31441
30874
  if (ph.shape === "circular_hole_with_rect_pad") {
31442
- cyGeom = (0, import_primitives11.cylinder)({
30875
+ cyGeom = (0, import_primitives7.cylinder)({
31443
30876
  center: [
31444
30877
  ph.x + (ph.hole_offset_x || 0),
31445
30878
  ph.y + (ph.hole_offset_y || 0),
@@ -31451,7 +30884,7 @@ var BoardGeomBuilder = class {
31451
30884
  // Ensure it cuts through
31452
30885
  });
31453
30886
  } else {
31454
- cyGeom = (0, import_primitives11.cylinder)({
30887
+ cyGeom = (0, import_primitives7.cylinder)({
31455
30888
  center: [ph.x, ph.y, 0],
31456
30889
  radius: ph.hole_diameter / 2 + M,
31457
30890
  // Add margin for subtraction
@@ -31460,10 +30893,10 @@ var BoardGeomBuilder = class {
31460
30893
  });
31461
30894
  }
31462
30895
  if (!opts.dontCutBoard) {
31463
- this.boardGeom = (0, import_booleans7.subtract)(this.boardGeom, cyGeom);
30896
+ this.boardGeom = (0, import_booleans5.subtract)(this.boardGeom, cyGeom);
31464
30897
  }
31465
30898
  this.padGeoms = this.padGeoms.map(
31466
- (pg) => (0, import_colors7.colorize)(colors.copper, (0, import_booleans7.subtract)(pg, cyGeom))
30899
+ (pg) => (0, import_colors3.colorize)(colors.copper, (0, import_booleans5.subtract)(pg, cyGeom))
31467
30900
  );
31468
30901
  const platedHoleGeom = platedHole(ph, this.ctx, {
31469
30902
  clipGeom: this.boardClipGeom
@@ -31476,17 +30909,17 @@ var BoardGeomBuilder = class {
31476
30909
  const holeRadius = holeHeight / 2;
31477
30910
  const rectLength = Math.abs(holeWidth - holeHeight);
31478
30911
  let pillHole;
31479
- pillHole = (0, import_booleans7.union)(
31480
- (0, import_primitives11.cuboid)({
30912
+ pillHole = (0, import_booleans5.union)(
30913
+ (0, import_primitives7.cuboid)({
31481
30914
  center: [ph.x, ph.y, 0],
31482
30915
  size: shouldRotate ? [holeHeight, rectLength, this.ctx.pcbThickness * 1.5] : [rectLength, holeHeight, this.ctx.pcbThickness * 1.5]
31483
30916
  }),
31484
- (0, import_primitives11.cylinder)({
30917
+ (0, import_primitives7.cylinder)({
31485
30918
  center: shouldRotate ? [ph.x, ph.y - rectLength / 2, 0] : [ph.x - rectLength / 2, ph.y, 0],
31486
30919
  radius: holeRadius,
31487
30920
  height: this.ctx.pcbThickness * 1.5
31488
30921
  }),
31489
- (0, import_primitives11.cylinder)({
30922
+ (0, import_primitives7.cylinder)({
31490
30923
  center: shouldRotate ? [ph.x, ph.y + rectLength / 2, 0] : [ph.x + rectLength / 2, ph.y, 0],
31491
30924
  radius: holeRadius,
31492
30925
  height: this.ctx.pcbThickness * 1.5
@@ -31494,16 +30927,16 @@ var BoardGeomBuilder = class {
31494
30927
  );
31495
30928
  if (ph.ccw_rotation) {
31496
30929
  const rotationRadians = ph.ccw_rotation * Math.PI / 180;
31497
- pillHole = (0, import_transforms10.translate)(
30930
+ pillHole = (0, import_transforms6.translate)(
31498
30931
  [ph.x, ph.y, 0],
31499
- (0, import_transforms10.rotateZ)(rotationRadians, (0, import_transforms10.translate)([-ph.x, -ph.y, 0], pillHole))
30932
+ (0, import_transforms6.rotateZ)(rotationRadians, (0, import_transforms6.translate)([-ph.x, -ph.y, 0], pillHole))
31500
30933
  );
31501
30934
  }
31502
30935
  if (!opts.dontCutBoard) {
31503
- this.boardGeom = (0, import_booleans7.subtract)(this.boardGeom, pillHole);
30936
+ this.boardGeom = (0, import_booleans5.subtract)(this.boardGeom, pillHole);
31504
30937
  }
31505
30938
  this.padGeoms = this.padGeoms.map(
31506
- (pg) => (0, import_colors7.colorize)(colors.copper, (0, import_booleans7.subtract)(pg, pillHole))
30939
+ (pg) => (0, import_colors3.colorize)(colors.copper, (0, import_booleans5.subtract)(pg, pillHole))
31507
30940
  );
31508
30941
  const platedHoleGeom = platedHole(ph, this.ctx, {
31509
30942
  clipGeom: this.boardClipGeom
@@ -31516,8 +30949,8 @@ var BoardGeomBuilder = class {
31516
30949
  const holeRadius = holeHeight / 2;
31517
30950
  const rectLength = Math.abs(holeWidth - holeHeight);
31518
30951
  let pillHole;
31519
- pillHole = (0, import_booleans7.union)(
31520
- (0, import_primitives11.cuboid)({
30952
+ pillHole = (0, import_booleans5.union)(
30953
+ (0, import_primitives7.cuboid)({
31521
30954
  center: [
31522
30955
  ph.x + (ph.hole_offset_x || 0),
31523
30956
  ph.y + (ph.hole_offset_y || 0),
@@ -31525,7 +30958,7 @@ var BoardGeomBuilder = class {
31525
30958
  ],
31526
30959
  size: shouldRotate ? [holeHeight, rectLength, this.ctx.pcbThickness * 1.5] : [rectLength, holeHeight, this.ctx.pcbThickness * 1.5]
31527
30960
  }),
31528
- (0, import_primitives11.cylinder)({
30961
+ (0, import_primitives7.cylinder)({
31529
30962
  center: shouldRotate ? [
31530
30963
  ph.x + (ph.hole_offset_x || 0),
31531
30964
  ph.y + (ph.hole_offset_y || 0) - rectLength / 2,
@@ -31538,7 +30971,7 @@ var BoardGeomBuilder = class {
31538
30971
  radius: holeRadius,
31539
30972
  height: this.ctx.pcbThickness * 1.5
31540
30973
  }),
31541
- (0, import_primitives11.cylinder)({
30974
+ (0, import_primitives7.cylinder)({
31542
30975
  center: shouldRotate ? [
31543
30976
  ph.x + (ph.hole_offset_x || 0),
31544
30977
  ph.y + (ph.hole_offset_y || 0) + rectLength / 2,
@@ -31553,10 +30986,10 @@ var BoardGeomBuilder = class {
31553
30986
  })
31554
30987
  );
31555
30988
  if (!opts.dontCutBoard) {
31556
- this.boardGeom = (0, import_booleans7.subtract)(this.boardGeom, pillHole);
30989
+ this.boardGeom = (0, import_booleans5.subtract)(this.boardGeom, pillHole);
31557
30990
  }
31558
30991
  this.padGeoms = this.padGeoms.map(
31559
- (pg) => (0, import_colors7.colorize)(colors.copper, (0, import_booleans7.subtract)(pg, pillHole))
30992
+ (pg) => (0, import_colors3.colorize)(colors.copper, (0, import_booleans5.subtract)(pg, pillHole))
31560
30993
  );
31561
30994
  const platedHoleGeom = platedHole(ph, this.ctx, {
31562
30995
  clipGeom: this.boardClipGeom
@@ -31576,13 +31009,13 @@ var BoardGeomBuilder = class {
31576
31009
  });
31577
31010
  if (!boardHole || !copperHole) return;
31578
31011
  if (!opts.dontCutBoard) {
31579
- this.boardGeom = (0, import_booleans7.subtract)(this.boardGeom, boardHole);
31012
+ this.boardGeom = (0, import_booleans5.subtract)(this.boardGeom, boardHole);
31580
31013
  }
31581
31014
  this.padGeoms = this.padGeoms.map(
31582
- (pg) => (0, import_colors7.colorize)(colors.copper, (0, import_booleans7.subtract)(pg, boardHole))
31015
+ (pg) => (0, import_colors3.colorize)(colors.copper, (0, import_booleans5.subtract)(pg, boardHole))
31583
31016
  );
31584
31017
  this.platedHoleGeoms = this.platedHoleGeoms.map(
31585
- (phg) => (0, import_colors7.colorize)(colors.copper, (0, import_booleans7.subtract)(phg, copperHole))
31018
+ (phg) => (0, import_colors3.colorize)(colors.copper, (0, import_booleans5.subtract)(phg, copperHole))
31586
31019
  );
31587
31020
  const platedHoleGeom = platedHole(ph, this.ctx, {
31588
31021
  clipGeom: this.boardClipGeom
@@ -31595,22 +31028,22 @@ var BoardGeomBuilder = class {
31595
31028
  const holeDepth = this.ctx.pcbThickness * 1.5;
31596
31029
  const copperInset = 0.02;
31597
31030
  if (hole.hole_shape === "round" || hole.hole_shape === "circle") {
31598
- const cyGeom = (0, import_primitives11.cylinder)({
31031
+ const cyGeom = (0, import_primitives7.cylinder)({
31599
31032
  center: [hole.x, hole.y, 0],
31600
31033
  radius: hole.hole_diameter / 2 + M,
31601
31034
  height: holeDepth
31602
31035
  });
31603
- this.boardGeom = (0, import_booleans7.subtract)(this.boardGeom, cyGeom);
31036
+ this.boardGeom = (0, import_booleans5.subtract)(this.boardGeom, cyGeom);
31604
31037
  this.padGeoms = this.padGeoms.map(
31605
- (pg) => (0, import_colors7.colorize)(colors.copper, (0, import_booleans7.subtract)(pg, cyGeom))
31038
+ (pg) => (0, import_colors3.colorize)(colors.copper, (0, import_booleans5.subtract)(pg, cyGeom))
31606
31039
  );
31607
- const copperCut = (0, import_primitives11.cylinder)({
31040
+ const copperCut = (0, import_primitives7.cylinder)({
31608
31041
  center: [hole.x, hole.y, 0],
31609
31042
  radius: hole.hole_diameter / 2 + M / 2,
31610
31043
  height: holeDepth
31611
31044
  });
31612
31045
  this.platedHoleGeoms = this.platedHoleGeoms.map(
31613
- (phg) => (0, import_colors7.colorize)(colors.copper, (0, import_booleans7.subtract)(phg, copperCut))
31046
+ (phg) => (0, import_colors3.colorize)(colors.copper, (0, import_booleans5.subtract)(phg, copperCut))
31614
31047
  );
31615
31048
  } else if (hole.hole_shape === "pill" || hole.hole_shape === "rotated_pill") {
31616
31049
  const holeWidth = hole.hole_width;
@@ -31620,34 +31053,34 @@ var BoardGeomBuilder = class {
31620
31053
  const isRotated = hole.hole_shape === "rotated_pill";
31621
31054
  let pillHole;
31622
31055
  if (holeWidth > holeHeight) {
31623
- pillHole = (0, import_booleans7.union)(
31624
- (0, import_primitives11.cuboid)({
31056
+ pillHole = (0, import_booleans5.union)(
31057
+ (0, import_primitives7.cuboid)({
31625
31058
  center: [hole.x, hole.y, 0],
31626
31059
  size: [rectLength, holeHeight, holeDepth]
31627
31060
  }),
31628
- (0, import_primitives11.cylinder)({
31061
+ (0, import_primitives7.cylinder)({
31629
31062
  center: [hole.x - rectLength / 2, hole.y, 0],
31630
31063
  radius: holeRadius,
31631
31064
  height: holeDepth
31632
31065
  }),
31633
- (0, import_primitives11.cylinder)({
31066
+ (0, import_primitives7.cylinder)({
31634
31067
  center: [hole.x + rectLength / 2, hole.y, 0],
31635
31068
  radius: holeRadius,
31636
31069
  height: holeDepth
31637
31070
  })
31638
31071
  );
31639
31072
  } else {
31640
- pillHole = (0, import_booleans7.union)(
31641
- (0, import_primitives11.cuboid)({
31073
+ pillHole = (0, import_booleans5.union)(
31074
+ (0, import_primitives7.cuboid)({
31642
31075
  center: [hole.x, hole.y, 0],
31643
31076
  size: [holeWidth, rectLength, holeDepth]
31644
31077
  }),
31645
- (0, import_primitives11.cylinder)({
31078
+ (0, import_primitives7.cylinder)({
31646
31079
  center: [hole.x, hole.y - rectLength / 2, 0],
31647
31080
  radius: holeRadius,
31648
31081
  height: holeDepth
31649
31082
  }),
31650
- (0, import_primitives11.cylinder)({
31083
+ (0, import_primitives7.cylinder)({
31651
31084
  center: [hole.x, hole.y + rectLength / 2, 0],
31652
31085
  radius: holeRadius,
31653
31086
  height: holeDepth
@@ -31656,15 +31089,15 @@ var BoardGeomBuilder = class {
31656
31089
  }
31657
31090
  if (isRotated) {
31658
31091
  const rotationRadians = hole.ccw_rotation * Math.PI / 180;
31659
- pillHole = (0, import_transforms10.rotateZ)(rotationRadians, pillHole);
31092
+ pillHole = (0, import_transforms6.rotateZ)(rotationRadians, pillHole);
31660
31093
  }
31661
- this.boardGeom = (0, import_booleans7.subtract)(this.boardGeom, pillHole);
31094
+ this.boardGeom = (0, import_booleans5.subtract)(this.boardGeom, pillHole);
31662
31095
  this.padGeoms = this.padGeoms.map(
31663
- (pg) => (0, import_colors7.colorize)(colors.copper, (0, import_booleans7.subtract)(pg, pillHole))
31096
+ (pg) => (0, import_colors3.colorize)(colors.copper, (0, import_booleans5.subtract)(pg, pillHole))
31664
31097
  );
31665
- const copperPill = (0, import_expansions4.expand)({ delta: -copperInset }, pillHole);
31098
+ const copperPill = (0, import_expansions2.expand)({ delta: -copperInset }, pillHole);
31666
31099
  this.platedHoleGeoms = this.platedHoleGeoms.map(
31667
- (phg) => (0, import_colors7.colorize)(colors.copper, (0, import_booleans7.subtract)(phg, copperPill))
31100
+ (phg) => (0, import_colors3.colorize)(colors.copper, (0, import_booleans5.subtract)(phg, copperPill))
31668
31101
  );
31669
31102
  }
31670
31103
  }
@@ -31679,12 +31112,12 @@ var BoardGeomBuilder = class {
31679
31112
  M,
31680
31113
  rectBorderRadius
31681
31114
  );
31682
- const positionedPadGeom = (0, import_transforms10.translate)([pad2.x, pad2.y, zPos], basePadGeom);
31115
+ const positionedPadGeom = (0, import_transforms6.translate)([pad2.x, pad2.y, zPos], basePadGeom);
31683
31116
  let finalPadGeom = positionedPadGeom;
31684
31117
  if (this.boardClipGeom) {
31685
- finalPadGeom = (0, import_booleans7.intersect)(this.boardClipGeom, finalPadGeom);
31118
+ finalPadGeom = (0, import_booleans5.intersect)(this.boardClipGeom, finalPadGeom);
31686
31119
  }
31687
- finalPadGeom = (0, import_colors7.colorize)(colors.copper, finalPadGeom);
31120
+ finalPadGeom = (0, import_colors3.colorize)(colors.copper, finalPadGeom);
31688
31121
  this.padGeoms.push(finalPadGeom);
31689
31122
  } else if (pad2.shape === "rotated_rect") {
31690
31123
  let basePadGeom = createCenteredRectPadGeom(
@@ -31694,24 +31127,24 @@ var BoardGeomBuilder = class {
31694
31127
  rectBorderRadius
31695
31128
  );
31696
31129
  const rotationRadians = pad2.ccw_rotation * Math.PI / 180;
31697
- basePadGeom = (0, import_transforms10.rotateZ)(rotationRadians, basePadGeom);
31698
- const positionedPadGeom = (0, import_transforms10.translate)([pad2.x, pad2.y, zPos], basePadGeom);
31130
+ basePadGeom = (0, import_transforms6.rotateZ)(rotationRadians, basePadGeom);
31131
+ const positionedPadGeom = (0, import_transforms6.translate)([pad2.x, pad2.y, zPos], basePadGeom);
31699
31132
  let finalPadGeom = positionedPadGeom;
31700
31133
  if (this.boardClipGeom) {
31701
- finalPadGeom = (0, import_booleans7.intersect)(this.boardClipGeom, finalPadGeom);
31134
+ finalPadGeom = (0, import_booleans5.intersect)(this.boardClipGeom, finalPadGeom);
31702
31135
  }
31703
- finalPadGeom = (0, import_colors7.colorize)(colors.copper, finalPadGeom);
31136
+ finalPadGeom = (0, import_colors3.colorize)(colors.copper, finalPadGeom);
31704
31137
  this.padGeoms.push(finalPadGeom);
31705
31138
  } else if (pad2.shape === "circle") {
31706
- let padGeom = (0, import_primitives11.cylinder)({
31139
+ let padGeom = (0, import_primitives7.cylinder)({
31707
31140
  center: [pad2.x, pad2.y, zPos],
31708
31141
  radius: pad2.radius,
31709
31142
  height: M
31710
31143
  });
31711
31144
  if (this.boardClipGeom) {
31712
- padGeom = (0, import_booleans7.intersect)(this.boardClipGeom, padGeom);
31145
+ padGeom = (0, import_booleans5.intersect)(this.boardClipGeom, padGeom);
31713
31146
  }
31714
- padGeom = (0, import_colors7.colorize)(colors.copper, padGeom);
31147
+ padGeom = (0, import_colors3.colorize)(colors.copper, padGeom);
31715
31148
  this.padGeoms.push(padGeom);
31716
31149
  }
31717
31150
  }
@@ -31726,14 +31159,14 @@ var BoardGeomBuilder = class {
31726
31159
  const layerSign = currentLayer === "bottom" ? -1 : 1;
31727
31160
  const traceOffset = BOARD_SURFACE_OFFSET.traces - 2e-3;
31728
31161
  const zCenter = layerSign * this.ctx.pcbThickness / 2 + layerSign * traceOffset;
31729
- const linePath = (0, import_primitives11.line)(currentSegmentPoints);
31730
- const expandedPath = (0, import_expansions4.expand)(
31162
+ const linePath = (0, import_primitives7.line)(currentSegmentPoints);
31163
+ const expandedPath = (0, import_expansions2.expand)(
31731
31164
  { delta: currentWidth / 2, corners: "round" },
31732
31165
  linePath
31733
31166
  );
31734
- let traceGeom = (0, import_transforms10.translate)(
31167
+ let traceGeom = (0, import_transforms6.translate)(
31735
31168
  [0, 0, zCenter - M / 2],
31736
- (0, import_extrusions8.extrudeLinear)({ height: M }, expandedPath)
31169
+ (0, import_extrusions4.extrudeLinear)({ height: M }, expandedPath)
31737
31170
  );
31738
31171
  const startPointCoords = currentSegmentPoints[0];
31739
31172
  const endPointCoords = currentSegmentPoints[currentSegmentPoints.length - 1];
@@ -31742,27 +31175,27 @@ var BoardGeomBuilder = class {
31742
31175
  startPointCoords[1]
31743
31176
  );
31744
31177
  if (startHole) {
31745
- const cuttingCylinder = (0, import_primitives11.cylinder)({
31178
+ const cuttingCylinder = (0, import_primitives7.cylinder)({
31746
31179
  center: [startPointCoords[0], startPointCoords[1], zCenter],
31747
31180
  radius: startHole.diameter / 2 + M,
31748
31181
  height: M
31749
31182
  });
31750
- traceGeom = (0, import_booleans7.subtract)(traceGeom, cuttingCylinder);
31183
+ traceGeom = (0, import_booleans5.subtract)(traceGeom, cuttingCylinder);
31751
31184
  }
31752
31185
  const endHole = this.getHoleToCut(endPointCoords[0], endPointCoords[1]);
31753
31186
  if (endHole) {
31754
- const cuttingCylinder = (0, import_primitives11.cylinder)({
31187
+ const cuttingCylinder = (0, import_primitives7.cylinder)({
31755
31188
  center: [endPointCoords[0], endPointCoords[1], zCenter],
31756
31189
  radius: endHole.diameter / 2 + M,
31757
31190
  height: M
31758
31191
  });
31759
- traceGeom = (0, import_booleans7.subtract)(traceGeom, cuttingCylinder);
31192
+ traceGeom = (0, import_booleans5.subtract)(traceGeom, cuttingCylinder);
31760
31193
  }
31761
31194
  const tracesMaterialColor = tracesMaterialColors[this.board.material] ?? colors.fr4TracesWithoutMaskTan;
31762
31195
  if (this.boardClipGeom) {
31763
- traceGeom = (0, import_booleans7.intersect)(this.boardClipGeom, traceGeom);
31196
+ traceGeom = (0, import_booleans5.intersect)(this.boardClipGeom, traceGeom);
31764
31197
  }
31765
- traceGeom = (0, import_colors7.colorize)(tracesMaterialColor, traceGeom);
31198
+ traceGeom = (0, import_colors3.colorize)(tracesMaterialColor, traceGeom);
31766
31199
  this.traceGeoms.push(traceGeom);
31767
31200
  }
31768
31201
  currentSegmentPoints = [];
@@ -31814,8 +31247,8 @@ var BoardGeomBuilder = class {
31814
31247
  });
31815
31248
  let finalViaGeom = viaCopperGeom;
31816
31249
  if (this.boardClipGeom) {
31817
- finalViaGeom = (0, import_booleans7.intersect)(this.boardClipGeom, viaCopperGeom);
31818
- finalViaGeom = (0, import_colors7.colorize)(colors.copper, finalViaGeom);
31250
+ finalViaGeom = (0, import_booleans5.intersect)(this.boardClipGeom, viaCopperGeom);
31251
+ finalViaGeom = (0, import_colors3.colorize)(colors.copper, finalViaGeom);
31819
31252
  }
31820
31253
  this.viaGeoms.push(finalViaGeom);
31821
31254
  }
@@ -31826,87 +31259,23 @@ var BoardGeomBuilder = class {
31826
31259
  holeDiameter: via.hole_diameter,
31827
31260
  thickness: this.ctx.pcbThickness
31828
31261
  });
31829
- this.boardGeom = (0, import_booleans7.subtract)(this.boardGeom, viaDrill);
31262
+ this.boardGeom = (0, import_booleans5.subtract)(this.boardGeom, viaDrill);
31830
31263
  this.padGeoms = this.padGeoms.map(
31831
- (pg) => (0, import_colors7.colorize)(colors.copper, (0, import_booleans7.subtract)(pg, viaDrill))
31264
+ (pg) => (0, import_colors3.colorize)(colors.copper, (0, import_booleans5.subtract)(pg, viaDrill))
31832
31265
  );
31833
31266
  }
31834
31267
  }
31835
- processSilkscreenText(st) {
31836
- const { textOutlines, xOffset, yOffset } = createSilkscreenTextGeoms(st);
31837
- for (const outline of textOutlines) {
31838
- const alignedOutline = outline.map((point2) => [
31839
- point2[0] + xOffset + st.anchor_position.x,
31840
- point2[1] + yOffset + st.anchor_position.y
31841
- ]);
31842
- const textPath = (0, import_primitives11.line)(alignedOutline);
31843
- const fontSize = st.font_size || 0.25;
31844
- const expansionDelta = Math.min(
31845
- Math.max(0.01, fontSize * 0.1),
31846
- fontSize * 0.05
31847
- );
31848
- const expandedPath = (0, import_expansions4.expand)(
31849
- { delta: expansionDelta, corners: "round" },
31850
- textPath
31851
- );
31852
- let textGeom;
31853
- if (st.layer === "bottom") {
31854
- textGeom = (0, import_transforms10.translate)(
31855
- [0, 0, -this.ctx.pcbThickness / 2 - M],
31856
- // Position above board
31857
- (0, import_extrusions8.extrudeLinear)({ height: 0.012 }, expandedPath)
31858
- );
31859
- } else {
31860
- textGeom = (0, import_transforms10.translate)(
31861
- [0, 0, this.ctx.pcbThickness / 2 + M],
31862
- // Position above board
31863
- (0, import_extrusions8.extrudeLinear)({ height: 0.012 }, expandedPath)
31864
- );
31865
- }
31866
- textGeom = (0, import_colors7.colorize)([1, 1, 1], textGeom);
31867
- this.silkscreenTextGeoms.push(textGeom);
31868
- }
31869
- }
31870
- processSilkscreenPath(sp) {
31871
- const pathGeom = createSilkscreenPathGeom(sp, this.ctx);
31872
- if (pathGeom) {
31873
- this.silkscreenPathGeoms.push(pathGeom);
31874
- }
31875
- }
31876
- processSilkscreenLine(sl) {
31877
- const lineGeom = createSilkscreenLineGeom(sl, this.ctx);
31878
- if (lineGeom) {
31879
- this.silkscreenLineGeoms.push(lineGeom);
31880
- }
31881
- }
31882
- processSilkscreenCircle(sc) {
31883
- const circleGeom = createSilkscreenCircleGeom(sc, this.ctx);
31884
- if (circleGeom) {
31885
- this.silkscreenCircleGeoms.push(circleGeom);
31886
- }
31887
- }
31888
- processSilkscreenRect(sr) {
31889
- const rectGeom = createSilkscreenRectGeom(sr, this.ctx);
31890
- if (rectGeom) {
31891
- this.silkscreenRectGeoms.push(rectGeom);
31892
- }
31893
- }
31894
31268
  finalize() {
31895
31269
  if (!this.boardGeom) return;
31896
31270
  const boardMaterialColor = boardMaterialColors[this.board.material] ?? colors.fr4Tan;
31897
- this.boardGeom = (0, import_colors7.colorize)(boardMaterialColor, this.boardGeom);
31271
+ this.boardGeom = (0, import_colors3.colorize)(boardMaterialColor, this.boardGeom);
31898
31272
  this.finalGeoms = [
31899
31273
  this.boardGeom,
31900
31274
  ...this.platedHoleGeoms,
31901
31275
  ...this.padGeoms,
31902
31276
  ...this.traceGeoms,
31903
31277
  ...this.viaGeoms,
31904
- ...this.copperPourGeoms,
31905
- ...this.silkscreenTextGeoms,
31906
- ...this.silkscreenLineGeoms,
31907
- ...this.silkscreenCircleGeoms,
31908
- ...this.silkscreenRectGeoms,
31909
- ...this.silkscreenPathGeoms
31278
+ ...this.copperPourGeoms
31910
31279
  ];
31911
31280
  if (this.onCompleteCallback) {
31912
31281
  this.onCompleteCallback(this.finalGeoms);
@@ -32258,8 +31627,8 @@ var ThreeErrorBoundary = class extends React11.Component {
32258
31627
 
32259
31628
  // src/three-components/JscadBoardTextures.tsx
32260
31629
  import { useEffect as useEffect22, useMemo as useMemo19 } from "react";
32261
- import * as THREE21 from "three";
32262
- import { su as su8 } from "@tscircuit/circuit-json-util";
31630
+ import * as THREE23 from "three";
31631
+ import { su as su9 } from "@tscircuit/circuit-json-util";
32263
31632
 
32264
31633
  // src/utils/soldermask-texture.ts
32265
31634
  import * as THREE18 from "three";
@@ -32760,9 +32129,268 @@ function createSoldermaskTextureForLayer({
32760
32129
  }
32761
32130
 
32762
32131
  // src/utils/silkscreen-texture.ts
32763
- var import_text2 = __toESM(require_text(), 1);
32132
+ var import_text = __toESM(require_text(), 1);
32764
32133
  import * as THREE19 from "three";
32134
+
32135
+ // node_modules/transformation-matrix/src/applyToPoint.js
32136
+ function applyToPoint(matrix, point2) {
32137
+ return Array.isArray(point2) ? [
32138
+ matrix.a * point2[0] + matrix.c * point2[1] + matrix.e,
32139
+ matrix.b * point2[0] + matrix.d * point2[1] + matrix.f
32140
+ ] : {
32141
+ x: matrix.a * point2.x + matrix.c * point2.y + matrix.e,
32142
+ y: matrix.b * point2.x + matrix.d * point2.y + matrix.f
32143
+ };
32144
+ }
32145
+
32146
+ // node_modules/transformation-matrix/src/utils.js
32147
+ function isUndefined(val) {
32148
+ return typeof val === "undefined";
32149
+ }
32150
+
32151
+ // node_modules/transformation-matrix/src/translate.js
32152
+ function translate6(tx, ty = 0) {
32153
+ return {
32154
+ a: 1,
32155
+ c: 0,
32156
+ e: tx,
32157
+ b: 0,
32158
+ d: 1,
32159
+ f: ty
32160
+ };
32161
+ }
32162
+
32163
+ // node_modules/transformation-matrix/src/transform.js
32164
+ function transform(...matrices) {
32165
+ matrices = Array.isArray(matrices[0]) ? matrices[0] : matrices;
32166
+ const multiply = (m1, m2) => {
32167
+ return {
32168
+ a: m1.a * m2.a + m1.c * m2.b,
32169
+ c: m1.a * m2.c + m1.c * m2.d,
32170
+ e: m1.a * m2.e + m1.c * m2.f + m1.e,
32171
+ b: m1.b * m2.a + m1.d * m2.b,
32172
+ d: m1.b * m2.c + m1.d * m2.d,
32173
+ f: m1.b * m2.e + m1.d * m2.f + m1.f
32174
+ };
32175
+ };
32176
+ switch (matrices.length) {
32177
+ case 0:
32178
+ throw new Error("no matrices provided");
32179
+ case 1:
32180
+ return matrices[0];
32181
+ case 2:
32182
+ return multiply(matrices[0], matrices[1]);
32183
+ default: {
32184
+ const [m1, m2, ...rest] = matrices;
32185
+ const m = multiply(m1, m2);
32186
+ return transform(m, ...rest);
32187
+ }
32188
+ }
32189
+ }
32190
+ function compose(...matrices) {
32191
+ return transform(...matrices);
32192
+ }
32193
+
32194
+ // node_modules/transformation-matrix/src/rotate.js
32195
+ var { cos, sin, PI } = Math;
32196
+ function rotate2(angle, cx, cy) {
32197
+ const cosAngle = cos(angle);
32198
+ const sinAngle = sin(angle);
32199
+ const rotationMatrix = {
32200
+ a: cosAngle,
32201
+ c: -sinAngle,
32202
+ e: 0,
32203
+ b: sinAngle,
32204
+ d: cosAngle,
32205
+ f: 0
32206
+ };
32207
+ if (isUndefined(cx) || isUndefined(cy)) {
32208
+ return rotationMatrix;
32209
+ }
32210
+ return transform([
32211
+ translate6(cx, cy),
32212
+ rotationMatrix,
32213
+ translate6(-cx, -cy)
32214
+ ]);
32215
+ }
32216
+
32217
+ // node_modules/transformation-matrix/src/skew.js
32218
+ var { tan } = Math;
32219
+
32220
+ // node_modules/transformation-matrix/src/fromTransformAttribute.autogenerated.js
32221
+ function peg$subclass(child, parent) {
32222
+ function C() {
32223
+ this.constructor = child;
32224
+ }
32225
+ C.prototype = parent.prototype;
32226
+ child.prototype = new C();
32227
+ }
32228
+ function peg$SyntaxError(message, expected, found, location) {
32229
+ var self = Error.call(this, message);
32230
+ if (Object.setPrototypeOf) {
32231
+ Object.setPrototypeOf(self, peg$SyntaxError.prototype);
32232
+ }
32233
+ self.expected = expected;
32234
+ self.found = found;
32235
+ self.location = location;
32236
+ self.name = "SyntaxError";
32237
+ return self;
32238
+ }
32239
+ peg$subclass(peg$SyntaxError, Error);
32240
+ function peg$padEnd(str, targetLength, padString) {
32241
+ padString = padString || " ";
32242
+ if (str.length > targetLength) {
32243
+ return str;
32244
+ }
32245
+ targetLength -= str.length;
32246
+ padString += padString.repeat(targetLength);
32247
+ return str + padString.slice(0, targetLength);
32248
+ }
32249
+ peg$SyntaxError.prototype.format = function(sources) {
32250
+ var str = "Error: " + this.message;
32251
+ if (this.location) {
32252
+ var src = null;
32253
+ var k;
32254
+ for (k = 0; k < sources.length; k++) {
32255
+ if (sources[k].source === this.location.source) {
32256
+ src = sources[k].text.split(/\r\n|\n|\r/g);
32257
+ break;
32258
+ }
32259
+ }
32260
+ var s = this.location.start;
32261
+ var offset_s = this.location.source && typeof this.location.source.offset === "function" ? this.location.source.offset(s) : s;
32262
+ var loc = this.location.source + ":" + offset_s.line + ":" + offset_s.column;
32263
+ if (src) {
32264
+ var e = this.location.end;
32265
+ var filler = peg$padEnd("", offset_s.line.toString().length, " ");
32266
+ var line2 = src[s.line - 1];
32267
+ var last = s.line === e.line ? e.column : line2.length + 1;
32268
+ var hatLen = last - s.column || 1;
32269
+ str += "\n --> " + loc + "\n" + filler + " |\n" + offset_s.line + " | " + line2 + "\n" + filler + " | " + peg$padEnd("", s.column - 1, " ") + peg$padEnd("", hatLen, "^");
32270
+ } else {
32271
+ str += "\n at " + loc;
32272
+ }
32273
+ }
32274
+ return str;
32275
+ };
32276
+ peg$SyntaxError.buildMessage = function(expected, found) {
32277
+ var DESCRIBE_EXPECTATION_FNS = {
32278
+ literal: function(expectation) {
32279
+ return '"' + literalEscape(expectation.text) + '"';
32280
+ },
32281
+ class: function(expectation) {
32282
+ var escapedParts = expectation.parts.map(function(part) {
32283
+ return Array.isArray(part) ? classEscape(part[0]) + "-" + classEscape(part[1]) : classEscape(part);
32284
+ });
32285
+ return "[" + (expectation.inverted ? "^" : "") + escapedParts.join("") + "]";
32286
+ },
32287
+ any: function() {
32288
+ return "any character";
32289
+ },
32290
+ end: function() {
32291
+ return "end of input";
32292
+ },
32293
+ other: function(expectation) {
32294
+ return expectation.description;
32295
+ }
32296
+ };
32297
+ function hex(ch) {
32298
+ return ch.charCodeAt(0).toString(16).toUpperCase();
32299
+ }
32300
+ function literalEscape(s) {
32301
+ return s.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\0/g, "\\0").replace(/\t/g, "\\t").replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/[\x00-\x0F]/g, function(ch) {
32302
+ return "\\x0" + hex(ch);
32303
+ }).replace(/[\x10-\x1F\x7F-\x9F]/g, function(ch) {
32304
+ return "\\x" + hex(ch);
32305
+ });
32306
+ }
32307
+ function classEscape(s) {
32308
+ return s.replace(/\\/g, "\\\\").replace(/\]/g, "\\]").replace(/\^/g, "\\^").replace(/-/g, "\\-").replace(/\0/g, "\\0").replace(/\t/g, "\\t").replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/[\x00-\x0F]/g, function(ch) {
32309
+ return "\\x0" + hex(ch);
32310
+ }).replace(/[\x10-\x1F\x7F-\x9F]/g, function(ch) {
32311
+ return "\\x" + hex(ch);
32312
+ });
32313
+ }
32314
+ function describeExpectation(expectation) {
32315
+ return DESCRIBE_EXPECTATION_FNS[expectation.type](expectation);
32316
+ }
32317
+ function describeExpected(expected2) {
32318
+ var descriptions = expected2.map(describeExpectation);
32319
+ var i, j;
32320
+ descriptions.sort();
32321
+ if (descriptions.length > 0) {
32322
+ for (i = 1, j = 1; i < descriptions.length; i++) {
32323
+ if (descriptions[i - 1] !== descriptions[i]) {
32324
+ descriptions[j] = descriptions[i];
32325
+ j++;
32326
+ }
32327
+ }
32328
+ descriptions.length = j;
32329
+ }
32330
+ switch (descriptions.length) {
32331
+ case 1:
32332
+ return descriptions[0];
32333
+ case 2:
32334
+ return descriptions[0] + " or " + descriptions[1];
32335
+ default:
32336
+ return descriptions.slice(0, -1).join(", ") + ", or " + descriptions[descriptions.length - 1];
32337
+ }
32338
+ }
32339
+ function describeFound(found2) {
32340
+ return found2 ? '"' + literalEscape(found2) + '"' : "end of input";
32341
+ }
32342
+ return "Expected " + describeExpected(expected) + " but " + describeFound(found) + " found.";
32343
+ };
32344
+
32345
+ // src/utils/silkscreen-texture.ts
32765
32346
  import { su as su6 } from "@tscircuit/circuit-json-util";
32347
+
32348
+ // src/utils/units.ts
32349
+ var MM_PER_INCH = 25.4;
32350
+ var MM_PER_MIL = MM_PER_INCH / 1e3;
32351
+ var dimensionRegex = /^\s*(-?\d*(?:\.\d+)?)(?:\s*(mm|mil|inch|in|"))?\s*$/i;
32352
+ function normalizeUnit(unit) {
32353
+ if (!unit) return void 0;
32354
+ const normalized = unit.trim().toLowerCase();
32355
+ if (normalized === '"') return "in";
32356
+ if (normalized === "inch") return "in";
32357
+ return normalized;
32358
+ }
32359
+ function parseDimensionToMm(value) {
32360
+ if (value === null || value === void 0) return void 0;
32361
+ if (typeof value === "number") {
32362
+ return Number.isFinite(value) ? value : void 0;
32363
+ }
32364
+ if (typeof value !== "string") return void 0;
32365
+ const trimmed = value.trim();
32366
+ if (trimmed.length === 0) return void 0;
32367
+ const match = trimmed.match(dimensionRegex);
32368
+ if (!match) {
32369
+ const numeric = Number.parseFloat(trimmed);
32370
+ return Number.isFinite(numeric) ? numeric : void 0;
32371
+ }
32372
+ const [, magnitudeRaw, unitRaw] = match;
32373
+ const magnitude = Number.parseFloat(magnitudeRaw || "0");
32374
+ if (!Number.isFinite(magnitude)) return void 0;
32375
+ const unit = normalizeUnit(unitRaw);
32376
+ switch (unit) {
32377
+ case "mil":
32378
+ return magnitude * MM_PER_MIL;
32379
+ case "in":
32380
+ return magnitude * MM_PER_INCH;
32381
+ case "mm":
32382
+ case void 0:
32383
+ return magnitude;
32384
+ default:
32385
+ return magnitude;
32386
+ }
32387
+ }
32388
+ function coerceDimensionToMm(value, fallback) {
32389
+ const parsed = parseDimensionToMm(value);
32390
+ return parsed === void 0 ? fallback : parsed;
32391
+ }
32392
+
32393
+ // src/utils/silkscreen-texture.ts
32766
32394
  function parseFabricationNoteColor(colorString) {
32767
32395
  let hex = colorString;
32768
32396
  if (hex.startsWith("#")) {
@@ -33040,7 +32668,7 @@ function createSilkscreenTextureForLayer({
33040
32668
  ctx.lineWidth = textStrokeWidth;
33041
32669
  ctx.lineCap = "butt";
33042
32670
  ctx.lineJoin = "miter";
33043
- const rawTextOutlines = (0, import_text2.vectorText)({
32671
+ const rawTextOutlines = (0, import_text.vectorText)({
33044
32672
  height: fontSize * 0.45,
33045
32673
  input: textS.text
33046
32674
  });
@@ -33090,18 +32718,18 @@ function createSilkscreenTextureForLayer({
33090
32718
  let rotationDeg = textS.ccw_rotation ?? 0;
33091
32719
  if (textS.layer === "bottom") {
33092
32720
  transformMatrices.push(
33093
- translate4(textCenterX, textCenterY),
32721
+ translate6(textCenterX, textCenterY),
33094
32722
  { a: -1, b: 0, c: 0, d: 1, e: 0, f: 0 },
33095
- translate4(-textCenterX, -textCenterY)
32723
+ translate6(-textCenterX, -textCenterY)
33096
32724
  );
33097
32725
  rotationDeg = -rotationDeg;
33098
32726
  }
33099
32727
  if (rotationDeg) {
33100
32728
  const rad = rotationDeg * Math.PI / 180;
33101
32729
  transformMatrices.push(
33102
- translate4(textCenterX, textCenterY),
32730
+ translate6(textCenterX, textCenterY),
33103
32731
  rotate2(rad),
33104
- translate4(-textCenterX, -textCenterY)
32732
+ translate6(-textCenterX, -textCenterY)
33105
32733
  );
33106
32734
  }
33107
32735
  const finalTransformMatrix = transformMatrices.length > 0 ? compose(...transformMatrices) : void 0;
@@ -33224,6 +32852,317 @@ function createTraceTextureForLayer({
33224
32852
  return texture;
33225
32853
  }
33226
32854
 
32855
+ // src/utils/copper-text-texture.ts
32856
+ var import_text2 = __toESM(require_text(), 1);
32857
+ import * as THREE21 from "three";
32858
+ function parseDimension2(value, defaultValue) {
32859
+ if (value === void 0) return defaultValue;
32860
+ if (typeof value === "number") return value;
32861
+ const num = parseFloat(value.replace(/mm$/, ""));
32862
+ return isNaN(num) ? defaultValue : num;
32863
+ }
32864
+ function shouldMirrorText(text) {
32865
+ if (text.layer === "bottom") {
32866
+ return text.is_mirrored !== false;
32867
+ }
32868
+ return text.is_mirrored === true;
32869
+ }
32870
+ function getTextMetrics(outlines) {
32871
+ const points = outlines.flat();
32872
+ if (points.length === 0) {
32873
+ return {
32874
+ minX: 0,
32875
+ maxX: 0,
32876
+ minY: 0,
32877
+ maxY: 0,
32878
+ width: 0,
32879
+ height: 0,
32880
+ centerX: 0,
32881
+ centerY: 0
32882
+ };
32883
+ }
32884
+ const minX = Math.min(...points.map((p) => p[0]));
32885
+ const maxX = Math.max(...points.map((p) => p[0]));
32886
+ const minY = Math.min(...points.map((p) => p[1]));
32887
+ const maxY = Math.max(...points.map((p) => p[1]));
32888
+ return {
32889
+ minX,
32890
+ maxX,
32891
+ minY,
32892
+ maxY,
32893
+ width: maxX - minX,
32894
+ height: maxY - minY,
32895
+ centerX: (minX + maxX) / 2,
32896
+ centerY: (minY + maxY) / 2
32897
+ };
32898
+ }
32899
+ function processTextOutlines(rawOutlines) {
32900
+ const processed = [];
32901
+ rawOutlines.forEach((outline) => {
32902
+ if (outline.length === 29) {
32903
+ processed.push(outline.slice(0, 15));
32904
+ processed.push(outline.slice(14, 29));
32905
+ } else if (outline.length === 17) {
32906
+ processed.push(outline.slice(0, 10));
32907
+ processed.push(outline.slice(9, 17));
32908
+ } else {
32909
+ processed.push(outline);
32910
+ }
32911
+ });
32912
+ return processed;
32913
+ }
32914
+ function getAlignmentOffset(metrics, alignment) {
32915
+ let xOff = -metrics.centerX;
32916
+ let yOff = -metrics.centerY;
32917
+ if (alignment.includes("left")) {
32918
+ xOff = -metrics.minX;
32919
+ } else if (alignment.includes("right")) {
32920
+ xOff = -metrics.maxX;
32921
+ }
32922
+ if (alignment.includes("top")) {
32923
+ yOff = -metrics.maxY;
32924
+ } else if (alignment.includes("bottom")) {
32925
+ yOff = -metrics.minY;
32926
+ }
32927
+ return { x: xOff, y: yOff };
32928
+ }
32929
+ function buildTransformMatrix(text, metrics) {
32930
+ const transformMatrices = [];
32931
+ let rotationDeg = text.ccw_rotation ?? 0;
32932
+ const shouldMirror = shouldMirrorText(text);
32933
+ if (shouldMirror) {
32934
+ transformMatrices.push(
32935
+ translate6(metrics.centerX, metrics.centerY),
32936
+ { a: -1, b: 0, c: 0, d: 1, e: 0, f: 0 },
32937
+ // horizontal flip
32938
+ translate6(-metrics.centerX, -metrics.centerY)
32939
+ );
32940
+ rotationDeg = -rotationDeg;
32941
+ }
32942
+ if (rotationDeg) {
32943
+ const rad = rotationDeg * Math.PI / 180;
32944
+ transformMatrices.push(
32945
+ translate6(metrics.centerX, metrics.centerY),
32946
+ rotate2(rad),
32947
+ translate6(-metrics.centerX, -metrics.centerY)
32948
+ );
32949
+ }
32950
+ const matrix = transformMatrices.length > 0 ? compose(...transformMatrices) : void 0;
32951
+ return { matrix, rotationDeg };
32952
+ }
32953
+ function drawTextStrokes(ctx, outlines, transform2, offset4, anchorPos, canvasXFromPcb, canvasYFromPcb) {
32954
+ outlines.forEach((segment) => {
32955
+ ctx.beginPath();
32956
+ segment.forEach((p, index2) => {
32957
+ let transformedP = { x: p[0], y: p[1] };
32958
+ if (transform2) {
32959
+ transformedP = applyToPoint(transform2, transformedP);
32960
+ }
32961
+ const pcbX = transformedP.x + offset4.x + anchorPos.x;
32962
+ const pcbY = transformedP.y + offset4.y + anchorPos.y;
32963
+ const canvasX = canvasXFromPcb(pcbX);
32964
+ const canvasY = canvasYFromPcb(pcbY);
32965
+ if (index2 === 0) ctx.moveTo(canvasX, canvasY);
32966
+ else ctx.lineTo(canvasX, canvasY);
32967
+ });
32968
+ ctx.stroke();
32969
+ });
32970
+ }
32971
+ function drawRotatedRect(ctx, centerX, centerY, width10, height10, rotationRad) {
32972
+ ctx.save();
32973
+ ctx.translate(centerX, centerY);
32974
+ ctx.rotate(-rotationRad);
32975
+ ctx.fillRect(-width10 / 2, -height10 / 2, width10, height10);
32976
+ ctx.restore();
32977
+ }
32978
+ function drawKnockoutText(ctx, text, outlines, metrics, transform2, rotationDeg, canvasXFromPcb, canvasYFromPcb, traceTextureResolution, copperColor) {
32979
+ const fontSize = typeof text.font_size === "number" ? text.font_size : 0.2;
32980
+ const padding = {
32981
+ left: parseDimension2(text.knockout_padding?.left, fontSize * 0.5),
32982
+ right: parseDimension2(text.knockout_padding?.right, fontSize * 0.5),
32983
+ top: parseDimension2(text.knockout_padding?.top, fontSize * 0.3),
32984
+ bottom: parseDimension2(text.knockout_padding?.bottom, fontSize * 0.3)
32985
+ };
32986
+ const rectWidth = metrics.width + padding.left + padding.right;
32987
+ const rectHeight = metrics.height + padding.top + padding.bottom;
32988
+ const rectCenterCanvasX = canvasXFromPcb(text.anchor_position.x);
32989
+ const rectCenterCanvasY = canvasYFromPcb(text.anchor_position.y);
32990
+ const rectWidthPx = rectWidth * traceTextureResolution;
32991
+ const rectHeightPx = rectHeight * traceTextureResolution;
32992
+ ctx.fillStyle = copperColor;
32993
+ const rotationRad = rotationDeg * Math.PI / 180;
32994
+ drawRotatedRect(
32995
+ ctx,
32996
+ rectCenterCanvasX,
32997
+ rectCenterCanvasY,
32998
+ rectWidthPx,
32999
+ rectHeightPx,
33000
+ rotationRad
33001
+ );
33002
+ const textOffset = {
33003
+ x: -metrics.centerX,
33004
+ y: -metrics.centerY
33005
+ };
33006
+ ctx.globalCompositeOperation = "destination-out";
33007
+ drawTextStrokes(
33008
+ ctx,
33009
+ outlines,
33010
+ transform2,
33011
+ textOffset,
33012
+ text.anchor_position,
33013
+ canvasXFromPcb,
33014
+ canvasYFromPcb
33015
+ );
33016
+ ctx.globalCompositeOperation = "source-over";
33017
+ }
33018
+ function createCopperTextTextureForLayer({
33019
+ layer,
33020
+ circuitJson,
33021
+ boardData,
33022
+ copperColor = "rgb(230, 153, 51)",
33023
+ // Same as colors.copper [0.9, 0.6, 0.2]
33024
+ traceTextureResolution
33025
+ }) {
33026
+ const copperTexts = circuitJson.filter(
33027
+ (e) => e.type === "pcb_copper_text"
33028
+ );
33029
+ const textsOnLayer = copperTexts.filter((t) => t.layer === layer);
33030
+ if (textsOnLayer.length === 0) {
33031
+ return null;
33032
+ }
33033
+ const canvas = document.createElement("canvas");
33034
+ const canvasWidth = Math.floor(boardData.width * traceTextureResolution);
33035
+ const canvasHeight = Math.floor(boardData.height * traceTextureResolution);
33036
+ canvas.width = canvasWidth;
33037
+ canvas.height = canvasHeight;
33038
+ const ctx = canvas.getContext("2d");
33039
+ if (!ctx) return null;
33040
+ if (layer === "bottom") {
33041
+ ctx.translate(0, canvasHeight);
33042
+ ctx.scale(1, -1);
33043
+ }
33044
+ ctx.strokeStyle = copperColor;
33045
+ ctx.fillStyle = copperColor;
33046
+ const canvasXFromPcb = (pcbX) => (pcbX - boardData.center.x + boardData.width / 2) * traceTextureResolution;
33047
+ const canvasYFromPcb = (pcbY) => (-(pcbY - boardData.center.y) + boardData.height / 2) * traceTextureResolution;
33048
+ textsOnLayer.forEach((textS) => {
33049
+ const fontSize = typeof textS.font_size === "number" ? textS.font_size : 0.2;
33050
+ const textStrokeWidth = Math.max(0.02, fontSize * 0.08) * traceTextureResolution;
33051
+ ctx.lineWidth = textStrokeWidth;
33052
+ ctx.lineCap = "round";
33053
+ ctx.lineJoin = "round";
33054
+ const rawTextOutlines = (0, import_text2.vectorText)({
33055
+ height: fontSize * 0.45,
33056
+ input: textS.text
33057
+ });
33058
+ const processedOutlines = processTextOutlines(rawTextOutlines);
33059
+ const metrics = getTextMetrics(processedOutlines);
33060
+ const { matrix: transform2, rotationDeg } = buildTransformMatrix(
33061
+ textS,
33062
+ metrics
33063
+ );
33064
+ if (textS.is_knockout) {
33065
+ drawKnockoutText(
33066
+ ctx,
33067
+ textS,
33068
+ processedOutlines,
33069
+ metrics,
33070
+ transform2,
33071
+ rotationDeg,
33072
+ canvasXFromPcb,
33073
+ canvasYFromPcb,
33074
+ traceTextureResolution,
33075
+ copperColor
33076
+ );
33077
+ } else {
33078
+ const alignment = textS.anchor_alignment || "center";
33079
+ const offset4 = getAlignmentOffset(metrics, alignment);
33080
+ drawTextStrokes(
33081
+ ctx,
33082
+ processedOutlines,
33083
+ transform2,
33084
+ offset4,
33085
+ textS.anchor_position,
33086
+ canvasXFromPcb,
33087
+ canvasYFromPcb
33088
+ );
33089
+ }
33090
+ });
33091
+ const texture = new THREE21.CanvasTexture(canvas);
33092
+ texture.generateMipmaps = true;
33093
+ texture.minFilter = THREE21.LinearMipmapLinearFilter;
33094
+ texture.magFilter = THREE21.LinearFilter;
33095
+ texture.anisotropy = 16;
33096
+ texture.needsUpdate = true;
33097
+ return texture;
33098
+ }
33099
+
33100
+ // src/utils/panel-outline-texture.ts
33101
+ import * as THREE22 from "three";
33102
+ import { su as su8 } from "@tscircuit/circuit-json-util";
33103
+ function createPanelOutlineTextureForLayer({
33104
+ layer,
33105
+ circuitJson,
33106
+ panelData,
33107
+ outlineColor = "black",
33108
+ traceTextureResolution
33109
+ }) {
33110
+ const boardsInPanel = su8(circuitJson).pcb_board.list().filter((b) => b.pcb_panel_id === panelData.pcb_board_id);
33111
+ if (boardsInPanel.length === 0) {
33112
+ return null;
33113
+ }
33114
+ const canvas = document.createElement("canvas");
33115
+ const canvasWidth = Math.floor(panelData.width * traceTextureResolution);
33116
+ const canvasHeight = Math.floor(panelData.height * traceTextureResolution);
33117
+ canvas.width = canvasWidth;
33118
+ canvas.height = canvasHeight;
33119
+ const ctx = canvas.getContext("2d");
33120
+ if (!ctx) return null;
33121
+ if (layer === "bottom") {
33122
+ ctx.translate(0, canvasHeight);
33123
+ ctx.scale(1, -1);
33124
+ }
33125
+ ctx.strokeStyle = outlineColor;
33126
+ ctx.lineWidth = 0.05 * traceTextureResolution;
33127
+ const canvasXFromPcb = (pcbX) => (pcbX - panelData.center.x + panelData.width / 2) * traceTextureResolution;
33128
+ const canvasYFromPcb = (pcbY) => (-(pcbY - panelData.center.y) + panelData.height / 2) * traceTextureResolution;
33129
+ boardsInPanel.forEach((board) => {
33130
+ if (board.outline && board.outline.length >= 2) {
33131
+ ctx.beginPath();
33132
+ board.outline.forEach((point2, index2) => {
33133
+ const x = canvasXFromPcb(point2.x);
33134
+ const y = canvasYFromPcb(point2.y);
33135
+ if (index2 === 0) {
33136
+ ctx.moveTo(x, y);
33137
+ } else {
33138
+ ctx.lineTo(x, y);
33139
+ }
33140
+ });
33141
+ ctx.closePath();
33142
+ ctx.stroke();
33143
+ } else {
33144
+ const width10 = board.width;
33145
+ const height10 = board.height;
33146
+ const { x: centerX, y: centerY } = board.center;
33147
+ const x = canvasXFromPcb(centerX - width10 / 2);
33148
+ const y = canvasYFromPcb(centerY + height10 / 2);
33149
+ ctx.strokeRect(
33150
+ x,
33151
+ y,
33152
+ width10 * traceTextureResolution,
33153
+ height10 * traceTextureResolution
33154
+ );
33155
+ }
33156
+ });
33157
+ const texture = new THREE22.CanvasTexture(canvas);
33158
+ texture.generateMipmaps = true;
33159
+ texture.minFilter = THREE22.LinearMipmapLinearFilter;
33160
+ texture.magFilter = THREE22.LinearFilter;
33161
+ texture.anisotropy = 16;
33162
+ texture.needsUpdate = true;
33163
+ return texture;
33164
+ }
33165
+
33227
33166
  // src/three-components/JscadBoardTextures.tsx
33228
33167
  function JscadBoardTextures({
33229
33168
  circuitJson,
@@ -33232,8 +33171,30 @@ function JscadBoardTextures({
33232
33171
  const { rootObject } = useThree();
33233
33172
  const { visibility } = useLayerVisibility();
33234
33173
  const boardData = useMemo19(() => {
33235
- const boards = su8(circuitJson).pcb_board.list();
33236
- return boards.length > 0 ? boards[0] : null;
33174
+ const panels = circuitJson.filter(
33175
+ (e) => e.type === "pcb_panel"
33176
+ );
33177
+ const boards = su9(circuitJson).pcb_board.list();
33178
+ if (panels.length > 0) {
33179
+ const panel = panels[0];
33180
+ const firstBoardInPanel = boards.find(
33181
+ (b) => b.pcb_panel_id === panel.pcb_panel_id
33182
+ );
33183
+ return {
33184
+ type: "pcb_board",
33185
+ pcb_board_id: panel.pcb_panel_id,
33186
+ center: panel.center,
33187
+ width: panel.width,
33188
+ height: panel.height,
33189
+ thickness: firstBoardInPanel?.thickness ?? 1.6,
33190
+ material: firstBoardInPanel?.material ?? "fr4",
33191
+ num_layers: firstBoardInPanel?.num_layers ?? 2
33192
+ };
33193
+ }
33194
+ const boardsNotInPanel = boards.filter(
33195
+ (b) => !b.pcb_panel_id
33196
+ );
33197
+ return boardsNotInPanel.length > 0 ? boardsNotInPanel[0] : null;
33237
33198
  }, [circuitJson]);
33238
33199
  const textures = useMemo19(() => {
33239
33200
  if (!boardData || !boardData.width || !boardData.height) return null;
@@ -33284,28 +33245,54 @@ function JscadBoardTextures({
33284
33245
  boardData,
33285
33246
  traceColor: traceColorWithMask,
33286
33247
  traceTextureResolution: TRACE_TEXTURE_RESOLUTION
33248
+ }),
33249
+ topCopperText: createCopperTextTextureForLayer({
33250
+ layer: "top",
33251
+ circuitJson,
33252
+ boardData,
33253
+ copperColor: `rgb(${Math.round(colors.copper[0] * 255)}, ${Math.round(colors.copper[1] * 255)}, ${Math.round(colors.copper[2] * 255)})`,
33254
+ traceTextureResolution: TRACE_TEXTURE_RESOLUTION
33255
+ }),
33256
+ bottomCopperText: createCopperTextTextureForLayer({
33257
+ layer: "bottom",
33258
+ circuitJson,
33259
+ boardData,
33260
+ copperColor: `rgb(${Math.round(colors.copper[0] * 255)}, ${Math.round(colors.copper[1] * 255)}, ${Math.round(colors.copper[2] * 255)})`,
33261
+ traceTextureResolution: TRACE_TEXTURE_RESOLUTION
33262
+ }),
33263
+ topPanelOutlines: createPanelOutlineTextureForLayer({
33264
+ layer: "top",
33265
+ circuitJson,
33266
+ panelData: boardData,
33267
+ traceTextureResolution: TRACE_TEXTURE_RESOLUTION
33268
+ }),
33269
+ bottomPanelOutlines: createPanelOutlineTextureForLayer({
33270
+ layer: "bottom",
33271
+ circuitJson,
33272
+ panelData: boardData,
33273
+ traceTextureResolution: TRACE_TEXTURE_RESOLUTION
33287
33274
  })
33288
33275
  };
33289
33276
  }, [circuitJson, boardData]);
33290
33277
  useEffect22(() => {
33291
33278
  if (!rootObject || !boardData || !textures) return;
33292
33279
  const meshes = [];
33293
- const createTexturePlane = (texture, zOffset, isBottomLayer, name, usePolygonOffset = false) => {
33280
+ const createTexturePlane = (texture, zOffset, isBottomLayer, name, usePolygonOffset = false, depthWrite = false) => {
33294
33281
  if (!texture) return null;
33295
- const planeGeom = new THREE21.PlaneGeometry(
33282
+ const planeGeom = new THREE23.PlaneGeometry(
33296
33283
  boardData.width,
33297
33284
  boardData.height
33298
33285
  );
33299
- const material = new THREE21.MeshBasicMaterial({
33286
+ const material = new THREE23.MeshBasicMaterial({
33300
33287
  map: texture,
33301
33288
  transparent: true,
33302
- side: THREE21.DoubleSide,
33303
- depthWrite: false,
33289
+ side: THREE23.DoubleSide,
33290
+ depthWrite,
33304
33291
  polygonOffset: usePolygonOffset,
33305
33292
  polygonOffsetFactor: usePolygonOffset ? -1 : 0,
33306
33293
  polygonOffsetUnits: usePolygonOffset ? -1 : 0
33307
33294
  });
33308
- const mesh = new THREE21.Mesh(planeGeom, material);
33295
+ const mesh = new THREE23.Mesh(planeGeom, material);
33309
33296
  mesh.position.set(boardData.center.x, boardData.center.y, zOffset);
33310
33297
  if (isBottomLayer) {
33311
33298
  mesh.rotation.set(Math.PI, 0, 0);
@@ -33388,13 +33375,65 @@ function JscadBoardTextures({
33388
33375
  rootObject.add(bottomSilkscreenMesh);
33389
33376
  }
33390
33377
  }
33378
+ if (visibility.topCopper) {
33379
+ const topCopperTextMesh = createTexturePlane(
33380
+ textures.topCopperText,
33381
+ pcbThickness / 2 + BOARD_SURFACE_OFFSET.copper,
33382
+ false,
33383
+ "jscad-top-copper-text"
33384
+ );
33385
+ if (topCopperTextMesh) {
33386
+ meshes.push(topCopperTextMesh);
33387
+ rootObject.add(topCopperTextMesh);
33388
+ }
33389
+ }
33390
+ if (visibility.bottomCopper) {
33391
+ const bottomCopperTextMesh = createTexturePlane(
33392
+ textures.bottomCopperText,
33393
+ -pcbThickness / 2 - BOARD_SURFACE_OFFSET.copper,
33394
+ true,
33395
+ "jscad-bottom-copper-text"
33396
+ );
33397
+ if (bottomCopperTextMesh) {
33398
+ meshes.push(bottomCopperTextMesh);
33399
+ rootObject.add(bottomCopperTextMesh);
33400
+ }
33401
+ }
33402
+ if (visibility.boardBody) {
33403
+ const topPanelOutlinesMesh = createTexturePlane(
33404
+ textures.topPanelOutlines,
33405
+ pcbThickness / 2 + SURFACE_OFFSET + 3e-3,
33406
+ // Above silkscreen
33407
+ false,
33408
+ "jscad-top-panel-outlines",
33409
+ false,
33410
+ true
33411
+ );
33412
+ if (topPanelOutlinesMesh) {
33413
+ meshes.push(topPanelOutlinesMesh);
33414
+ rootObject.add(topPanelOutlinesMesh);
33415
+ }
33416
+ const bottomPanelOutlinesMesh = createTexturePlane(
33417
+ textures.bottomPanelOutlines,
33418
+ -pcbThickness / 2 - SURFACE_OFFSET - 3e-3,
33419
+ // Below bottom silkscreen
33420
+ true,
33421
+ "jscad-bottom-panel-outlines",
33422
+ false,
33423
+ true
33424
+ );
33425
+ if (bottomPanelOutlinesMesh) {
33426
+ meshes.push(bottomPanelOutlinesMesh);
33427
+ rootObject.add(bottomPanelOutlinesMesh);
33428
+ }
33429
+ }
33391
33430
  return () => {
33392
33431
  meshes.forEach((mesh) => {
33393
33432
  if (mesh.parent === rootObject) {
33394
33433
  rootObject.remove(mesh);
33395
33434
  }
33396
33435
  mesh.geometry.dispose();
33397
- if (mesh.material instanceof THREE21.Material) {
33436
+ if (mesh.material instanceof THREE23.Material) {
33398
33437
  mesh.material.dispose();
33399
33438
  }
33400
33439
  });
@@ -33404,16 +33443,16 @@ function JscadBoardTextures({
33404
33443
  }
33405
33444
 
33406
33445
  // src/utils/preprocess-circuit-json.ts
33407
- import { su as su10 } from "@tscircuit/circuit-json-util";
33446
+ import { su as su11 } from "@tscircuit/circuit-json-util";
33408
33447
 
33409
33448
  // src/utils/create-faux-board.ts
33410
- import { su as su9, getBoundsOfPcbElements } from "@tscircuit/circuit-json-util";
33449
+ import { su as su10, getBoundsOfPcbElements } from "@tscircuit/circuit-json-util";
33411
33450
  function createFauxBoard(circuitJson) {
33412
- const cadComponents = su9(circuitJson).cad_component.list();
33413
- const pads = su9(circuitJson).pcb_smtpad.list();
33414
- const holes = su9(circuitJson).pcb_hole.list();
33415
- const platedHoles = su9(circuitJson).pcb_plated_hole.list();
33416
- const vias = su9(circuitJson).pcb_via.list();
33451
+ const cadComponents = su10(circuitJson).cad_component.list();
33452
+ const pads = su10(circuitJson).pcb_smtpad.list();
33453
+ const holes = su10(circuitJson).pcb_hole.list();
33454
+ const platedHoles = su10(circuitJson).pcb_plated_hole.list();
33455
+ const vias = su10(circuitJson).pcb_via.list();
33417
33456
  if (cadComponents.length === 0 && pads.length === 0 && holes.length === 0 && platedHoles.length === 0 && vias.length === 0) {
33418
33457
  return null;
33419
33458
  }
@@ -33462,7 +33501,7 @@ function createFauxBoard(circuitJson) {
33462
33501
 
33463
33502
  // src/utils/preprocess-circuit-json.ts
33464
33503
  function addFauxBoardIfNeeded(circuitJson) {
33465
- const boards = su10(circuitJson).pcb_board.list();
33504
+ const boards = su11(circuitJson).pcb_board.list();
33466
33505
  if (boards.length > 0) {
33467
33506
  return circuitJson;
33468
33507
  }
@@ -33512,7 +33551,7 @@ var CadViewerJscad = forwardRef3(
33512
33551
  const initialCameraPosition = useMemo20(() => {
33513
33552
  if (!internalCircuitJson) return [5, -5, 5];
33514
33553
  try {
33515
- const board = su11(internalCircuitJson).pcb_board.list()[0];
33554
+ const board = su12(internalCircuitJson).pcb_board.list()[0];
33516
33555
  if (!board) return [5, -5, 5];
33517
33556
  const { width: width10, height: height10 } = board;
33518
33557
  if (!width10 && !height10) {
@@ -33538,7 +33577,7 @@ var CadViewerJscad = forwardRef3(
33538
33577
  const isFauxBoard = useMemo20(() => {
33539
33578
  if (!internalCircuitJson) return false;
33540
33579
  try {
33541
- const board = su11(internalCircuitJson).pcb_board.list()[0];
33580
+ const board = su12(internalCircuitJson).pcb_board.list()[0];
33542
33581
  return !!board && board.pcb_board_id === "faux-board";
33543
33582
  } catch (e) {
33544
33583
  return false;
@@ -33547,7 +33586,7 @@ var CadViewerJscad = forwardRef3(
33547
33586
  const boardDimensions = useMemo20(() => {
33548
33587
  if (!internalCircuitJson) return void 0;
33549
33588
  try {
33550
- const board = su11(internalCircuitJson).pcb_board.list()[0];
33589
+ const board = su12(internalCircuitJson).pcb_board.list()[0];
33551
33590
  if (!board) return void 0;
33552
33591
  return { width: board.width ?? 0, height: board.height ?? 0 };
33553
33592
  } catch (e) {
@@ -33558,7 +33597,7 @@ var CadViewerJscad = forwardRef3(
33558
33597
  const boardCenter = useMemo20(() => {
33559
33598
  if (!internalCircuitJson) return void 0;
33560
33599
  try {
33561
- const board = su11(internalCircuitJson).pcb_board.list()[0];
33600
+ const board = su12(internalCircuitJson).pcb_board.list()[0];
33562
33601
  if (!board || !board.center) return void 0;
33563
33602
  return { x: board.center.x, y: board.center.y };
33564
33603
  } catch (e) {
@@ -33568,7 +33607,7 @@ var CadViewerJscad = forwardRef3(
33568
33607
  }, [internalCircuitJson]);
33569
33608
  const pcbThickness = usePcbThickness(internalCircuitJson);
33570
33609
  const { stls: boardStls, loading } = useStlsFromGeom(boardGeom);
33571
- const cad_components = su11(internalCircuitJson).cad_component.list();
33610
+ const cad_components = su12(internalCircuitJson).cad_component.list();
33572
33611
  return /* @__PURE__ */ jsxs5(
33573
33612
  CadViewerContainer,
33574
33613
  {
@@ -33620,13 +33659,13 @@ var CadViewerJscad = forwardRef3(
33620
33659
  );
33621
33660
 
33622
33661
  // src/CadViewerManifold.tsx
33623
- import { su as su18 } from "@tscircuit/circuit-json-util";
33662
+ import { su as su19 } from "@tscircuit/circuit-json-util";
33624
33663
  import { useEffect as useEffect24, useMemo as useMemo22, useState as useState15 } from "react";
33625
33664
 
33626
33665
  // src/hooks/useManifoldBoardBuilder.ts
33627
33666
  import { useState as useState14, useEffect as useEffect23, useMemo as useMemo21, useRef as useRef9 } from "react";
33628
- import { su as su17 } from "@tscircuit/circuit-json-util";
33629
- import * as THREE27 from "three";
33667
+ import { su as su18 } from "@tscircuit/circuit-json-util";
33668
+ import * as THREE29 from "three";
33630
33669
 
33631
33670
  // src/utils/manifold/create-manifold-board.ts
33632
33671
  var arePointsClockwise3 = (points) => {
@@ -33687,17 +33726,17 @@ function createManifoldBoard(Manifold, CrossSection, boardData, pcbThickness, ma
33687
33726
  }
33688
33727
 
33689
33728
  // src/utils/manifold/process-copper-pours.ts
33690
- import * as THREE23 from "three";
33729
+ import * as THREE25 from "three";
33691
33730
 
33692
33731
  // src/utils/manifold-mesh-to-three-geometry.ts
33693
- import * as THREE22 from "three";
33732
+ import * as THREE24 from "three";
33694
33733
  function manifoldMeshToThreeGeometry(manifoldMesh) {
33695
- const geometry = new THREE22.BufferGeometry();
33734
+ const geometry = new THREE24.BufferGeometry();
33696
33735
  geometry.setAttribute(
33697
33736
  "position",
33698
- new THREE22.Float32BufferAttribute(manifoldMesh.vertProperties, 3)
33737
+ new THREE24.Float32BufferAttribute(manifoldMesh.vertProperties, 3)
33699
33738
  );
33700
- geometry.setIndex(new THREE22.Uint32BufferAttribute(manifoldMesh.triVerts, 1));
33739
+ geometry.setIndex(new THREE24.Uint32BufferAttribute(manifoldMesh.triVerts, 1));
33701
33740
  if (manifoldMesh.runIndex && manifoldMesh.runIndex.length > 1 && manifoldMesh.runOriginalID) {
33702
33741
  for (let i = 0; i < manifoldMesh.runIndex.length - 1; i++) {
33703
33742
  const start = manifoldMesh.runIndex[i];
@@ -33870,7 +33909,7 @@ function processCopperPoursForManifold(Manifold, CrossSection, circuitJson, pcbT
33870
33909
  }
33871
33910
  const covered = pour.covered_with_solder_mask !== false;
33872
33911
  const pourColorArr = covered ? tracesMaterialColors[boardMaterial] ?? colors.fr4TracesWithoutMaskTan : colors.copper;
33873
- const pourColor = new THREE23.Color(...pourColorArr);
33912
+ const pourColor = new THREE25.Color(...pourColorArr);
33874
33913
  const threeGeom = manifoldMeshToThreeGeometry(pourOp.getMesh());
33875
33914
  copperPourGeoms.push({
33876
33915
  key: `coppour-${pour.pcb_copper_pour_id}`,
@@ -33883,7 +33922,7 @@ function processCopperPoursForManifold(Manifold, CrossSection, circuitJson, pcbT
33883
33922
  }
33884
33923
 
33885
33924
  // src/utils/manifold/process-cutouts.ts
33886
- import { su as su12 } from "@tscircuit/circuit-json-util";
33925
+ import { su as su13 } from "@tscircuit/circuit-json-util";
33887
33926
 
33888
33927
  // src/utils/pad-geoms.ts
33889
33928
  var RECT_PAD_SEGMENTS2 = 64;
@@ -33975,7 +34014,7 @@ var arePointsClockwise5 = (points) => {
33975
34014
  };
33976
34015
  function processCutoutsForManifold(Manifold, CrossSection, circuitJson, pcbThickness, manifoldInstancesForCleanup) {
33977
34016
  const cutoutOps = [];
33978
- const pcbCutouts = su12(circuitJson).pcb_cutout.list();
34017
+ const pcbCutouts = su13(circuitJson).pcb_cutout.list();
33979
34018
  for (const cutout of pcbCutouts) {
33980
34019
  let cutoutOp;
33981
34020
  const cutoutHeight = pcbThickness * 1.5;
@@ -34070,7 +34109,7 @@ function processCutoutsForManifold(Manifold, CrossSection, circuitJson, pcbThick
34070
34109
  }
34071
34110
 
34072
34111
  // src/utils/manifold/process-non-plated-holes.ts
34073
- import { su as su13 } from "@tscircuit/circuit-json-util";
34112
+ import { su as su14 } from "@tscircuit/circuit-json-util";
34074
34113
 
34075
34114
  // src/utils/hole-geoms.ts
34076
34115
  function createCircleHoleDrill({
@@ -34122,7 +34161,7 @@ function isRotatedPillHole(hole) {
34122
34161
  }
34123
34162
  function processNonPlatedHolesForManifold(Manifold, circuitJson, pcbThickness, manifoldInstancesForCleanup) {
34124
34163
  const nonPlatedHoleBoardDrills = [];
34125
- const pcbHoles = su13(circuitJson).pcb_hole.list();
34164
+ const pcbHoles = su14(circuitJson).pcb_hole.list();
34126
34165
  const createPillOp = (width10, height10, depth) => {
34127
34166
  const pillOp = createRoundedRectPrism({
34128
34167
  Manifold,
@@ -34171,8 +34210,8 @@ function processNonPlatedHolesForManifold(Manifold, circuitJson, pcbThickness, m
34171
34210
  }
34172
34211
 
34173
34212
  // src/utils/manifold/process-plated-holes.ts
34174
- import { su as su14 } from "@tscircuit/circuit-json-util";
34175
- import * as THREE24 from "three";
34213
+ import { su as su15 } from "@tscircuit/circuit-json-util";
34214
+ import * as THREE26 from "three";
34176
34215
  var arePointsClockwise6 = (points) => {
34177
34216
  let area = 0;
34178
34217
  for (let i = 0; i < points.length; i++) {
@@ -34193,11 +34232,11 @@ var createEllipsePoints = (width10, height10, segments) => {
34193
34232
  }
34194
34233
  return points;
34195
34234
  };
34196
- var COPPER_COLOR = new THREE24.Color(...colors.copper);
34235
+ var COPPER_COLOR = new THREE26.Color(...colors.copper);
34197
34236
  var PLATED_HOLE_LIP_HEIGHT = 0.05;
34198
34237
  function processPlatedHolesForManifold(Manifold, CrossSection, circuitJson, pcbThickness, manifoldInstancesForCleanup, boardClipVolume) {
34199
34238
  const platedHoleBoardDrills = [];
34200
- const pcbPlatedHoles = su14(circuitJson).pcb_plated_hole.list();
34239
+ const pcbPlatedHoles = su15(circuitJson).pcb_plated_hole.list();
34201
34240
  const platedHoleCopperGeoms = [];
34202
34241
  const platedHoleCopperOpsForSubtract = [];
34203
34242
  const createPillOp = (width10, height10, depth) => {
@@ -34766,12 +34805,12 @@ function processPlatedHolesForManifold(Manifold, CrossSection, circuitJson, pcbT
34766
34805
  }
34767
34806
 
34768
34807
  // src/utils/manifold/process-smt-pads.ts
34769
- import { su as su15 } from "@tscircuit/circuit-json-util";
34770
- import * as THREE25 from "three";
34771
- var COPPER_COLOR2 = new THREE25.Color(...colors.copper);
34808
+ import { su as su16 } from "@tscircuit/circuit-json-util";
34809
+ import * as THREE27 from "three";
34810
+ var COPPER_COLOR2 = new THREE27.Color(...colors.copper);
34772
34811
  function processSmtPadsForManifold(Manifold, circuitJson, pcbThickness, manifoldInstancesForCleanup, holeUnion, boardClipVolume) {
34773
34812
  const smtPadGeoms = [];
34774
- const smtPads = su15(circuitJson).pcb_smtpad.list();
34813
+ const smtPads = su16(circuitJson).pcb_smtpad.list();
34775
34814
  smtPads.forEach((pad2, index2) => {
34776
34815
  const padBaseThickness = DEFAULT_SMT_PAD_THICKNESS;
34777
34816
  const zPos = pad2.layer === "bottom" ? -pcbThickness / 2 - BOARD_SURFACE_OFFSET.copper : pcbThickness / 2 + BOARD_SURFACE_OFFSET.copper;
@@ -34806,8 +34845,8 @@ function processSmtPadsForManifold(Manifold, circuitJson, pcbThickness, manifold
34806
34845
  }
34807
34846
 
34808
34847
  // src/utils/manifold/process-vias.ts
34809
- import { su as su16 } from "@tscircuit/circuit-json-util";
34810
- import * as THREE26 from "three";
34848
+ import { su as su17 } from "@tscircuit/circuit-json-util";
34849
+ import * as THREE28 from "three";
34811
34850
 
34812
34851
  // src/utils/via-geoms.ts
34813
34852
  function createViaCopper2({
@@ -34860,10 +34899,10 @@ function createViaCopper2({
34860
34899
  }
34861
34900
 
34862
34901
  // src/utils/manifold/process-vias.ts
34863
- var COPPER_COLOR3 = new THREE26.Color(...colors.copper);
34902
+ var COPPER_COLOR3 = new THREE28.Color(...colors.copper);
34864
34903
  function processViasForManifold(Manifold, circuitJson, pcbThickness, manifoldInstancesForCleanup, boardClipVolume) {
34865
34904
  const viaBoardDrills = [];
34866
- const pcbVias = su16(circuitJson).pcb_via.list();
34905
+ const pcbVias = su17(circuitJson).pcb_via.list();
34867
34906
  const viaCopperGeoms = [];
34868
34907
  pcbVias.forEach((via, index2) => {
34869
34908
  if (typeof via.hole_diameter === "number") {
@@ -34923,26 +34962,28 @@ var useManifoldBoardBuilder = (manifoldJSModule, circuitJson) => {
34923
34962
  const panels = circuitJson.filter(
34924
34963
  (e) => e.type === "pcb_panel"
34925
34964
  );
34926
- const boards = su17(circuitJson).pcb_board.list();
34965
+ const boards = su18(circuitJson).pcb_board.list();
34927
34966
  if (panels.length > 0) {
34928
34967
  const panel = panels[0];
34968
+ const firstBoardInPanel = boards.find(
34969
+ (b) => b.pcb_panel_id === panel.pcb_panel_id
34970
+ );
34929
34971
  return {
34930
34972
  type: "pcb_board",
34931
34973
  pcb_board_id: panel.pcb_panel_id,
34932
34974
  center: panel.center,
34933
34975
  width: panel.width,
34934
34976
  height: panel.height,
34935
- thickness: 1.6,
34936
- // Default thickness
34937
- material: "fr4",
34938
- num_layers: 2
34977
+ thickness: firstBoardInPanel?.thickness ?? 1.6,
34978
+ material: firstBoardInPanel?.material ?? "fr4",
34979
+ num_layers: firstBoardInPanel?.num_layers ?? 2
34939
34980
  };
34940
34981
  }
34941
34982
  const boardsNotInPanel = boards.filter((b) => !b.pcb_panel_id);
34942
34983
  return boardsNotInPanel.length > 0 ? boardsNotInPanel[0] : null;
34943
34984
  }, [circuitJson]);
34944
34985
  const isFauxBoard = useMemo21(() => {
34945
- const boards = su17(circuitJson).pcb_board.list();
34986
+ const boards = su18(circuitJson).pcb_board.list();
34946
34987
  return boards.length > 0 && boards[0].pcb_board_id === "faux-board";
34947
34988
  }, [circuitJson]);
34948
34989
  useEffect23(() => {
@@ -35077,7 +35118,7 @@ var useManifoldBoardBuilder = (manifoldJSModule, circuitJson) => {
35077
35118
  {
35078
35119
  key: "plated-holes-union",
35079
35120
  geometry: cutPlatedGeom,
35080
- color: new THREE27.Color(
35121
+ color: new THREE29.Color(
35081
35122
  colors.copper[0],
35082
35123
  colors.copper[1],
35083
35124
  colors.copper[2]
@@ -35107,7 +35148,7 @@ var useManifoldBoardBuilder = (manifoldJSModule, circuitJson) => {
35107
35148
  const matColorArray = boardMaterialColors[boardData.material] ?? colors.fr4Tan;
35108
35149
  currentGeoms.board = {
35109
35150
  geometry: finalBoardGeom,
35110
- color: new THREE27.Color(
35151
+ color: new THREE29.Color(
35111
35152
  matColorArray[0],
35112
35153
  matColorArray[1],
35113
35154
  matColorArray[2]
@@ -35200,6 +35241,34 @@ var useManifoldBoardBuilder = (manifoldJSModule, circuitJson) => {
35200
35241
  soldermaskColor,
35201
35242
  traceTextureResolution: TRACE_TEXTURE_RESOLUTION
35202
35243
  });
35244
+ const copperColorArr = colors.copper;
35245
+ const copperColor = `rgb(${Math.round(copperColorArr[0] * 255)}, ${Math.round(copperColorArr[1] * 255)}, ${Math.round(copperColorArr[2] * 255)})`;
35246
+ currentTextures.topCopperText = createCopperTextTextureForLayer({
35247
+ layer: "top",
35248
+ circuitJson,
35249
+ boardData,
35250
+ copperColor,
35251
+ traceTextureResolution: TRACE_TEXTURE_RESOLUTION
35252
+ });
35253
+ currentTextures.bottomCopperText = createCopperTextTextureForLayer({
35254
+ layer: "bottom",
35255
+ circuitJson,
35256
+ boardData,
35257
+ copperColor,
35258
+ traceTextureResolution: TRACE_TEXTURE_RESOLUTION
35259
+ });
35260
+ currentTextures.topPanelOutlines = createPanelOutlineTextureForLayer({
35261
+ layer: "top",
35262
+ circuitJson,
35263
+ panelData: boardData,
35264
+ traceTextureResolution: TRACE_TEXTURE_RESOLUTION
35265
+ });
35266
+ currentTextures.bottomPanelOutlines = createPanelOutlineTextureForLayer({
35267
+ layer: "bottom",
35268
+ circuitJson,
35269
+ panelData: boardData,
35270
+ traceTextureResolution: TRACE_TEXTURE_RESOLUTION
35271
+ });
35203
35272
  setTextures(currentTextures);
35204
35273
  } catch (e) {
35205
35274
  console.error("Error processing geometry with Manifold in hook:", e);
@@ -35228,11 +35297,11 @@ var useManifoldBoardBuilder = (manifoldJSModule, circuitJson) => {
35228
35297
  };
35229
35298
 
35230
35299
  // src/utils/manifold/create-three-geometry-meshes.ts
35231
- import * as THREE29 from "three";
35300
+ import * as THREE31 from "three";
35232
35301
 
35233
35302
  // src/utils/create-board-material.ts
35234
- import * as THREE28 from "three";
35235
- var DEFAULT_SIDE = THREE28.DoubleSide;
35303
+ import * as THREE30 from "three";
35304
+ var DEFAULT_SIDE = THREE30.DoubleSide;
35236
35305
  var createBoardMaterial = ({
35237
35306
  material,
35238
35307
  color,
@@ -35240,7 +35309,7 @@ var createBoardMaterial = ({
35240
35309
  isFaux = false
35241
35310
  }) => {
35242
35311
  if (material === "fr4") {
35243
- return new THREE28.MeshPhysicalMaterial({
35312
+ return new THREE30.MeshPhysicalMaterial({
35244
35313
  color,
35245
35314
  side,
35246
35315
  metalness: 0,
@@ -35254,7 +35323,7 @@ var createBoardMaterial = ({
35254
35323
  flatShading: true
35255
35324
  });
35256
35325
  }
35257
- return new THREE28.MeshStandardMaterial({
35326
+ return new THREE30.MeshStandardMaterial({
35258
35327
  color,
35259
35328
  side,
35260
35329
  flatShading: true,
@@ -35270,12 +35339,12 @@ function createGeometryMeshes(geoms) {
35270
35339
  const meshes = [];
35271
35340
  if (!geoms) return meshes;
35272
35341
  if (geoms.board && geoms.board.geometry) {
35273
- const mesh = new THREE29.Mesh(
35342
+ const mesh = new THREE31.Mesh(
35274
35343
  geoms.board.geometry,
35275
35344
  createBoardMaterial({
35276
35345
  material: geoms.board.material,
35277
35346
  color: geoms.board.color,
35278
- side: THREE29.DoubleSide,
35347
+ side: THREE31.DoubleSide,
35279
35348
  isFaux: geoms.board.isFaux
35280
35349
  })
35281
35350
  );
@@ -35285,11 +35354,11 @@ function createGeometryMeshes(geoms) {
35285
35354
  const createMeshesFromArray = (geomArray) => {
35286
35355
  if (geomArray) {
35287
35356
  geomArray.forEach((comp) => {
35288
- const mesh = new THREE29.Mesh(
35357
+ const mesh = new THREE31.Mesh(
35289
35358
  comp.geometry,
35290
- new THREE29.MeshStandardMaterial({
35359
+ new THREE31.MeshStandardMaterial({
35291
35360
  color: comp.color,
35292
- side: THREE29.DoubleSide,
35361
+ side: THREE31.DoubleSide,
35293
35362
  flatShading: true,
35294
35363
  // Consistent with board
35295
35364
  polygonOffset: true,
@@ -35310,25 +35379,24 @@ function createGeometryMeshes(geoms) {
35310
35379
  }
35311
35380
 
35312
35381
  // src/utils/manifold/create-three-texture-meshes.ts
35313
- import * as THREE30 from "three";
35382
+ import * as THREE32 from "three";
35314
35383
  function createTextureMeshes(textures, boardData, pcbThickness) {
35315
35384
  const meshes = [];
35316
35385
  if (!textures || !boardData || pcbThickness === null) return meshes;
35317
35386
  const createTexturePlane = (texture, yOffset, isBottomLayer, keySuffix, usePolygonOffset = false, renderOrder = 0) => {
35318
35387
  if (!texture) return null;
35319
- const planeGeom = new THREE30.PlaneGeometry(boardData.width, boardData.height);
35320
- const material = new THREE30.MeshBasicMaterial({
35388
+ const planeGeom = new THREE32.PlaneGeometry(boardData.width, boardData.height);
35389
+ const material = new THREE32.MeshBasicMaterial({
35321
35390
  map: texture,
35322
35391
  transparent: true,
35323
- side: THREE30.DoubleSide,
35324
- depthWrite: false,
35325
- // Important for layers to avoid z-fighting issues with board itself
35392
+ side: THREE32.DoubleSide,
35393
+ depthWrite: keySuffix === "panel-outlines",
35326
35394
  polygonOffset: usePolygonOffset,
35327
35395
  polygonOffsetFactor: usePolygonOffset ? -4 : 0,
35328
35396
  // Increased for better z-fighting prevention
35329
35397
  polygonOffsetUnits: usePolygonOffset ? -4 : 0
35330
35398
  });
35331
- const mesh = new THREE30.Mesh(planeGeom, material);
35399
+ const mesh = new THREE32.Mesh(planeGeom, material);
35332
35400
  mesh.position.set(boardData.center.x, boardData.center.y, yOffset);
35333
35401
  if (isBottomLayer) {
35334
35402
  mesh.rotation.set(Math.PI, 0, 0);
@@ -35424,6 +35492,46 @@ function createTextureMeshes(textures, boardData, pcbThickness) {
35424
35492
  // Render after board (renderOrder)
35425
35493
  );
35426
35494
  if (bottomSoldermaskMesh) meshes.push(bottomSoldermaskMesh);
35495
+ const topCopperTextMesh = createTexturePlane(
35496
+ textures.topCopperText,
35497
+ pcbThickness / 2 + BOARD_SURFACE_OFFSET.copper,
35498
+ false,
35499
+ "copper-text",
35500
+ false,
35501
+ 2
35502
+ // Render after soldermask
35503
+ );
35504
+ if (topCopperTextMesh) meshes.push(topCopperTextMesh);
35505
+ const bottomCopperTextMesh = createTexturePlane(
35506
+ textures.bottomCopperText,
35507
+ -pcbThickness / 2 - BOARD_SURFACE_OFFSET.copper,
35508
+ true,
35509
+ "copper-text",
35510
+ false,
35511
+ 2
35512
+ // Render after soldermask
35513
+ );
35514
+ if (bottomCopperTextMesh) meshes.push(bottomCopperTextMesh);
35515
+ const topPanelOutlinesMesh = createTexturePlane(
35516
+ textures.topPanelOutlines,
35517
+ pcbThickness / 2 + 4e-3,
35518
+ // Above silkscreen
35519
+ false,
35520
+ "panel-outlines",
35521
+ false,
35522
+ 4
35523
+ );
35524
+ if (topPanelOutlinesMesh) meshes.push(topPanelOutlinesMesh);
35525
+ const bottomPanelOutlinesMesh = createTexturePlane(
35526
+ textures.bottomPanelOutlines,
35527
+ -pcbThickness / 2 - 4e-3,
35528
+ // Below bottom silkscreen
35529
+ true,
35530
+ "panel-outlines",
35531
+ false,
35532
+ 4
35533
+ );
35534
+ if (bottomPanelOutlinesMesh) meshes.push(bottomPanelOutlinesMesh);
35427
35535
  return meshes;
35428
35536
  }
35429
35537
 
@@ -35476,6 +35584,12 @@ var BoardMeshes = ({
35476
35584
  shouldShow = visibility.topMask;
35477
35585
  } else if (mesh.name.includes("bottom-soldermask")) {
35478
35586
  shouldShow = visibility.bottomMask;
35587
+ } else if (mesh.name.includes("top-copper-text")) {
35588
+ shouldShow = visibility.topCopper;
35589
+ } else if (mesh.name.includes("bottom-copper-text")) {
35590
+ shouldShow = visibility.bottomCopper;
35591
+ } else if (mesh.name.includes("panel-outlines")) {
35592
+ shouldShow = visibility.boardBody;
35479
35593
  }
35480
35594
  if (shouldShow) {
35481
35595
  rootObject.add(mesh);
@@ -35588,7 +35702,7 @@ try {
35588
35702
  [textures, boardData, pcbThickness]
35589
35703
  );
35590
35704
  const cadComponents = useMemo22(
35591
- () => su18(circuitJson).cad_component.list(),
35705
+ () => su19(circuitJson).cad_component.list(),
35592
35706
  [circuitJson]
35593
35707
  );
35594
35708
  const boardDimensions = useMemo22(() => {
@@ -42330,7 +42444,7 @@ var KeyboardShortcutsDialog = ({
42330
42444
 
42331
42445
  // src/CadViewer.tsx
42332
42446
  import { jsx as jsx37, jsxs as jsxs11 } from "react/jsx-runtime";
42333
- var DEFAULT_TARGET = new THREE31.Vector3(0, 0, 0);
42447
+ var DEFAULT_TARGET = new THREE33.Vector3(0, 0, 0);
42334
42448
  var INITIAL_CAMERA_POSITION = [5, -5, 5];
42335
42449
  var CadViewerInner = (props) => {
42336
42450
  const [engine, setEngine] = useState35("manifold");
@@ -42596,12 +42710,12 @@ var CadViewer = (props) => {
42596
42710
 
42597
42711
  // src/convert-circuit-json-to-3d-svg.ts
42598
42712
  var import_debug = __toESM(require_browser(), 1);
42599
- import { su as su19 } from "@tscircuit/circuit-json-util";
42600
- import * as THREE35 from "three";
42713
+ import { su as su20 } from "@tscircuit/circuit-json-util";
42714
+ import * as THREE37 from "three";
42601
42715
  import { SVGRenderer } from "three/examples/jsm/renderers/SVGRenderer.js";
42602
42716
 
42603
42717
  // src/utils/create-geometry-from-polygons.ts
42604
- import * as THREE32 from "three";
42718
+ import * as THREE34 from "three";
42605
42719
  import { BufferGeometry as BufferGeometry3, Float32BufferAttribute as Float32BufferAttribute2 } from "three";
42606
42720
  function createGeometryFromPolygons(polygons) {
42607
42721
  const geometry = new BufferGeometry3();
@@ -42615,12 +42729,12 @@ function createGeometryFromPolygons(polygons) {
42615
42729
  ...polygon3.vertices[i + 1]
42616
42730
  // Third vertex
42617
42731
  );
42618
- const v1 = new THREE32.Vector3(...polygon3.vertices[0]);
42619
- const v2 = new THREE32.Vector3(...polygon3.vertices[i]);
42620
- const v3 = new THREE32.Vector3(...polygon3.vertices[i + 1]);
42621
- const normal = new THREE32.Vector3().crossVectors(
42622
- new THREE32.Vector3().subVectors(v2, v1),
42623
- new THREE32.Vector3().subVectors(v3, v1)
42732
+ const v1 = new THREE34.Vector3(...polygon3.vertices[0]);
42733
+ const v2 = new THREE34.Vector3(...polygon3.vertices[i]);
42734
+ const v3 = new THREE34.Vector3(...polygon3.vertices[i + 1]);
42735
+ const normal = new THREE34.Vector3().crossVectors(
42736
+ new THREE34.Vector3().subVectors(v2, v1),
42737
+ new THREE34.Vector3().subVectors(v3, v1)
42624
42738
  ).normalize();
42625
42739
  normals.push(
42626
42740
  normal.x,
@@ -42644,10 +42758,10 @@ function createGeometryFromPolygons(polygons) {
42644
42758
  var import_modeling2 = __toESM(require_src(), 1);
42645
42759
  var import_jscad_planner2 = __toESM(require_dist(), 1);
42646
42760
  var jscadModeling2 = __toESM(require_src(), 1);
42647
- import * as THREE34 from "three";
42761
+ import * as THREE36 from "three";
42648
42762
 
42649
42763
  // src/utils/load-model.ts
42650
- import * as THREE33 from "three";
42764
+ import * as THREE35 from "three";
42651
42765
  import { GLTFLoader as GLTFLoader2 } from "three/examples/jsm/loaders/GLTFLoader.js";
42652
42766
  import { OBJLoader as OBJLoader2 } from "three/examples/jsm/loaders/OBJLoader.js";
42653
42767
  import { STLLoader as STLLoader2 } from "three/examples/jsm/loaders/STLLoader.js";
@@ -42655,12 +42769,12 @@ async function load3DModel(url) {
42655
42769
  if (url.endsWith(".stl")) {
42656
42770
  const loader = new STLLoader2();
42657
42771
  const geometry = await loader.loadAsync(url);
42658
- const material = new THREE33.MeshStandardMaterial({
42772
+ const material = new THREE35.MeshStandardMaterial({
42659
42773
  color: 8947848,
42660
42774
  metalness: 0.5,
42661
42775
  roughness: 0.5
42662
42776
  });
42663
- return new THREE33.Mesh(geometry, material);
42777
+ return new THREE35.Mesh(geometry, material);
42664
42778
  }
42665
42779
  if (url.endsWith(".obj")) {
42666
42780
  const loader = new OBJLoader2();
@@ -42693,9 +42807,9 @@ async function renderComponent(component, scene) {
42693
42807
  }
42694
42808
  if (component.rotation) {
42695
42809
  model.rotation.set(
42696
- THREE34.MathUtils.degToRad(component.rotation.x ?? 0),
42697
- THREE34.MathUtils.degToRad(component.rotation.y ?? 0),
42698
- THREE34.MathUtils.degToRad(component.rotation.z ?? 0)
42810
+ THREE36.MathUtils.degToRad(component.rotation.x ?? 0),
42811
+ THREE36.MathUtils.degToRad(component.rotation.y ?? 0),
42812
+ THREE36.MathUtils.degToRad(component.rotation.z ?? 0)
42699
42813
  );
42700
42814
  }
42701
42815
  scene.add(model);
@@ -42709,13 +42823,13 @@ async function renderComponent(component, scene) {
42709
42823
  );
42710
42824
  if (jscadObject && (jscadObject.polygons || jscadObject.sides)) {
42711
42825
  const threeGeom = convertCSGToThreeGeom(jscadObject);
42712
- const material2 = new THREE34.MeshStandardMaterial({
42826
+ const material2 = new THREE36.MeshStandardMaterial({
42713
42827
  color: 8947848,
42714
42828
  metalness: 0.5,
42715
42829
  roughness: 0.5,
42716
- side: THREE34.DoubleSide
42830
+ side: THREE36.DoubleSide
42717
42831
  });
42718
- const mesh2 = new THREE34.Mesh(threeGeom, material2);
42832
+ const mesh2 = new THREE36.Mesh(threeGeom, material2);
42719
42833
  if (component.position) {
42720
42834
  mesh2.position.set(
42721
42835
  component.position.x ?? 0,
@@ -42725,9 +42839,9 @@ async function renderComponent(component, scene) {
42725
42839
  }
42726
42840
  if (component.rotation) {
42727
42841
  mesh2.rotation.set(
42728
- THREE34.MathUtils.degToRad(component.rotation.x ?? 0),
42729
- THREE34.MathUtils.degToRad(component.rotation.y ?? 0),
42730
- THREE34.MathUtils.degToRad(component.rotation.z ?? 0)
42842
+ THREE36.MathUtils.degToRad(component.rotation.x ?? 0),
42843
+ THREE36.MathUtils.degToRad(component.rotation.y ?? 0),
42844
+ THREE36.MathUtils.degToRad(component.rotation.z ?? 0)
42731
42845
  );
42732
42846
  }
42733
42847
  scene.add(mesh2);
@@ -42744,17 +42858,17 @@ async function renderComponent(component, scene) {
42744
42858
  if (!geom || !geom.polygons && !geom.sides) {
42745
42859
  continue;
42746
42860
  }
42747
- const color = new THREE34.Color(geomInfo.color);
42861
+ const color = new THREE36.Color(geomInfo.color);
42748
42862
  color.convertLinearToSRGB();
42749
42863
  const geomWithColor = { ...geom, color: [color.r, color.g, color.b] };
42750
42864
  const threeGeom = convertCSGToThreeGeom(geomWithColor);
42751
- const material2 = new THREE34.MeshStandardMaterial({
42865
+ const material2 = new THREE36.MeshStandardMaterial({
42752
42866
  vertexColors: true,
42753
42867
  metalness: 0.2,
42754
42868
  roughness: 0.8,
42755
- side: THREE34.DoubleSide
42869
+ side: THREE36.DoubleSide
42756
42870
  });
42757
- const mesh2 = new THREE34.Mesh(threeGeom, material2);
42871
+ const mesh2 = new THREE36.Mesh(threeGeom, material2);
42758
42872
  if (component.position) {
42759
42873
  mesh2.position.set(
42760
42874
  component.position.x ?? 0,
@@ -42764,22 +42878,22 @@ async function renderComponent(component, scene) {
42764
42878
  }
42765
42879
  if (component.rotation) {
42766
42880
  mesh2.rotation.set(
42767
- THREE34.MathUtils.degToRad(component.rotation.x ?? 0),
42768
- THREE34.MathUtils.degToRad(component.rotation.y ?? 0),
42769
- THREE34.MathUtils.degToRad(component.rotation.z ?? 0)
42881
+ THREE36.MathUtils.degToRad(component.rotation.x ?? 0),
42882
+ THREE36.MathUtils.degToRad(component.rotation.y ?? 0),
42883
+ THREE36.MathUtils.degToRad(component.rotation.z ?? 0)
42770
42884
  );
42771
42885
  }
42772
42886
  scene.add(mesh2);
42773
42887
  }
42774
42888
  return;
42775
42889
  }
42776
- const geometry = new THREE34.BoxGeometry(0.5, 0.5, 0.5);
42777
- const material = new THREE34.MeshStandardMaterial({
42890
+ const geometry = new THREE36.BoxGeometry(0.5, 0.5, 0.5);
42891
+ const material = new THREE36.MeshStandardMaterial({
42778
42892
  color: 16711680,
42779
42893
  transparent: true,
42780
42894
  opacity: 0.25
42781
42895
  });
42782
- const mesh = new THREE34.Mesh(geometry, material);
42896
+ const mesh = new THREE36.Mesh(geometry, material);
42783
42897
  if (component.position) {
42784
42898
  mesh.position.set(
42785
42899
  component.position.x ?? 0,
@@ -42800,11 +42914,11 @@ async function convertCircuitJsonTo3dSvg(circuitJson, options = {}) {
42800
42914
  padding = 20,
42801
42915
  zoom = 1.5
42802
42916
  } = options;
42803
- const scene = new THREE35.Scene();
42917
+ const scene = new THREE37.Scene();
42804
42918
  const renderer = new SVGRenderer();
42805
42919
  renderer.setSize(width10, height10);
42806
- renderer.setClearColor(new THREE35.Color(backgroundColor), 1);
42807
- const camera = new THREE35.OrthographicCamera();
42920
+ renderer.setClearColor(new THREE37.Color(backgroundColor), 1);
42921
+ const camera = new THREE37.OrthographicCamera();
42808
42922
  const aspect = width10 / height10;
42809
42923
  const frustumSize = 100;
42810
42924
  const halfFrustumSize = frustumSize / 2 / zoom;
@@ -42818,22 +42932,22 @@ async function convertCircuitJsonTo3dSvg(circuitJson, options = {}) {
42818
42932
  camera.position.set(position.x, position.y, position.z);
42819
42933
  camera.up.set(0, 1, 0);
42820
42934
  const lookAt = options.camera?.lookAt ?? { x: 0, y: 0, z: 0 };
42821
- camera.lookAt(new THREE35.Vector3(lookAt.x, lookAt.y, lookAt.z));
42935
+ camera.lookAt(new THREE37.Vector3(lookAt.x, lookAt.y, lookAt.z));
42822
42936
  camera.updateProjectionMatrix();
42823
- const ambientLight = new THREE35.AmbientLight(16777215, Math.PI / 2);
42937
+ const ambientLight = new THREE37.AmbientLight(16777215, Math.PI / 2);
42824
42938
  scene.add(ambientLight);
42825
- const pointLight = new THREE35.PointLight(16777215, Math.PI / 4);
42939
+ const pointLight = new THREE37.PointLight(16777215, Math.PI / 4);
42826
42940
  pointLight.position.set(-10, -10, 10);
42827
42941
  scene.add(pointLight);
42828
- const components = su19(circuitJson).cad_component.list();
42942
+ const components = su20(circuitJson).cad_component.list();
42829
42943
  for (const component of components) {
42830
42944
  await renderComponent(component, scene);
42831
42945
  }
42832
- const boardData = su19(circuitJson).pcb_board.list()[0];
42946
+ const boardData = su20(circuitJson).pcb_board.list()[0];
42833
42947
  const boardGeom = createBoardGeomFromCircuitJson(circuitJson);
42834
42948
  if (boardGeom) {
42835
42949
  const solderMaskColor = colors.fr4SolderMaskGreen;
42836
- const baseColor = new THREE35.Color(
42950
+ const baseColor = new THREE37.Color(
42837
42951
  solderMaskColor[0],
42838
42952
  solderMaskColor[1],
42839
42953
  solderMaskColor[2]
@@ -42845,28 +42959,28 @@ async function convertCircuitJsonTo3dSvg(circuitJson, options = {}) {
42845
42959
  const material = createBoardMaterial({
42846
42960
  material: boardData?.material,
42847
42961
  color: baseColor,
42848
- side: THREE35.DoubleSide
42962
+ side: THREE37.DoubleSide
42849
42963
  });
42850
- const mesh = new THREE35.Mesh(geometry, material);
42964
+ const mesh = new THREE37.Mesh(geometry, material);
42851
42965
  scene.add(mesh);
42852
42966
  }
42853
42967
  }
42854
- const gridColor = new THREE35.Color(8947848);
42855
- const gridHelper = new THREE35.GridHelper(100, 100, gridColor, gridColor);
42968
+ const gridColor = new THREE37.Color(8947848);
42969
+ const gridHelper = new THREE37.GridHelper(100, 100, gridColor, gridColor);
42856
42970
  gridHelper.rotation.x = Math.PI / 2;
42857
42971
  const materials = Array.isArray(gridHelper.material) ? gridHelper.material : [gridHelper.material];
42858
42972
  for (const mat of materials) {
42859
42973
  mat.transparent = true;
42860
42974
  mat.opacity = 0.3;
42861
- if (mat instanceof THREE35.LineBasicMaterial) {
42975
+ if (mat instanceof THREE37.LineBasicMaterial) {
42862
42976
  mat.color = gridColor;
42863
42977
  mat.vertexColors = false;
42864
42978
  }
42865
42979
  }
42866
42980
  scene.add(gridHelper);
42867
- const box = new THREE35.Box3().setFromObject(scene);
42868
- const center = box.getCenter(new THREE35.Vector3());
42869
- const size5 = box.getSize(new THREE35.Vector3());
42981
+ const box = new THREE37.Box3().setFromObject(scene);
42982
+ const center = box.getCenter(new THREE37.Vector3());
42983
+ const size5 = box.getSize(new THREE37.Vector3());
42870
42984
  scene.position.sub(center);
42871
42985
  const maxDim = Math.max(size5.x, size5.y, size5.z);
42872
42986
  if (maxDim > 0) {