@tscircuit/3d-viewer 0.0.422 → 0.0.424

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +516 -242
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1053,7 +1053,7 @@ var require_rotateY = __commonJS({
1053
1053
  var require_rotateZ = __commonJS({
1054
1054
  "node_modules/@jscad/modeling/src/maths/vec3/rotateZ.js"(exports, module) {
1055
1055
  "use strict";
1056
- var rotateZ2 = (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 = rotateZ2;
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 subtract4 = (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 = subtract4;
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 rotateZ2 = (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 = rotateZ2;
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 subtract4 = (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 = subtract4;
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 translate6 = (out, matrix, offsets) => {
1715
+ var translate8 = (out, matrix, offsets) => {
1716
1716
  const x = offsets[0];
1717
1717
  const y = offsets[1];
1718
1718
  const z126 = offsets[2];
@@ -1765,7 +1765,7 @@ var require_translate = __commonJS({
1765
1765
  }
1766
1766
  return out;
1767
1767
  };
1768
- module.exports = translate6;
1768
+ module.exports = translate8;
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 subtract4 = (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 = subtract4;
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 subtract4 = 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
- subtract4(ab, b, a);
2681
- subtract4(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 subtract4 = require_subtract();
2700
+ var subtract5 = require_subtract();
2701
2701
  var planeNormal = (out, point1, point2, point32) => {
2702
2702
  const tmp = [0, 0, 0];
2703
- subtract4(out, point1, point2);
2704
- subtract4(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 scale2 = require_scale();
2918
- var subtract4 = 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 = subtract4([], 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
- subtract4(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 = subtract4([], p2, p1);
2983
+ const maxVector = subtract5([], p2, p1);
2984
2984
  const maxLength = Math.sqrt(maxSquaredLength);
2985
2985
  scale2(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 colorize5 = (color, ...objects) => {
5429
+ var colorize7 = (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 = colorize5;
5445
+ module.exports = colorize7;
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 = (line3) => {
6270
+ var clone = (line4) => {
6271
6271
  const out = create();
6272
- out[0] = line3[0];
6273
- out[1] = line3[1];
6274
- out[2] = line3[2];
6272
+ out[0] = line4[0];
6273
+ out[1] = line4[1];
6274
+ out[2] = line4[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 = (line3) => {
6287
- const vector = vec2.normal(vec2.create(), line3);
6286
+ var direction = (line4) => {
6287
+ const vector = vec2.normal(vec2.create(), line4);
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 = (line3) => vec2.scale(vec2.create(), line3, line3[2]);
6300
+ var origin = (line4) => vec2.scale(vec2.create(), line4, line4[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 = (line3, point2) => {
6313
- const orig = origin(line3);
6314
- const dir = direction(line3);
6312
+ var closestPoint = (line4, point2) => {
6313
+ const orig = origin(line4);
6314
+ const dir = direction(line4);
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, line3) => {
6330
- out[0] = line3[0];
6331
- out[1] = line3[1];
6332
- out[2] = line3[2];
6329
+ var copy = (out, line4) => {
6330
+ out[0] = line4[0];
6331
+ out[1] = line4[1];
6332
+ out[2] = line4[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 = (line3, point2) => {
6345
- let distance2 = vec2.dot(point2, line3);
6346
- distance2 = Math.abs(distance2 - line3[2]);
6344
+ var distanceToPoint = (line4, point2) => {
6345
+ let distance2 = vec2.dot(point2, line4);
6346
+ distance2 = Math.abs(distance2 - line4[2]);
6347
6347
  return distance2;
6348
6348
  };
6349
6349
  module.exports = distanceToPoint;
@@ -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, line3) => {
6515
- const normal = vec2.negate(vec2.create(), line3);
6516
- const distance2 = -line3[2];
6514
+ var reverse = (out, line4) => {
6515
+ const normal = vec2.negate(vec2.create(), line4);
6516
+ const distance2 = -line4[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 = (line3) => `line2: (${line3[0].toFixed(7)}, ${line3[1].toFixed(7)}, ${line3[2].toFixed(7)})`;
6527
+ var toString = (line4) => `line2: (${line4[0].toFixed(7)}, ${line4[1].toFixed(7)}, ${line4[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, line3, matrix) => {
6541
- const org = origin(line3);
6542
- const dir = direction(line3);
6540
+ var transform2 = (out, line4, matrix) => {
6541
+ const org = origin(line4);
6542
+ const dir = direction(line4);
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 = (line3, y) => {
6557
- let x = (line3[2] - line3[1] * y) / line3[0];
6556
+ var xAtY = (line4, y) => {
6557
+ let x = (line4[2] - line4[1] * y) / line4[0];
6558
6558
  if (Number.isNaN(x)) {
6559
- const org = origin(line3);
6559
+ const org = origin(line4);
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 = (line3) => {
6613
+ var clone = (line4) => {
6614
6614
  const out = create();
6615
- vec3.copy(out[0], line3[0]);
6616
- vec3.copy(out[1], line3[1]);
6615
+ vec3.copy(out[0], line4[0]);
6616
+ vec3.copy(out[1], line4[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 = (line3, point2) => {
6629
- const lpoint = line3[0];
6630
- const ldirection = line3[1];
6628
+ var closestPoint = (line4, point2) => {
6629
+ const lpoint = line4[0];
6630
+ const ldirection = line4[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, line3) => {
6648
- vec3.copy(out[0], line3[0]);
6649
- vec3.copy(out[1], line3[1]);
6647
+ var copy = (out, line4) => {
6648
+ vec3.copy(out[0], line4[0]);
6649
+ vec3.copy(out[1], line4[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 = (line3) => line3[1];
6660
+ var direction = (line4) => line4[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 = (line3, point2) => {
6672
- const closest = closestPoint(line3, point2);
6671
+ var distanceToPoint = (line4, point2) => {
6672
+ const closest = closestPoint(line4, point2);
6673
6673
  const distancevector = vec3.subtract(vec3.create(), point2, closest);
6674
6674
  return vec3.length(distancevector);
6675
6675
  };
@@ -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 = (line3, plane) => {
6765
+ var intersectToPlane = (line4, plane) => {
6766
6766
  const pnormal = plane;
6767
6767
  const pw = plane[3];
6768
- const lpoint = line3[0];
6769
- const ldirection = line3[1];
6768
+ const lpoint = line4[0];
6769
+ const ldirection = line4[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 = (line3) => line3[0];
6782
+ var origin = (line4) => line4[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, line3) => {
6794
- const point2 = vec3.clone(line3[0]);
6795
- const direction = vec3.negate(vec3.create(), line3[1]);
6793
+ var reverse = (out, line4) => {
6794
+ const point2 = vec3.clone(line4[0]);
6795
+ const direction = vec3.negate(vec3.create(), line4[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 = (line3) => {
6807
- const point2 = line3[0];
6808
- const direction = line3[1];
6806
+ var toString = (line4) => {
6807
+ const point2 = line4[0];
6808
+ const direction = line4[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, line3, matrix) => {
6822
- const point2 = line3[0];
6823
- const direction = line3[1];
6821
+ var transform2 = (out, line4, matrix) => {
6822
+ const point2 = line4[0];
6823
+ const direction = line4[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);
@@ -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 line3 = (points) => {
8036
+ var line4 = (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 = line3;
8040
+ module.exports = line4;
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 roundedRectangle3 = (options) => {
8400
+ var roundedRectangle4 = (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 = roundedRectangle3;
8440
+ module.exports = roundedRectangle4;
8441
8441
  }
8442
8442
  });
8443
8443
 
@@ -9727,12 +9727,12 @@ var require_rotate3 = __commonJS({
9727
9727
  };
9728
9728
  var rotateX = (angle, ...objects) => rotate2([angle, 0, 0], objects);
9729
9729
  var rotateY = (angle, ...objects) => rotate2([0, angle, 0], objects);
9730
- var rotateZ2 = (angle, ...objects) => rotate2([0, 0, angle], objects);
9730
+ var rotateZ3 = (angle, ...objects) => rotate2([0, 0, angle], objects);
9731
9731
  module.exports = {
9732
9732
  rotate: rotate2,
9733
9733
  rotateX,
9734
9734
  rotateY,
9735
- rotateZ: rotateZ2
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 translate6 = (offset4, ...objects) => {
9749
+ var translate8 = (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) => translate6([offset4, 0, 0], objects);
9765
- var translateY = (offset4, ...objects) => translate6([0, offset4, 0], objects);
9766
- var translateZ = (offset4, ...objects) => translate6([0, 0, offset4], objects);
9764
+ var translateX = (offset4, ...objects) => translate8([offset4, 0, 0], objects);
9765
+ var translateY = (offset4, ...objects) => translate8([0, offset4, 0], objects);
9766
+ var translateZ = (offset4, ...objects) => translate8([0, 0, offset4], objects);
9767
9767
  module.exports = {
9768
- translate: translate6,
9768
+ translate: translate8,
9769
9769
  translateX,
9770
9770
  translateY,
9771
9771
  translateZ
@@ -9780,7 +9780,7 @@ var require_torus = __commonJS({
9780
9780
  var { TAU } = require_constants();
9781
9781
  var extrudeRotate = require_extrudeRotate();
9782
9782
  var { rotate: rotate2 } = require_rotate3();
9783
- var { translate: translate6 } = require_translate2();
9783
+ var { translate: translate8 } = require_translate2();
9784
9784
  var circle = require_circle();
9785
9785
  var { isGT, isGTE } = require_commonChecks();
9786
9786
  var torus = (options) => {
@@ -9805,7 +9805,7 @@ var require_torus = __commonJS({
9805
9805
  if (innerRotation !== 0) {
9806
9806
  innerCircle = rotate2([0, 0, innerRotation], innerCircle);
9807
9807
  }
9808
- innerCircle = translate6([outerRadius, 0], innerCircle);
9808
+ innerCircle = translate8([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, line3) => {
10151
+ var translateLine = (options, line4) => {
10152
10152
  const { x, y } = Object.assign({ x: 0, y: 0 }, options || {});
10153
- const segments = line3.segments;
10153
+ const segments = line4.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 line3;
10163
+ return line4;
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 line3 = { width: 0, segments: [] };
10179
+ let line4 = { 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(line3);
10186
- maxWidth = Math.max(maxWidth, line3.width);
10187
- line3 = { width: 0, segments: [] };
10185
+ lines.push(line4);
10186
+ maxWidth = Math.max(maxWidth, line4.width);
10187
+ line4 = { 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
- line3.width += width10;
10199
+ line4.width += width10;
10200
10200
  x += width10;
10201
10201
  if (char !== " ") {
10202
- line3.segments = line3.segments.concat(vect.segments);
10202
+ line4.segments = line4.segments.concat(vect.segments);
10203
10203
  }
10204
10204
  }
10205
- if (line3.segments.length) {
10205
+ if (line4.segments.length) {
10206
10206
  pushLine();
10207
10207
  }
10208
10208
  for (i = 0, il = lines.length; i < il; i++) {
10209
- line3 = lines[i];
10210
- if (maxWidth > line3.width) {
10211
- diff = maxWidth - line3.width;
10209
+ line4 = lines[i];
10210
+ if (maxWidth > line4.width) {
10211
+ diff = maxWidth - line4.width;
10212
10212
  if (align === "right") {
10213
- line3 = translateLine({ x: diff }, line3);
10213
+ line4 = translateLine({ x: diff }, line4);
10214
10214
  } else if (align === "center") {
10215
- line3 = translateLine({ x: diff / 2 }, line3);
10215
+ line4 = translateLine({ x: diff / 2 }, line4);
10216
10216
  }
10217
10217
  }
10218
- output = output.concat(line3.segments);
10218
+ output = output.concat(line4.segments);
10219
10219
  }
10220
10220
  return output;
10221
10221
  };
@@ -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 subtract4 = (...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 = subtract4;
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 subtract4 = (...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 = subtract4;
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 subtract4 = (...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 = subtract4;
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 union3 = (...geometries) => {
11712
+ var union4 = (...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 = union3;
11722
+ module.exports = union4;
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 union3 = (...geometries) => {
11736
+ var union4 = (...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 = union3;
11743
+ module.exports = union4;
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 union3 = (...geometries) => {
11757
+ var union4 = (...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 = union3;
11768
+ module.exports = union4;
11769
11769
  }
11770
11770
  });
11771
11771
 
@@ -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 union3 = require_union();
12158
+ var union4 = 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 union3(geometry, expanded);
12174
+ return union4(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 expand4 = (options, ...objects) => {
12272
+ var expand5 = (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 = expand4;
12283
+ module.exports = expand5;
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 extrudeLinear5 = (options, ...objects) => {
12454
+ var extrudeLinear7 = (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 = extrudeLinear5;
12472
+ module.exports = extrudeLinear7;
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 expand4 = require_expand();
12481
+ var expand5 = 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 = expand4(options, geometry);
12493
+ const newgeometry = expand5(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 expand4 = require_expand();
12507
+ var expand5 = 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 expand4(options, path2.fromPoints({ closed: true }, outline));
12521
+ return expand5(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 union3 = require_union();
12889
+ var union4 = 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 union3(hulls);
12898
+ return union4(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: translate6 } = require_translate2();
13531
+ var { translate: translate8 } = 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 translate6(translation, geometry);
13568
+ return translate8(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: translate6 } = require_translate2();
13605
+ var { translate: translate8 } = 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 translate6(offset4, object);
13617
+ return translate8(offset4, object);
13618
13618
  };
13619
13619
  var center = (options, ...objects) => {
13620
13620
  const defaults = {
@@ -24177,7 +24177,7 @@ var m2host = (raw_params) => {
24177
24177
  }
24178
24178
  const centerX = (minX + maxX) / 2;
24179
24179
  const centerY = (minY + maxY) / 2;
24180
- const translate6 = (el) => {
24180
+ const translate8 = (el) => {
24181
24181
  if (typeof el.x === "number") el.x -= centerX;
24182
24182
  if (typeof el.y === "number") el.y -= centerY;
24183
24183
  if (el.center) {
@@ -24191,9 +24191,9 @@ var m2host = (raw_params) => {
24191
24191
  }));
24192
24192
  }
24193
24193
  };
24194
- for (const pad2 of pads) translate6(pad2);
24195
- translate6(cutout);
24196
- translate6(pin1Marker);
24194
+ for (const pad2 of pads) translate8(pad2);
24195
+ translate8(cutout);
24196
+ translate8(pin1Marker);
24197
24197
  return {
24198
24198
  circuitJson: [
24199
24199
  ...pads,
@@ -26647,7 +26647,7 @@ import * as THREE14 from "three";
26647
26647
  // package.json
26648
26648
  var package_default = {
26649
26649
  name: "@tscircuit/3d-viewer",
26650
- version: "0.0.421",
26650
+ version: "0.0.423",
26651
26651
  main: "./dist/index.js",
26652
26652
  module: "./dist/index.js",
26653
26653
  type: "module",
@@ -27810,10 +27810,10 @@ var createBoardGeomFromCircuitJson = (circuitJson, opts = {}) => {
27810
27810
  };
27811
27811
 
27812
27812
  // src/BoardGeomBuilder.ts
27813
- var import_transforms4 = __toESM(require_transforms(), 1);
27814
- var import_primitives6 = __toESM(require_primitives(), 1);
27815
- var import_colors4 = __toESM(require_colors(), 1);
27816
- var import_booleans3 = __toESM(require_booleans(), 1);
27813
+ var import_transforms6 = __toESM(require_transforms(), 1);
27814
+ var import_primitives8 = __toESM(require_primitives(), 1);
27815
+ var import_colors6 = __toESM(require_colors(), 1);
27816
+ var import_booleans4 = __toESM(require_booleans(), 1);
27817
27817
  import { su as su3 } from "@tscircuit/circuit-json-util";
27818
27818
 
27819
27819
  // src/geoms/plated-hole.ts
@@ -28196,8 +28196,8 @@ var platedHole = (plated_hole, ctx, options = {}) => {
28196
28196
  };
28197
28197
 
28198
28198
  // src/BoardGeomBuilder.ts
28199
- var import_extrusions4 = __toESM(require_extrusions(), 1);
28200
- var import_expansions3 = __toESM(require_expansions(), 1);
28199
+ var import_extrusions6 = __toESM(require_extrusions(), 1);
28200
+ var import_expansions4 = __toESM(require_expansions(), 1);
28201
28201
 
28202
28202
  // src/geoms/create-geoms-for-silkscreen-text.ts
28203
28203
  var import_text = __toESM(require_text(), 1);
@@ -28333,10 +28333,10 @@ peg$SyntaxError.prototype.format = function(sources) {
28333
28333
  if (src) {
28334
28334
  var e = this.location.end;
28335
28335
  var filler = peg$padEnd("", offset_s.line.toString().length, " ");
28336
- var line3 = src[s.line - 1];
28337
- var last = s.line === e.line ? e.column : line3.length + 1;
28336
+ var line4 = src[s.line - 1];
28337
+ var last = s.line === e.line ? e.column : line4.length + 1;
28338
28338
  var hatLen = last - s.column || 1;
28339
- str += "\n --> " + loc + "\n" + filler + " |\n" + offset_s.line + " | " + line3 + "\n" + filler + " | " + peg$padEnd("", s.column - 1, " ") + peg$padEnd("", hatLen, "^");
28339
+ str += "\n --> " + loc + "\n" + filler + " |\n" + offset_s.line + " | " + line4 + "\n" + filler + " | " + peg$padEnd("", s.column - 1, " ") + peg$padEnd("", hatLen, "^");
28340
28340
  } else {
28341
28341
  str += "\n at " + loc;
28342
28342
  }
@@ -28506,11 +28506,61 @@ var import_expansions2 = __toESM(require_expansions(), 1);
28506
28506
  var import_extrusions3 = __toESM(require_extrusions(), 1);
28507
28507
  var import_transforms3 = __toESM(require_transforms(), 1);
28508
28508
  var import_colors3 = __toESM(require_colors(), 1);
28509
+
28510
+ // src/utils/units.ts
28511
+ var MM_PER_INCH = 25.4;
28512
+ var MM_PER_MIL = MM_PER_INCH / 1e3;
28513
+ var dimensionRegex = /^\s*(-?\d*(?:\.\d+)?)(?:\s*(mm|mil|inch|in|"))?\s*$/i;
28514
+ function normalizeUnit(unit) {
28515
+ if (!unit) return void 0;
28516
+ const normalized = unit.trim().toLowerCase();
28517
+ if (normalized === '"') return "in";
28518
+ if (normalized === "inch") return "in";
28519
+ return normalized;
28520
+ }
28521
+ function parseDimensionToMm(value) {
28522
+ if (value === null || value === void 0) return void 0;
28523
+ if (typeof value === "number") {
28524
+ return Number.isFinite(value) ? value : void 0;
28525
+ }
28526
+ if (typeof value !== "string") return void 0;
28527
+ const trimmed = value.trim();
28528
+ if (trimmed.length === 0) return void 0;
28529
+ const match = trimmed.match(dimensionRegex);
28530
+ if (!match) {
28531
+ const numeric = Number.parseFloat(trimmed);
28532
+ return Number.isFinite(numeric) ? numeric : void 0;
28533
+ }
28534
+ const [, magnitudeRaw, unitRaw] = match;
28535
+ const magnitude = Number.parseFloat(magnitudeRaw || "0");
28536
+ if (!Number.isFinite(magnitude)) return void 0;
28537
+ const unit = normalizeUnit(unitRaw);
28538
+ switch (unit) {
28539
+ case "mil":
28540
+ return magnitude * MM_PER_MIL;
28541
+ case "in":
28542
+ return magnitude * MM_PER_INCH;
28543
+ case "mm":
28544
+ case void 0:
28545
+ return magnitude;
28546
+ default:
28547
+ return magnitude;
28548
+ }
28549
+ }
28550
+ function coerceDimensionToMm(value, fallback) {
28551
+ const parsed = parseDimensionToMm(value);
28552
+ return parsed === void 0 ? fallback : parsed;
28553
+ }
28554
+
28555
+ // src/geoms/create-geoms-for-silkscreen-path.ts
28509
28556
  function createSilkscreenPathGeom(sp, ctx) {
28510
28557
  if (sp.route.length < 2) return void 0;
28511
- const routePoints = sp.route.map((p) => [p.x, p.y]);
28558
+ const routePoints = sp.route.map((p) => [
28559
+ parseDimensionToMm(p.x) ?? 0,
28560
+ parseDimensionToMm(p.y) ?? 0
28561
+ ]);
28512
28562
  const pathLine = (0, import_primitives4.line)(routePoints);
28513
- const strokeWidth = sp.stroke_width || 0.1;
28563
+ const strokeWidth = coerceDimensionToMm(sp.stroke_width, 0.1);
28514
28564
  const expandedPath = (0, import_expansions2.expand)(
28515
28565
  { delta: strokeWidth / 2, corners: "round" },
28516
28566
  pathLine
@@ -28526,9 +28576,103 @@ function createSilkscreenPathGeom(sp, ctx) {
28526
28576
  return pathGeom;
28527
28577
  }
28528
28578
 
28529
- // src/geoms/brep-converter.ts
28579
+ // src/geoms/create-geoms-for-silkscreen-line.ts
28530
28580
  var import_primitives5 = __toESM(require_primitives(), 1);
28581
+ var import_expansions3 = __toESM(require_expansions(), 1);
28582
+ var import_extrusions4 = __toESM(require_extrusions(), 1);
28583
+ var import_transforms4 = __toESM(require_transforms(), 1);
28584
+ var import_colors4 = __toESM(require_colors(), 1);
28585
+ function createSilkscreenLineGeom(sl, ctx) {
28586
+ const x1 = parseDimensionToMm(sl.x1) ?? 0;
28587
+ const y1 = parseDimensionToMm(sl.y1) ?? 0;
28588
+ const x2 = parseDimensionToMm(sl.x2) ?? 0;
28589
+ const y2 = parseDimensionToMm(sl.y2) ?? 0;
28590
+ if (x1 === x2 && y1 === y2) return void 0;
28591
+ const routePoints = [
28592
+ [x1, y1],
28593
+ [x2, y2]
28594
+ ];
28595
+ const baseLine = (0, import_primitives5.line)(routePoints);
28596
+ const strokeWidth = coerceDimensionToMm(sl.stroke_width, 0.1);
28597
+ const expandedLine = (0, import_expansions3.expand)(
28598
+ { delta: strokeWidth / 2, corners: "round" },
28599
+ baseLine
28600
+ );
28601
+ const layerSign = sl.layer === "bottom" ? -1 : 1;
28602
+ const zPos = layerSign * ctx.pcbThickness / 2 + layerSign * M * 1.5;
28603
+ let lineGeom = (0, import_transforms4.translate)(
28604
+ [0, 0, zPos],
28605
+ (0, import_extrusions4.extrudeLinear)({ height: 0.012 }, expandedLine)
28606
+ );
28607
+ lineGeom = (0, import_colors4.colorize)([1, 1, 1], lineGeom);
28608
+ return lineGeom;
28609
+ }
28610
+
28611
+ // src/geoms/create-geoms-for-silkscreen-rect.ts
28612
+ var import_primitives6 = __toESM(require_primitives(), 1);
28613
+ var import_extrusions5 = __toESM(require_extrusions(), 1);
28614
+ var import_transforms5 = __toESM(require_transforms(), 1);
28615
+ var import_colors5 = __toESM(require_colors(), 1);
28531
28616
  var import_booleans2 = __toESM(require_booleans(), 1);
28617
+ var RECT_SEGMENTS = 64;
28618
+ function createSilkscreenRectGeom(rect, ctx) {
28619
+ const width10 = coerceDimensionToMm(rect.width, 0);
28620
+ const height10 = coerceDimensionToMm(rect.height, 0);
28621
+ if (width10 <= 0 || height10 <= 0) return void 0;
28622
+ const centerX = parseDimensionToMm(rect.center?.x) ?? 0;
28623
+ const centerY = parseDimensionToMm(rect.center?.y) ?? 0;
28624
+ const rawBorderRadius = extractRectBorderRadius(rect);
28625
+ const borderRadius = clampRectBorderRadius(
28626
+ width10,
28627
+ height10,
28628
+ typeof rawBorderRadius === "string" ? parseDimensionToMm(rawBorderRadius) : rawBorderRadius
28629
+ );
28630
+ const createRectGeom = (rectWidth, rectHeight, radius) => (0, import_extrusions5.extrudeLinear)(
28631
+ { height: 0.012 },
28632
+ (0, import_primitives6.roundedRectangle)({
28633
+ size: [rectWidth, rectHeight],
28634
+ roundRadius: radius,
28635
+ segments: RECT_SEGMENTS
28636
+ })
28637
+ );
28638
+ const isFilled = rect.is_filled ?? true;
28639
+ const hasStroke = rect.has_stroke ?? false;
28640
+ const strokeWidth = hasStroke ? coerceDimensionToMm(rect.stroke_width, 0.1) : 0;
28641
+ let fillGeom;
28642
+ if (isFilled) {
28643
+ fillGeom = createRectGeom(width10, height10, borderRadius);
28644
+ }
28645
+ let strokeGeom;
28646
+ if (hasStroke && strokeWidth > 0) {
28647
+ const outerGeom = createRectGeom(width10, height10, borderRadius);
28648
+ const innerWidth = width10 - strokeWidth * 2;
28649
+ const innerHeight = height10 - strokeWidth * 2;
28650
+ if (innerWidth > 0 && innerHeight > 0) {
28651
+ const innerRadius = clampRectBorderRadius(
28652
+ innerWidth,
28653
+ innerHeight,
28654
+ Math.max(borderRadius - strokeWidth, 0)
28655
+ );
28656
+ const innerGeom = createRectGeom(innerWidth, innerHeight, innerRadius);
28657
+ strokeGeom = (0, import_booleans2.subtract)(outerGeom, innerGeom);
28658
+ } else {
28659
+ strokeGeom = outerGeom;
28660
+ }
28661
+ }
28662
+ let rectGeom = fillGeom;
28663
+ if (strokeGeom) {
28664
+ rectGeom = rectGeom ? (0, import_booleans2.union)(rectGeom, strokeGeom) : strokeGeom;
28665
+ }
28666
+ if (!rectGeom) return void 0;
28667
+ const layerSign = rect.layer === "bottom" ? -1 : 1;
28668
+ const zPos = layerSign * ctx.pcbThickness / 2 + layerSign * M * 1.5;
28669
+ rectGeom = (0, import_transforms5.translate)([centerX, centerY, zPos], rectGeom);
28670
+ return (0, import_colors5.colorize)([1, 1, 1], rectGeom);
28671
+ }
28672
+
28673
+ // src/geoms/brep-converter.ts
28674
+ var import_primitives7 = __toESM(require_primitives(), 1);
28675
+ var import_booleans3 = __toESM(require_booleans(), 1);
28532
28676
  function segmentToPoints(p1, p2, bulge, arcSegments) {
28533
28677
  if (!bulge || Math.abs(bulge) < 1e-9) {
28534
28678
  return [];
@@ -28596,7 +28740,7 @@ function createGeom2FromBRep(brep, arcSegments = 16) {
28596
28740
  if (arePointsClockwise2(outerPoints)) {
28597
28741
  outerPoints.reverse();
28598
28742
  }
28599
- const outerGeom = (0, import_primitives5.polygon)({ points: outerPoints });
28743
+ const outerGeom = (0, import_primitives7.polygon)({ points: outerPoints });
28600
28744
  if (!brep.inner_rings || brep.inner_rings.length === 0) {
28601
28745
  return outerGeom;
28602
28746
  }
@@ -28605,10 +28749,10 @@ function createGeom2FromBRep(brep, arcSegments = 16) {
28605
28749
  if (arePointsClockwise2(innerPoints)) {
28606
28750
  innerPoints.reverse();
28607
28751
  }
28608
- return (0, import_primitives5.polygon)({ points: innerPoints });
28752
+ return (0, import_primitives7.polygon)({ points: innerPoints });
28609
28753
  });
28610
28754
  if (innerGeoms.length === 0) return outerGeom;
28611
- return (0, import_booleans2.subtract)(outerGeom, innerGeoms);
28755
+ return (0, import_booleans3.subtract)(outerGeom, innerGeoms);
28612
28756
  }
28613
28757
 
28614
28758
  // src/BoardGeomBuilder.ts
@@ -28618,15 +28762,15 @@ var BOARD_CLIP_XY_OUTSET = 0.05;
28618
28762
  var createCenteredRectPadGeom = (width10, height10, thickness, rectBorderRadius) => {
28619
28763
  const clampedRadius = clampRectBorderRadius(width10, height10, rectBorderRadius);
28620
28764
  if (clampedRadius <= 0) {
28621
- return (0, import_primitives6.cuboid)({ center: [0, 0, 0], size: [width10, height10, thickness] });
28765
+ return (0, import_primitives8.cuboid)({ center: [0, 0, 0], size: [width10, height10, thickness] });
28622
28766
  }
28623
- const rect2d = (0, import_primitives6.roundedRectangle)({
28767
+ const rect2d = (0, import_primitives8.roundedRectangle)({
28624
28768
  size: [width10, height10],
28625
28769
  roundRadius: clampedRadius,
28626
28770
  segments: PAD_ROUNDED_SEGMENTS
28627
28771
  });
28628
- const extruded = (0, import_extrusions4.extrudeLinear)({ height: thickness }, rect2d);
28629
- return (0, import_transforms4.translate)([0, 0, -thickness / 2], extruded);
28772
+ const extruded = (0, import_extrusions6.extrudeLinear)({ height: thickness }, rect2d);
28773
+ return (0, import_transforms6.translate)([0, 0, -thickness / 2], extruded);
28630
28774
  };
28631
28775
  var buildStateOrder = [
28632
28776
  "initializing",
@@ -28638,6 +28782,8 @@ var buildStateOrder = [
28638
28782
  "processing_traces",
28639
28783
  "processing_vias",
28640
28784
  "processing_silkscreen_text",
28785
+ "processing_silkscreen_lines",
28786
+ "processing_silkscreen_rects",
28641
28787
  "processing_silkscreen_paths",
28642
28788
  "finalizing",
28643
28789
  "done"
@@ -28652,6 +28798,8 @@ var BoardGeomBuilder = class {
28652
28798
  pcb_vias;
28653
28799
  silkscreenTexts;
28654
28800
  silkscreenPaths;
28801
+ silkscreenLines;
28802
+ silkscreenRects;
28655
28803
  pcb_cutouts;
28656
28804
  pcb_copper_pours;
28657
28805
  boardGeom = null;
@@ -28664,6 +28812,8 @@ var BoardGeomBuilder = class {
28664
28812
  // Combined with platedHoleGeoms
28665
28813
  silkscreenTextGeoms = [];
28666
28814
  silkscreenPathGeoms = [];
28815
+ silkscreenLineGeoms = [];
28816
+ silkscreenRectGeoms = [];
28667
28817
  copperPourGeoms = [];
28668
28818
  boardClipGeom = null;
28669
28819
  state = "initializing";
@@ -28697,6 +28847,8 @@ var BoardGeomBuilder = class {
28697
28847
  this.pcb_vias = su3(circuitJson).pcb_via.list();
28698
28848
  this.silkscreenTexts = su3(circuitJson).pcb_silkscreen_text.list();
28699
28849
  this.silkscreenPaths = su3(circuitJson).pcb_silkscreen_path.list();
28850
+ this.silkscreenLines = su3(circuitJson).pcb_silkscreen_line.list();
28851
+ this.silkscreenRects = su3(circuitJson).pcb_silkscreen_rect.list();
28700
28852
  this.pcb_cutouts = su3(circuitJson).pcb_cutout.list();
28701
28853
  this.pcb_copper_pours = circuitJson.filter(
28702
28854
  (e) => e.type === "pcb_copper_pour"
@@ -28721,11 +28873,11 @@ var BoardGeomBuilder = class {
28721
28873
  { xyOutset: BOARD_CLIP_XY_OUTSET }
28722
28874
  );
28723
28875
  } else {
28724
- this.boardGeom = (0, import_primitives6.cuboid)({
28876
+ this.boardGeom = (0, import_primitives8.cuboid)({
28725
28877
  size: [this.board.width, this.board.height, this.ctx.pcbThickness],
28726
28878
  center: [this.board.center.x, this.board.center.y, 0]
28727
28879
  });
28728
- this.boardClipGeom = (0, import_primitives6.cuboid)({
28880
+ this.boardClipGeom = (0, import_primitives8.cuboid)({
28729
28881
  size: [
28730
28882
  this.board.width + 2 * BOARD_CLIP_XY_OUTSET,
28731
28883
  this.board.height + 2 * BOARD_CLIP_XY_OUTSET,
@@ -28797,6 +28949,22 @@ var BoardGeomBuilder = class {
28797
28949
  this.goToNextState();
28798
28950
  }
28799
28951
  break;
28952
+ case "processing_silkscreen_lines":
28953
+ if (this.currentIndex < this.silkscreenLines.length) {
28954
+ this.processSilkscreenLine(this.silkscreenLines[this.currentIndex]);
28955
+ this.currentIndex++;
28956
+ } else {
28957
+ this.goToNextState();
28958
+ }
28959
+ break;
28960
+ case "processing_silkscreen_rects":
28961
+ if (this.currentIndex < this.silkscreenRects.length) {
28962
+ this.processSilkscreenRect(this.silkscreenRects[this.currentIndex]);
28963
+ this.currentIndex++;
28964
+ } else {
28965
+ this.goToNextState();
28966
+ }
28967
+ break;
28800
28968
  case "processing_silkscreen_paths":
28801
28969
  if (this.currentIndex < this.silkscreenPaths.length) {
28802
28970
  this.processSilkscreenPath(this.silkscreenPaths[this.currentIndex]);
@@ -28835,17 +29003,17 @@ var BoardGeomBuilder = class {
28835
29003
  const cutoutHeight = this.ctx.pcbThickness * 1.5;
28836
29004
  switch (cutout.shape) {
28837
29005
  case "rect":
28838
- cutoutGeom = (0, import_primitives6.cuboid)({
29006
+ cutoutGeom = (0, import_primitives8.cuboid)({
28839
29007
  center: [cutout.center.x, cutout.center.y, 0],
28840
29008
  size: [cutout.width, cutout.height, cutoutHeight]
28841
29009
  });
28842
29010
  if (cutout.rotation) {
28843
29011
  const rotationRadians = cutout.rotation * Math.PI / 180;
28844
- cutoutGeom = (0, import_transforms4.rotateZ)(rotationRadians, cutoutGeom);
29012
+ cutoutGeom = (0, import_transforms6.rotateZ)(rotationRadians, cutoutGeom);
28845
29013
  }
28846
29014
  break;
28847
29015
  case "circle":
28848
- cutoutGeom = (0, import_primitives6.cylinder)({
29016
+ cutoutGeom = (0, import_primitives8.cylinder)({
28849
29017
  center: [cutout.center.x, cutout.center.y, 0],
28850
29018
  radius: cutout.radius,
28851
29019
  height: cutoutHeight
@@ -28862,13 +29030,13 @@ var BoardGeomBuilder = class {
28862
29030
  if (arePointsClockwise(pointsVec2)) {
28863
29031
  pointsVec2 = pointsVec2.reverse();
28864
29032
  }
28865
- const polygon2d = (0, import_primitives6.polygon)({ points: pointsVec2 });
28866
- cutoutGeom = (0, import_extrusions4.extrudeLinear)({ height: cutoutHeight }, polygon2d);
28867
- cutoutGeom = (0, import_transforms4.translate)([0, 0, -cutoutHeight / 2], cutoutGeom);
29033
+ const polygon2d = (0, import_primitives8.polygon)({ points: pointsVec2 });
29034
+ cutoutGeom = (0, import_extrusions6.extrudeLinear)({ height: cutoutHeight }, polygon2d);
29035
+ cutoutGeom = (0, import_transforms6.translate)([0, 0, -cutoutHeight / 2], cutoutGeom);
28868
29036
  break;
28869
29037
  }
28870
29038
  if (cutoutGeom) {
28871
- this.boardGeom = (0, import_booleans3.subtract)(this.boardGeom, cutoutGeom);
29039
+ this.boardGeom = (0, import_booleans4.subtract)(this.boardGeom, cutoutGeom);
28872
29040
  }
28873
29041
  }
28874
29042
  processCopperPour(pour) {
@@ -28876,22 +29044,22 @@ var BoardGeomBuilder = class {
28876
29044
  const zPos = layerSign * this.ctx.pcbThickness / 2 + layerSign * BOARD_SURFACE_OFFSET.copper;
28877
29045
  let pourGeom = null;
28878
29046
  if (pour.shape === "rect") {
28879
- let baseGeom = (0, import_primitives6.cuboid)({
29047
+ let baseGeom = (0, import_primitives8.cuboid)({
28880
29048
  center: [0, 0, 0],
28881
29049
  // Create at origin for rotation
28882
29050
  size: [pour.width, pour.height, M]
28883
29051
  });
28884
29052
  if ("rotation" in pour && pour.rotation) {
28885
29053
  const rotationRadians = pour.rotation * Math.PI / 180;
28886
- baseGeom = (0, import_transforms4.rotateZ)(rotationRadians, baseGeom);
29054
+ baseGeom = (0, import_transforms6.rotateZ)(rotationRadians, baseGeom);
28887
29055
  }
28888
- pourGeom = (0, import_transforms4.translate)([pour.center.x, pour.center.y, zPos], baseGeom);
29056
+ pourGeom = (0, import_transforms6.translate)([pour.center.x, pour.center.y, zPos], baseGeom);
28889
29057
  } else if (pour.shape === "brep") {
28890
29058
  const brepShape = pour.brep_shape;
28891
29059
  if (brepShape && brepShape.outer_ring) {
28892
29060
  const pourGeom2 = createGeom2FromBRep(brepShape);
28893
- pourGeom = (0, import_extrusions4.extrudeLinear)({ height: M }, pourGeom2);
28894
- pourGeom = (0, import_transforms4.translate)([0, 0, zPos], pourGeom);
29061
+ pourGeom = (0, import_extrusions6.extrudeLinear)({ height: M }, pourGeom2);
29062
+ pourGeom = (0, import_transforms6.translate)([0, 0, zPos], pourGeom);
28895
29063
  }
28896
29064
  } else if (pour.shape === "polygon") {
28897
29065
  let pointsVec2 = pour.points.map((p) => [p.x, p.y]);
@@ -28904,15 +29072,15 @@ var BoardGeomBuilder = class {
28904
29072
  if (arePointsClockwise(pointsVec2)) {
28905
29073
  pointsVec2 = pointsVec2.reverse();
28906
29074
  }
28907
- const polygon2d = (0, import_primitives6.polygon)({ points: pointsVec2 });
28908
- pourGeom = (0, import_extrusions4.extrudeLinear)({ height: M }, polygon2d);
28909
- pourGeom = (0, import_transforms4.translate)([0, 0, zPos], pourGeom);
29075
+ const polygon2d = (0, import_primitives8.polygon)({ points: pointsVec2 });
29076
+ pourGeom = (0, import_extrusions6.extrudeLinear)({ height: M }, polygon2d);
29077
+ pourGeom = (0, import_transforms6.translate)([0, 0, zPos], pourGeom);
28910
29078
  }
28911
29079
  if (pourGeom) {
28912
29080
  if (this.boardClipGeom) {
28913
- pourGeom = (0, import_booleans3.intersect)(this.boardClipGeom, pourGeom);
29081
+ pourGeom = (0, import_booleans4.intersect)(this.boardClipGeom, pourGeom);
28914
29082
  }
28915
- const coloredPourGeom = (0, import_colors4.colorize)(colors.copper, pourGeom);
29083
+ const coloredPourGeom = (0, import_colors6.colorize)(colors.copper, pourGeom);
28916
29084
  this.copperPourGeoms.push(coloredPourGeom);
28917
29085
  }
28918
29086
  }
@@ -28921,7 +29089,7 @@ var BoardGeomBuilder = class {
28921
29089
  if (ph.shape === "circle" || ph.shape === "circular_hole_with_rect_pad") {
28922
29090
  let cyGeom = null;
28923
29091
  if (ph.shape === "circular_hole_with_rect_pad") {
28924
- cyGeom = (0, import_primitives6.cylinder)({
29092
+ cyGeom = (0, import_primitives8.cylinder)({
28925
29093
  center: [
28926
29094
  ph.x + (ph.hole_offset_x || 0),
28927
29095
  ph.y + (ph.hole_offset_y || 0),
@@ -28933,7 +29101,7 @@ var BoardGeomBuilder = class {
28933
29101
  // Ensure it cuts through
28934
29102
  });
28935
29103
  } else {
28936
- cyGeom = (0, import_primitives6.cylinder)({
29104
+ cyGeom = (0, import_primitives8.cylinder)({
28937
29105
  center: [ph.x, ph.y, 0],
28938
29106
  radius: ph.hole_diameter / 2 + M,
28939
29107
  // Add margin for subtraction
@@ -28942,10 +29110,10 @@ var BoardGeomBuilder = class {
28942
29110
  });
28943
29111
  }
28944
29112
  if (!opts.dontCutBoard) {
28945
- this.boardGeom = (0, import_booleans3.subtract)(this.boardGeom, cyGeom);
29113
+ this.boardGeom = (0, import_booleans4.subtract)(this.boardGeom, cyGeom);
28946
29114
  }
28947
29115
  this.padGeoms = this.padGeoms.map(
28948
- (pg) => (0, import_colors4.colorize)(colors.copper, (0, import_booleans3.subtract)(pg, cyGeom))
29116
+ (pg) => (0, import_colors6.colorize)(colors.copper, (0, import_booleans4.subtract)(pg, cyGeom))
28949
29117
  );
28950
29118
  const platedHoleGeom = platedHole(ph, this.ctx, {
28951
29119
  clipGeom: this.boardClipGeom
@@ -28959,8 +29127,8 @@ var BoardGeomBuilder = class {
28959
29127
  const rectLength = Math.abs(holeWidth - holeHeight);
28960
29128
  let pillHole;
28961
29129
  if (ph.shape === "pill_hole_with_rect_pad") {
28962
- pillHole = (0, import_booleans3.union)(
28963
- (0, import_primitives6.cuboid)({
29130
+ pillHole = (0, import_booleans4.union)(
29131
+ (0, import_primitives8.cuboid)({
28964
29132
  center: [
28965
29133
  ph.x + (ph.hole_offset_x || 0),
28966
29134
  ph.y + (ph.hole_offset_y || 0),
@@ -28968,7 +29136,7 @@ var BoardGeomBuilder = class {
28968
29136
  ],
28969
29137
  size: shouldRotate ? [holeHeight, rectLength, this.ctx.pcbThickness * 1.5] : [rectLength, holeHeight, this.ctx.pcbThickness * 1.5]
28970
29138
  }),
28971
- (0, import_primitives6.cylinder)({
29139
+ (0, import_primitives8.cylinder)({
28972
29140
  center: shouldRotate ? [
28973
29141
  ph.x + (ph.hole_offset_x || 0),
28974
29142
  ph.y + (ph.hole_offset_y || 0) - rectLength / 2,
@@ -28981,7 +29149,7 @@ var BoardGeomBuilder = class {
28981
29149
  radius: holeRadius,
28982
29150
  height: this.ctx.pcbThickness * 1.5
28983
29151
  }),
28984
- (0, import_primitives6.cylinder)({
29152
+ (0, import_primitives8.cylinder)({
28985
29153
  center: shouldRotate ? [
28986
29154
  ph.x + (ph.hole_offset_x || 0),
28987
29155
  ph.y + (ph.hole_offset_y || 0) + rectLength / 2,
@@ -28996,17 +29164,17 @@ var BoardGeomBuilder = class {
28996
29164
  })
28997
29165
  );
28998
29166
  } else {
28999
- pillHole = (0, import_booleans3.union)(
29000
- (0, import_primitives6.cuboid)({
29167
+ pillHole = (0, import_booleans4.union)(
29168
+ (0, import_primitives8.cuboid)({
29001
29169
  center: [ph.x, ph.y, 0],
29002
29170
  size: shouldRotate ? [holeHeight, rectLength, this.ctx.pcbThickness * 1.5] : [rectLength, holeHeight, this.ctx.pcbThickness * 1.5]
29003
29171
  }),
29004
- (0, import_primitives6.cylinder)({
29172
+ (0, import_primitives8.cylinder)({
29005
29173
  center: shouldRotate ? [ph.x, ph.y - rectLength / 2, 0] : [ph.x - rectLength / 2, ph.y, 0],
29006
29174
  radius: holeRadius,
29007
29175
  height: this.ctx.pcbThickness * 1.5
29008
29176
  }),
29009
- (0, import_primitives6.cylinder)({
29177
+ (0, import_primitives8.cylinder)({
29010
29178
  center: shouldRotate ? [ph.x, ph.y + rectLength / 2, 0] : [ph.x + rectLength / 2, ph.y, 0],
29011
29179
  radius: holeRadius,
29012
29180
  height: this.ctx.pcbThickness * 1.5
@@ -29014,10 +29182,10 @@ var BoardGeomBuilder = class {
29014
29182
  );
29015
29183
  }
29016
29184
  if (!opts.dontCutBoard) {
29017
- this.boardGeom = (0, import_booleans3.subtract)(this.boardGeom, pillHole);
29185
+ this.boardGeom = (0, import_booleans4.subtract)(this.boardGeom, pillHole);
29018
29186
  }
29019
29187
  this.padGeoms = this.padGeoms.map(
29020
- (pg) => (0, import_colors4.colorize)(colors.copper, (0, import_booleans3.subtract)(pg, pillHole))
29188
+ (pg) => (0, import_colors6.colorize)(colors.copper, (0, import_booleans4.subtract)(pg, pillHole))
29021
29189
  );
29022
29190
  const platedHoleGeom = platedHole(ph, this.ctx, {
29023
29191
  clipGeom: this.boardClipGeom
@@ -29030,22 +29198,22 @@ var BoardGeomBuilder = class {
29030
29198
  const holeDepth = this.ctx.pcbThickness * 1.5;
29031
29199
  const copperInset = 0.02;
29032
29200
  if (hole.hole_shape === "round" || hole.hole_shape === "circle") {
29033
- const cyGeom = (0, import_primitives6.cylinder)({
29201
+ const cyGeom = (0, import_primitives8.cylinder)({
29034
29202
  center: [hole.x, hole.y, 0],
29035
29203
  radius: hole.hole_diameter / 2 + M,
29036
29204
  height: holeDepth
29037
29205
  });
29038
- this.boardGeom = (0, import_booleans3.subtract)(this.boardGeom, cyGeom);
29206
+ this.boardGeom = (0, import_booleans4.subtract)(this.boardGeom, cyGeom);
29039
29207
  this.padGeoms = this.padGeoms.map(
29040
- (pg) => (0, import_colors4.colorize)(colors.copper, (0, import_booleans3.subtract)(pg, cyGeom))
29208
+ (pg) => (0, import_colors6.colorize)(colors.copper, (0, import_booleans4.subtract)(pg, cyGeom))
29041
29209
  );
29042
- const copperCut = (0, import_primitives6.cylinder)({
29210
+ const copperCut = (0, import_primitives8.cylinder)({
29043
29211
  center: [hole.x, hole.y, 0],
29044
29212
  radius: hole.hole_diameter / 2 + M / 2,
29045
29213
  height: holeDepth
29046
29214
  });
29047
29215
  this.platedHoleGeoms = this.platedHoleGeoms.map(
29048
- (phg) => (0, import_colors4.colorize)(colors.copper, (0, import_booleans3.subtract)(phg, copperCut))
29216
+ (phg) => (0, import_colors6.colorize)(colors.copper, (0, import_booleans4.subtract)(phg, copperCut))
29049
29217
  );
29050
29218
  } else if (hole.hole_shape === "pill" || hole.hole_shape === "rotated_pill") {
29051
29219
  const holeWidth = hole.hole_width;
@@ -29055,34 +29223,34 @@ var BoardGeomBuilder = class {
29055
29223
  const isRotated = hole.hole_shape === "rotated_pill";
29056
29224
  let pillHole;
29057
29225
  if (holeWidth > holeHeight) {
29058
- pillHole = (0, import_booleans3.union)(
29059
- (0, import_primitives6.cuboid)({
29226
+ pillHole = (0, import_booleans4.union)(
29227
+ (0, import_primitives8.cuboid)({
29060
29228
  center: [hole.x, hole.y, 0],
29061
29229
  size: [rectLength, holeHeight, holeDepth]
29062
29230
  }),
29063
- (0, import_primitives6.cylinder)({
29231
+ (0, import_primitives8.cylinder)({
29064
29232
  center: [hole.x - rectLength / 2, hole.y, 0],
29065
29233
  radius: holeRadius,
29066
29234
  height: holeDepth
29067
29235
  }),
29068
- (0, import_primitives6.cylinder)({
29236
+ (0, import_primitives8.cylinder)({
29069
29237
  center: [hole.x + rectLength / 2, hole.y, 0],
29070
29238
  radius: holeRadius,
29071
29239
  height: holeDepth
29072
29240
  })
29073
29241
  );
29074
29242
  } else {
29075
- pillHole = (0, import_booleans3.union)(
29076
- (0, import_primitives6.cuboid)({
29243
+ pillHole = (0, import_booleans4.union)(
29244
+ (0, import_primitives8.cuboid)({
29077
29245
  center: [hole.x, hole.y, 0],
29078
29246
  size: [holeWidth, rectLength, holeDepth]
29079
29247
  }),
29080
- (0, import_primitives6.cylinder)({
29248
+ (0, import_primitives8.cylinder)({
29081
29249
  center: [hole.x, hole.y - rectLength / 2, 0],
29082
29250
  radius: holeRadius,
29083
29251
  height: holeDepth
29084
29252
  }),
29085
- (0, import_primitives6.cylinder)({
29253
+ (0, import_primitives8.cylinder)({
29086
29254
  center: [hole.x, hole.y + rectLength / 2, 0],
29087
29255
  radius: holeRadius,
29088
29256
  height: holeDepth
@@ -29091,15 +29259,15 @@ var BoardGeomBuilder = class {
29091
29259
  }
29092
29260
  if (isRotated) {
29093
29261
  const rotationRadians = hole.ccw_rotation * Math.PI / 180;
29094
- pillHole = (0, import_transforms4.rotateZ)(rotationRadians, pillHole);
29262
+ pillHole = (0, import_transforms6.rotateZ)(rotationRadians, pillHole);
29095
29263
  }
29096
- this.boardGeom = (0, import_booleans3.subtract)(this.boardGeom, pillHole);
29264
+ this.boardGeom = (0, import_booleans4.subtract)(this.boardGeom, pillHole);
29097
29265
  this.padGeoms = this.padGeoms.map(
29098
- (pg) => (0, import_colors4.colorize)(colors.copper, (0, import_booleans3.subtract)(pg, pillHole))
29266
+ (pg) => (0, import_colors6.colorize)(colors.copper, (0, import_booleans4.subtract)(pg, pillHole))
29099
29267
  );
29100
- const copperPill = (0, import_expansions3.expand)({ delta: -copperInset }, pillHole);
29268
+ const copperPill = (0, import_expansions4.expand)({ delta: -copperInset }, pillHole);
29101
29269
  this.platedHoleGeoms = this.platedHoleGeoms.map(
29102
- (phg) => (0, import_colors4.colorize)(colors.copper, (0, import_booleans3.subtract)(phg, copperPill))
29270
+ (phg) => (0, import_colors6.colorize)(colors.copper, (0, import_booleans4.subtract)(phg, copperPill))
29103
29271
  );
29104
29272
  }
29105
29273
  }
@@ -29114,12 +29282,12 @@ var BoardGeomBuilder = class {
29114
29282
  M,
29115
29283
  rectBorderRadius
29116
29284
  );
29117
- const positionedPadGeom = (0, import_transforms4.translate)([pad2.x, pad2.y, zPos], basePadGeom);
29285
+ const positionedPadGeom = (0, import_transforms6.translate)([pad2.x, pad2.y, zPos], basePadGeom);
29118
29286
  let finalPadGeom = positionedPadGeom;
29119
29287
  if (this.boardClipGeom) {
29120
- finalPadGeom = (0, import_booleans3.intersect)(this.boardClipGeom, finalPadGeom);
29288
+ finalPadGeom = (0, import_booleans4.intersect)(this.boardClipGeom, finalPadGeom);
29121
29289
  }
29122
- finalPadGeom = (0, import_colors4.colorize)(colors.copper, finalPadGeom);
29290
+ finalPadGeom = (0, import_colors6.colorize)(colors.copper, finalPadGeom);
29123
29291
  this.padGeoms.push(finalPadGeom);
29124
29292
  } else if (pad2.shape === "rotated_rect") {
29125
29293
  let basePadGeom = createCenteredRectPadGeom(
@@ -29129,24 +29297,24 @@ var BoardGeomBuilder = class {
29129
29297
  rectBorderRadius
29130
29298
  );
29131
29299
  const rotationRadians = pad2.ccw_rotation * Math.PI / 180;
29132
- basePadGeom = (0, import_transforms4.rotateZ)(rotationRadians, basePadGeom);
29133
- const positionedPadGeom = (0, import_transforms4.translate)([pad2.x, pad2.y, zPos], basePadGeom);
29300
+ basePadGeom = (0, import_transforms6.rotateZ)(rotationRadians, basePadGeom);
29301
+ const positionedPadGeom = (0, import_transforms6.translate)([pad2.x, pad2.y, zPos], basePadGeom);
29134
29302
  let finalPadGeom = positionedPadGeom;
29135
29303
  if (this.boardClipGeom) {
29136
- finalPadGeom = (0, import_booleans3.intersect)(this.boardClipGeom, finalPadGeom);
29304
+ finalPadGeom = (0, import_booleans4.intersect)(this.boardClipGeom, finalPadGeom);
29137
29305
  }
29138
- finalPadGeom = (0, import_colors4.colorize)(colors.copper, finalPadGeom);
29306
+ finalPadGeom = (0, import_colors6.colorize)(colors.copper, finalPadGeom);
29139
29307
  this.padGeoms.push(finalPadGeom);
29140
29308
  } else if (pad2.shape === "circle") {
29141
- let padGeom = (0, import_primitives6.cylinder)({
29309
+ let padGeom = (0, import_primitives8.cylinder)({
29142
29310
  center: [pad2.x, pad2.y, zPos],
29143
29311
  radius: pad2.radius,
29144
29312
  height: M
29145
29313
  });
29146
29314
  if (this.boardClipGeom) {
29147
- padGeom = (0, import_booleans3.intersect)(this.boardClipGeom, padGeom);
29315
+ padGeom = (0, import_booleans4.intersect)(this.boardClipGeom, padGeom);
29148
29316
  }
29149
- padGeom = (0, import_colors4.colorize)(colors.copper, padGeom);
29317
+ padGeom = (0, import_colors6.colorize)(colors.copper, padGeom);
29150
29318
  this.padGeoms.push(padGeom);
29151
29319
  }
29152
29320
  }
@@ -29160,14 +29328,14 @@ var BoardGeomBuilder = class {
29160
29328
  if (currentSegmentPoints.length >= 2 && currentLayer) {
29161
29329
  const layerSign = currentLayer === "bottom" ? -1 : 1;
29162
29330
  const zCenter = layerSign * this.ctx.pcbThickness / 2 + layerSign * BOARD_SURFACE_OFFSET.traces;
29163
- const linePath = (0, import_primitives6.line)(currentSegmentPoints);
29164
- const expandedPath = (0, import_expansions3.expand)(
29331
+ const linePath = (0, import_primitives8.line)(currentSegmentPoints);
29332
+ const expandedPath = (0, import_expansions4.expand)(
29165
29333
  { delta: currentWidth / 2, corners: "round" },
29166
29334
  linePath
29167
29335
  );
29168
- let traceGeom = (0, import_transforms4.translate)(
29336
+ let traceGeom = (0, import_transforms6.translate)(
29169
29337
  [0, 0, zCenter - M / 2],
29170
- (0, import_extrusions4.extrudeLinear)({ height: M }, expandedPath)
29338
+ (0, import_extrusions6.extrudeLinear)({ height: M }, expandedPath)
29171
29339
  );
29172
29340
  const startPointCoords = currentSegmentPoints[0];
29173
29341
  const endPointCoords = currentSegmentPoints[currentSegmentPoints.length - 1];
@@ -29176,27 +29344,27 @@ var BoardGeomBuilder = class {
29176
29344
  startPointCoords[1]
29177
29345
  );
29178
29346
  if (startHole) {
29179
- const cuttingCylinder = (0, import_primitives6.cylinder)({
29347
+ const cuttingCylinder = (0, import_primitives8.cylinder)({
29180
29348
  center: [startPointCoords[0], startPointCoords[1], zCenter],
29181
29349
  radius: startHole.diameter / 2 + M,
29182
29350
  height: M
29183
29351
  });
29184
- traceGeom = (0, import_booleans3.subtract)(traceGeom, cuttingCylinder);
29352
+ traceGeom = (0, import_booleans4.subtract)(traceGeom, cuttingCylinder);
29185
29353
  }
29186
29354
  const endHole = this.getHoleToCut(endPointCoords[0], endPointCoords[1]);
29187
29355
  if (endHole) {
29188
- const cuttingCylinder = (0, import_primitives6.cylinder)({
29356
+ const cuttingCylinder = (0, import_primitives8.cylinder)({
29189
29357
  center: [endPointCoords[0], endPointCoords[1], zCenter],
29190
29358
  radius: endHole.diameter / 2 + M,
29191
29359
  height: M
29192
29360
  });
29193
- traceGeom = (0, import_booleans3.subtract)(traceGeom, cuttingCylinder);
29361
+ traceGeom = (0, import_booleans4.subtract)(traceGeom, cuttingCylinder);
29194
29362
  }
29195
29363
  const tracesMaterialColor = tracesMaterialColors[this.board.material] ?? colors.fr4GreenSolderWithMask;
29196
29364
  if (this.boardClipGeom) {
29197
- traceGeom = (0, import_booleans3.intersect)(this.boardClipGeom, traceGeom);
29365
+ traceGeom = (0, import_booleans4.intersect)(this.boardClipGeom, traceGeom);
29198
29366
  }
29199
- traceGeom = (0, import_colors4.colorize)(tracesMaterialColor, traceGeom);
29367
+ traceGeom = (0, import_colors6.colorize)(tracesMaterialColor, traceGeom);
29200
29368
  this.traceGeoms.push(traceGeom);
29201
29369
  }
29202
29370
  currentSegmentPoints = [];
@@ -29263,31 +29431,31 @@ var BoardGeomBuilder = class {
29263
29431
  point2[0] + xOffset + st.anchor_position.x,
29264
29432
  point2[1] + yOffset + st.anchor_position.y
29265
29433
  ]);
29266
- const textPath = (0, import_primitives6.line)(alignedOutline);
29434
+ const textPath = (0, import_primitives8.line)(alignedOutline);
29267
29435
  const fontSize = st.font_size || 0.25;
29268
29436
  const expansionDelta = Math.min(
29269
29437
  Math.max(0.01, fontSize * 0.1),
29270
29438
  fontSize * 0.05
29271
29439
  );
29272
- const expandedPath = (0, import_expansions3.expand)(
29440
+ const expandedPath = (0, import_expansions4.expand)(
29273
29441
  { delta: expansionDelta, corners: "round" },
29274
29442
  textPath
29275
29443
  );
29276
29444
  let textGeom;
29277
29445
  if (st.layer === "bottom") {
29278
- textGeom = (0, import_transforms4.translate)(
29446
+ textGeom = (0, import_transforms6.translate)(
29279
29447
  [0, 0, -this.ctx.pcbThickness / 2 - M],
29280
29448
  // Position above board
29281
- (0, import_extrusions4.extrudeLinear)({ height: 0.012 }, expandedPath)
29449
+ (0, import_extrusions6.extrudeLinear)({ height: 0.012 }, expandedPath)
29282
29450
  );
29283
29451
  } else {
29284
- textGeom = (0, import_transforms4.translate)(
29452
+ textGeom = (0, import_transforms6.translate)(
29285
29453
  [0, 0, this.ctx.pcbThickness / 2 + M],
29286
29454
  // Position above board
29287
- (0, import_extrusions4.extrudeLinear)({ height: 0.012 }, expandedPath)
29455
+ (0, import_extrusions6.extrudeLinear)({ height: 0.012 }, expandedPath)
29288
29456
  );
29289
29457
  }
29290
- textGeom = (0, import_colors4.colorize)([1, 1, 1], textGeom);
29458
+ textGeom = (0, import_colors6.colorize)([1, 1, 1], textGeom);
29291
29459
  this.silkscreenTextGeoms.push(textGeom);
29292
29460
  }
29293
29461
  }
@@ -29297,10 +29465,22 @@ var BoardGeomBuilder = class {
29297
29465
  this.silkscreenPathGeoms.push(pathGeom);
29298
29466
  }
29299
29467
  }
29468
+ processSilkscreenLine(sl) {
29469
+ const lineGeom = createSilkscreenLineGeom(sl, this.ctx);
29470
+ if (lineGeom) {
29471
+ this.silkscreenLineGeoms.push(lineGeom);
29472
+ }
29473
+ }
29474
+ processSilkscreenRect(sr) {
29475
+ const rectGeom = createSilkscreenRectGeom(sr, this.ctx);
29476
+ if (rectGeom) {
29477
+ this.silkscreenRectGeoms.push(rectGeom);
29478
+ }
29479
+ }
29300
29480
  finalize() {
29301
29481
  if (!this.boardGeom) return;
29302
29482
  const boardMaterialColor = boardMaterialColors[this.board.material] ?? colors.fr4Green;
29303
- this.boardGeom = (0, import_colors4.colorize)(boardMaterialColor, this.boardGeom);
29483
+ this.boardGeom = (0, import_colors6.colorize)(boardMaterialColor, this.boardGeom);
29304
29484
  this.finalGeoms = [
29305
29485
  this.boardGeom,
29306
29486
  ...this.platedHoleGeoms,
@@ -29309,6 +29489,8 @@ var BoardGeomBuilder = class {
29309
29489
  ...this.viaGeoms,
29310
29490
  ...this.copperPourGeoms,
29311
29491
  ...this.silkscreenTextGeoms,
29492
+ ...this.silkscreenLineGeoms,
29493
+ ...this.silkscreenRectGeoms,
29312
29494
  ...this.silkscreenPathGeoms
29313
29495
  ];
29314
29496
  if (this.onCompleteCallback) {
@@ -29825,9 +30007,15 @@ function createSilkscreenTextureForLayer({
29825
30007
  }) {
29826
30008
  const pcbSilkscreenTexts = su6(circuitJson).pcb_silkscreen_text.list();
29827
30009
  const pcbSilkscreenPaths = su6(circuitJson).pcb_silkscreen_path.list();
30010
+ const pcbSilkscreenLines = su6(circuitJson).pcb_silkscreen_line.list();
30011
+ const pcbSilkscreenRects = su6(circuitJson).pcb_silkscreen_rect.list();
29828
30012
  const textsOnLayer = pcbSilkscreenTexts.filter((t) => t.layer === layer);
29829
30013
  const pathsOnLayer = pcbSilkscreenPaths.filter((p) => p.layer === layer);
29830
- if (textsOnLayer.length === 0 && pathsOnLayer.length === 0) return null;
30014
+ const linesOnLayer = pcbSilkscreenLines.filter((l) => l.layer === layer);
30015
+ const rectsOnLayer = pcbSilkscreenRects.filter((r) => r.layer === layer);
30016
+ if (textsOnLayer.length === 0 && pathsOnLayer.length === 0 && linesOnLayer.length === 0 && rectsOnLayer.length === 0) {
30017
+ return null;
30018
+ }
29831
30019
  const canvas = document.createElement("canvas");
29832
30020
  const canvasWidth = Math.floor(boardData.width * traceTextureResolution);
29833
30021
  const canvasHeight = Math.floor(boardData.height * traceTextureResolution);
@@ -29841,20 +30029,106 @@ function createSilkscreenTextureForLayer({
29841
30029
  }
29842
30030
  ctx.strokeStyle = silkscreenColor;
29843
30031
  ctx.fillStyle = silkscreenColor;
30032
+ const canvasXFromPcb = (pcbX) => (pcbX - boardData.center.x + boardData.width / 2) * traceTextureResolution;
30033
+ const canvasYFromPcb = (pcbY) => (-(pcbY - boardData.center.y) + boardData.height / 2) * traceTextureResolution;
30034
+ linesOnLayer.forEach((lineEl) => {
30035
+ const startXmm = parseDimensionToMm(lineEl.x1) ?? 0;
30036
+ const startYmm = parseDimensionToMm(lineEl.y1) ?? 0;
30037
+ const endXmm = parseDimensionToMm(lineEl.x2) ?? 0;
30038
+ const endYmm = parseDimensionToMm(lineEl.y2) ?? 0;
30039
+ if (startXmm === endXmm && startYmm === endYmm) return;
30040
+ ctx.beginPath();
30041
+ ctx.lineWidth = coerceDimensionToMm(lineEl.stroke_width, 0.1) * traceTextureResolution;
30042
+ ctx.lineCap = "round";
30043
+ ctx.moveTo(canvasXFromPcb(startXmm), canvasYFromPcb(startYmm));
30044
+ ctx.lineTo(canvasXFromPcb(endXmm), canvasYFromPcb(endYmm));
30045
+ ctx.stroke();
30046
+ });
29844
30047
  pathsOnLayer.forEach((path) => {
29845
30048
  if (path.route.length < 2) return;
29846
30049
  ctx.beginPath();
29847
- ctx.lineWidth = (path.stroke_width || 0.1) * traceTextureResolution;
30050
+ ctx.lineWidth = coerceDimensionToMm(path.stroke_width, 0.1) * traceTextureResolution;
29848
30051
  ctx.lineCap = "round";
29849
30052
  ctx.lineJoin = "round";
29850
30053
  path.route.forEach((point2, index2) => {
29851
- const canvasX = (point2.x - boardData.center.x + boardData.width / 2) * traceTextureResolution;
29852
- const canvasY = (-(point2.y - boardData.center.y) + boardData.height / 2) * traceTextureResolution;
30054
+ const canvasX = canvasXFromPcb(parseDimensionToMm(point2.x) ?? 0);
30055
+ const canvasY = canvasYFromPcb(parseDimensionToMm(point2.y) ?? 0);
29853
30056
  if (index2 === 0) ctx.moveTo(canvasX, canvasY);
29854
30057
  else ctx.lineTo(canvasX, canvasY);
29855
30058
  });
29856
30059
  ctx.stroke();
29857
30060
  });
30061
+ rectsOnLayer.forEach((rect) => {
30062
+ const width10 = coerceDimensionToMm(rect.width, 0);
30063
+ const height10 = coerceDimensionToMm(rect.height, 0);
30064
+ if (width10 <= 0 || height10 <= 0) return;
30065
+ const centerXmm = parseDimensionToMm(rect.center?.x) ?? 0;
30066
+ const centerYmm = parseDimensionToMm(rect.center?.y) ?? 0;
30067
+ const canvasCenterX = canvasXFromPcb(centerXmm);
30068
+ const canvasCenterY = canvasYFromPcb(centerYmm);
30069
+ const rawRadius = extractRectBorderRadius(rect);
30070
+ const borderRadiusInput = typeof rawRadius === "string" ? parseDimensionToMm(rawRadius) : rawRadius;
30071
+ const borderRadiusMm = clampRectBorderRadius(
30072
+ width10,
30073
+ height10,
30074
+ borderRadiusInput
30075
+ );
30076
+ ctx.save();
30077
+ ctx.translate(canvasCenterX, canvasCenterY);
30078
+ const halfWidthPx = width10 / 2 * traceTextureResolution;
30079
+ const halfHeightPx = height10 / 2 * traceTextureResolution;
30080
+ const borderRadiusPx = Math.min(
30081
+ borderRadiusMm * traceTextureResolution,
30082
+ halfWidthPx,
30083
+ halfHeightPx
30084
+ );
30085
+ const hasStroke = rect.has_stroke ?? false;
30086
+ const isFilled = rect.is_filled ?? true;
30087
+ const isDashed = rect.is_stroke_dashed ?? false;
30088
+ const strokeWidthPx = hasStroke ? coerceDimensionToMm(rect.stroke_width, 0.1) * traceTextureResolution : 0;
30089
+ const drawRoundedRectPath = (x, y, rectWidth, rectHeight, radius) => {
30090
+ ctx.beginPath();
30091
+ if (radius <= 0) {
30092
+ ctx.rect(x, y, rectWidth, rectHeight);
30093
+ } else {
30094
+ const r = radius;
30095
+ const right = x + rectWidth;
30096
+ const bottom = y + rectHeight;
30097
+ ctx.moveTo(x + r, y);
30098
+ ctx.lineTo(right - r, y);
30099
+ ctx.quadraticCurveTo(right, y, right, y + r);
30100
+ ctx.lineTo(right, bottom - r);
30101
+ ctx.quadraticCurveTo(right, bottom, right - r, bottom);
30102
+ ctx.lineTo(x + r, bottom);
30103
+ ctx.quadraticCurveTo(x, bottom, x, bottom - r);
30104
+ ctx.lineTo(x, y + r);
30105
+ ctx.quadraticCurveTo(x, y, x + r, y);
30106
+ ctx.closePath();
30107
+ }
30108
+ };
30109
+ drawRoundedRectPath(
30110
+ -halfWidthPx,
30111
+ -halfHeightPx,
30112
+ halfWidthPx * 2,
30113
+ halfHeightPx * 2,
30114
+ borderRadiusPx
30115
+ );
30116
+ if (isFilled) {
30117
+ ctx.fill();
30118
+ }
30119
+ if (hasStroke && strokeWidthPx > 0) {
30120
+ ctx.lineWidth = strokeWidthPx;
30121
+ if (isDashed) {
30122
+ const dashLength = Math.max(strokeWidthPx * 2, 1);
30123
+ ctx.setLineDash([dashLength, dashLength]);
30124
+ }
30125
+ ctx.stroke();
30126
+ if (isDashed) {
30127
+ ctx.setLineDash([]);
30128
+ }
30129
+ }
30130
+ ctx.restore();
30131
+ });
29858
30132
  textsOnLayer.forEach((textS) => {
29859
30133
  const fontSize = textS.font_size || 0.25;
29860
30134
  const textStrokeWidth = Math.min(Math.max(0.01, fontSize * 0.1), fontSize * 0.05) * traceTextureResolution;
@@ -29935,8 +30209,8 @@ function createSilkscreenTextureForLayer({
29935
30209
  }
29936
30210
  const pcbX = transformedP.x + xOff + textS.anchor_position.x;
29937
30211
  const pcbY = transformedP.y + yOff + textS.anchor_position.y;
29938
- const canvasX = (pcbX - boardData.center.x + boardData.width / 2) * traceTextureResolution;
29939
- const canvasY = (-(pcbY - boardData.center.y) + boardData.height / 2) * traceTextureResolution;
30212
+ const canvasX = canvasXFromPcb(pcbX);
30213
+ const canvasY = canvasYFromPcb(pcbY);
29940
30214
  if (index2 === 0) ctx.moveTo(canvasX, canvasY);
29941
30215
  else ctx.lineTo(canvasX, canvasY);
29942
30216
  });