@tscircuit/3d-viewer 0.0.468 → 0.0.470

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/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,7 +14229,7 @@ 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 THREE32 from "three";
14233
14233
 
14234
14234
  // src/CadViewerJscad.tsx
14235
14235
  import { su as su11 } from "@tscircuit/circuit-json-util";
@@ -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.467",
28512
+ version: "0.0.469",
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
@@ -29821,10 +29821,10 @@ var createBoardGeomFromCircuitJson = (circuitJson, opts = {}) => {
29821
29821
  };
29822
29822
 
29823
29823
  // 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);
29824
+ var import_transforms6 = __toESM(require_transforms(), 1);
29825
+ var import_primitives7 = __toESM(require_primitives(), 1);
29826
+ var import_colors3 = __toESM(require_colors(), 1);
29827
+ var import_booleans5 = __toESM(require_booleans(), 1);
29828
29828
  import { su as su3 } from "@tscircuit/circuit-json-util";
29829
29829
 
29830
29830
  // src/geoms/plated-hole.ts
@@ -29996,19 +29996,19 @@ var platedHole = (plated_hole, ctx, options = {}) => {
29996
29996
  const holeWidth = plated_hole.hole_width || 0;
29997
29997
  const holeHeight = plated_hole.hole_height || 0;
29998
29998
  const copperBody = (() => {
29999
- const circle2 = (0, import_primitives4.cylinder)({
29999
+ const circle = (0, import_primitives4.cylinder)({
30000
30000
  center: [0, 0, 0],
30001
30001
  radius: 1,
30002
30002
  height: copperSpan + 0.01,
30003
30003
  segments: 64
30004
30004
  // High segment count for smooth ellipse
30005
30005
  });
30006
- const scaled = (0, import_transforms3.scale)([outerWidth / 2, outerHeight / 2, 1], circle2);
30006
+ const scaled = (0, import_transforms3.scale)([outerWidth / 2, outerHeight / 2, 1], circle);
30007
30007
  return (0, import_transforms4.translate)([plated_hole.x, plated_hole.y, 0], scaled);
30008
30008
  })();
30009
30009
  const copperSolid = maybeClip(copperBody, clipGeom);
30010
30010
  const drill = (() => {
30011
- const circle2 = (0, import_primitives4.cylinder)({
30011
+ const circle = (0, import_primitives4.cylinder)({
30012
30012
  center: [0, 0, 0],
30013
30013
  radius: 1,
30014
30014
  height: throughDrillHeight,
@@ -30017,7 +30017,7 @@ var platedHole = (plated_hole, ctx, options = {}) => {
30017
30017
  });
30018
30018
  const scaled = (0, import_transforms3.scale)(
30019
30019
  [Math.max(holeWidth / 2, 0.01), Math.max(holeHeight / 2, 0.01), 1],
30020
- circle2
30020
+ circle
30021
30021
  );
30022
30022
  return (0, import_transforms4.translate)([plated_hole.x, plated_hole.y, 0], scaled);
30023
30023
  })();
@@ -30379,526 +30379,12 @@ var platedHole = (plated_hole, ctx, options = {}) => {
30379
30379
  };
30380
30380
 
30381
30381
  // 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
30382
  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
- }
30383
+ var import_expansions2 = __toESM(require_expansions(), 1);
30898
30384
 
30899
30385
  // src/geoms/brep-converter.ts
30900
- var import_primitives9 = __toESM(require_primitives(), 1);
30901
- var import_booleans5 = __toESM(require_booleans(), 1);
30386
+ var import_primitives5 = __toESM(require_primitives(), 1);
30387
+ var import_booleans3 = __toESM(require_booleans(), 1);
30902
30388
  function segmentToPoints(p1, p2, bulge, arcSegments) {
30903
30389
  if (!bulge || Math.abs(bulge) < 1e-9) {
30904
30390
  return [];
@@ -30966,7 +30452,7 @@ function createGeom2FromBRep(brep, arcSegments = 16) {
30966
30452
  if (arePointsClockwise2(outerPoints)) {
30967
30453
  outerPoints.reverse();
30968
30454
  }
30969
- const outerGeom = (0, import_primitives9.polygon)({ points: outerPoints });
30455
+ const outerGeom = (0, import_primitives5.polygon)({ points: outerPoints });
30970
30456
  if (!brep.inner_rings || brep.inner_rings.length === 0) {
30971
30457
  return outerGeom;
30972
30458
  }
@@ -30975,16 +30461,16 @@ function createGeom2FromBRep(brep, arcSegments = 16) {
30975
30461
  if (arePointsClockwise2(innerPoints)) {
30976
30462
  innerPoints.reverse();
30977
30463
  }
30978
- return (0, import_primitives9.polygon)({ points: innerPoints });
30464
+ return (0, import_primitives5.polygon)({ points: innerPoints });
30979
30465
  });
30980
30466
  if (innerGeoms.length === 0) return outerGeom;
30981
- return (0, import_booleans5.subtract)(outerGeom, innerGeoms);
30467
+ return (0, import_booleans3.subtract)(outerGeom, innerGeoms);
30982
30468
  }
30983
30469
 
30984
30470
  // 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);
30471
+ var import_booleans4 = __toESM(require_booleans(), 1);
30472
+ var import_transforms5 = __toESM(require_transforms(), 1);
30473
+ var import_primitives6 = __toESM(require_primitives(), 1);
30988
30474
  function createViaCopper({
30989
30475
  x,
30990
30476
  y,
@@ -31003,34 +30489,34 @@ function createViaCopper({
31003
30489
  outerDiameter / 2,
31004
30490
  holeDiameter / 2 + platingThickness
31005
30491
  );
31006
- const barrel = (0, import_primitives10.cylinder)({
30492
+ const barrel = (0, import_primitives6.cylinder)({
31007
30493
  center: [0, 0, 0],
31008
30494
  radius: barrelRadius,
31009
30495
  height: thickness,
31010
30496
  segments: SMOOTH_CIRCLE_SEGMENTS
31011
30497
  });
31012
- const topPad = (0, import_primitives10.cylinder)({
30498
+ const topPad = (0, import_primitives6.cylinder)({
31013
30499
  center: [0, 0, thickness / 2],
31014
30500
  radius: outerDiameter / 2,
31015
30501
  height: padThickness,
31016
30502
  segments: SMOOTH_CIRCLE_SEGMENTS
31017
30503
  });
31018
- const bottomPad = (0, import_primitives10.cylinder)({
30504
+ const bottomPad = (0, import_primitives6.cylinder)({
31019
30505
  center: [0, 0, -thickness / 2],
31020
30506
  radius: outerDiameter / 2,
31021
30507
  height: padThickness,
31022
30508
  segments: SMOOTH_CIRCLE_SEGMENTS
31023
30509
  });
31024
- const viaSolid = (0, import_booleans6.union)([barrel, topPad, bottomPad]);
30510
+ const viaSolid = (0, import_booleans4.union)([barrel, topPad, bottomPad]);
31025
30511
  const drillHeight = thickness + padThickness * 2;
31026
- const drill = (0, import_primitives10.cylinder)({
30512
+ const drill = (0, import_primitives6.cylinder)({
31027
30513
  center: [0, 0, 0],
31028
30514
  radius: holeDiameter / 2,
31029
30515
  height: drillHeight,
31030
30516
  segments: SMOOTH_CIRCLE_SEGMENTS
31031
30517
  });
31032
- const finalViaCopper = (0, import_booleans6.subtract)(viaSolid, drill);
31033
- const positionedVia = (0, import_transforms9.translate)([x, y, 0], finalViaCopper);
30518
+ const finalViaCopper = (0, import_booleans4.subtract)(viaSolid, drill);
30519
+ const positionedVia = (0, import_transforms5.translate)([x, y, 0], finalViaCopper);
31034
30520
  return positionedVia;
31035
30521
  }
31036
30522
  function createViaBoardDrill({
@@ -31041,7 +30527,7 @@ function createViaBoardDrill({
31041
30527
  }) {
31042
30528
  const drillHeight = thickness * 1.5;
31043
30529
  const drillRadius = holeDiameter / 2 + M;
31044
- const drill = (0, import_primitives10.cylinder)({
30530
+ const drill = (0, import_primitives6.cylinder)({
31045
30531
  center: [x, y, 0],
31046
30532
  radius: drillRadius,
31047
30533
  height: drillHeight,
@@ -31057,15 +30543,15 @@ var BOARD_CLIP_XY_OUTSET = 0.05;
31057
30543
  var createCenteredRectPadGeom = (width10, height10, thickness, rectBorderRadius) => {
31058
30544
  const clampedRadius = clampRectBorderRadius(width10, height10, rectBorderRadius);
31059
30545
  if (clampedRadius <= 0) {
31060
- return (0, import_primitives11.cuboid)({ center: [0, 0, 0], size: [width10, height10, thickness] });
30546
+ return (0, import_primitives7.cuboid)({ center: [0, 0, 0], size: [width10, height10, thickness] });
31061
30547
  }
31062
- const rect2d = (0, import_primitives11.roundedRectangle)({
30548
+ const rect2d = (0, import_primitives7.roundedRectangle)({
31063
30549
  size: [width10, height10],
31064
30550
  roundRadius: clampedRadius,
31065
30551
  segments: PAD_ROUNDED_SEGMENTS
31066
30552
  });
31067
- const extruded = (0, import_extrusions8.extrudeLinear)({ height: thickness }, rect2d);
31068
- return (0, import_transforms10.translate)([0, 0, -thickness / 2], extruded);
30553
+ const extruded = (0, import_extrusions4.extrudeLinear)({ height: thickness }, rect2d);
30554
+ return (0, import_transforms6.translate)([0, 0, -thickness / 2], extruded);
31069
30555
  };
31070
30556
  var buildStateOrder = [
31071
30557
  "initializing",
@@ -31076,11 +30562,6 @@ var buildStateOrder = [
31076
30562
  "processing_cutouts",
31077
30563
  "processing_traces",
31078
30564
  "processing_vias",
31079
- "processing_silkscreen_text",
31080
- "processing_silkscreen_lines",
31081
- "processing_silkscreen_circles",
31082
- "processing_silkscreen_rects",
31083
- "processing_silkscreen_paths",
31084
30565
  "finalizing",
31085
30566
  "done"
31086
30567
  ];
@@ -31092,11 +30573,6 @@ var BoardGeomBuilder = class {
31092
30573
  pads;
31093
30574
  traces;
31094
30575
  pcb_vias;
31095
- silkscreenTexts;
31096
- silkscreenPaths;
31097
- silkscreenLines;
31098
- silkscreenCircles;
31099
- silkscreenRects;
31100
30576
  pcb_cutouts;
31101
30577
  pcb_copper_pours;
31102
30578
  boardGeom = null;
@@ -31105,11 +30581,6 @@ var BoardGeomBuilder = class {
31105
30581
  traceGeoms = [];
31106
30582
  viaGeoms = [];
31107
30583
  // Combined with platedHoleGeoms
31108
- silkscreenTextGeoms = [];
31109
- silkscreenPathGeoms = [];
31110
- silkscreenLineGeoms = [];
31111
- silkscreenCircleGeoms = [];
31112
- silkscreenRectGeoms = [];
31113
30584
  copperPourGeoms = [];
31114
30585
  boardClipGeom = null;
31115
30586
  state = "initializing";
@@ -31161,11 +30632,6 @@ var BoardGeomBuilder = class {
31161
30632
  this.pads = su3(circuitJson).pcb_smtpad.list();
31162
30633
  this.traces = su3(circuitJson).pcb_trace.list();
31163
30634
  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
30635
  this.pcb_cutouts = su3(circuitJson).pcb_cutout.list();
31170
30636
  this.pcb_copper_pours = circuitJson.filter(
31171
30637
  (e) => e.type === "pcb_copper_pour"
@@ -31190,11 +30656,11 @@ var BoardGeomBuilder = class {
31190
30656
  { xyOutset: BOARD_CLIP_XY_OUTSET }
31191
30657
  );
31192
30658
  } else {
31193
- this.boardGeom = (0, import_primitives11.cuboid)({
30659
+ this.boardGeom = (0, import_primitives7.cuboid)({
31194
30660
  size: [this.board.width, this.board.height, this.ctx.pcbThickness],
31195
30661
  center: [this.board.center.x, this.board.center.y, 0]
31196
30662
  });
31197
- this.boardClipGeom = (0, import_primitives11.cuboid)({
30663
+ this.boardClipGeom = (0, import_primitives7.cuboid)({
31198
30664
  size: [
31199
30665
  this.board.width + 2 * BOARD_CLIP_XY_OUTSET,
31200
30666
  this.board.height + 2 * BOARD_CLIP_XY_OUTSET,
@@ -31258,48 +30724,6 @@ var BoardGeomBuilder = class {
31258
30724
  this.goToNextState();
31259
30725
  }
31260
30726
  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
30727
  case "processing_cutouts":
31304
30728
  if (this.currentIndex < this.pcb_cutouts.length) {
31305
30729
  this.processCutout(this.pcb_cutouts[this.currentIndex]);
@@ -31336,31 +30760,31 @@ var BoardGeomBuilder = class {
31336
30760
  extractRectBorderRadius(cutout)
31337
30761
  );
31338
30762
  if (rectCornerRadius > 0) {
31339
- const rect2d = (0, import_primitives11.roundedRectangle)({
30763
+ const rect2d = (0, import_primitives7.roundedRectangle)({
31340
30764
  size: [cutout.width, cutout.height],
31341
30765
  roundRadius: rectCornerRadius,
31342
30766
  segments: PAD_ROUNDED_SEGMENTS
31343
30767
  });
31344
- cutoutGeom = (0, import_extrusions8.extrudeLinear)({ height: cutoutHeight }, rect2d);
31345
- cutoutGeom = (0, import_transforms10.translate)([0, 0, -cutoutHeight / 2], cutoutGeom);
30768
+ cutoutGeom = (0, import_extrusions4.extrudeLinear)({ height: cutoutHeight }, rect2d);
30769
+ cutoutGeom = (0, import_transforms6.translate)([0, 0, -cutoutHeight / 2], cutoutGeom);
31346
30770
  } else {
31347
- cutoutGeom = (0, import_primitives11.cuboid)({
30771
+ cutoutGeom = (0, import_primitives7.cuboid)({
31348
30772
  center: [0, 0, 0],
31349
30773
  size: [cutout.width, cutout.height, cutoutHeight]
31350
30774
  });
31351
30775
  }
31352
30776
  if (cutout.rotation) {
31353
30777
  const rotationRadians = cutout.rotation * Math.PI / 180;
31354
- cutoutGeom = (0, import_transforms10.rotateZ)(rotationRadians, cutoutGeom);
30778
+ cutoutGeom = (0, import_transforms6.rotateZ)(rotationRadians, cutoutGeom);
31355
30779
  }
31356
- cutoutGeom = (0, import_transforms10.translate)(
30780
+ cutoutGeom = (0, import_transforms6.translate)(
31357
30781
  [cutout.center.x, cutout.center.y, 0],
31358
30782
  cutoutGeom
31359
30783
  );
31360
30784
  break;
31361
30785
  }
31362
30786
  case "circle":
31363
- cutoutGeom = (0, import_primitives11.cylinder)({
30787
+ cutoutGeom = (0, import_primitives7.cylinder)({
31364
30788
  center: [cutout.center.x, cutout.center.y, 0],
31365
30789
  radius: cutout.radius,
31366
30790
  height: cutoutHeight
@@ -31377,14 +30801,14 @@ var BoardGeomBuilder = class {
31377
30801
  if (arePointsClockwise(pointsVec2)) {
31378
30802
  pointsVec2 = pointsVec2.reverse();
31379
30803
  }
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);
30804
+ const polygon2d = (0, import_primitives7.polygon)({ points: pointsVec2 });
30805
+ cutoutGeom = (0, import_extrusions4.extrudeLinear)({ height: cutoutHeight }, polygon2d);
30806
+ cutoutGeom = (0, import_transforms6.translate)([0, 0, -cutoutHeight / 2], cutoutGeom);
31383
30807
  break;
31384
30808
  }
31385
30809
  }
31386
30810
  if (cutoutGeom) {
31387
- this.boardGeom = (0, import_booleans7.subtract)(this.boardGeom, cutoutGeom);
30811
+ this.boardGeom = (0, import_booleans5.subtract)(this.boardGeom, cutoutGeom);
31388
30812
  }
31389
30813
  }
31390
30814
  processCopperPour(pour) {
@@ -31392,22 +30816,22 @@ var BoardGeomBuilder = class {
31392
30816
  const zPos = layerSign * this.ctx.pcbThickness / 2 + layerSign * BOARD_SURFACE_OFFSET.copper;
31393
30817
  let pourGeom = null;
31394
30818
  if (pour.shape === "rect") {
31395
- let baseGeom = (0, import_primitives11.cuboid)({
30819
+ let baseGeom = (0, import_primitives7.cuboid)({
31396
30820
  center: [0, 0, 0],
31397
30821
  // Create at origin for rotation
31398
30822
  size: [pour.width, pour.height, M]
31399
30823
  });
31400
30824
  if ("rotation" in pour && pour.rotation) {
31401
30825
  const rotationRadians = pour.rotation * Math.PI / 180;
31402
- baseGeom = (0, import_transforms10.rotateZ)(rotationRadians, baseGeom);
30826
+ baseGeom = (0, import_transforms6.rotateZ)(rotationRadians, baseGeom);
31403
30827
  }
31404
- pourGeom = (0, import_transforms10.translate)([pour.center.x, pour.center.y, zPos], baseGeom);
30828
+ pourGeom = (0, import_transforms6.translate)([pour.center.x, pour.center.y, zPos], baseGeom);
31405
30829
  } else if (pour.shape === "brep") {
31406
30830
  const brepShape = pour.brep_shape;
31407
30831
  if (brepShape?.outer_ring) {
31408
30832
  const pourGeom2 = createGeom2FromBRep(brepShape);
31409
- pourGeom = (0, import_extrusions8.extrudeLinear)({ height: M }, pourGeom2);
31410
- pourGeom = (0, import_transforms10.translate)([0, 0, zPos], pourGeom);
30833
+ pourGeom = (0, import_extrusions4.extrudeLinear)({ height: M }, pourGeom2);
30834
+ pourGeom = (0, import_transforms6.translate)([0, 0, zPos], pourGeom);
31411
30835
  }
31412
30836
  } else if (pour.shape === "polygon") {
31413
30837
  let pointsVec2 = pour.points.map((p) => [p.x, p.y]);
@@ -31420,17 +30844,17 @@ var BoardGeomBuilder = class {
31420
30844
  if (arePointsClockwise(pointsVec2)) {
31421
30845
  pointsVec2 = pointsVec2.reverse();
31422
30846
  }
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);
30847
+ const polygon2d = (0, import_primitives7.polygon)({ points: pointsVec2 });
30848
+ pourGeom = (0, import_extrusions4.extrudeLinear)({ height: M }, polygon2d);
30849
+ pourGeom = (0, import_transforms6.translate)([0, 0, zPos], pourGeom);
31426
30850
  }
31427
30851
  if (pourGeom) {
31428
30852
  if (this.boardClipGeom) {
31429
- pourGeom = (0, import_booleans7.intersect)(this.boardClipGeom, pourGeom);
30853
+ pourGeom = (0, import_booleans5.intersect)(this.boardClipGeom, pourGeom);
31430
30854
  }
31431
30855
  const covered = pour.covered_with_solder_mask !== false;
31432
30856
  const pourMaterialColor = covered ? tracesMaterialColors[this.board.material] ?? colors.fr4TracesWithoutMaskTan : colors.copper;
31433
- const coloredPourGeom = (0, import_colors7.colorize)(pourMaterialColor, pourGeom);
30857
+ const coloredPourGeom = (0, import_colors3.colorize)(pourMaterialColor, pourGeom);
31434
30858
  this.copperPourGeoms.push(coloredPourGeom);
31435
30859
  }
31436
30860
  }
@@ -31439,7 +30863,7 @@ var BoardGeomBuilder = class {
31439
30863
  if (ph.shape === "circle" || ph.shape === "circular_hole_with_rect_pad") {
31440
30864
  let cyGeom = null;
31441
30865
  if (ph.shape === "circular_hole_with_rect_pad") {
31442
- cyGeom = (0, import_primitives11.cylinder)({
30866
+ cyGeom = (0, import_primitives7.cylinder)({
31443
30867
  center: [
31444
30868
  ph.x + (ph.hole_offset_x || 0),
31445
30869
  ph.y + (ph.hole_offset_y || 0),
@@ -31451,7 +30875,7 @@ var BoardGeomBuilder = class {
31451
30875
  // Ensure it cuts through
31452
30876
  });
31453
30877
  } else {
31454
- cyGeom = (0, import_primitives11.cylinder)({
30878
+ cyGeom = (0, import_primitives7.cylinder)({
31455
30879
  center: [ph.x, ph.y, 0],
31456
30880
  radius: ph.hole_diameter / 2 + M,
31457
30881
  // Add margin for subtraction
@@ -31460,10 +30884,10 @@ var BoardGeomBuilder = class {
31460
30884
  });
31461
30885
  }
31462
30886
  if (!opts.dontCutBoard) {
31463
- this.boardGeom = (0, import_booleans7.subtract)(this.boardGeom, cyGeom);
30887
+ this.boardGeom = (0, import_booleans5.subtract)(this.boardGeom, cyGeom);
31464
30888
  }
31465
30889
  this.padGeoms = this.padGeoms.map(
31466
- (pg) => (0, import_colors7.colorize)(colors.copper, (0, import_booleans7.subtract)(pg, cyGeom))
30890
+ (pg) => (0, import_colors3.colorize)(colors.copper, (0, import_booleans5.subtract)(pg, cyGeom))
31467
30891
  );
31468
30892
  const platedHoleGeom = platedHole(ph, this.ctx, {
31469
30893
  clipGeom: this.boardClipGeom
@@ -31476,17 +30900,17 @@ var BoardGeomBuilder = class {
31476
30900
  const holeRadius = holeHeight / 2;
31477
30901
  const rectLength = Math.abs(holeWidth - holeHeight);
31478
30902
  let pillHole;
31479
- pillHole = (0, import_booleans7.union)(
31480
- (0, import_primitives11.cuboid)({
30903
+ pillHole = (0, import_booleans5.union)(
30904
+ (0, import_primitives7.cuboid)({
31481
30905
  center: [ph.x, ph.y, 0],
31482
30906
  size: shouldRotate ? [holeHeight, rectLength, this.ctx.pcbThickness * 1.5] : [rectLength, holeHeight, this.ctx.pcbThickness * 1.5]
31483
30907
  }),
31484
- (0, import_primitives11.cylinder)({
30908
+ (0, import_primitives7.cylinder)({
31485
30909
  center: shouldRotate ? [ph.x, ph.y - rectLength / 2, 0] : [ph.x - rectLength / 2, ph.y, 0],
31486
30910
  radius: holeRadius,
31487
30911
  height: this.ctx.pcbThickness * 1.5
31488
30912
  }),
31489
- (0, import_primitives11.cylinder)({
30913
+ (0, import_primitives7.cylinder)({
31490
30914
  center: shouldRotate ? [ph.x, ph.y + rectLength / 2, 0] : [ph.x + rectLength / 2, ph.y, 0],
31491
30915
  radius: holeRadius,
31492
30916
  height: this.ctx.pcbThickness * 1.5
@@ -31494,16 +30918,16 @@ var BoardGeomBuilder = class {
31494
30918
  );
31495
30919
  if (ph.ccw_rotation) {
31496
30920
  const rotationRadians = ph.ccw_rotation * Math.PI / 180;
31497
- pillHole = (0, import_transforms10.translate)(
30921
+ pillHole = (0, import_transforms6.translate)(
31498
30922
  [ph.x, ph.y, 0],
31499
- (0, import_transforms10.rotateZ)(rotationRadians, (0, import_transforms10.translate)([-ph.x, -ph.y, 0], pillHole))
30923
+ (0, import_transforms6.rotateZ)(rotationRadians, (0, import_transforms6.translate)([-ph.x, -ph.y, 0], pillHole))
31500
30924
  );
31501
30925
  }
31502
30926
  if (!opts.dontCutBoard) {
31503
- this.boardGeom = (0, import_booleans7.subtract)(this.boardGeom, pillHole);
30927
+ this.boardGeom = (0, import_booleans5.subtract)(this.boardGeom, pillHole);
31504
30928
  }
31505
30929
  this.padGeoms = this.padGeoms.map(
31506
- (pg) => (0, import_colors7.colorize)(colors.copper, (0, import_booleans7.subtract)(pg, pillHole))
30930
+ (pg) => (0, import_colors3.colorize)(colors.copper, (0, import_booleans5.subtract)(pg, pillHole))
31507
30931
  );
31508
30932
  const platedHoleGeom = platedHole(ph, this.ctx, {
31509
30933
  clipGeom: this.boardClipGeom
@@ -31516,8 +30940,8 @@ var BoardGeomBuilder = class {
31516
30940
  const holeRadius = holeHeight / 2;
31517
30941
  const rectLength = Math.abs(holeWidth - holeHeight);
31518
30942
  let pillHole;
31519
- pillHole = (0, import_booleans7.union)(
31520
- (0, import_primitives11.cuboid)({
30943
+ pillHole = (0, import_booleans5.union)(
30944
+ (0, import_primitives7.cuboid)({
31521
30945
  center: [
31522
30946
  ph.x + (ph.hole_offset_x || 0),
31523
30947
  ph.y + (ph.hole_offset_y || 0),
@@ -31525,7 +30949,7 @@ var BoardGeomBuilder = class {
31525
30949
  ],
31526
30950
  size: shouldRotate ? [holeHeight, rectLength, this.ctx.pcbThickness * 1.5] : [rectLength, holeHeight, this.ctx.pcbThickness * 1.5]
31527
30951
  }),
31528
- (0, import_primitives11.cylinder)({
30952
+ (0, import_primitives7.cylinder)({
31529
30953
  center: shouldRotate ? [
31530
30954
  ph.x + (ph.hole_offset_x || 0),
31531
30955
  ph.y + (ph.hole_offset_y || 0) - rectLength / 2,
@@ -31538,7 +30962,7 @@ var BoardGeomBuilder = class {
31538
30962
  radius: holeRadius,
31539
30963
  height: this.ctx.pcbThickness * 1.5
31540
30964
  }),
31541
- (0, import_primitives11.cylinder)({
30965
+ (0, import_primitives7.cylinder)({
31542
30966
  center: shouldRotate ? [
31543
30967
  ph.x + (ph.hole_offset_x || 0),
31544
30968
  ph.y + (ph.hole_offset_y || 0) + rectLength / 2,
@@ -31553,10 +30977,10 @@ var BoardGeomBuilder = class {
31553
30977
  })
31554
30978
  );
31555
30979
  if (!opts.dontCutBoard) {
31556
- this.boardGeom = (0, import_booleans7.subtract)(this.boardGeom, pillHole);
30980
+ this.boardGeom = (0, import_booleans5.subtract)(this.boardGeom, pillHole);
31557
30981
  }
31558
30982
  this.padGeoms = this.padGeoms.map(
31559
- (pg) => (0, import_colors7.colorize)(colors.copper, (0, import_booleans7.subtract)(pg, pillHole))
30983
+ (pg) => (0, import_colors3.colorize)(colors.copper, (0, import_booleans5.subtract)(pg, pillHole))
31560
30984
  );
31561
30985
  const platedHoleGeom = platedHole(ph, this.ctx, {
31562
30986
  clipGeom: this.boardClipGeom
@@ -31576,13 +31000,13 @@ var BoardGeomBuilder = class {
31576
31000
  });
31577
31001
  if (!boardHole || !copperHole) return;
31578
31002
  if (!opts.dontCutBoard) {
31579
- this.boardGeom = (0, import_booleans7.subtract)(this.boardGeom, boardHole);
31003
+ this.boardGeom = (0, import_booleans5.subtract)(this.boardGeom, boardHole);
31580
31004
  }
31581
31005
  this.padGeoms = this.padGeoms.map(
31582
- (pg) => (0, import_colors7.colorize)(colors.copper, (0, import_booleans7.subtract)(pg, boardHole))
31006
+ (pg) => (0, import_colors3.colorize)(colors.copper, (0, import_booleans5.subtract)(pg, boardHole))
31583
31007
  );
31584
31008
  this.platedHoleGeoms = this.platedHoleGeoms.map(
31585
- (phg) => (0, import_colors7.colorize)(colors.copper, (0, import_booleans7.subtract)(phg, copperHole))
31009
+ (phg) => (0, import_colors3.colorize)(colors.copper, (0, import_booleans5.subtract)(phg, copperHole))
31586
31010
  );
31587
31011
  const platedHoleGeom = platedHole(ph, this.ctx, {
31588
31012
  clipGeom: this.boardClipGeom
@@ -31595,22 +31019,22 @@ var BoardGeomBuilder = class {
31595
31019
  const holeDepth = this.ctx.pcbThickness * 1.5;
31596
31020
  const copperInset = 0.02;
31597
31021
  if (hole.hole_shape === "round" || hole.hole_shape === "circle") {
31598
- const cyGeom = (0, import_primitives11.cylinder)({
31022
+ const cyGeom = (0, import_primitives7.cylinder)({
31599
31023
  center: [hole.x, hole.y, 0],
31600
31024
  radius: hole.hole_diameter / 2 + M,
31601
31025
  height: holeDepth
31602
31026
  });
31603
- this.boardGeom = (0, import_booleans7.subtract)(this.boardGeom, cyGeom);
31027
+ this.boardGeom = (0, import_booleans5.subtract)(this.boardGeom, cyGeom);
31604
31028
  this.padGeoms = this.padGeoms.map(
31605
- (pg) => (0, import_colors7.colorize)(colors.copper, (0, import_booleans7.subtract)(pg, cyGeom))
31029
+ (pg) => (0, import_colors3.colorize)(colors.copper, (0, import_booleans5.subtract)(pg, cyGeom))
31606
31030
  );
31607
- const copperCut = (0, import_primitives11.cylinder)({
31031
+ const copperCut = (0, import_primitives7.cylinder)({
31608
31032
  center: [hole.x, hole.y, 0],
31609
31033
  radius: hole.hole_diameter / 2 + M / 2,
31610
31034
  height: holeDepth
31611
31035
  });
31612
31036
  this.platedHoleGeoms = this.platedHoleGeoms.map(
31613
- (phg) => (0, import_colors7.colorize)(colors.copper, (0, import_booleans7.subtract)(phg, copperCut))
31037
+ (phg) => (0, import_colors3.colorize)(colors.copper, (0, import_booleans5.subtract)(phg, copperCut))
31614
31038
  );
31615
31039
  } else if (hole.hole_shape === "pill" || hole.hole_shape === "rotated_pill") {
31616
31040
  const holeWidth = hole.hole_width;
@@ -31620,34 +31044,34 @@ var BoardGeomBuilder = class {
31620
31044
  const isRotated = hole.hole_shape === "rotated_pill";
31621
31045
  let pillHole;
31622
31046
  if (holeWidth > holeHeight) {
31623
- pillHole = (0, import_booleans7.union)(
31624
- (0, import_primitives11.cuboid)({
31047
+ pillHole = (0, import_booleans5.union)(
31048
+ (0, import_primitives7.cuboid)({
31625
31049
  center: [hole.x, hole.y, 0],
31626
31050
  size: [rectLength, holeHeight, holeDepth]
31627
31051
  }),
31628
- (0, import_primitives11.cylinder)({
31052
+ (0, import_primitives7.cylinder)({
31629
31053
  center: [hole.x - rectLength / 2, hole.y, 0],
31630
31054
  radius: holeRadius,
31631
31055
  height: holeDepth
31632
31056
  }),
31633
- (0, import_primitives11.cylinder)({
31057
+ (0, import_primitives7.cylinder)({
31634
31058
  center: [hole.x + rectLength / 2, hole.y, 0],
31635
31059
  radius: holeRadius,
31636
31060
  height: holeDepth
31637
31061
  })
31638
31062
  );
31639
31063
  } else {
31640
- pillHole = (0, import_booleans7.union)(
31641
- (0, import_primitives11.cuboid)({
31064
+ pillHole = (0, import_booleans5.union)(
31065
+ (0, import_primitives7.cuboid)({
31642
31066
  center: [hole.x, hole.y, 0],
31643
31067
  size: [holeWidth, rectLength, holeDepth]
31644
31068
  }),
31645
- (0, import_primitives11.cylinder)({
31069
+ (0, import_primitives7.cylinder)({
31646
31070
  center: [hole.x, hole.y - rectLength / 2, 0],
31647
31071
  radius: holeRadius,
31648
31072
  height: holeDepth
31649
31073
  }),
31650
- (0, import_primitives11.cylinder)({
31074
+ (0, import_primitives7.cylinder)({
31651
31075
  center: [hole.x, hole.y + rectLength / 2, 0],
31652
31076
  radius: holeRadius,
31653
31077
  height: holeDepth
@@ -31656,15 +31080,15 @@ var BoardGeomBuilder = class {
31656
31080
  }
31657
31081
  if (isRotated) {
31658
31082
  const rotationRadians = hole.ccw_rotation * Math.PI / 180;
31659
- pillHole = (0, import_transforms10.rotateZ)(rotationRadians, pillHole);
31083
+ pillHole = (0, import_transforms6.rotateZ)(rotationRadians, pillHole);
31660
31084
  }
31661
- this.boardGeom = (0, import_booleans7.subtract)(this.boardGeom, pillHole);
31085
+ this.boardGeom = (0, import_booleans5.subtract)(this.boardGeom, pillHole);
31662
31086
  this.padGeoms = this.padGeoms.map(
31663
- (pg) => (0, import_colors7.colorize)(colors.copper, (0, import_booleans7.subtract)(pg, pillHole))
31087
+ (pg) => (0, import_colors3.colorize)(colors.copper, (0, import_booleans5.subtract)(pg, pillHole))
31664
31088
  );
31665
- const copperPill = (0, import_expansions4.expand)({ delta: -copperInset }, pillHole);
31089
+ const copperPill = (0, import_expansions2.expand)({ delta: -copperInset }, pillHole);
31666
31090
  this.platedHoleGeoms = this.platedHoleGeoms.map(
31667
- (phg) => (0, import_colors7.colorize)(colors.copper, (0, import_booleans7.subtract)(phg, copperPill))
31091
+ (phg) => (0, import_colors3.colorize)(colors.copper, (0, import_booleans5.subtract)(phg, copperPill))
31668
31092
  );
31669
31093
  }
31670
31094
  }
@@ -31679,12 +31103,12 @@ var BoardGeomBuilder = class {
31679
31103
  M,
31680
31104
  rectBorderRadius
31681
31105
  );
31682
- const positionedPadGeom = (0, import_transforms10.translate)([pad2.x, pad2.y, zPos], basePadGeom);
31106
+ const positionedPadGeom = (0, import_transforms6.translate)([pad2.x, pad2.y, zPos], basePadGeom);
31683
31107
  let finalPadGeom = positionedPadGeom;
31684
31108
  if (this.boardClipGeom) {
31685
- finalPadGeom = (0, import_booleans7.intersect)(this.boardClipGeom, finalPadGeom);
31109
+ finalPadGeom = (0, import_booleans5.intersect)(this.boardClipGeom, finalPadGeom);
31686
31110
  }
31687
- finalPadGeom = (0, import_colors7.colorize)(colors.copper, finalPadGeom);
31111
+ finalPadGeom = (0, import_colors3.colorize)(colors.copper, finalPadGeom);
31688
31112
  this.padGeoms.push(finalPadGeom);
31689
31113
  } else if (pad2.shape === "rotated_rect") {
31690
31114
  let basePadGeom = createCenteredRectPadGeom(
@@ -31694,24 +31118,24 @@ var BoardGeomBuilder = class {
31694
31118
  rectBorderRadius
31695
31119
  );
31696
31120
  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);
31121
+ basePadGeom = (0, import_transforms6.rotateZ)(rotationRadians, basePadGeom);
31122
+ const positionedPadGeom = (0, import_transforms6.translate)([pad2.x, pad2.y, zPos], basePadGeom);
31699
31123
  let finalPadGeom = positionedPadGeom;
31700
31124
  if (this.boardClipGeom) {
31701
- finalPadGeom = (0, import_booleans7.intersect)(this.boardClipGeom, finalPadGeom);
31125
+ finalPadGeom = (0, import_booleans5.intersect)(this.boardClipGeom, finalPadGeom);
31702
31126
  }
31703
- finalPadGeom = (0, import_colors7.colorize)(colors.copper, finalPadGeom);
31127
+ finalPadGeom = (0, import_colors3.colorize)(colors.copper, finalPadGeom);
31704
31128
  this.padGeoms.push(finalPadGeom);
31705
31129
  } else if (pad2.shape === "circle") {
31706
- let padGeom = (0, import_primitives11.cylinder)({
31130
+ let padGeom = (0, import_primitives7.cylinder)({
31707
31131
  center: [pad2.x, pad2.y, zPos],
31708
31132
  radius: pad2.radius,
31709
31133
  height: M
31710
31134
  });
31711
31135
  if (this.boardClipGeom) {
31712
- padGeom = (0, import_booleans7.intersect)(this.boardClipGeom, padGeom);
31136
+ padGeom = (0, import_booleans5.intersect)(this.boardClipGeom, padGeom);
31713
31137
  }
31714
- padGeom = (0, import_colors7.colorize)(colors.copper, padGeom);
31138
+ padGeom = (0, import_colors3.colorize)(colors.copper, padGeom);
31715
31139
  this.padGeoms.push(padGeom);
31716
31140
  }
31717
31141
  }
@@ -31724,15 +31148,16 @@ var BoardGeomBuilder = class {
31724
31148
  const finishSegment = () => {
31725
31149
  if (currentSegmentPoints.length >= 2 && currentLayer) {
31726
31150
  const layerSign = currentLayer === "bottom" ? -1 : 1;
31727
- const zCenter = layerSign * this.ctx.pcbThickness / 2 + layerSign * BOARD_SURFACE_OFFSET.traces;
31728
- const linePath = (0, import_primitives11.line)(currentSegmentPoints);
31729
- const expandedPath = (0, import_expansions4.expand)(
31151
+ const traceOffset = BOARD_SURFACE_OFFSET.traces - 2e-3;
31152
+ const zCenter = layerSign * this.ctx.pcbThickness / 2 + layerSign * traceOffset;
31153
+ const linePath = (0, import_primitives7.line)(currentSegmentPoints);
31154
+ const expandedPath = (0, import_expansions2.expand)(
31730
31155
  { delta: currentWidth / 2, corners: "round" },
31731
31156
  linePath
31732
31157
  );
31733
- let traceGeom = (0, import_transforms10.translate)(
31158
+ let traceGeom = (0, import_transforms6.translate)(
31734
31159
  [0, 0, zCenter - M / 2],
31735
- (0, import_extrusions8.extrudeLinear)({ height: M }, expandedPath)
31160
+ (0, import_extrusions4.extrudeLinear)({ height: M }, expandedPath)
31736
31161
  );
31737
31162
  const startPointCoords = currentSegmentPoints[0];
31738
31163
  const endPointCoords = currentSegmentPoints[currentSegmentPoints.length - 1];
@@ -31741,27 +31166,27 @@ var BoardGeomBuilder = class {
31741
31166
  startPointCoords[1]
31742
31167
  );
31743
31168
  if (startHole) {
31744
- const cuttingCylinder = (0, import_primitives11.cylinder)({
31169
+ const cuttingCylinder = (0, import_primitives7.cylinder)({
31745
31170
  center: [startPointCoords[0], startPointCoords[1], zCenter],
31746
31171
  radius: startHole.diameter / 2 + M,
31747
31172
  height: M
31748
31173
  });
31749
- traceGeom = (0, import_booleans7.subtract)(traceGeom, cuttingCylinder);
31174
+ traceGeom = (0, import_booleans5.subtract)(traceGeom, cuttingCylinder);
31750
31175
  }
31751
31176
  const endHole = this.getHoleToCut(endPointCoords[0], endPointCoords[1]);
31752
31177
  if (endHole) {
31753
- const cuttingCylinder = (0, import_primitives11.cylinder)({
31178
+ const cuttingCylinder = (0, import_primitives7.cylinder)({
31754
31179
  center: [endPointCoords[0], endPointCoords[1], zCenter],
31755
31180
  radius: endHole.diameter / 2 + M,
31756
31181
  height: M
31757
31182
  });
31758
- traceGeom = (0, import_booleans7.subtract)(traceGeom, cuttingCylinder);
31183
+ traceGeom = (0, import_booleans5.subtract)(traceGeom, cuttingCylinder);
31759
31184
  }
31760
31185
  const tracesMaterialColor = tracesMaterialColors[this.board.material] ?? colors.fr4TracesWithoutMaskTan;
31761
31186
  if (this.boardClipGeom) {
31762
- traceGeom = (0, import_booleans7.intersect)(this.boardClipGeom, traceGeom);
31187
+ traceGeom = (0, import_booleans5.intersect)(this.boardClipGeom, traceGeom);
31763
31188
  }
31764
- traceGeom = (0, import_colors7.colorize)(tracesMaterialColor, traceGeom);
31189
+ traceGeom = (0, import_colors3.colorize)(tracesMaterialColor, traceGeom);
31765
31190
  this.traceGeoms.push(traceGeom);
31766
31191
  }
31767
31192
  currentSegmentPoints = [];
@@ -31813,8 +31238,8 @@ var BoardGeomBuilder = class {
31813
31238
  });
31814
31239
  let finalViaGeom = viaCopperGeom;
31815
31240
  if (this.boardClipGeom) {
31816
- finalViaGeom = (0, import_booleans7.intersect)(this.boardClipGeom, viaCopperGeom);
31817
- finalViaGeom = (0, import_colors7.colorize)(colors.copper, finalViaGeom);
31241
+ finalViaGeom = (0, import_booleans5.intersect)(this.boardClipGeom, viaCopperGeom);
31242
+ finalViaGeom = (0, import_colors3.colorize)(colors.copper, finalViaGeom);
31818
31243
  }
31819
31244
  this.viaGeoms.push(finalViaGeom);
31820
31245
  }
@@ -31825,87 +31250,23 @@ var BoardGeomBuilder = class {
31825
31250
  holeDiameter: via.hole_diameter,
31826
31251
  thickness: this.ctx.pcbThickness
31827
31252
  });
31828
- this.boardGeom = (0, import_booleans7.subtract)(this.boardGeom, viaDrill);
31253
+ this.boardGeom = (0, import_booleans5.subtract)(this.boardGeom, viaDrill);
31829
31254
  this.padGeoms = this.padGeoms.map(
31830
- (pg) => (0, import_colors7.colorize)(colors.copper, (0, import_booleans7.subtract)(pg, viaDrill))
31255
+ (pg) => (0, import_colors3.colorize)(colors.copper, (0, import_booleans5.subtract)(pg, viaDrill))
31831
31256
  );
31832
31257
  }
31833
31258
  }
31834
- processSilkscreenText(st) {
31835
- const { textOutlines, xOffset, yOffset } = createSilkscreenTextGeoms(st);
31836
- for (const outline of textOutlines) {
31837
- const alignedOutline = outline.map((point2) => [
31838
- point2[0] + xOffset + st.anchor_position.x,
31839
- point2[1] + yOffset + st.anchor_position.y
31840
- ]);
31841
- const textPath = (0, import_primitives11.line)(alignedOutline);
31842
- const fontSize = st.font_size || 0.25;
31843
- const expansionDelta = Math.min(
31844
- Math.max(0.01, fontSize * 0.1),
31845
- fontSize * 0.05
31846
- );
31847
- const expandedPath = (0, import_expansions4.expand)(
31848
- { delta: expansionDelta, corners: "round" },
31849
- textPath
31850
- );
31851
- let textGeom;
31852
- if (st.layer === "bottom") {
31853
- textGeom = (0, import_transforms10.translate)(
31854
- [0, 0, -this.ctx.pcbThickness / 2 - M],
31855
- // Position above board
31856
- (0, import_extrusions8.extrudeLinear)({ height: 0.012 }, expandedPath)
31857
- );
31858
- } else {
31859
- textGeom = (0, import_transforms10.translate)(
31860
- [0, 0, this.ctx.pcbThickness / 2 + M],
31861
- // Position above board
31862
- (0, import_extrusions8.extrudeLinear)({ height: 0.012 }, expandedPath)
31863
- );
31864
- }
31865
- textGeom = (0, import_colors7.colorize)([1, 1, 1], textGeom);
31866
- this.silkscreenTextGeoms.push(textGeom);
31867
- }
31868
- }
31869
- processSilkscreenPath(sp) {
31870
- const pathGeom = createSilkscreenPathGeom(sp, this.ctx);
31871
- if (pathGeom) {
31872
- this.silkscreenPathGeoms.push(pathGeom);
31873
- }
31874
- }
31875
- processSilkscreenLine(sl) {
31876
- const lineGeom = createSilkscreenLineGeom(sl, this.ctx);
31877
- if (lineGeom) {
31878
- this.silkscreenLineGeoms.push(lineGeom);
31879
- }
31880
- }
31881
- processSilkscreenCircle(sc) {
31882
- const circleGeom = createSilkscreenCircleGeom(sc, this.ctx);
31883
- if (circleGeom) {
31884
- this.silkscreenCircleGeoms.push(circleGeom);
31885
- }
31886
- }
31887
- processSilkscreenRect(sr) {
31888
- const rectGeom = createSilkscreenRectGeom(sr, this.ctx);
31889
- if (rectGeom) {
31890
- this.silkscreenRectGeoms.push(rectGeom);
31891
- }
31892
- }
31893
31259
  finalize() {
31894
31260
  if (!this.boardGeom) return;
31895
31261
  const boardMaterialColor = boardMaterialColors[this.board.material] ?? colors.fr4Tan;
31896
- this.boardGeom = (0, import_colors7.colorize)(boardMaterialColor, this.boardGeom);
31262
+ this.boardGeom = (0, import_colors3.colorize)(boardMaterialColor, this.boardGeom);
31897
31263
  this.finalGeoms = [
31898
31264
  this.boardGeom,
31899
31265
  ...this.platedHoleGeoms,
31900
31266
  ...this.padGeoms,
31901
31267
  ...this.traceGeoms,
31902
31268
  ...this.viaGeoms,
31903
- ...this.copperPourGeoms,
31904
- ...this.silkscreenTextGeoms,
31905
- ...this.silkscreenLineGeoms,
31906
- ...this.silkscreenCircleGeoms,
31907
- ...this.silkscreenRectGeoms,
31908
- ...this.silkscreenPathGeoms
31269
+ ...this.copperPourGeoms
31909
31270
  ];
31910
31271
  if (this.onCompleteCallback) {
31911
31272
  this.onCompleteCallback(this.finalGeoms);
@@ -32257,7 +31618,7 @@ var ThreeErrorBoundary = class extends React11.Component {
32257
31618
 
32258
31619
  // src/three-components/JscadBoardTextures.tsx
32259
31620
  import { useEffect as useEffect22, useMemo as useMemo19 } from "react";
32260
- import * as THREE21 from "three";
31621
+ import * as THREE22 from "three";
32261
31622
  import { su as su8 } from "@tscircuit/circuit-json-util";
32262
31623
 
32263
31624
  // src/utils/soldermask-texture.ts
@@ -32759,9 +32120,268 @@ function createSoldermaskTextureForLayer({
32759
32120
  }
32760
32121
 
32761
32122
  // src/utils/silkscreen-texture.ts
32762
- var import_text2 = __toESM(require_text(), 1);
32123
+ var import_text = __toESM(require_text(), 1);
32763
32124
  import * as THREE19 from "three";
32125
+
32126
+ // node_modules/transformation-matrix/src/applyToPoint.js
32127
+ function applyToPoint(matrix, point2) {
32128
+ return Array.isArray(point2) ? [
32129
+ matrix.a * point2[0] + matrix.c * point2[1] + matrix.e,
32130
+ matrix.b * point2[0] + matrix.d * point2[1] + matrix.f
32131
+ ] : {
32132
+ x: matrix.a * point2.x + matrix.c * point2.y + matrix.e,
32133
+ y: matrix.b * point2.x + matrix.d * point2.y + matrix.f
32134
+ };
32135
+ }
32136
+
32137
+ // node_modules/transformation-matrix/src/utils.js
32138
+ function isUndefined(val) {
32139
+ return typeof val === "undefined";
32140
+ }
32141
+
32142
+ // node_modules/transformation-matrix/src/translate.js
32143
+ function translate6(tx, ty = 0) {
32144
+ return {
32145
+ a: 1,
32146
+ c: 0,
32147
+ e: tx,
32148
+ b: 0,
32149
+ d: 1,
32150
+ f: ty
32151
+ };
32152
+ }
32153
+
32154
+ // node_modules/transformation-matrix/src/transform.js
32155
+ function transform(...matrices) {
32156
+ matrices = Array.isArray(matrices[0]) ? matrices[0] : matrices;
32157
+ const multiply = (m1, m2) => {
32158
+ return {
32159
+ a: m1.a * m2.a + m1.c * m2.b,
32160
+ c: m1.a * m2.c + m1.c * m2.d,
32161
+ e: m1.a * m2.e + m1.c * m2.f + m1.e,
32162
+ b: m1.b * m2.a + m1.d * m2.b,
32163
+ d: m1.b * m2.c + m1.d * m2.d,
32164
+ f: m1.b * m2.e + m1.d * m2.f + m1.f
32165
+ };
32166
+ };
32167
+ switch (matrices.length) {
32168
+ case 0:
32169
+ throw new Error("no matrices provided");
32170
+ case 1:
32171
+ return matrices[0];
32172
+ case 2:
32173
+ return multiply(matrices[0], matrices[1]);
32174
+ default: {
32175
+ const [m1, m2, ...rest] = matrices;
32176
+ const m = multiply(m1, m2);
32177
+ return transform(m, ...rest);
32178
+ }
32179
+ }
32180
+ }
32181
+ function compose(...matrices) {
32182
+ return transform(...matrices);
32183
+ }
32184
+
32185
+ // node_modules/transformation-matrix/src/rotate.js
32186
+ var { cos, sin, PI } = Math;
32187
+ function rotate2(angle, cx, cy) {
32188
+ const cosAngle = cos(angle);
32189
+ const sinAngle = sin(angle);
32190
+ const rotationMatrix = {
32191
+ a: cosAngle,
32192
+ c: -sinAngle,
32193
+ e: 0,
32194
+ b: sinAngle,
32195
+ d: cosAngle,
32196
+ f: 0
32197
+ };
32198
+ if (isUndefined(cx) || isUndefined(cy)) {
32199
+ return rotationMatrix;
32200
+ }
32201
+ return transform([
32202
+ translate6(cx, cy),
32203
+ rotationMatrix,
32204
+ translate6(-cx, -cy)
32205
+ ]);
32206
+ }
32207
+
32208
+ // node_modules/transformation-matrix/src/skew.js
32209
+ var { tan } = Math;
32210
+
32211
+ // node_modules/transformation-matrix/src/fromTransformAttribute.autogenerated.js
32212
+ function peg$subclass(child, parent) {
32213
+ function C() {
32214
+ this.constructor = child;
32215
+ }
32216
+ C.prototype = parent.prototype;
32217
+ child.prototype = new C();
32218
+ }
32219
+ function peg$SyntaxError(message, expected, found, location) {
32220
+ var self = Error.call(this, message);
32221
+ if (Object.setPrototypeOf) {
32222
+ Object.setPrototypeOf(self, peg$SyntaxError.prototype);
32223
+ }
32224
+ self.expected = expected;
32225
+ self.found = found;
32226
+ self.location = location;
32227
+ self.name = "SyntaxError";
32228
+ return self;
32229
+ }
32230
+ peg$subclass(peg$SyntaxError, Error);
32231
+ function peg$padEnd(str, targetLength, padString) {
32232
+ padString = padString || " ";
32233
+ if (str.length > targetLength) {
32234
+ return str;
32235
+ }
32236
+ targetLength -= str.length;
32237
+ padString += padString.repeat(targetLength);
32238
+ return str + padString.slice(0, targetLength);
32239
+ }
32240
+ peg$SyntaxError.prototype.format = function(sources) {
32241
+ var str = "Error: " + this.message;
32242
+ if (this.location) {
32243
+ var src = null;
32244
+ var k;
32245
+ for (k = 0; k < sources.length; k++) {
32246
+ if (sources[k].source === this.location.source) {
32247
+ src = sources[k].text.split(/\r\n|\n|\r/g);
32248
+ break;
32249
+ }
32250
+ }
32251
+ var s = this.location.start;
32252
+ var offset_s = this.location.source && typeof this.location.source.offset === "function" ? this.location.source.offset(s) : s;
32253
+ var loc = this.location.source + ":" + offset_s.line + ":" + offset_s.column;
32254
+ if (src) {
32255
+ var e = this.location.end;
32256
+ var filler = peg$padEnd("", offset_s.line.toString().length, " ");
32257
+ var line2 = src[s.line - 1];
32258
+ var last = s.line === e.line ? e.column : line2.length + 1;
32259
+ var hatLen = last - s.column || 1;
32260
+ str += "\n --> " + loc + "\n" + filler + " |\n" + offset_s.line + " | " + line2 + "\n" + filler + " | " + peg$padEnd("", s.column - 1, " ") + peg$padEnd("", hatLen, "^");
32261
+ } else {
32262
+ str += "\n at " + loc;
32263
+ }
32264
+ }
32265
+ return str;
32266
+ };
32267
+ peg$SyntaxError.buildMessage = function(expected, found) {
32268
+ var DESCRIBE_EXPECTATION_FNS = {
32269
+ literal: function(expectation) {
32270
+ return '"' + literalEscape(expectation.text) + '"';
32271
+ },
32272
+ class: function(expectation) {
32273
+ var escapedParts = expectation.parts.map(function(part) {
32274
+ return Array.isArray(part) ? classEscape(part[0]) + "-" + classEscape(part[1]) : classEscape(part);
32275
+ });
32276
+ return "[" + (expectation.inverted ? "^" : "") + escapedParts.join("") + "]";
32277
+ },
32278
+ any: function() {
32279
+ return "any character";
32280
+ },
32281
+ end: function() {
32282
+ return "end of input";
32283
+ },
32284
+ other: function(expectation) {
32285
+ return expectation.description;
32286
+ }
32287
+ };
32288
+ function hex(ch) {
32289
+ return ch.charCodeAt(0).toString(16).toUpperCase();
32290
+ }
32291
+ function literalEscape(s) {
32292
+ 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) {
32293
+ return "\\x0" + hex(ch);
32294
+ }).replace(/[\x10-\x1F\x7F-\x9F]/g, function(ch) {
32295
+ return "\\x" + hex(ch);
32296
+ });
32297
+ }
32298
+ function classEscape(s) {
32299
+ 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) {
32300
+ return "\\x0" + hex(ch);
32301
+ }).replace(/[\x10-\x1F\x7F-\x9F]/g, function(ch) {
32302
+ return "\\x" + hex(ch);
32303
+ });
32304
+ }
32305
+ function describeExpectation(expectation) {
32306
+ return DESCRIBE_EXPECTATION_FNS[expectation.type](expectation);
32307
+ }
32308
+ function describeExpected(expected2) {
32309
+ var descriptions = expected2.map(describeExpectation);
32310
+ var i, j;
32311
+ descriptions.sort();
32312
+ if (descriptions.length > 0) {
32313
+ for (i = 1, j = 1; i < descriptions.length; i++) {
32314
+ if (descriptions[i - 1] !== descriptions[i]) {
32315
+ descriptions[j] = descriptions[i];
32316
+ j++;
32317
+ }
32318
+ }
32319
+ descriptions.length = j;
32320
+ }
32321
+ switch (descriptions.length) {
32322
+ case 1:
32323
+ return descriptions[0];
32324
+ case 2:
32325
+ return descriptions[0] + " or " + descriptions[1];
32326
+ default:
32327
+ return descriptions.slice(0, -1).join(", ") + ", or " + descriptions[descriptions.length - 1];
32328
+ }
32329
+ }
32330
+ function describeFound(found2) {
32331
+ return found2 ? '"' + literalEscape(found2) + '"' : "end of input";
32332
+ }
32333
+ return "Expected " + describeExpected(expected) + " but " + describeFound(found) + " found.";
32334
+ };
32335
+
32336
+ // src/utils/silkscreen-texture.ts
32764
32337
  import { su as su6 } from "@tscircuit/circuit-json-util";
32338
+
32339
+ // src/utils/units.ts
32340
+ var MM_PER_INCH = 25.4;
32341
+ var MM_PER_MIL = MM_PER_INCH / 1e3;
32342
+ var dimensionRegex = /^\s*(-?\d*(?:\.\d+)?)(?:\s*(mm|mil|inch|in|"))?\s*$/i;
32343
+ function normalizeUnit(unit) {
32344
+ if (!unit) return void 0;
32345
+ const normalized = unit.trim().toLowerCase();
32346
+ if (normalized === '"') return "in";
32347
+ if (normalized === "inch") return "in";
32348
+ return normalized;
32349
+ }
32350
+ function parseDimensionToMm(value) {
32351
+ if (value === null || value === void 0) return void 0;
32352
+ if (typeof value === "number") {
32353
+ return Number.isFinite(value) ? value : void 0;
32354
+ }
32355
+ if (typeof value !== "string") return void 0;
32356
+ const trimmed = value.trim();
32357
+ if (trimmed.length === 0) return void 0;
32358
+ const match = trimmed.match(dimensionRegex);
32359
+ if (!match) {
32360
+ const numeric = Number.parseFloat(trimmed);
32361
+ return Number.isFinite(numeric) ? numeric : void 0;
32362
+ }
32363
+ const [, magnitudeRaw, unitRaw] = match;
32364
+ const magnitude = Number.parseFloat(magnitudeRaw || "0");
32365
+ if (!Number.isFinite(magnitude)) return void 0;
32366
+ const unit = normalizeUnit(unitRaw);
32367
+ switch (unit) {
32368
+ case "mil":
32369
+ return magnitude * MM_PER_MIL;
32370
+ case "in":
32371
+ return magnitude * MM_PER_INCH;
32372
+ case "mm":
32373
+ case void 0:
32374
+ return magnitude;
32375
+ default:
32376
+ return magnitude;
32377
+ }
32378
+ }
32379
+ function coerceDimensionToMm(value, fallback) {
32380
+ const parsed = parseDimensionToMm(value);
32381
+ return parsed === void 0 ? fallback : parsed;
32382
+ }
32383
+
32384
+ // src/utils/silkscreen-texture.ts
32765
32385
  function parseFabricationNoteColor(colorString) {
32766
32386
  let hex = colorString;
32767
32387
  if (hex.startsWith("#")) {
@@ -33039,7 +32659,7 @@ function createSilkscreenTextureForLayer({
33039
32659
  ctx.lineWidth = textStrokeWidth;
33040
32660
  ctx.lineCap = "butt";
33041
32661
  ctx.lineJoin = "miter";
33042
- const rawTextOutlines = (0, import_text2.vectorText)({
32662
+ const rawTextOutlines = (0, import_text.vectorText)({
33043
32663
  height: fontSize * 0.45,
33044
32664
  input: textS.text
33045
32665
  });
@@ -33089,18 +32709,18 @@ function createSilkscreenTextureForLayer({
33089
32709
  let rotationDeg = textS.ccw_rotation ?? 0;
33090
32710
  if (textS.layer === "bottom") {
33091
32711
  transformMatrices.push(
33092
- translate4(textCenterX, textCenterY),
32712
+ translate6(textCenterX, textCenterY),
33093
32713
  { a: -1, b: 0, c: 0, d: 1, e: 0, f: 0 },
33094
- translate4(-textCenterX, -textCenterY)
32714
+ translate6(-textCenterX, -textCenterY)
33095
32715
  );
33096
32716
  rotationDeg = -rotationDeg;
33097
32717
  }
33098
32718
  if (rotationDeg) {
33099
32719
  const rad = rotationDeg * Math.PI / 180;
33100
32720
  transformMatrices.push(
33101
- translate4(textCenterX, textCenterY),
32721
+ translate6(textCenterX, textCenterY),
33102
32722
  rotate2(rad),
33103
- translate4(-textCenterX, -textCenterY)
32723
+ translate6(-textCenterX, -textCenterY)
33104
32724
  );
33105
32725
  }
33106
32726
  const finalTransformMatrix = transformMatrices.length > 0 ? compose(...transformMatrices) : void 0;
@@ -33223,6 +32843,251 @@ function createTraceTextureForLayer({
33223
32843
  return texture;
33224
32844
  }
33225
32845
 
32846
+ // src/utils/copper-text-texture.ts
32847
+ var import_text2 = __toESM(require_text(), 1);
32848
+ import * as THREE21 from "three";
32849
+ function parseDimension2(value, defaultValue) {
32850
+ if (value === void 0) return defaultValue;
32851
+ if (typeof value === "number") return value;
32852
+ const num = parseFloat(value.replace(/mm$/, ""));
32853
+ return isNaN(num) ? defaultValue : num;
32854
+ }
32855
+ function shouldMirrorText(text) {
32856
+ if (text.layer === "bottom") {
32857
+ return text.is_mirrored !== false;
32858
+ }
32859
+ return text.is_mirrored === true;
32860
+ }
32861
+ function getTextMetrics(outlines) {
32862
+ const points = outlines.flat();
32863
+ if (points.length === 0) {
32864
+ return {
32865
+ minX: 0,
32866
+ maxX: 0,
32867
+ minY: 0,
32868
+ maxY: 0,
32869
+ width: 0,
32870
+ height: 0,
32871
+ centerX: 0,
32872
+ centerY: 0
32873
+ };
32874
+ }
32875
+ const minX = Math.min(...points.map((p) => p[0]));
32876
+ const maxX = Math.max(...points.map((p) => p[0]));
32877
+ const minY = Math.min(...points.map((p) => p[1]));
32878
+ const maxY = Math.max(...points.map((p) => p[1]));
32879
+ return {
32880
+ minX,
32881
+ maxX,
32882
+ minY,
32883
+ maxY,
32884
+ width: maxX - minX,
32885
+ height: maxY - minY,
32886
+ centerX: (minX + maxX) / 2,
32887
+ centerY: (minY + maxY) / 2
32888
+ };
32889
+ }
32890
+ function processTextOutlines(rawOutlines) {
32891
+ const processed = [];
32892
+ rawOutlines.forEach((outline) => {
32893
+ if (outline.length === 29) {
32894
+ processed.push(outline.slice(0, 15));
32895
+ processed.push(outline.slice(14, 29));
32896
+ } else if (outline.length === 17) {
32897
+ processed.push(outline.slice(0, 10));
32898
+ processed.push(outline.slice(9, 17));
32899
+ } else {
32900
+ processed.push(outline);
32901
+ }
32902
+ });
32903
+ return processed;
32904
+ }
32905
+ function getAlignmentOffset(metrics, alignment) {
32906
+ let xOff = -metrics.centerX;
32907
+ let yOff = -metrics.centerY;
32908
+ if (alignment.includes("left")) {
32909
+ xOff = -metrics.minX;
32910
+ } else if (alignment.includes("right")) {
32911
+ xOff = -metrics.maxX;
32912
+ }
32913
+ if (alignment.includes("top")) {
32914
+ yOff = -metrics.maxY;
32915
+ } else if (alignment.includes("bottom")) {
32916
+ yOff = -metrics.minY;
32917
+ }
32918
+ return { x: xOff, y: yOff };
32919
+ }
32920
+ function buildTransformMatrix(text, metrics) {
32921
+ const transformMatrices = [];
32922
+ let rotationDeg = text.ccw_rotation ?? 0;
32923
+ const shouldMirror = shouldMirrorText(text);
32924
+ if (shouldMirror) {
32925
+ transformMatrices.push(
32926
+ translate6(metrics.centerX, metrics.centerY),
32927
+ { a: -1, b: 0, c: 0, d: 1, e: 0, f: 0 },
32928
+ // horizontal flip
32929
+ translate6(-metrics.centerX, -metrics.centerY)
32930
+ );
32931
+ rotationDeg = -rotationDeg;
32932
+ }
32933
+ if (rotationDeg) {
32934
+ const rad = rotationDeg * Math.PI / 180;
32935
+ transformMatrices.push(
32936
+ translate6(metrics.centerX, metrics.centerY),
32937
+ rotate2(rad),
32938
+ translate6(-metrics.centerX, -metrics.centerY)
32939
+ );
32940
+ }
32941
+ const matrix = transformMatrices.length > 0 ? compose(...transformMatrices) : void 0;
32942
+ return { matrix, rotationDeg };
32943
+ }
32944
+ function drawTextStrokes(ctx, outlines, transform2, offset4, anchorPos, canvasXFromPcb, canvasYFromPcb) {
32945
+ outlines.forEach((segment) => {
32946
+ ctx.beginPath();
32947
+ segment.forEach((p, index2) => {
32948
+ let transformedP = { x: p[0], y: p[1] };
32949
+ if (transform2) {
32950
+ transformedP = applyToPoint(transform2, transformedP);
32951
+ }
32952
+ const pcbX = transformedP.x + offset4.x + anchorPos.x;
32953
+ const pcbY = transformedP.y + offset4.y + anchorPos.y;
32954
+ const canvasX = canvasXFromPcb(pcbX);
32955
+ const canvasY = canvasYFromPcb(pcbY);
32956
+ if (index2 === 0) ctx.moveTo(canvasX, canvasY);
32957
+ else ctx.lineTo(canvasX, canvasY);
32958
+ });
32959
+ ctx.stroke();
32960
+ });
32961
+ }
32962
+ function drawRotatedRect(ctx, centerX, centerY, width10, height10, rotationRad) {
32963
+ ctx.save();
32964
+ ctx.translate(centerX, centerY);
32965
+ ctx.rotate(-rotationRad);
32966
+ ctx.fillRect(-width10 / 2, -height10 / 2, width10, height10);
32967
+ ctx.restore();
32968
+ }
32969
+ function drawKnockoutText(ctx, text, outlines, metrics, transform2, rotationDeg, canvasXFromPcb, canvasYFromPcb, traceTextureResolution, copperColor) {
32970
+ const fontSize = typeof text.font_size === "number" ? text.font_size : 0.2;
32971
+ const padding = {
32972
+ left: parseDimension2(text.knockout_padding?.left, fontSize * 0.5),
32973
+ right: parseDimension2(text.knockout_padding?.right, fontSize * 0.5),
32974
+ top: parseDimension2(text.knockout_padding?.top, fontSize * 0.3),
32975
+ bottom: parseDimension2(text.knockout_padding?.bottom, fontSize * 0.3)
32976
+ };
32977
+ const rectWidth = metrics.width + padding.left + padding.right;
32978
+ const rectHeight = metrics.height + padding.top + padding.bottom;
32979
+ const rectCenterCanvasX = canvasXFromPcb(text.anchor_position.x);
32980
+ const rectCenterCanvasY = canvasYFromPcb(text.anchor_position.y);
32981
+ const rectWidthPx = rectWidth * traceTextureResolution;
32982
+ const rectHeightPx = rectHeight * traceTextureResolution;
32983
+ ctx.fillStyle = copperColor;
32984
+ const rotationRad = rotationDeg * Math.PI / 180;
32985
+ drawRotatedRect(
32986
+ ctx,
32987
+ rectCenterCanvasX,
32988
+ rectCenterCanvasY,
32989
+ rectWidthPx,
32990
+ rectHeightPx,
32991
+ rotationRad
32992
+ );
32993
+ const textOffset = {
32994
+ x: -metrics.centerX,
32995
+ y: -metrics.centerY
32996
+ };
32997
+ ctx.globalCompositeOperation = "destination-out";
32998
+ drawTextStrokes(
32999
+ ctx,
33000
+ outlines,
33001
+ transform2,
33002
+ textOffset,
33003
+ text.anchor_position,
33004
+ canvasXFromPcb,
33005
+ canvasYFromPcb
33006
+ );
33007
+ ctx.globalCompositeOperation = "source-over";
33008
+ }
33009
+ function createCopperTextTextureForLayer({
33010
+ layer,
33011
+ circuitJson,
33012
+ boardData,
33013
+ copperColor = "rgb(230, 153, 51)",
33014
+ // Same as colors.copper [0.9, 0.6, 0.2]
33015
+ traceTextureResolution
33016
+ }) {
33017
+ const copperTexts = circuitJson.filter(
33018
+ (e) => e.type === "pcb_copper_text"
33019
+ );
33020
+ const textsOnLayer = copperTexts.filter((t) => t.layer === layer);
33021
+ if (textsOnLayer.length === 0) {
33022
+ return null;
33023
+ }
33024
+ const canvas = document.createElement("canvas");
33025
+ const canvasWidth = Math.floor(boardData.width * traceTextureResolution);
33026
+ const canvasHeight = Math.floor(boardData.height * traceTextureResolution);
33027
+ canvas.width = canvasWidth;
33028
+ canvas.height = canvasHeight;
33029
+ const ctx = canvas.getContext("2d");
33030
+ if (!ctx) return null;
33031
+ if (layer === "bottom") {
33032
+ ctx.translate(0, canvasHeight);
33033
+ ctx.scale(1, -1);
33034
+ }
33035
+ ctx.strokeStyle = copperColor;
33036
+ ctx.fillStyle = copperColor;
33037
+ const canvasXFromPcb = (pcbX) => (pcbX - boardData.center.x + boardData.width / 2) * traceTextureResolution;
33038
+ const canvasYFromPcb = (pcbY) => (-(pcbY - boardData.center.y) + boardData.height / 2) * traceTextureResolution;
33039
+ textsOnLayer.forEach((textS) => {
33040
+ const fontSize = typeof textS.font_size === "number" ? textS.font_size : 0.2;
33041
+ const textStrokeWidth = Math.max(0.02, fontSize * 0.08) * traceTextureResolution;
33042
+ ctx.lineWidth = textStrokeWidth;
33043
+ ctx.lineCap = "round";
33044
+ ctx.lineJoin = "round";
33045
+ const rawTextOutlines = (0, import_text2.vectorText)({
33046
+ height: fontSize * 0.45,
33047
+ input: textS.text
33048
+ });
33049
+ const processedOutlines = processTextOutlines(rawTextOutlines);
33050
+ const metrics = getTextMetrics(processedOutlines);
33051
+ const { matrix: transform2, rotationDeg } = buildTransformMatrix(
33052
+ textS,
33053
+ metrics
33054
+ );
33055
+ if (textS.is_knockout) {
33056
+ drawKnockoutText(
33057
+ ctx,
33058
+ textS,
33059
+ processedOutlines,
33060
+ metrics,
33061
+ transform2,
33062
+ rotationDeg,
33063
+ canvasXFromPcb,
33064
+ canvasYFromPcb,
33065
+ traceTextureResolution,
33066
+ copperColor
33067
+ );
33068
+ } else {
33069
+ const alignment = textS.anchor_alignment || "center";
33070
+ const offset4 = getAlignmentOffset(metrics, alignment);
33071
+ drawTextStrokes(
33072
+ ctx,
33073
+ processedOutlines,
33074
+ transform2,
33075
+ offset4,
33076
+ textS.anchor_position,
33077
+ canvasXFromPcb,
33078
+ canvasYFromPcb
33079
+ );
33080
+ }
33081
+ });
33082
+ const texture = new THREE21.CanvasTexture(canvas);
33083
+ texture.generateMipmaps = true;
33084
+ texture.minFilter = THREE21.LinearMipmapLinearFilter;
33085
+ texture.magFilter = THREE21.LinearFilter;
33086
+ texture.anisotropy = 16;
33087
+ texture.needsUpdate = true;
33088
+ return texture;
33089
+ }
33090
+
33226
33091
  // src/three-components/JscadBoardTextures.tsx
33227
33092
  function JscadBoardTextures({
33228
33093
  circuitJson,
@@ -33283,6 +33148,20 @@ function JscadBoardTextures({
33283
33148
  boardData,
33284
33149
  traceColor: traceColorWithMask,
33285
33150
  traceTextureResolution: TRACE_TEXTURE_RESOLUTION
33151
+ }),
33152
+ topCopperText: createCopperTextTextureForLayer({
33153
+ layer: "top",
33154
+ circuitJson,
33155
+ boardData,
33156
+ copperColor: `rgb(${Math.round(colors.copper[0] * 255)}, ${Math.round(colors.copper[1] * 255)}, ${Math.round(colors.copper[2] * 255)})`,
33157
+ traceTextureResolution: TRACE_TEXTURE_RESOLUTION
33158
+ }),
33159
+ bottomCopperText: createCopperTextTextureForLayer({
33160
+ layer: "bottom",
33161
+ circuitJson,
33162
+ boardData,
33163
+ copperColor: `rgb(${Math.round(colors.copper[0] * 255)}, ${Math.round(colors.copper[1] * 255)}, ${Math.round(colors.copper[2] * 255)})`,
33164
+ traceTextureResolution: TRACE_TEXTURE_RESOLUTION
33286
33165
  })
33287
33166
  };
33288
33167
  }, [circuitJson, boardData]);
@@ -33291,20 +33170,20 @@ function JscadBoardTextures({
33291
33170
  const meshes = [];
33292
33171
  const createTexturePlane = (texture, zOffset, isBottomLayer, name, usePolygonOffset = false) => {
33293
33172
  if (!texture) return null;
33294
- const planeGeom = new THREE21.PlaneGeometry(
33173
+ const planeGeom = new THREE22.PlaneGeometry(
33295
33174
  boardData.width,
33296
33175
  boardData.height
33297
33176
  );
33298
- const material = new THREE21.MeshBasicMaterial({
33177
+ const material = new THREE22.MeshBasicMaterial({
33299
33178
  map: texture,
33300
33179
  transparent: true,
33301
- side: THREE21.DoubleSide,
33180
+ side: THREE22.DoubleSide,
33302
33181
  depthWrite: false,
33303
33182
  polygonOffset: usePolygonOffset,
33304
33183
  polygonOffsetFactor: usePolygonOffset ? -1 : 0,
33305
33184
  polygonOffsetUnits: usePolygonOffset ? -1 : 0
33306
33185
  });
33307
- const mesh = new THREE21.Mesh(planeGeom, material);
33186
+ const mesh = new THREE22.Mesh(planeGeom, material);
33308
33187
  mesh.position.set(boardData.center.x, boardData.center.y, zOffset);
33309
33188
  if (isBottomLayer) {
33310
33189
  mesh.rotation.set(Math.PI, 0, 0);
@@ -33342,7 +33221,7 @@ function JscadBoardTextures({
33342
33221
  if (visibility.topCopper && visibility.topMask) {
33343
33222
  const topTraceWithMaskMesh = createTexturePlane(
33344
33223
  textures.topTraceWithMask,
33345
- pcbThickness / 2 + SURFACE_OFFSET + 1e-3,
33224
+ pcbThickness / 2 + BOARD_SURFACE_OFFSET.traces + 4e-3,
33346
33225
  false,
33347
33226
  "jscad-top-trace-with-mask"
33348
33227
  );
@@ -33354,7 +33233,7 @@ function JscadBoardTextures({
33354
33233
  if (visibility.bottomCopper && visibility.bottomMask) {
33355
33234
  const bottomTraceWithMaskMesh = createTexturePlane(
33356
33235
  textures.bottomTraceWithMask,
33357
- -pcbThickness / 2 - SURFACE_OFFSET - 1e-3,
33236
+ -pcbThickness / 2 - BOARD_SURFACE_OFFSET.traces - 5e-3,
33358
33237
  true,
33359
33238
  "jscad-bottom-trace-with-mask"
33360
33239
  );
@@ -33387,13 +33266,37 @@ function JscadBoardTextures({
33387
33266
  rootObject.add(bottomSilkscreenMesh);
33388
33267
  }
33389
33268
  }
33269
+ if (visibility.topCopper) {
33270
+ const topCopperTextMesh = createTexturePlane(
33271
+ textures.topCopperText,
33272
+ pcbThickness / 2 + BOARD_SURFACE_OFFSET.copper,
33273
+ false,
33274
+ "jscad-top-copper-text"
33275
+ );
33276
+ if (topCopperTextMesh) {
33277
+ meshes.push(topCopperTextMesh);
33278
+ rootObject.add(topCopperTextMesh);
33279
+ }
33280
+ }
33281
+ if (visibility.bottomCopper) {
33282
+ const bottomCopperTextMesh = createTexturePlane(
33283
+ textures.bottomCopperText,
33284
+ -pcbThickness / 2 - BOARD_SURFACE_OFFSET.copper,
33285
+ true,
33286
+ "jscad-bottom-copper-text"
33287
+ );
33288
+ if (bottomCopperTextMesh) {
33289
+ meshes.push(bottomCopperTextMesh);
33290
+ rootObject.add(bottomCopperTextMesh);
33291
+ }
33292
+ }
33390
33293
  return () => {
33391
33294
  meshes.forEach((mesh) => {
33392
33295
  if (mesh.parent === rootObject) {
33393
33296
  rootObject.remove(mesh);
33394
33297
  }
33395
33298
  mesh.geometry.dispose();
33396
- if (mesh.material instanceof THREE21.Material) {
33299
+ if (mesh.material instanceof THREE22.Material) {
33397
33300
  mesh.material.dispose();
33398
33301
  }
33399
33302
  });
@@ -33625,7 +33528,7 @@ import { useEffect as useEffect24, useMemo as useMemo22, useState as useState15
33625
33528
  // src/hooks/useManifoldBoardBuilder.ts
33626
33529
  import { useState as useState14, useEffect as useEffect23, useMemo as useMemo21, useRef as useRef9 } from "react";
33627
33530
  import { su as su17 } from "@tscircuit/circuit-json-util";
33628
- import * as THREE27 from "three";
33531
+ import * as THREE28 from "three";
33629
33532
 
33630
33533
  // src/utils/manifold/create-manifold-board.ts
33631
33534
  var arePointsClockwise3 = (points) => {
@@ -33686,17 +33589,17 @@ function createManifoldBoard(Manifold, CrossSection, boardData, pcbThickness, ma
33686
33589
  }
33687
33590
 
33688
33591
  // src/utils/manifold/process-copper-pours.ts
33689
- import * as THREE23 from "three";
33592
+ import * as THREE24 from "three";
33690
33593
 
33691
33594
  // src/utils/manifold-mesh-to-three-geometry.ts
33692
- import * as THREE22 from "three";
33595
+ import * as THREE23 from "three";
33693
33596
  function manifoldMeshToThreeGeometry(manifoldMesh) {
33694
- const geometry = new THREE22.BufferGeometry();
33597
+ const geometry = new THREE23.BufferGeometry();
33695
33598
  geometry.setAttribute(
33696
33599
  "position",
33697
- new THREE22.Float32BufferAttribute(manifoldMesh.vertProperties, 3)
33600
+ new THREE23.Float32BufferAttribute(manifoldMesh.vertProperties, 3)
33698
33601
  );
33699
- geometry.setIndex(new THREE22.Uint32BufferAttribute(manifoldMesh.triVerts, 1));
33602
+ geometry.setIndex(new THREE23.Uint32BufferAttribute(manifoldMesh.triVerts, 1));
33700
33603
  if (manifoldMesh.runIndex && manifoldMesh.runIndex.length > 1 && manifoldMesh.runOriginalID) {
33701
33604
  for (let i = 0; i < manifoldMesh.runIndex.length - 1; i++) {
33702
33605
  const start = manifoldMesh.runIndex[i];
@@ -33869,7 +33772,7 @@ function processCopperPoursForManifold(Manifold, CrossSection, circuitJson, pcbT
33869
33772
  }
33870
33773
  const covered = pour.covered_with_solder_mask !== false;
33871
33774
  const pourColorArr = covered ? tracesMaterialColors[boardMaterial] ?? colors.fr4TracesWithoutMaskTan : colors.copper;
33872
- const pourColor = new THREE23.Color(...pourColorArr);
33775
+ const pourColor = new THREE24.Color(...pourColorArr);
33873
33776
  const threeGeom = manifoldMeshToThreeGeometry(pourOp.getMesh());
33874
33777
  copperPourGeoms.push({
33875
33778
  key: `coppour-${pour.pcb_copper_pour_id}`,
@@ -34171,7 +34074,7 @@ function processNonPlatedHolesForManifold(Manifold, circuitJson, pcbThickness, m
34171
34074
 
34172
34075
  // src/utils/manifold/process-plated-holes.ts
34173
34076
  import { su as su14 } from "@tscircuit/circuit-json-util";
34174
- import * as THREE24 from "three";
34077
+ import * as THREE25 from "three";
34175
34078
  var arePointsClockwise6 = (points) => {
34176
34079
  let area = 0;
34177
34080
  for (let i = 0; i < points.length; i++) {
@@ -34192,7 +34095,7 @@ var createEllipsePoints = (width10, height10, segments) => {
34192
34095
  }
34193
34096
  return points;
34194
34097
  };
34195
- var COPPER_COLOR = new THREE24.Color(...colors.copper);
34098
+ var COPPER_COLOR = new THREE25.Color(...colors.copper);
34196
34099
  var PLATED_HOLE_LIP_HEIGHT = 0.05;
34197
34100
  function processPlatedHolesForManifold(Manifold, CrossSection, circuitJson, pcbThickness, manifoldInstancesForCleanup, boardClipVolume) {
34198
34101
  const platedHoleBoardDrills = [];
@@ -34766,8 +34669,8 @@ function processPlatedHolesForManifold(Manifold, CrossSection, circuitJson, pcbT
34766
34669
 
34767
34670
  // src/utils/manifold/process-smt-pads.ts
34768
34671
  import { su as su15 } from "@tscircuit/circuit-json-util";
34769
- import * as THREE25 from "three";
34770
- var COPPER_COLOR2 = new THREE25.Color(...colors.copper);
34672
+ import * as THREE26 from "three";
34673
+ var COPPER_COLOR2 = new THREE26.Color(...colors.copper);
34771
34674
  function processSmtPadsForManifold(Manifold, circuitJson, pcbThickness, manifoldInstancesForCleanup, holeUnion, boardClipVolume) {
34772
34675
  const smtPadGeoms = [];
34773
34676
  const smtPads = su15(circuitJson).pcb_smtpad.list();
@@ -34806,7 +34709,7 @@ function processSmtPadsForManifold(Manifold, circuitJson, pcbThickness, manifold
34806
34709
 
34807
34710
  // src/utils/manifold/process-vias.ts
34808
34711
  import { su as su16 } from "@tscircuit/circuit-json-util";
34809
- import * as THREE26 from "three";
34712
+ import * as THREE27 from "three";
34810
34713
 
34811
34714
  // src/utils/via-geoms.ts
34812
34715
  function createViaCopper2({
@@ -34859,7 +34762,7 @@ function createViaCopper2({
34859
34762
  }
34860
34763
 
34861
34764
  // src/utils/manifold/process-vias.ts
34862
- var COPPER_COLOR3 = new THREE26.Color(...colors.copper);
34765
+ var COPPER_COLOR3 = new THREE27.Color(...colors.copper);
34863
34766
  function processViasForManifold(Manifold, circuitJson, pcbThickness, manifoldInstancesForCleanup, boardClipVolume) {
34864
34767
  const viaBoardDrills = [];
34865
34768
  const pcbVias = su16(circuitJson).pcb_via.list();
@@ -35076,7 +34979,7 @@ var useManifoldBoardBuilder = (manifoldJSModule, circuitJson) => {
35076
34979
  {
35077
34980
  key: "plated-holes-union",
35078
34981
  geometry: cutPlatedGeom,
35079
- color: new THREE27.Color(
34982
+ color: new THREE28.Color(
35080
34983
  colors.copper[0],
35081
34984
  colors.copper[1],
35082
34985
  colors.copper[2]
@@ -35106,7 +35009,7 @@ var useManifoldBoardBuilder = (manifoldJSModule, circuitJson) => {
35106
35009
  const matColorArray = boardMaterialColors[boardData.material] ?? colors.fr4Tan;
35107
35010
  currentGeoms.board = {
35108
35011
  geometry: finalBoardGeom,
35109
- color: new THREE27.Color(
35012
+ color: new THREE28.Color(
35110
35013
  matColorArray[0],
35111
35014
  matColorArray[1],
35112
35015
  matColorArray[2]
@@ -35199,6 +35102,22 @@ var useManifoldBoardBuilder = (manifoldJSModule, circuitJson) => {
35199
35102
  soldermaskColor,
35200
35103
  traceTextureResolution: TRACE_TEXTURE_RESOLUTION
35201
35104
  });
35105
+ const copperColorArr = colors.copper;
35106
+ const copperColor = `rgb(${Math.round(copperColorArr[0] * 255)}, ${Math.round(copperColorArr[1] * 255)}, ${Math.round(copperColorArr[2] * 255)})`;
35107
+ currentTextures.topCopperText = createCopperTextTextureForLayer({
35108
+ layer: "top",
35109
+ circuitJson,
35110
+ boardData,
35111
+ copperColor,
35112
+ traceTextureResolution: TRACE_TEXTURE_RESOLUTION
35113
+ });
35114
+ currentTextures.bottomCopperText = createCopperTextTextureForLayer({
35115
+ layer: "bottom",
35116
+ circuitJson,
35117
+ boardData,
35118
+ copperColor,
35119
+ traceTextureResolution: TRACE_TEXTURE_RESOLUTION
35120
+ });
35202
35121
  setTextures(currentTextures);
35203
35122
  } catch (e) {
35204
35123
  console.error("Error processing geometry with Manifold in hook:", e);
@@ -35227,11 +35146,11 @@ var useManifoldBoardBuilder = (manifoldJSModule, circuitJson) => {
35227
35146
  };
35228
35147
 
35229
35148
  // src/utils/manifold/create-three-geometry-meshes.ts
35230
- import * as THREE29 from "three";
35149
+ import * as THREE30 from "three";
35231
35150
 
35232
35151
  // src/utils/create-board-material.ts
35233
- import * as THREE28 from "three";
35234
- var DEFAULT_SIDE = THREE28.DoubleSide;
35152
+ import * as THREE29 from "three";
35153
+ var DEFAULT_SIDE = THREE29.DoubleSide;
35235
35154
  var createBoardMaterial = ({
35236
35155
  material,
35237
35156
  color,
@@ -35239,7 +35158,7 @@ var createBoardMaterial = ({
35239
35158
  isFaux = false
35240
35159
  }) => {
35241
35160
  if (material === "fr4") {
35242
- return new THREE28.MeshPhysicalMaterial({
35161
+ return new THREE29.MeshPhysicalMaterial({
35243
35162
  color,
35244
35163
  side,
35245
35164
  metalness: 0,
@@ -35253,7 +35172,7 @@ var createBoardMaterial = ({
35253
35172
  flatShading: true
35254
35173
  });
35255
35174
  }
35256
- return new THREE28.MeshStandardMaterial({
35175
+ return new THREE29.MeshStandardMaterial({
35257
35176
  color,
35258
35177
  side,
35259
35178
  flatShading: true,
@@ -35269,12 +35188,12 @@ function createGeometryMeshes(geoms) {
35269
35188
  const meshes = [];
35270
35189
  if (!geoms) return meshes;
35271
35190
  if (geoms.board && geoms.board.geometry) {
35272
- const mesh = new THREE29.Mesh(
35191
+ const mesh = new THREE30.Mesh(
35273
35192
  geoms.board.geometry,
35274
35193
  createBoardMaterial({
35275
35194
  material: geoms.board.material,
35276
35195
  color: geoms.board.color,
35277
- side: THREE29.DoubleSide,
35196
+ side: THREE30.DoubleSide,
35278
35197
  isFaux: geoms.board.isFaux
35279
35198
  })
35280
35199
  );
@@ -35284,11 +35203,11 @@ function createGeometryMeshes(geoms) {
35284
35203
  const createMeshesFromArray = (geomArray) => {
35285
35204
  if (geomArray) {
35286
35205
  geomArray.forEach((comp) => {
35287
- const mesh = new THREE29.Mesh(
35206
+ const mesh = new THREE30.Mesh(
35288
35207
  comp.geometry,
35289
- new THREE29.MeshStandardMaterial({
35208
+ new THREE30.MeshStandardMaterial({
35290
35209
  color: comp.color,
35291
- side: THREE29.DoubleSide,
35210
+ side: THREE30.DoubleSide,
35292
35211
  flatShading: true,
35293
35212
  // Consistent with board
35294
35213
  polygonOffset: true,
@@ -35309,17 +35228,17 @@ function createGeometryMeshes(geoms) {
35309
35228
  }
35310
35229
 
35311
35230
  // src/utils/manifold/create-three-texture-meshes.ts
35312
- import * as THREE30 from "three";
35231
+ import * as THREE31 from "three";
35313
35232
  function createTextureMeshes(textures, boardData, pcbThickness) {
35314
35233
  const meshes = [];
35315
35234
  if (!textures || !boardData || pcbThickness === null) return meshes;
35316
35235
  const createTexturePlane = (texture, yOffset, isBottomLayer, keySuffix, usePolygonOffset = false, renderOrder = 0) => {
35317
35236
  if (!texture) return null;
35318
- const planeGeom = new THREE30.PlaneGeometry(boardData.width, boardData.height);
35319
- const material = new THREE30.MeshBasicMaterial({
35237
+ const planeGeom = new THREE31.PlaneGeometry(boardData.width, boardData.height);
35238
+ const material = new THREE31.MeshBasicMaterial({
35320
35239
  map: texture,
35321
35240
  transparent: true,
35322
- side: THREE30.DoubleSide,
35241
+ side: THREE31.DoubleSide,
35323
35242
  depthWrite: false,
35324
35243
  // Important for layers to avoid z-fighting issues with board itself
35325
35244
  polygonOffset: usePolygonOffset,
@@ -35327,7 +35246,7 @@ function createTextureMeshes(textures, boardData, pcbThickness) {
35327
35246
  // Increased for better z-fighting prevention
35328
35247
  polygonOffsetUnits: usePolygonOffset ? -4 : 0
35329
35248
  });
35330
- const mesh = new THREE30.Mesh(planeGeom, material);
35249
+ const mesh = new THREE31.Mesh(planeGeom, material);
35331
35250
  mesh.position.set(boardData.center.x, boardData.center.y, yOffset);
35332
35251
  if (isBottomLayer) {
35333
35252
  mesh.rotation.set(Math.PI, 0, 0);
@@ -35423,6 +35342,26 @@ function createTextureMeshes(textures, boardData, pcbThickness) {
35423
35342
  // Render after board (renderOrder)
35424
35343
  );
35425
35344
  if (bottomSoldermaskMesh) meshes.push(bottomSoldermaskMesh);
35345
+ const topCopperTextMesh = createTexturePlane(
35346
+ textures.topCopperText,
35347
+ pcbThickness / 2 + BOARD_SURFACE_OFFSET.copper,
35348
+ false,
35349
+ "copper-text",
35350
+ false,
35351
+ 2
35352
+ // Render after soldermask
35353
+ );
35354
+ if (topCopperTextMesh) meshes.push(topCopperTextMesh);
35355
+ const bottomCopperTextMesh = createTexturePlane(
35356
+ textures.bottomCopperText,
35357
+ -pcbThickness / 2 - BOARD_SURFACE_OFFSET.copper,
35358
+ true,
35359
+ "copper-text",
35360
+ false,
35361
+ 2
35362
+ // Render after soldermask
35363
+ );
35364
+ if (bottomCopperTextMesh) meshes.push(bottomCopperTextMesh);
35426
35365
  return meshes;
35427
35366
  }
35428
35367
 
@@ -35475,6 +35414,10 @@ var BoardMeshes = ({
35475
35414
  shouldShow = visibility.topMask;
35476
35415
  } else if (mesh.name.includes("bottom-soldermask")) {
35477
35416
  shouldShow = visibility.bottomMask;
35417
+ } else if (mesh.name.includes("top-copper-text")) {
35418
+ shouldShow = visibility.topCopper;
35419
+ } else if (mesh.name.includes("bottom-copper-text")) {
35420
+ shouldShow = visibility.bottomCopper;
35478
35421
  }
35479
35422
  if (shouldShow) {
35480
35423
  rootObject.add(mesh);
@@ -42329,7 +42272,7 @@ var KeyboardShortcutsDialog = ({
42329
42272
 
42330
42273
  // src/CadViewer.tsx
42331
42274
  import { jsx as jsx37, jsxs as jsxs11 } from "react/jsx-runtime";
42332
- var DEFAULT_TARGET = new THREE31.Vector3(0, 0, 0);
42275
+ var DEFAULT_TARGET = new THREE32.Vector3(0, 0, 0);
42333
42276
  var INITIAL_CAMERA_POSITION = [5, -5, 5];
42334
42277
  var CadViewerInner = (props) => {
42335
42278
  const [engine, setEngine] = useState35("manifold");
@@ -42596,11 +42539,11 @@ var CadViewer = (props) => {
42596
42539
  // src/convert-circuit-json-to-3d-svg.ts
42597
42540
  var import_debug = __toESM(require_browser(), 1);
42598
42541
  import { su as su19 } from "@tscircuit/circuit-json-util";
42599
- import * as THREE35 from "three";
42542
+ import * as THREE36 from "three";
42600
42543
  import { SVGRenderer } from "three/examples/jsm/renderers/SVGRenderer.js";
42601
42544
 
42602
42545
  // src/utils/create-geometry-from-polygons.ts
42603
- import * as THREE32 from "three";
42546
+ import * as THREE33 from "three";
42604
42547
  import { BufferGeometry as BufferGeometry3, Float32BufferAttribute as Float32BufferAttribute2 } from "three";
42605
42548
  function createGeometryFromPolygons(polygons) {
42606
42549
  const geometry = new BufferGeometry3();
@@ -42614,12 +42557,12 @@ function createGeometryFromPolygons(polygons) {
42614
42557
  ...polygon3.vertices[i + 1]
42615
42558
  // Third vertex
42616
42559
  );
42617
- const v1 = new THREE32.Vector3(...polygon3.vertices[0]);
42618
- const v2 = new THREE32.Vector3(...polygon3.vertices[i]);
42619
- const v3 = new THREE32.Vector3(...polygon3.vertices[i + 1]);
42620
- const normal = new THREE32.Vector3().crossVectors(
42621
- new THREE32.Vector3().subVectors(v2, v1),
42622
- new THREE32.Vector3().subVectors(v3, v1)
42560
+ const v1 = new THREE33.Vector3(...polygon3.vertices[0]);
42561
+ const v2 = new THREE33.Vector3(...polygon3.vertices[i]);
42562
+ const v3 = new THREE33.Vector3(...polygon3.vertices[i + 1]);
42563
+ const normal = new THREE33.Vector3().crossVectors(
42564
+ new THREE33.Vector3().subVectors(v2, v1),
42565
+ new THREE33.Vector3().subVectors(v3, v1)
42623
42566
  ).normalize();
42624
42567
  normals.push(
42625
42568
  normal.x,
@@ -42643,10 +42586,10 @@ function createGeometryFromPolygons(polygons) {
42643
42586
  var import_modeling2 = __toESM(require_src(), 1);
42644
42587
  var import_jscad_planner2 = __toESM(require_dist(), 1);
42645
42588
  var jscadModeling2 = __toESM(require_src(), 1);
42646
- import * as THREE34 from "three";
42589
+ import * as THREE35 from "three";
42647
42590
 
42648
42591
  // src/utils/load-model.ts
42649
- import * as THREE33 from "three";
42592
+ import * as THREE34 from "three";
42650
42593
  import { GLTFLoader as GLTFLoader2 } from "three/examples/jsm/loaders/GLTFLoader.js";
42651
42594
  import { OBJLoader as OBJLoader2 } from "three/examples/jsm/loaders/OBJLoader.js";
42652
42595
  import { STLLoader as STLLoader2 } from "three/examples/jsm/loaders/STLLoader.js";
@@ -42654,12 +42597,12 @@ async function load3DModel(url) {
42654
42597
  if (url.endsWith(".stl")) {
42655
42598
  const loader = new STLLoader2();
42656
42599
  const geometry = await loader.loadAsync(url);
42657
- const material = new THREE33.MeshStandardMaterial({
42600
+ const material = new THREE34.MeshStandardMaterial({
42658
42601
  color: 8947848,
42659
42602
  metalness: 0.5,
42660
42603
  roughness: 0.5
42661
42604
  });
42662
- return new THREE33.Mesh(geometry, material);
42605
+ return new THREE34.Mesh(geometry, material);
42663
42606
  }
42664
42607
  if (url.endsWith(".obj")) {
42665
42608
  const loader = new OBJLoader2();
@@ -42692,9 +42635,9 @@ async function renderComponent(component, scene) {
42692
42635
  }
42693
42636
  if (component.rotation) {
42694
42637
  model.rotation.set(
42695
- THREE34.MathUtils.degToRad(component.rotation.x ?? 0),
42696
- THREE34.MathUtils.degToRad(component.rotation.y ?? 0),
42697
- THREE34.MathUtils.degToRad(component.rotation.z ?? 0)
42638
+ THREE35.MathUtils.degToRad(component.rotation.x ?? 0),
42639
+ THREE35.MathUtils.degToRad(component.rotation.y ?? 0),
42640
+ THREE35.MathUtils.degToRad(component.rotation.z ?? 0)
42698
42641
  );
42699
42642
  }
42700
42643
  scene.add(model);
@@ -42708,13 +42651,13 @@ async function renderComponent(component, scene) {
42708
42651
  );
42709
42652
  if (jscadObject && (jscadObject.polygons || jscadObject.sides)) {
42710
42653
  const threeGeom = convertCSGToThreeGeom(jscadObject);
42711
- const material2 = new THREE34.MeshStandardMaterial({
42654
+ const material2 = new THREE35.MeshStandardMaterial({
42712
42655
  color: 8947848,
42713
42656
  metalness: 0.5,
42714
42657
  roughness: 0.5,
42715
- side: THREE34.DoubleSide
42658
+ side: THREE35.DoubleSide
42716
42659
  });
42717
- const mesh2 = new THREE34.Mesh(threeGeom, material2);
42660
+ const mesh2 = new THREE35.Mesh(threeGeom, material2);
42718
42661
  if (component.position) {
42719
42662
  mesh2.position.set(
42720
42663
  component.position.x ?? 0,
@@ -42724,9 +42667,9 @@ async function renderComponent(component, scene) {
42724
42667
  }
42725
42668
  if (component.rotation) {
42726
42669
  mesh2.rotation.set(
42727
- THREE34.MathUtils.degToRad(component.rotation.x ?? 0),
42728
- THREE34.MathUtils.degToRad(component.rotation.y ?? 0),
42729
- THREE34.MathUtils.degToRad(component.rotation.z ?? 0)
42670
+ THREE35.MathUtils.degToRad(component.rotation.x ?? 0),
42671
+ THREE35.MathUtils.degToRad(component.rotation.y ?? 0),
42672
+ THREE35.MathUtils.degToRad(component.rotation.z ?? 0)
42730
42673
  );
42731
42674
  }
42732
42675
  scene.add(mesh2);
@@ -42743,17 +42686,17 @@ async function renderComponent(component, scene) {
42743
42686
  if (!geom || !geom.polygons && !geom.sides) {
42744
42687
  continue;
42745
42688
  }
42746
- const color = new THREE34.Color(geomInfo.color);
42689
+ const color = new THREE35.Color(geomInfo.color);
42747
42690
  color.convertLinearToSRGB();
42748
42691
  const geomWithColor = { ...geom, color: [color.r, color.g, color.b] };
42749
42692
  const threeGeom = convertCSGToThreeGeom(geomWithColor);
42750
- const material2 = new THREE34.MeshStandardMaterial({
42693
+ const material2 = new THREE35.MeshStandardMaterial({
42751
42694
  vertexColors: true,
42752
42695
  metalness: 0.2,
42753
42696
  roughness: 0.8,
42754
- side: THREE34.DoubleSide
42697
+ side: THREE35.DoubleSide
42755
42698
  });
42756
- const mesh2 = new THREE34.Mesh(threeGeom, material2);
42699
+ const mesh2 = new THREE35.Mesh(threeGeom, material2);
42757
42700
  if (component.position) {
42758
42701
  mesh2.position.set(
42759
42702
  component.position.x ?? 0,
@@ -42763,22 +42706,22 @@ async function renderComponent(component, scene) {
42763
42706
  }
42764
42707
  if (component.rotation) {
42765
42708
  mesh2.rotation.set(
42766
- THREE34.MathUtils.degToRad(component.rotation.x ?? 0),
42767
- THREE34.MathUtils.degToRad(component.rotation.y ?? 0),
42768
- THREE34.MathUtils.degToRad(component.rotation.z ?? 0)
42709
+ THREE35.MathUtils.degToRad(component.rotation.x ?? 0),
42710
+ THREE35.MathUtils.degToRad(component.rotation.y ?? 0),
42711
+ THREE35.MathUtils.degToRad(component.rotation.z ?? 0)
42769
42712
  );
42770
42713
  }
42771
42714
  scene.add(mesh2);
42772
42715
  }
42773
42716
  return;
42774
42717
  }
42775
- const geometry = new THREE34.BoxGeometry(0.5, 0.5, 0.5);
42776
- const material = new THREE34.MeshStandardMaterial({
42718
+ const geometry = new THREE35.BoxGeometry(0.5, 0.5, 0.5);
42719
+ const material = new THREE35.MeshStandardMaterial({
42777
42720
  color: 16711680,
42778
42721
  transparent: true,
42779
42722
  opacity: 0.25
42780
42723
  });
42781
- const mesh = new THREE34.Mesh(geometry, material);
42724
+ const mesh = new THREE35.Mesh(geometry, material);
42782
42725
  if (component.position) {
42783
42726
  mesh.position.set(
42784
42727
  component.position.x ?? 0,
@@ -42799,11 +42742,11 @@ async function convertCircuitJsonTo3dSvg(circuitJson, options = {}) {
42799
42742
  padding = 20,
42800
42743
  zoom = 1.5
42801
42744
  } = options;
42802
- const scene = new THREE35.Scene();
42745
+ const scene = new THREE36.Scene();
42803
42746
  const renderer = new SVGRenderer();
42804
42747
  renderer.setSize(width10, height10);
42805
- renderer.setClearColor(new THREE35.Color(backgroundColor), 1);
42806
- const camera = new THREE35.OrthographicCamera();
42748
+ renderer.setClearColor(new THREE36.Color(backgroundColor), 1);
42749
+ const camera = new THREE36.OrthographicCamera();
42807
42750
  const aspect = width10 / height10;
42808
42751
  const frustumSize = 100;
42809
42752
  const halfFrustumSize = frustumSize / 2 / zoom;
@@ -42817,11 +42760,11 @@ async function convertCircuitJsonTo3dSvg(circuitJson, options = {}) {
42817
42760
  camera.position.set(position.x, position.y, position.z);
42818
42761
  camera.up.set(0, 1, 0);
42819
42762
  const lookAt = options.camera?.lookAt ?? { x: 0, y: 0, z: 0 };
42820
- camera.lookAt(new THREE35.Vector3(lookAt.x, lookAt.y, lookAt.z));
42763
+ camera.lookAt(new THREE36.Vector3(lookAt.x, lookAt.y, lookAt.z));
42821
42764
  camera.updateProjectionMatrix();
42822
- const ambientLight = new THREE35.AmbientLight(16777215, Math.PI / 2);
42765
+ const ambientLight = new THREE36.AmbientLight(16777215, Math.PI / 2);
42823
42766
  scene.add(ambientLight);
42824
- const pointLight = new THREE35.PointLight(16777215, Math.PI / 4);
42767
+ const pointLight = new THREE36.PointLight(16777215, Math.PI / 4);
42825
42768
  pointLight.position.set(-10, -10, 10);
42826
42769
  scene.add(pointLight);
42827
42770
  const components = su19(circuitJson).cad_component.list();
@@ -42832,7 +42775,7 @@ async function convertCircuitJsonTo3dSvg(circuitJson, options = {}) {
42832
42775
  const boardGeom = createBoardGeomFromCircuitJson(circuitJson);
42833
42776
  if (boardGeom) {
42834
42777
  const solderMaskColor = colors.fr4SolderMaskGreen;
42835
- const baseColor = new THREE35.Color(
42778
+ const baseColor = new THREE36.Color(
42836
42779
  solderMaskColor[0],
42837
42780
  solderMaskColor[1],
42838
42781
  solderMaskColor[2]
@@ -42844,28 +42787,28 @@ async function convertCircuitJsonTo3dSvg(circuitJson, options = {}) {
42844
42787
  const material = createBoardMaterial({
42845
42788
  material: boardData?.material,
42846
42789
  color: baseColor,
42847
- side: THREE35.DoubleSide
42790
+ side: THREE36.DoubleSide
42848
42791
  });
42849
- const mesh = new THREE35.Mesh(geometry, material);
42792
+ const mesh = new THREE36.Mesh(geometry, material);
42850
42793
  scene.add(mesh);
42851
42794
  }
42852
42795
  }
42853
- const gridColor = new THREE35.Color(8947848);
42854
- const gridHelper = new THREE35.GridHelper(100, 100, gridColor, gridColor);
42796
+ const gridColor = new THREE36.Color(8947848);
42797
+ const gridHelper = new THREE36.GridHelper(100, 100, gridColor, gridColor);
42855
42798
  gridHelper.rotation.x = Math.PI / 2;
42856
42799
  const materials = Array.isArray(gridHelper.material) ? gridHelper.material : [gridHelper.material];
42857
42800
  for (const mat of materials) {
42858
42801
  mat.transparent = true;
42859
42802
  mat.opacity = 0.3;
42860
- if (mat instanceof THREE35.LineBasicMaterial) {
42803
+ if (mat instanceof THREE36.LineBasicMaterial) {
42861
42804
  mat.color = gridColor;
42862
42805
  mat.vertexColors = false;
42863
42806
  }
42864
42807
  }
42865
42808
  scene.add(gridHelper);
42866
- const box = new THREE35.Box3().setFromObject(scene);
42867
- const center = box.getCenter(new THREE35.Vector3());
42868
- const size5 = box.getSize(new THREE35.Vector3());
42809
+ const box = new THREE36.Box3().setFromObject(scene);
42810
+ const center = box.getCenter(new THREE36.Vector3());
42811
+ const size5 = box.getSize(new THREE36.Vector3());
42869
42812
  scene.position.sub(center);
42870
42813
  const maxDim = Math.max(size5.x, size5.y, size5.z);
42871
42814
  if (maxDim > 0) {