@tscircuit/3d-viewer 0.0.436 → 0.0.438

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 +651 -270
  2. package/package.json +2 -2
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 rotateZ3 = (out, vector, origin, radians) => {
1056
+ var rotateZ4 = (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 = rotateZ3;
1068
+ module.exports = rotateZ4;
1069
1069
  }
1070
1070
  });
1071
1071
 
@@ -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 rotateZ3 = (out, matrix, radians) => {
1610
+ var rotateZ4 = (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 = rotateZ3;
1641
+ module.exports = rotateZ4;
1642
1642
  }
1643
1643
  });
1644
1644
 
@@ -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 translate9 = (out, matrix, offsets) => {
1715
+ var translate10 = (out, matrix, offsets) => {
1716
1716
  const x = offsets[0];
1717
1717
  const y = offsets[1];
1718
1718
  const z134 = offsets[2];
@@ -1765,7 +1765,7 @@ var require_translate = __commonJS({
1765
1765
  }
1766
1766
  return out;
1767
1767
  };
1768
- module.exports = translate9;
1768
+ module.exports = translate10;
1769
1769
  }
1770
1770
  });
1771
1771
 
@@ -7502,7 +7502,7 @@ var require_ellipse = __commonJS({
7502
7502
  var geom2 = require_geom2();
7503
7503
  var { sin: sin2, cos: cos2 } = require_trigonometry();
7504
7504
  var { isGTE, isNumberArray } = require_commonChecks();
7505
- var ellipse = (options) => {
7505
+ var ellipse2 = (options) => {
7506
7506
  const defaults = {
7507
7507
  center: [0, 0],
7508
7508
  radius: [1, 1],
@@ -7544,7 +7544,7 @@ var require_ellipse = __commonJS({
7544
7544
  if (rotation2 < TAU) points.push(centerv);
7545
7545
  return geom2.fromPoints(points);
7546
7546
  };
7547
- module.exports = ellipse;
7547
+ module.exports = ellipse2;
7548
7548
  }
7549
7549
  });
7550
7550
 
@@ -7553,7 +7553,7 @@ var require_circle = __commonJS({
7553
7553
  "node_modules/@jscad/modeling/src/primitives/circle.js"(exports, module) {
7554
7554
  "use strict";
7555
7555
  var { TAU } = require_constants();
7556
- var ellipse = require_ellipse();
7556
+ var ellipse2 = require_ellipse();
7557
7557
  var { isGTE } = require_commonChecks();
7558
7558
  var circle2 = (options) => {
7559
7559
  const defaults = {
@@ -7566,7 +7566,7 @@ var require_circle = __commonJS({
7566
7566
  let { center, radius, startAngle, endAngle, segments } = Object.assign({}, defaults, options);
7567
7567
  if (!isGTE(radius, 0)) throw new Error("radius must be positive");
7568
7568
  radius = [radius, radius];
7569
- return ellipse({ center, radius, startAngle, endAngle, segments });
7569
+ return ellipse2({ center, radius, startAngle, endAngle, segments });
7570
7570
  };
7571
7571
  module.exports = circle2;
7572
7572
  }
@@ -7579,7 +7579,7 @@ var require_cuboid = __commonJS({
7579
7579
  var geom3 = require_geom3();
7580
7580
  var poly3 = require_poly3();
7581
7581
  var { isNumberArray } = require_commonChecks();
7582
- var cuboid4 = (options) => {
7582
+ var cuboid5 = (options) => {
7583
7583
  const defaults = {
7584
7584
  center: [0, 0, 0],
7585
7585
  size: [2, 2, 2]
@@ -7612,7 +7612,7 @@ var require_cuboid = __commonJS({
7612
7612
  );
7613
7613
  return result;
7614
7614
  };
7615
- module.exports = cuboid4;
7615
+ module.exports = cuboid5;
7616
7616
  }
7617
7617
  });
7618
7618
 
@@ -7620,7 +7620,7 @@ var require_cuboid = __commonJS({
7620
7620
  var require_cube = __commonJS({
7621
7621
  "node_modules/@jscad/modeling/src/primitives/cube.js"(exports, module) {
7622
7622
  "use strict";
7623
- var cuboid4 = require_cuboid();
7623
+ var cuboid5 = require_cuboid();
7624
7624
  var { isGTE } = require_commonChecks();
7625
7625
  var cube = (options) => {
7626
7626
  const defaults = {
@@ -7630,7 +7630,7 @@ var require_cube = __commonJS({
7630
7630
  let { center, size: size5 } = Object.assign({}, defaults, options);
7631
7631
  if (!isGTE(size5, 0)) throw new Error("size must be positive");
7632
7632
  size5 = [size5, size5, size5];
7633
- return cuboid4({ center, size: size5 });
7633
+ return cuboid5({ center, size: size5 });
7634
7634
  };
7635
7635
  module.exports = cube;
7636
7636
  }
@@ -7745,7 +7745,7 @@ var require_cylinder = __commonJS({
7745
7745
  var geom3 = require_geom3();
7746
7746
  var cylinderElliptic = require_cylinderElliptic();
7747
7747
  var { isGTE } = require_commonChecks();
7748
- var cylinder3 = (options) => {
7748
+ var cylinder4 = (options) => {
7749
7749
  const defaults = {
7750
7750
  center: [0, 0, 0],
7751
7751
  height: 2,
@@ -7764,7 +7764,7 @@ var require_cylinder = __commonJS({
7764
7764
  };
7765
7765
  return cylinderElliptic(newoptions);
7766
7766
  };
7767
- module.exports = cylinder3;
7767
+ module.exports = cylinder4;
7768
7768
  }
7769
7769
  });
7770
7770
 
@@ -8133,7 +8133,7 @@ var require_roundedCuboid = __commonJS({
8133
8133
  var poly3 = require_poly3();
8134
8134
  var { sin: sin2, cos: cos2 } = require_trigonometry();
8135
8135
  var { isGTE, isNumberArray } = require_commonChecks();
8136
- var cuboid4 = require_cuboid();
8136
+ var cuboid5 = require_cuboid();
8137
8137
  var createCorners = (center, size5, radius, segments, slice, positive) => {
8138
8138
  const pitch = TAU / 4 * slice / segments;
8139
8139
  const cospitch = cos2(pitch);
@@ -8235,7 +8235,7 @@ var require_roundedCuboid = __commonJS({
8235
8235
  if (!isGTE(roundRadius, 0)) throw new Error("roundRadius must be positive");
8236
8236
  if (!isGTE(segments, 4)) throw new Error("segments must be four or more");
8237
8237
  if (size5[0] === 0 || size5[1] === 0 || size5[2] === 0) return geom3.create();
8238
- if (roundRadius === 0) return cuboid4({ center, size: size5 });
8238
+ if (roundRadius === 0) return cuboid5({ center, size: size5 });
8239
8239
  size5 = size5.map((v) => v / 2);
8240
8240
  if (roundRadius > size5[0] - EPS || roundRadius > size5[1] - EPS || roundRadius > size5[2] - EPS) throw new Error("roundRadius must be smaller than the radius of all dimensions");
8241
8241
  segments = Math.floor(segments / 4);
@@ -8285,7 +8285,7 @@ var require_roundedCylinder = __commonJS({
8285
8285
  var poly3 = require_poly3();
8286
8286
  var { sin: sin2, cos: cos2 } = require_trigonometry();
8287
8287
  var { isGTE, isNumberArray } = require_commonChecks();
8288
- var cylinder3 = require_cylinder();
8288
+ var cylinder4 = require_cylinder();
8289
8289
  var roundedCylinder = (options) => {
8290
8290
  const defaults = {
8291
8291
  center: [0, 0, 0],
@@ -8302,7 +8302,7 @@ var require_roundedCylinder = __commonJS({
8302
8302
  if (roundRadius > radius) throw new Error("roundRadius must be smaller than the radius");
8303
8303
  if (!isGTE(segments, 4)) throw new Error("segments must be four or more");
8304
8304
  if (height10 === 0 || radius === 0) return geom3.create();
8305
- if (roundRadius === 0) return cylinder3({ center, height: height10, radius });
8305
+ if (roundRadius === 0) return cylinder4({ center, height: height10, radius });
8306
8306
  const start = [0, 0, -(height10 / 2)];
8307
8307
  const end = [0, 0, height10 / 2];
8308
8308
  const direction = vec3.subtract(vec3.create(), end, start);
@@ -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 rotateZ3 = (angle, ...objects) => rotate2([0, 0, angle], objects);
9730
+ var rotateZ4 = (angle, ...objects) => rotate2([0, 0, angle], objects);
9731
9731
  module.exports = {
9732
9732
  rotate: rotate2,
9733
9733
  rotateX,
9734
9734
  rotateY,
9735
- rotateZ: rotateZ3
9735
+ rotateZ: rotateZ4
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 translate9 = (offset4, ...objects) => {
9749
+ var translate10 = (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) => translate9([offset4, 0, 0], objects);
9765
- var translateY = (offset4, ...objects) => translate9([0, offset4, 0], objects);
9766
- var translateZ = (offset4, ...objects) => translate9([0, 0, offset4], objects);
9764
+ var translateX = (offset4, ...objects) => translate10([offset4, 0, 0], objects);
9765
+ var translateY = (offset4, ...objects) => translate10([0, offset4, 0], objects);
9766
+ var translateZ = (offset4, ...objects) => translate10([0, 0, offset4], objects);
9767
9767
  module.exports = {
9768
- translate: translate9,
9768
+ translate: translate10,
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: translate9 } = require_translate2();
9783
+ var { translate: translate10 } = require_translate2();
9784
9784
  var circle2 = 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 = translate9([outerRadius, 0], innerCircle);
9808
+ innerCircle = translate10([outerRadius, 0], innerCircle);
9809
9809
  const extrudeOptions = {
9810
9810
  startAngle,
9811
9811
  angle: outerRotation,
@@ -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 union4 = (...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 = union4;
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 union4 = (...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 = union4;
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 union4 = (...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 = union4;
11768
+ module.exports = union5;
11769
11769
  }
11770
11770
  });
11771
11771
 
@@ -12110,8 +12110,8 @@ var require_expandShell = __commonJS({
12110
12110
  endfacevertices.reverse();
12111
12111
  polygons2.push(poly3.create(startfacevertices));
12112
12112
  polygons2.push(poly3.create(endfacevertices));
12113
- const cylinder3 = geom3.create(polygons2);
12114
- result = unionGeom3Sub(result, cylinder3);
12113
+ const cylinder4 = geom3.create(polygons2);
12114
+ result = unionGeom3Sub(result, cylinder4);
12115
12115
  });
12116
12116
  vertices2planes.forEach((item) => {
12117
12117
  const vertex = item[0];
@@ -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 union4 = 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 union4(geometry, expanded);
12174
+ return union5(geometry, expanded);
12175
12175
  };
12176
12176
  module.exports = expandGeom3;
12177
12177
  }
@@ -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 extrudeLinear8 = (options, ...objects) => {
12454
+ var extrudeLinear9 = (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 = extrudeLinear8;
12472
+ module.exports = extrudeLinear9;
12473
12473
  }
12474
12474
  });
12475
12475
 
@@ -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 union4 = 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 union4(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: translate9 } = require_translate2();
13531
+ var { translate: translate10 } = 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 translate9(translation, geometry);
13568
+ return translate10(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: translate9 } = require_translate2();
13605
+ var { translate: translate10 } = 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 translate9(offset4, object);
13617
+ return translate10(offset4, object);
13618
13618
  };
13619
13619
  var center = (options, ...objects) => {
13620
13620
  const defaults = {
@@ -15847,10 +15847,12 @@ var schematic_voltage_probe = z61.object({
15847
15847
  type: z61.literal("schematic_voltage_probe"),
15848
15848
  schematic_voltage_probe_id: z61.string(),
15849
15849
  source_component_id: z61.string().optional(),
15850
+ name: z61.string().optional(),
15850
15851
  position: point,
15851
15852
  schematic_trace_id: z61.string(),
15852
15853
  voltage: voltage.optional(),
15853
- subcircuit_id: z61.string().optional()
15854
+ subcircuit_id: z61.string().optional(),
15855
+ color: z61.string().optional()
15854
15856
  }).describe("Defines a voltage probe measurement point on a schematic trace");
15855
15857
  expectTypesMatch(true);
15856
15858
  var schematic_manual_edit_conflict_warning = z62.object({
@@ -15984,7 +15986,8 @@ var pcb_hole_circle = z71.object({
15984
15986
  hole_shape: z71.literal("circle"),
15985
15987
  hole_diameter: z71.number(),
15986
15988
  x: distance,
15987
- y: distance
15989
+ y: distance,
15990
+ soldermask_margin: z71.number().optional()
15988
15991
  });
15989
15992
  var pcb_hole_circle_shape = pcb_hole_circle.describe(
15990
15993
  "Defines a circular hole on the PCB"
@@ -15999,7 +16002,8 @@ var pcb_hole_rect = z71.object({
15999
16002
  hole_width: z71.number(),
16000
16003
  hole_height: z71.number(),
16001
16004
  x: distance,
16002
- y: distance
16005
+ y: distance,
16006
+ soldermask_margin: z71.number().optional()
16003
16007
  });
16004
16008
  var pcb_hole_rect_shape = pcb_hole_rect.describe(
16005
16009
  "Defines a rectangular (square-capable) hole on the PCB. Use equal width/height for square."
@@ -16013,7 +16017,8 @@ var pcb_hole_circle_or_square = z71.object({
16013
16017
  hole_shape: z71.enum(["circle", "square"]),
16014
16018
  hole_diameter: z71.number(),
16015
16019
  x: distance,
16016
- y: distance
16020
+ y: distance,
16021
+ soldermask_margin: z71.number().optional()
16017
16022
  });
16018
16023
  var pcb_hole_circle_or_square_shape = pcb_hole_circle_or_square.describe(
16019
16024
  "Defines a circular or square hole on the PCB"
@@ -16028,7 +16033,8 @@ var pcb_hole_oval = z71.object({
16028
16033
  hole_width: z71.number(),
16029
16034
  hole_height: z71.number(),
16030
16035
  x: distance,
16031
- y: distance
16036
+ y: distance,
16037
+ soldermask_margin: z71.number().optional()
16032
16038
  });
16033
16039
  var pcb_hole_oval_shape = pcb_hole_oval.describe(
16034
16040
  "Defines an oval hole on the PCB"
@@ -16043,7 +16049,8 @@ var pcb_hole_pill = z71.object({
16043
16049
  hole_width: z71.number(),
16044
16050
  hole_height: z71.number(),
16045
16051
  x: distance,
16046
- y: distance
16052
+ y: distance,
16053
+ soldermask_margin: z71.number().optional()
16047
16054
  });
16048
16055
  var pcb_hole_pill_shape = pcb_hole_pill.describe(
16049
16056
  "Defines a pill-shaped hole on the PCB"
@@ -16059,7 +16066,8 @@ var pcb_hole_rotated_pill = z71.object({
16059
16066
  hole_height: z71.number(),
16060
16067
  x: distance,
16061
16068
  y: distance,
16062
- ccw_rotation: rotation
16069
+ ccw_rotation: rotation,
16070
+ soldermask_margin: z71.number().optional()
16063
16071
  });
16064
16072
  var pcb_hole_rotated_pill_shape = pcb_hole_rotated_pill.describe(
16065
16073
  "Defines a rotated pill-shaped hole on the PCB"
@@ -16079,7 +16087,8 @@ var pcb_plated_hole_circle = z72.object({
16079
16087
  port_hints: z72.array(z72.string()).optional(),
16080
16088
  pcb_component_id: z72.string().optional(),
16081
16089
  pcb_port_id: z72.string().optional(),
16082
- pcb_plated_hole_id: getZodPrefixedIdWithDefault("pcb_plated_hole")
16090
+ pcb_plated_hole_id: getZodPrefixedIdWithDefault("pcb_plated_hole"),
16091
+ soldermask_margin: z72.number().optional()
16083
16092
  });
16084
16093
  var pcb_plated_hole_oval = z72.object({
16085
16094
  type: z72.literal("pcb_plated_hole"),
@@ -16097,7 +16106,8 @@ var pcb_plated_hole_oval = z72.object({
16097
16106
  port_hints: z72.array(z72.string()).optional(),
16098
16107
  pcb_component_id: z72.string().optional(),
16099
16108
  pcb_port_id: z72.string().optional(),
16100
- pcb_plated_hole_id: getZodPrefixedIdWithDefault("pcb_plated_hole")
16109
+ pcb_plated_hole_id: getZodPrefixedIdWithDefault("pcb_plated_hole"),
16110
+ soldermask_margin: z72.number().optional()
16101
16111
  });
16102
16112
  var pcb_circular_hole_with_rect_pad = z72.object({
16103
16113
  type: z72.literal("pcb_plated_hole"),
@@ -16118,7 +16128,8 @@ var pcb_circular_hole_with_rect_pad = z72.object({
16118
16128
  port_hints: z72.array(z72.string()).optional(),
16119
16129
  pcb_component_id: z72.string().optional(),
16120
16130
  pcb_port_id: z72.string().optional(),
16121
- pcb_plated_hole_id: getZodPrefixedIdWithDefault("pcb_plated_hole")
16131
+ pcb_plated_hole_id: getZodPrefixedIdWithDefault("pcb_plated_hole"),
16132
+ soldermask_margin: z72.number().optional()
16122
16133
  });
16123
16134
  var pcb_pill_hole_with_rect_pad = z72.object({
16124
16135
  type: z72.literal("pcb_plated_hole"),
@@ -16140,7 +16151,8 @@ var pcb_pill_hole_with_rect_pad = z72.object({
16140
16151
  port_hints: z72.array(z72.string()).optional(),
16141
16152
  pcb_component_id: z72.string().optional(),
16142
16153
  pcb_port_id: z72.string().optional(),
16143
- pcb_plated_hole_id: getZodPrefixedIdWithDefault("pcb_plated_hole")
16154
+ pcb_plated_hole_id: getZodPrefixedIdWithDefault("pcb_plated_hole"),
16155
+ soldermask_margin: z72.number().optional()
16144
16156
  });
16145
16157
  var pcb_rotated_pill_hole_with_rect_pad = z72.object({
16146
16158
  type: z72.literal("pcb_plated_hole"),
@@ -16164,7 +16176,8 @@ var pcb_rotated_pill_hole_with_rect_pad = z72.object({
16164
16176
  port_hints: z72.array(z72.string()).optional(),
16165
16177
  pcb_component_id: z72.string().optional(),
16166
16178
  pcb_port_id: z72.string().optional(),
16167
- pcb_plated_hole_id: getZodPrefixedIdWithDefault("pcb_plated_hole")
16179
+ pcb_plated_hole_id: getZodPrefixedIdWithDefault("pcb_plated_hole"),
16180
+ soldermask_margin: z72.number().optional()
16168
16181
  });
16169
16182
  var pcb_hole_with_polygon_pad = z72.object({
16170
16183
  type: z72.literal("pcb_plated_hole"),
@@ -16189,7 +16202,8 @@ var pcb_hole_with_polygon_pad = z72.object({
16189
16202
  port_hints: z72.array(z72.string()).optional(),
16190
16203
  pcb_component_id: z72.string().optional(),
16191
16204
  pcb_port_id: z72.string().optional(),
16192
- pcb_plated_hole_id: getZodPrefixedIdWithDefault("pcb_plated_hole")
16205
+ pcb_plated_hole_id: getZodPrefixedIdWithDefault("pcb_plated_hole"),
16206
+ soldermask_margin: z72.number().optional()
16193
16207
  });
16194
16208
  var pcb_plated_hole = z72.union([
16195
16209
  pcb_plated_hole_circle,
@@ -16233,7 +16247,8 @@ var pcb_smtpad_circle = z74.object({
16233
16247
  port_hints: z74.array(z74.string()).optional(),
16234
16248
  pcb_component_id: z74.string().optional(),
16235
16249
  pcb_port_id: z74.string().optional(),
16236
- is_covered_with_solder_mask: z74.boolean().optional()
16250
+ is_covered_with_solder_mask: z74.boolean().optional(),
16251
+ soldermask_margin: z74.number().optional()
16237
16252
  });
16238
16253
  var pcb_smtpad_rect = z74.object({
16239
16254
  type: z74.literal("pcb_smtpad"),
@@ -16251,7 +16266,8 @@ var pcb_smtpad_rect = z74.object({
16251
16266
  port_hints: z74.array(z74.string()).optional(),
16252
16267
  pcb_component_id: z74.string().optional(),
16253
16268
  pcb_port_id: z74.string().optional(),
16254
- is_covered_with_solder_mask: z74.boolean().optional()
16269
+ is_covered_with_solder_mask: z74.boolean().optional(),
16270
+ soldermask_margin: z74.number().optional()
16255
16271
  });
16256
16272
  var pcb_smtpad_rotated_rect = z74.object({
16257
16273
  type: z74.literal("pcb_smtpad"),
@@ -16270,7 +16286,8 @@ var pcb_smtpad_rotated_rect = z74.object({
16270
16286
  port_hints: z74.array(z74.string()).optional(),
16271
16287
  pcb_component_id: z74.string().optional(),
16272
16288
  pcb_port_id: z74.string().optional(),
16273
- is_covered_with_solder_mask: z74.boolean().optional()
16289
+ is_covered_with_solder_mask: z74.boolean().optional(),
16290
+ soldermask_margin: z74.number().optional()
16274
16291
  });
16275
16292
  var pcb_smtpad_pill = z74.object({
16276
16293
  type: z74.literal("pcb_smtpad"),
@@ -16287,7 +16304,8 @@ var pcb_smtpad_pill = z74.object({
16287
16304
  port_hints: z74.array(z74.string()).optional(),
16288
16305
  pcb_component_id: z74.string().optional(),
16289
16306
  pcb_port_id: z74.string().optional(),
16290
- is_covered_with_solder_mask: z74.boolean().optional()
16307
+ is_covered_with_solder_mask: z74.boolean().optional(),
16308
+ soldermask_margin: z74.number().optional()
16291
16309
  });
16292
16310
  var pcb_smtpad_rotated_pill = z74.object({
16293
16311
  type: z74.literal("pcb_smtpad"),
@@ -16305,7 +16323,8 @@ var pcb_smtpad_rotated_pill = z74.object({
16305
16323
  port_hints: z74.array(z74.string()).optional(),
16306
16324
  pcb_component_id: z74.string().optional(),
16307
16325
  pcb_port_id: z74.string().optional(),
16308
- is_covered_with_solder_mask: z74.boolean().optional()
16326
+ is_covered_with_solder_mask: z74.boolean().optional(),
16327
+ soldermask_margin: z74.number().optional()
16309
16328
  });
16310
16329
  var pcb_smtpad_polygon = z74.object({
16311
16330
  type: z74.literal("pcb_smtpad"),
@@ -16318,7 +16337,8 @@ var pcb_smtpad_polygon = z74.object({
16318
16337
  port_hints: z74.array(z74.string()).optional(),
16319
16338
  pcb_component_id: z74.string().optional(),
16320
16339
  pcb_port_id: z74.string().optional(),
16321
- is_covered_with_solder_mask: z74.boolean().optional()
16340
+ is_covered_with_solder_mask: z74.boolean().optional(),
16341
+ soldermask_margin: z74.number().optional()
16322
16342
  });
16323
16343
  var pcb_smtpad = z74.discriminatedUnion("shape", [
16324
16344
  pcb_smtpad_circle,
@@ -16928,7 +16948,9 @@ var pcb_cutout_base = z106.object({
16928
16948
  type: z106.literal("pcb_cutout"),
16929
16949
  pcb_cutout_id: getZodPrefixedIdWithDefault("pcb_cutout"),
16930
16950
  pcb_group_id: z106.string().optional(),
16931
- subcircuit_id: z106.string().optional()
16951
+ subcircuit_id: z106.string().optional(),
16952
+ pcb_board_id: z106.string().optional(),
16953
+ pcb_panel_id: z106.string().optional()
16932
16954
  });
16933
16955
  var pcb_cutout_rect = pcb_cutout_base.extend({
16934
16956
  shape: z106.literal("rect"),
@@ -16949,10 +16971,20 @@ var pcb_cutout_polygon = pcb_cutout_base.extend({
16949
16971
  points: z106.array(point)
16950
16972
  });
16951
16973
  expectTypesMatch(true);
16974
+ var pcb_cutout_path = pcb_cutout_base.extend({
16975
+ shape: z106.literal("path"),
16976
+ route: z106.array(point),
16977
+ slot_width: length,
16978
+ slot_length: length.optional(),
16979
+ space_between_slots: length.optional(),
16980
+ slot_corner_radius: length.optional()
16981
+ });
16982
+ expectTypesMatch(true);
16952
16983
  var pcb_cutout = z106.discriminatedUnion("shape", [
16953
16984
  pcb_cutout_rect,
16954
16985
  pcb_cutout_circle,
16955
- pcb_cutout_polygon
16986
+ pcb_cutout_polygon,
16987
+ pcb_cutout_path
16956
16988
  ]).describe("Defines a cutout on the PCB, removing board material.");
16957
16989
  expectTypesMatch(true);
16958
16990
  var pcb_missing_footprint_error = z107.object({
@@ -17317,7 +17349,8 @@ var simulation_transient_voltage_graph = z127.object({
17317
17349
  time_per_step: duration_ms,
17318
17350
  start_time_ms: ms,
17319
17351
  end_time_ms: ms,
17320
- name: z127.string().optional()
17352
+ name: z127.string().optional(),
17353
+ color: z127.string().optional()
17321
17354
  }).describe("Stores voltage measurements over time for a simulation");
17322
17355
  expectTypesMatch(true);
17323
17356
  var simulation_switch = z128.object({
@@ -17336,9 +17369,11 @@ var simulation_voltage_probe = z129.object({
17336
17369
  "simulation_voltage_probe"
17337
17370
  ),
17338
17371
  source_component_id: z129.string().optional(),
17372
+ name: z129.string().optional(),
17339
17373
  source_port_id: z129.string().optional(),
17340
17374
  source_net_id: z129.string().optional(),
17341
- subcircuit_id: z129.string().optional()
17375
+ subcircuit_id: z129.string().optional(),
17376
+ color: z129.string().optional()
17342
17377
  }).describe(
17343
17378
  "Defines a voltage probe for simulation, connected to a port or a net"
17344
17379
  ).refine(
@@ -24390,7 +24425,7 @@ var m2host = (raw_params) => {
24390
24425
  }
24391
24426
  const centerX = (minX + maxX) / 2;
24392
24427
  const centerY = (minY + maxY) / 2;
24393
- const translate9 = (el) => {
24428
+ const translate10 = (el) => {
24394
24429
  if (typeof el.x === "number") el.x -= centerX;
24395
24430
  if (typeof el.y === "number") el.y -= centerY;
24396
24431
  if (el.center) {
@@ -24404,9 +24439,9 @@ var m2host = (raw_params) => {
24404
24439
  }));
24405
24440
  }
24406
24441
  };
24407
- for (const pad2 of pads) translate9(pad2);
24408
- translate9(cutout);
24409
- translate9(pin1Marker);
24442
+ for (const pad2 of pads) translate10(pad2);
24443
+ translate10(cutout);
24444
+ translate10(pin1Marker);
24410
24445
  return {
24411
24446
  circuitJson: [
24412
24447
  ...pads,
@@ -27997,6 +28032,17 @@ var tuple = (...args) => args;
27997
28032
  import { useRef as useRef2, useEffect as useEffect8, useState as useState4 } from "react";
27998
28033
  import ReactDOM from "react-dom";
27999
28034
  import * as THREE7 from "three";
28035
+
28036
+ // lib/utils/z-index-map.ts
28037
+ var zIndexMap = {
28038
+ clickToInteractOverlay: 100,
28039
+ htmlElements: 95,
28040
+ orientationCube: 95,
28041
+ contextMenu: 90,
28042
+ appearanceMenu: 91
28043
+ };
28044
+
28045
+ // src/react-three/Html.tsx
28000
28046
  var Html = ({ children, position, style }) => {
28001
28047
  const { camera, renderer } = useThree();
28002
28048
  const el = useRef2(document.createElement("div"));
@@ -28026,7 +28072,7 @@ var Html = ({ children, position, style }) => {
28026
28072
  el.current.style.left = `${x}px`;
28027
28073
  el.current.style.top = `${y}px`;
28028
28074
  el.current.style.pointerEvents = "none";
28029
- el.current.style.zIndex = "1000";
28075
+ el.current.style.zIndex = zIndexMap.htmlElements.toString();
28030
28076
  if (style) {
28031
28077
  Object.assign(el.current.style, style);
28032
28078
  }
@@ -28241,7 +28287,7 @@ import * as THREE15 from "three";
28241
28287
  // package.json
28242
28288
  var package_default = {
28243
28289
  name: "@tscircuit/3d-viewer",
28244
- version: "0.0.435",
28290
+ version: "0.0.437",
28245
28291
  main: "./dist/index.js",
28246
28292
  module: "./dist/index.js",
28247
28293
  type: "module",
@@ -28302,7 +28348,7 @@ var package_default = {
28302
28348
  "@vitejs/plugin-react": "^4.3.4",
28303
28349
  "bun-match-svg": "^0.0.9",
28304
28350
  "bun-types": "1.2.1",
28305
- "circuit-json": "0.0.311",
28351
+ "circuit-json": "0.0.316",
28306
28352
  "circuit-to-svg": "^0.0.179",
28307
28353
  debug: "^4.4.0",
28308
28354
  "jscad-electronics": "^0.0.89",
@@ -29218,7 +29264,7 @@ var OrientationCubeCanvas = () => {
29218
29264
  left: 0,
29219
29265
  width: 120,
29220
29266
  height: 120,
29221
- zIndex: 1e3
29267
+ zIndex: zIndexMap.orientationCube
29222
29268
  }
29223
29269
  }
29224
29270
  );
@@ -29352,7 +29398,7 @@ var CadViewerContainer = forwardRef2(
29352
29398
  position: "absolute",
29353
29399
  inset: 0,
29354
29400
  cursor: "pointer",
29355
- zIndex: 10,
29401
+ zIndex: zIndexMap.clickToInteractOverlay,
29356
29402
  display: "flex",
29357
29403
  alignItems: "center",
29358
29404
  justifyContent: "center"
@@ -29539,18 +29585,18 @@ var createBoardGeomFromCircuitJson = (circuitJson, opts = {}) => {
29539
29585
  };
29540
29586
 
29541
29587
  // src/BoardGeomBuilder.ts
29542
- var import_transforms7 = __toESM(require_transforms(), 1);
29543
- var import_primitives9 = __toESM(require_primitives(), 1);
29588
+ var import_transforms8 = __toESM(require_transforms(), 1);
29589
+ var import_primitives10 = __toESM(require_primitives(), 1);
29544
29590
  var import_colors7 = __toESM(require_colors(), 1);
29545
- var import_booleans5 = __toESM(require_booleans(), 1);
29591
+ var import_booleans6 = __toESM(require_booleans(), 1);
29546
29592
  import { su as su3 } from "@tscircuit/circuit-json-util";
29547
29593
 
29548
29594
  // src/geoms/plated-hole.ts
29549
- var import_primitives3 = __toESM(require_primitives(), 1);
29595
+ var import_primitives4 = __toESM(require_primitives(), 1);
29550
29596
  var import_colors2 = __toESM(require_colors(), 1);
29551
- var import_booleans = __toESM(require_booleans(), 1);
29552
- var import_extrusions2 = __toESM(require_extrusions(), 1);
29553
- var import_transforms2 = __toESM(require_transforms(), 1);
29597
+ var import_booleans2 = __toESM(require_booleans(), 1);
29598
+ var import_extrusions3 = __toESM(require_extrusions(), 1);
29599
+ var import_transforms3 = __toESM(require_transforms(), 1);
29554
29600
 
29555
29601
  // src/utils/rect-border-radius.ts
29556
29602
  function clampRectBorderRadius(width10, height10, rawRadius) {
@@ -29569,10 +29615,101 @@ function extractRectBorderRadius(source) {
29569
29615
  return source.corner_radius ?? source.cornerRadius ?? source.rect_pad_border_radius ?? source.rectPadBorderRadius ?? source.rect_border_radius ?? source.rectBorderRadius ?? void 0;
29570
29616
  }
29571
29617
 
29618
+ // src/geoms/create-hole-with-polygon-pad.ts
29619
+ var import_primitives3 = __toESM(require_primitives(), 1);
29620
+ var import_extrusions2 = __toESM(require_extrusions(), 1);
29621
+ var import_transforms2 = __toESM(require_transforms(), 1);
29622
+ var import_booleans = __toESM(require_booleans(), 1);
29623
+ var ELLIPSE_SEGMENTS = 64;
29624
+ var createEllipsePrism = (width10, height10, depth) => {
29625
+ const ellipse2d = (0, import_primitives3.ellipse)({
29626
+ center: [0, 0],
29627
+ radius: [Math.max(width10 / 2, M / 2), Math.max(height10 / 2, M / 2)],
29628
+ segments: ELLIPSE_SEGMENTS
29629
+ });
29630
+ const extruded = (0, import_extrusions2.extrudeLinear)({ height: depth }, ellipse2d);
29631
+ return (0, import_transforms2.translate)([0, 0, -depth / 2], extruded);
29632
+ };
29633
+ var createPillPrism = (width10, height10, depth) => {
29634
+ const clampedWidth = Math.max(width10, M);
29635
+ const clampedHeight = Math.max(height10, M);
29636
+ if (Math.abs(clampedWidth - clampedHeight) < 1e-6) {
29637
+ return (0, import_primitives3.cylinder)({
29638
+ center: [0, 0, 0],
29639
+ radius: clampedWidth / 2,
29640
+ height: depth
29641
+ });
29642
+ }
29643
+ const isHorizontal = clampedWidth >= clampedHeight;
29644
+ const longDim = isHorizontal ? clampedWidth : clampedHeight;
29645
+ const shortDim = isHorizontal ? clampedHeight : clampedWidth;
29646
+ const rectLength = Math.max(longDim - shortDim, 0);
29647
+ const rect = (0, import_primitives3.cuboid)({
29648
+ center: [0, 0, 0],
29649
+ size: isHorizontal ? [rectLength, shortDim, depth] : [shortDim, rectLength, depth]
29650
+ });
29651
+ if (rectLength <= 1e-6) {
29652
+ return (0, import_primitives3.cylinder)({ center: [0, 0, 0], radius: shortDim / 2, height: depth });
29653
+ }
29654
+ const offset4 = rectLength / 2;
29655
+ const firstCap = (0, import_primitives3.cylinder)({
29656
+ center: isHorizontal ? [-offset4, 0, 0] : [0, -offset4, 0],
29657
+ radius: shortDim / 2,
29658
+ height: depth
29659
+ });
29660
+ const secondCap = (0, import_primitives3.cylinder)({
29661
+ center: isHorizontal ? [offset4, 0, 0] : [0, offset4, 0],
29662
+ radius: shortDim / 2,
29663
+ height: depth
29664
+ });
29665
+ return (0, import_booleans.union)(rect, firstCap, secondCap);
29666
+ };
29667
+ var createHoleWithPolygonPadHoleGeom = (hole, height10, options = {}) => {
29668
+ const holeShape = hole.hole_shape || "circle";
29669
+ const sizeDelta = options.sizeDelta ?? 0;
29670
+ const offsetX = hole.hole_offset_x || 0;
29671
+ const offsetY = hole.hole_offset_y || 0;
29672
+ const center = [
29673
+ hole.x + offsetX,
29674
+ hole.y + offsetY,
29675
+ 0
29676
+ ];
29677
+ if (holeShape === "circle") {
29678
+ const diameter = Math.max((hole.hole_diameter ?? 0) + sizeDelta, M);
29679
+ const radius = Math.max(diameter / 2, M / 2);
29680
+ return (0, import_primitives3.cylinder)({ center, radius, height: height10 });
29681
+ }
29682
+ const baseWidth = hole.hole_width ?? hole.hole_diameter;
29683
+ const baseHeight = hole.hole_height ?? hole.hole_diameter;
29684
+ if (!baseWidth || !baseHeight) {
29685
+ return null;
29686
+ }
29687
+ const width10 = Math.max(baseWidth + sizeDelta, M);
29688
+ const heightVal = Math.max(baseHeight + sizeDelta, M);
29689
+ if (holeShape === "oval") {
29690
+ const ellipsePrism = createEllipsePrism(width10, heightVal, height10);
29691
+ return (0, import_transforms2.translate)([center[0], center[1], 0], ellipsePrism);
29692
+ }
29693
+ if (holeShape === "pill" || holeShape === "rotated_pill") {
29694
+ let pill = createPillPrism(width10, heightVal, height10);
29695
+ if (!pill) return null;
29696
+ const rotation2 = hole.ccw_rotation || 0;
29697
+ if (rotation2) {
29698
+ pill = (0, import_transforms2.rotateZ)(rotation2 * Math.PI / 180, pill);
29699
+ }
29700
+ return (0, import_transforms2.translate)(center, pill);
29701
+ }
29702
+ const fallbackDiameter = Math.max(
29703
+ (hole.hole_diameter ?? baseWidth ?? baseHeight ?? M) + sizeDelta,
29704
+ M
29705
+ );
29706
+ return (0, import_primitives3.cylinder)({ center, radius: fallbackDiameter / 2, height: height10 });
29707
+ };
29708
+
29572
29709
  // src/geoms/plated-hole.ts
29573
29710
  var platedHoleLipHeight = 0.02;
29574
29711
  var RECT_PAD_SEGMENTS = 64;
29575
- var maybeClip = (geom, clipGeom) => clipGeom ? (0, import_booleans.intersect)(clipGeom, geom) : geom;
29712
+ var maybeClip = (geom, clipGeom) => clipGeom ? (0, import_booleans2.intersect)(clipGeom, geom) : geom;
29576
29713
  var createRectPadGeom = ({
29577
29714
  width: width10,
29578
29715
  height: height10,
@@ -29582,16 +29719,16 @@ var createRectPadGeom = ({
29582
29719
  }) => {
29583
29720
  const clampedRadius = clampRectBorderRadius(width10, height10, borderRadius);
29584
29721
  if (clampedRadius <= 0) {
29585
- return (0, import_primitives3.cuboid)({ center, size: [width10, height10, thickness] });
29722
+ return (0, import_primitives4.cuboid)({ center, size: [width10, height10, thickness] });
29586
29723
  }
29587
- const rect2d = (0, import_primitives3.roundedRectangle)({
29724
+ const rect2d = (0, import_primitives4.roundedRectangle)({
29588
29725
  size: [width10, height10],
29589
29726
  roundRadius: clampedRadius,
29590
29727
  segments: RECT_PAD_SEGMENTS
29591
29728
  });
29592
- const extruded = (0, import_extrusions2.extrudeLinear)({ height: thickness }, rect2d);
29729
+ const extruded = (0, import_extrusions3.extrudeLinear)({ height: thickness }, rect2d);
29593
29730
  const offsetZ = center[2] - thickness / 2;
29594
- return (0, import_transforms2.translate)([center[0], center[1], offsetZ], extruded);
29731
+ return (0, import_transforms3.translate)([center[0], center[1], offsetZ], extruded);
29595
29732
  };
29596
29733
  var platedHole = (plated_hole, ctx, options = {}) => {
29597
29734
  const { clipGeom } = options;
@@ -29603,18 +29740,18 @@ var platedHole = (plated_hole, ctx, options = {}) => {
29603
29740
  if (plated_hole.shape === "circle") {
29604
29741
  const outerDiameter = plated_hole.outer_diameter ?? Math.max(plated_hole.hole_diameter, 0);
29605
29742
  const copperHeight = copperSpan + 0.01;
29606
- const copperBody = (0, import_primitives3.cylinder)({
29743
+ const copperBody = (0, import_primitives4.cylinder)({
29607
29744
  center: [plated_hole.x, plated_hole.y, 0],
29608
29745
  radius: outerDiameter / 2,
29609
29746
  height: copperHeight
29610
29747
  });
29611
29748
  const copperSolid = maybeClip(copperBody, clipGeom);
29612
- const drill = (0, import_primitives3.cylinder)({
29749
+ const drill = (0, import_primitives4.cylinder)({
29613
29750
  center: [plated_hole.x, plated_hole.y, 0],
29614
29751
  radius: Math.max(plated_hole.hole_diameter / 2, 0.01),
29615
29752
  height: throughDrillHeight
29616
29753
  });
29617
- return (0, import_colors2.colorize)(colors.copper, (0, import_booleans.subtract)(copperSolid, drill));
29754
+ return (0, import_colors2.colorize)(colors.copper, (0, import_booleans2.subtract)(copperSolid, drill));
29618
29755
  }
29619
29756
  if (plated_hole.shape === "circular_hole_with_rect_pad") {
29620
29757
  const holeOffsetX = plated_hole.hole_offset_x || 0;
@@ -29623,7 +29760,7 @@ var platedHole = (plated_hole, ctx, options = {}) => {
29623
29760
  const padHeight = plated_hole.rect_pad_height || plated_hole.hole_diameter;
29624
29761
  const rectBorderRadius = extractRectBorderRadius(plated_hole);
29625
29762
  const copperSolid = maybeClip(
29626
- (0, import_booleans.union)(
29763
+ (0, import_booleans2.union)(
29627
29764
  // Top rectangular pad (thicker to ensure connection)
29628
29765
  createRectPadGeom({
29629
29766
  width: padWidth,
@@ -29648,19 +29785,19 @@ var platedHole = (plated_hole, ctx, options = {}) => {
29648
29785
  const topPadBottom = topSurfaceZ;
29649
29786
  const bottomPadTop = bottomSurfaceZ;
29650
29787
  const centerZ = (topPadBottom + bottomPadTop) / 2;
29651
- const rect2d = (0, import_primitives3.roundedRectangle)({
29788
+ const rect2d = (0, import_primitives4.roundedRectangle)({
29652
29789
  size: [padWidth, padHeight],
29653
29790
  roundRadius: rectBorderRadius || 0,
29654
29791
  segments: RECT_PAD_SEGMENTS
29655
29792
  });
29656
- const extruded = (0, import_extrusions2.extrudeLinear)({ height: height10 }, rect2d);
29657
- return (0, import_transforms2.translate)(
29793
+ const extruded = (0, import_extrusions3.extrudeLinear)({ height: height10 }, rect2d);
29794
+ return (0, import_transforms3.translate)(
29658
29795
  [plated_hole.x, plated_hole.y, centerZ - height10 / 2],
29659
29796
  extruded
29660
29797
  );
29661
29798
  })(),
29662
29799
  // Plated barrel around hole (ensured connection with pads)
29663
- (0, import_primitives3.cylinder)({
29800
+ (0, import_primitives4.cylinder)({
29664
29801
  center: [
29665
29802
  plated_hole.x + (holeOffsetX || 0),
29666
29803
  plated_hole.y + (holeOffsetY || 0),
@@ -29672,7 +29809,7 @@ var platedHole = (plated_hole, ctx, options = {}) => {
29672
29809
  ),
29673
29810
  clipGeom
29674
29811
  );
29675
- const drill = (0, import_primitives3.cylinder)({
29812
+ const drill = (0, import_primitives4.cylinder)({
29676
29813
  center: [
29677
29814
  plated_hole.x + (holeOffsetX || 0),
29678
29815
  plated_hole.y + (holeOffsetY || 0),
@@ -29681,7 +29818,7 @@ var platedHole = (plated_hole, ctx, options = {}) => {
29681
29818
  radius: Math.max(plated_hole.hole_diameter / 2 - M, 0.01),
29682
29819
  height: throughDrillHeight
29683
29820
  });
29684
- const barrel = (0, import_primitives3.cylinder)({
29821
+ const barrel = (0, import_primitives4.cylinder)({
29685
29822
  center: [
29686
29823
  plated_hole.x + (holeOffsetX || 0),
29687
29824
  plated_hole.y + (holeOffsetY || 0),
@@ -29690,18 +29827,18 @@ var platedHole = (plated_hole, ctx, options = {}) => {
29690
29827
  radius: plated_hole.hole_diameter / 2,
29691
29828
  height: copperSpan
29692
29829
  });
29693
- let finalCopper = (0, import_booleans.union)(
29694
- (0, import_booleans.subtract)(copperSolid, barrel),
29830
+ let finalCopper = (0, import_booleans2.union)(
29831
+ (0, import_booleans2.subtract)(copperSolid, barrel),
29695
29832
  // Subtract the barrel from the main shape
29696
29833
  barrel
29697
29834
  // Add the barrel back to ensure proper connection
29698
29835
  );
29699
29836
  if (options.clipGeom) {
29700
- finalCopper = (0, import_booleans.subtract)(finalCopper, drill);
29701
- finalCopper = (0, import_booleans.intersect)(finalCopper, options.clipGeom);
29837
+ finalCopper = (0, import_booleans2.subtract)(finalCopper, drill);
29838
+ finalCopper = (0, import_booleans2.intersect)(finalCopper, options.clipGeom);
29702
29839
  return (0, import_colors2.colorize)(colors.copper, finalCopper);
29703
29840
  }
29704
- return (0, import_colors2.colorize)(colors.copper, (0, import_booleans.subtract)(finalCopper, drill));
29841
+ return (0, import_colors2.colorize)(colors.copper, (0, import_booleans2.subtract)(finalCopper, drill));
29705
29842
  }
29706
29843
  if (plated_hole.shape === "pill") {
29707
29844
  const shouldRotate = plated_hole.hole_height > plated_hole.hole_width;
@@ -29718,51 +29855,51 @@ var platedHole = (plated_hole, ctx, options = {}) => {
29718
29855
  const radius = height10 / 2;
29719
29856
  const length2 = Math.abs(width10 - height10);
29720
29857
  if (length2 <= 1e-6) {
29721
- return (0, import_primitives3.cylinder)({
29858
+ return (0, import_primitives4.cylinder)({
29722
29859
  center: [plated_hole.x, plated_hole.y, 0],
29723
29860
  radius,
29724
29861
  height: thickness
29725
29862
  });
29726
29863
  }
29727
- const rect = (0, import_primitives3.cuboid)({
29864
+ const rect = (0, import_primitives4.cuboid)({
29728
29865
  center: [plated_hole.x, plated_hole.y, 0],
29729
29866
  size: shouldRotate ? [height10, length2, thickness] : [length2, height10, thickness]
29730
29867
  });
29731
- const leftCap = (0, import_primitives3.cylinder)({
29868
+ const leftCap = (0, import_primitives4.cylinder)({
29732
29869
  center: shouldRotate ? [plated_hole.x, plated_hole.y - length2 / 2, 0] : [plated_hole.x - length2 / 2, plated_hole.y, 0],
29733
29870
  radius,
29734
29871
  height: thickness
29735
29872
  });
29736
- const rightCap = (0, import_primitives3.cylinder)({
29873
+ const rightCap = (0, import_primitives4.cylinder)({
29737
29874
  center: shouldRotate ? [plated_hole.x, plated_hole.y + length2 / 2, 0] : [plated_hole.x + length2 / 2, plated_hole.y, 0],
29738
29875
  radius,
29739
29876
  height: thickness
29740
29877
  });
29741
- return (0, import_booleans.union)(rect, leftCap, rightCap);
29878
+ return (0, import_booleans2.union)(rect, leftCap, rightCap);
29742
29879
  };
29743
29880
  const outerBarrel = createPillSection(
29744
29881
  outerPillWidth,
29745
29882
  outerPillHeight,
29746
29883
  copperHeight
29747
29884
  );
29748
- const drillRect = (0, import_primitives3.cuboid)({
29885
+ const drillRect = (0, import_primitives4.cuboid)({
29749
29886
  center: [plated_hole.x, plated_hole.y, 0],
29750
29887
  size: shouldRotate ? [holeHeight - 2 * M, rectLength, throughDrillHeight] : [rectLength, holeHeight - 2 * M, throughDrillHeight]
29751
29888
  });
29752
- const drillLeftCap = (0, import_primitives3.cylinder)({
29889
+ const drillLeftCap = (0, import_primitives4.cylinder)({
29753
29890
  center: shouldRotate ? [plated_hole.x, plated_hole.y - rectLength / 2, 0] : [plated_hole.x - rectLength / 2, plated_hole.y, 0],
29754
29891
  radius: holeRadius - M,
29755
29892
  height: throughDrillHeight
29756
29893
  });
29757
- const drillRightCap = (0, import_primitives3.cylinder)({
29894
+ const drillRightCap = (0, import_primitives4.cylinder)({
29758
29895
  center: shouldRotate ? [plated_hole.x, plated_hole.y + rectLength / 2, 0] : [plated_hole.x + rectLength / 2, plated_hole.y, 0],
29759
29896
  radius: holeRadius - M,
29760
29897
  height: throughDrillHeight
29761
29898
  });
29762
- const drillUnion = (0, import_booleans.union)(drillRect, drillLeftCap, drillRightCap);
29899
+ const drillUnion = (0, import_booleans2.union)(drillRect, drillLeftCap, drillRightCap);
29763
29900
  const copperSolid = maybeClip(outerBarrel, clipGeom);
29764
29901
  const drill = drillUnion;
29765
- return (0, import_colors2.colorize)(colors.copper, (0, import_booleans.subtract)(copperSolid, drill));
29902
+ return (0, import_colors2.colorize)(colors.copper, (0, import_booleans2.subtract)(copperSolid, drill));
29766
29903
  }
29767
29904
  if (plated_hole.shape === "pill_hole_with_rect_pad") {
29768
29905
  const holeOffsetX = plated_hole.hole_offset_x || 0;
@@ -29776,8 +29913,8 @@ var platedHole = (plated_hole, ctx, options = {}) => {
29776
29913
  const padHeight = plated_hole.rect_pad_height || holeHeight + 0.2;
29777
29914
  const rectBorderRadius = extractRectBorderRadius(plated_hole);
29778
29915
  const barrelMargin = 0.03;
29779
- const barrel = (0, import_booleans.union)(
29780
- (0, import_primitives3.cuboid)({
29916
+ const barrel = (0, import_booleans2.union)(
29917
+ (0, import_primitives4.cuboid)({
29781
29918
  center: [plated_hole.x + holeOffsetX, plated_hole.y + holeOffsetY, 0],
29782
29919
  size: shouldRotate ? [
29783
29920
  holeHeight + 2 * barrelMargin,
@@ -29789,7 +29926,7 @@ var platedHole = (plated_hole, ctx, options = {}) => {
29789
29926
  copperSpan
29790
29927
  ]
29791
29928
  }),
29792
- (0, import_primitives3.cylinder)({
29929
+ (0, import_primitives4.cylinder)({
29793
29930
  center: shouldRotate ? [
29794
29931
  plated_hole.x + holeOffsetX,
29795
29932
  plated_hole.y + holeOffsetY - rectLength / 2,
@@ -29802,7 +29939,7 @@ var platedHole = (plated_hole, ctx, options = {}) => {
29802
29939
  radius: holeRadius + barrelMargin,
29803
29940
  height: copperSpan
29804
29941
  }),
29805
- (0, import_primitives3.cylinder)({
29942
+ (0, import_primitives4.cylinder)({
29806
29943
  center: shouldRotate ? [
29807
29944
  plated_hole.x + holeOffsetX,
29808
29945
  plated_hole.y + holeOffsetY + rectLength / 2,
@@ -29816,12 +29953,12 @@ var platedHole = (plated_hole, ctx, options = {}) => {
29816
29953
  height: copperSpan
29817
29954
  })
29818
29955
  );
29819
- const holeCut = (0, import_booleans.union)(
29820
- (0, import_primitives3.cuboid)({
29956
+ const holeCut = (0, import_booleans2.union)(
29957
+ (0, import_primitives4.cuboid)({
29821
29958
  center: [plated_hole.x + holeOffsetX, plated_hole.y + holeOffsetY, 0],
29822
29959
  size: shouldRotate ? [holeHeight, rectLength, throughDrillHeight * 1.1] : [rectLength, holeHeight, throughDrillHeight * 1.1]
29823
29960
  }),
29824
- (0, import_primitives3.cylinder)({
29961
+ (0, import_primitives4.cylinder)({
29825
29962
  center: shouldRotate ? [
29826
29963
  plated_hole.x + holeOffsetX,
29827
29964
  plated_hole.y + holeOffsetY - rectLength / 2,
@@ -29834,7 +29971,7 @@ var platedHole = (plated_hole, ctx, options = {}) => {
29834
29971
  radius: holeRadius,
29835
29972
  height: throughDrillHeight * 1.1
29836
29973
  }),
29837
- (0, import_primitives3.cylinder)({
29974
+ (0, import_primitives4.cylinder)({
29838
29975
  center: shouldRotate ? [
29839
29976
  plated_hole.x + holeOffsetX,
29840
29977
  plated_hole.y + holeOffsetY + rectLength / 2,
@@ -29867,26 +30004,26 @@ var platedHole = (plated_hole, ctx, options = {}) => {
29867
30004
  const topPadBottom = topSurfaceZ;
29868
30005
  const bottomPadTop = bottomSurfaceZ;
29869
30006
  const centerZ = (topPadBottom + bottomPadTop) / 2;
29870
- const rect2d = (0, import_primitives3.roundedRectangle)({
30007
+ const rect2d = (0, import_primitives4.roundedRectangle)({
29871
30008
  size: [padWidth, padHeight],
29872
30009
  roundRadius: rectBorderRadius || 0,
29873
30010
  segments: RECT_PAD_SEGMENTS
29874
30011
  });
29875
- const extruded = (0, import_extrusions2.extrudeLinear)({ height: height10 }, rect2d);
29876
- return (0, import_transforms2.translate)(
30012
+ const extruded = (0, import_extrusions3.extrudeLinear)({ height: height10 }, rect2d);
30013
+ return (0, import_transforms3.translate)(
29877
30014
  [plated_hole.x, plated_hole.y, centerZ - height10 / 2],
29878
30015
  extruded
29879
30016
  );
29880
30017
  })();
29881
- const copperTopPadCut = (0, import_booleans.subtract)(copperTopPad, holeCut);
29882
- const copperBottomPadCut = (0, import_booleans.subtract)(copperBottomPad, holeCut);
29883
- const copperFillCut = (0, import_booleans.subtract)(copperFill, holeCut);
29884
- const barrelHoleCut = (0, import_booleans.union)(
29885
- (0, import_primitives3.cuboid)({
30018
+ const copperTopPadCut = (0, import_booleans2.subtract)(copperTopPad, holeCut);
30019
+ const copperBottomPadCut = (0, import_booleans2.subtract)(copperBottomPad, holeCut);
30020
+ const copperFillCut = (0, import_booleans2.subtract)(copperFill, holeCut);
30021
+ const barrelHoleCut = (0, import_booleans2.union)(
30022
+ (0, import_primitives4.cuboid)({
29886
30023
  center: [plated_hole.x + holeOffsetX, plated_hole.y + holeOffsetY, 0],
29887
30024
  size: shouldRotate ? [holeHeight - 2 * M, rectLength - 2 * M, throughDrillHeight * 1.1] : [rectLength - 2 * M, holeHeight - 2 * M, throughDrillHeight * 1.1]
29888
30025
  }),
29889
- (0, import_primitives3.cylinder)({
30026
+ (0, import_primitives4.cylinder)({
29890
30027
  center: shouldRotate ? [
29891
30028
  plated_hole.x + holeOffsetX,
29892
30029
  plated_hole.y + holeOffsetY - rectLength / 2,
@@ -29899,7 +30036,7 @@ var platedHole = (plated_hole, ctx, options = {}) => {
29899
30036
  radius: holeRadius - M,
29900
30037
  height: throughDrillHeight * 1.1
29901
30038
  }),
29902
- (0, import_primitives3.cylinder)({
30039
+ (0, import_primitives4.cylinder)({
29903
30040
  center: shouldRotate ? [
29904
30041
  plated_hole.x + holeOffsetX,
29905
30042
  plated_hole.y + holeOffsetY + rectLength / 2,
@@ -29913,19 +30050,59 @@ var platedHole = (plated_hole, ctx, options = {}) => {
29913
30050
  height: throughDrillHeight * 1.1
29914
30051
  })
29915
30052
  );
29916
- const barrelWithHole = (0, import_booleans.subtract)(barrel, barrelHoleCut);
30053
+ const barrelWithHole = (0, import_booleans2.subtract)(barrel, barrelHoleCut);
29917
30054
  const finalCopper = maybeClip(
29918
- (0, import_booleans.union)(copperTopPadCut, copperBottomPadCut, copperFillCut, barrelWithHole),
30055
+ (0, import_booleans2.union)(copperTopPadCut, copperBottomPadCut, copperFillCut, barrelWithHole),
29919
30056
  clipGeom
29920
30057
  );
29921
30058
  return (0, import_colors2.colorize)(colors.copper, finalCopper);
30059
+ } else if (plated_hole.shape === "hole_with_polygon_pad") {
30060
+ const padOutline = plated_hole.pad_outline;
30061
+ if (!Array.isArray(padOutline) || padOutline.length < 3) {
30062
+ throw new Error(
30063
+ `Invalid pad_outline for plated hole at (${plated_hole.x}, ${plated_hole.y})`
30064
+ );
30065
+ }
30066
+ const polygonPoints = padOutline.map((point2) => [
30067
+ point2.x,
30068
+ point2.y
30069
+ ]);
30070
+ const polygon2d = (0, import_primitives4.polygon)({ points: polygonPoints });
30071
+ const centerZ = (topSurfaceZ + bottomSurfaceZ) / 2;
30072
+ const createPolygonPad = (thickness, zCenter) => {
30073
+ const safeThickness = Math.max(thickness, M);
30074
+ const extruded = (0, import_extrusions3.extrudeLinear)({ height: safeThickness }, polygon2d);
30075
+ return (0, import_transforms3.translate)(
30076
+ [plated_hole.x, plated_hole.y, zCenter - safeThickness / 2],
30077
+ extruded
30078
+ );
30079
+ };
30080
+ const mainFill = createPolygonPad(
30081
+ Math.max(copperSpan - platedHoleLipHeight * 2, M),
30082
+ centerZ
30083
+ );
30084
+ const topPad = createPolygonPad(platedHoleLipHeight, topSurfaceZ);
30085
+ const bottomPad = createPolygonPad(platedHoleLipHeight, bottomSurfaceZ);
30086
+ const copperSolid = maybeClip((0, import_booleans2.union)(mainFill, topPad, bottomPad), clipGeom);
30087
+ const barrel = createHoleWithPolygonPadHoleGeom(plated_hole, copperSpan);
30088
+ if (!barrel) return (0, import_colors2.colorize)(colors.copper, copperSolid);
30089
+ const drill = createHoleWithPolygonPadHoleGeom(plated_hole, throughDrillHeight, {
30090
+ sizeDelta: -2 * M
30091
+ }) || barrel;
30092
+ let finalCopper = (0, import_booleans2.union)((0, import_booleans2.subtract)(copperSolid, barrel), barrel);
30093
+ if (options.clipGeom) {
30094
+ finalCopper = (0, import_booleans2.subtract)(finalCopper, drill);
30095
+ finalCopper = (0, import_booleans2.intersect)(finalCopper, options.clipGeom);
30096
+ return (0, import_colors2.colorize)(colors.copper, finalCopper);
30097
+ }
30098
+ return (0, import_colors2.colorize)(colors.copper, (0, import_booleans2.subtract)(finalCopper, drill));
29922
30099
  } else {
29923
30100
  throw new Error(`Unsupported plated hole shape: ${plated_hole.shape}`);
29924
30101
  }
29925
30102
  };
29926
30103
 
29927
30104
  // src/BoardGeomBuilder.ts
29928
- var import_extrusions7 = __toESM(require_extrusions(), 1);
30105
+ var import_extrusions8 = __toESM(require_extrusions(), 1);
29929
30106
  var import_expansions4 = __toESM(require_expansions(), 1);
29930
30107
 
29931
30108
  // src/geoms/create-geoms-for-silkscreen-text.ts
@@ -29948,7 +30125,7 @@ function isUndefined(val) {
29948
30125
  }
29949
30126
 
29950
30127
  // node_modules/transformation-matrix/src/translate.js
29951
- function translate3(tx, ty = 0) {
30128
+ function translate4(tx, ty = 0) {
29952
30129
  return {
29953
30130
  a: 1,
29954
30131
  c: 0,
@@ -30007,9 +30184,9 @@ function rotate(angle, cx, cy) {
30007
30184
  return rotationMatrix;
30008
30185
  }
30009
30186
  return transform([
30010
- translate3(cx, cy),
30187
+ translate4(cx, cy),
30011
30188
  rotationMatrix,
30012
- translate3(-cx, -cy)
30189
+ translate4(-cx, -cy)
30013
30190
  ]);
30014
30191
  }
30015
30192
 
@@ -30197,19 +30374,19 @@ function createSilkscreenTextGeoms(silkscreenText) {
30197
30374
  const transforms = [];
30198
30375
  if (silkscreenText.layer === "bottom") {
30199
30376
  transforms.push(
30200
- translate3(centerX, centerY),
30377
+ translate4(centerX, centerY),
30201
30378
  { a: -1, b: 0, c: 0, d: 1, e: 0, f: 0 },
30202
30379
  // horizontal flip matrix
30203
- translate3(-centerX, -centerY)
30380
+ translate4(-centerX, -centerY)
30204
30381
  );
30205
30382
  rotationDegrees = -rotationDegrees;
30206
30383
  }
30207
30384
  if (rotationDegrees) {
30208
30385
  const rad = rotationDegrees * Math.PI / 180;
30209
30386
  transforms.push(
30210
- translate3(centerX, centerY),
30387
+ translate4(centerX, centerY),
30211
30388
  rotate(rad),
30212
- translate3(-centerX, -centerY)
30389
+ translate4(-centerX, -centerY)
30213
30390
  );
30214
30391
  }
30215
30392
  let transformedOutlines = textOutlines;
@@ -30230,10 +30407,10 @@ function createSilkscreenTextGeoms(silkscreenText) {
30230
30407
  }
30231
30408
 
30232
30409
  // src/geoms/create-geoms-for-silkscreen-path.ts
30233
- var import_primitives4 = __toESM(require_primitives(), 1);
30410
+ var import_primitives5 = __toESM(require_primitives(), 1);
30234
30411
  var import_expansions2 = __toESM(require_expansions(), 1);
30235
- var import_extrusions3 = __toESM(require_extrusions(), 1);
30236
- var import_transforms3 = __toESM(require_transforms(), 1);
30412
+ var import_extrusions4 = __toESM(require_extrusions(), 1);
30413
+ var import_transforms4 = __toESM(require_transforms(), 1);
30237
30414
  var import_colors3 = __toESM(require_colors(), 1);
30238
30415
 
30239
30416
  // src/utils/units.ts
@@ -30288,7 +30465,7 @@ function createSilkscreenPathGeom(sp, ctx) {
30288
30465
  parseDimensionToMm(p.x) ?? 0,
30289
30466
  parseDimensionToMm(p.y) ?? 0
30290
30467
  ]);
30291
- const pathLine = (0, import_primitives4.line)(routePoints);
30468
+ const pathLine = (0, import_primitives5.line)(routePoints);
30292
30469
  const strokeWidth = coerceDimensionToMm(sp.stroke_width, 0.1);
30293
30470
  const expandedPath = (0, import_expansions2.expand)(
30294
30471
  { delta: strokeWidth / 2, corners: "round" },
@@ -30296,9 +30473,9 @@ function createSilkscreenPathGeom(sp, ctx) {
30296
30473
  );
30297
30474
  const layerSign = sp.layer === "bottom" ? -1 : 1;
30298
30475
  const zPos = layerSign * ctx.pcbThickness / 2 + layerSign * M * 1.5;
30299
- let pathGeom = (0, import_transforms3.translate)(
30476
+ let pathGeom = (0, import_transforms4.translate)(
30300
30477
  [0, 0, zPos],
30301
- (0, import_extrusions3.extrudeLinear)({ height: 0.012 }, expandedPath)
30478
+ (0, import_extrusions4.extrudeLinear)({ height: 0.012 }, expandedPath)
30302
30479
  // Standard silkscreen thickness
30303
30480
  );
30304
30481
  pathGeom = (0, import_colors3.colorize)([1, 1, 1], pathGeom);
@@ -30306,10 +30483,10 @@ function createSilkscreenPathGeom(sp, ctx) {
30306
30483
  }
30307
30484
 
30308
30485
  // src/geoms/create-geoms-for-silkscreen-line.ts
30309
- var import_primitives5 = __toESM(require_primitives(), 1);
30486
+ var import_primitives6 = __toESM(require_primitives(), 1);
30310
30487
  var import_expansions3 = __toESM(require_expansions(), 1);
30311
- var import_extrusions4 = __toESM(require_extrusions(), 1);
30312
- var import_transforms4 = __toESM(require_transforms(), 1);
30488
+ var import_extrusions5 = __toESM(require_extrusions(), 1);
30489
+ var import_transforms5 = __toESM(require_transforms(), 1);
30313
30490
  var import_colors4 = __toESM(require_colors(), 1);
30314
30491
  function createSilkscreenLineGeom(sl, ctx) {
30315
30492
  const x1 = parseDimensionToMm(sl.x1) ?? 0;
@@ -30321,7 +30498,7 @@ function createSilkscreenLineGeom(sl, ctx) {
30321
30498
  [x1, y1],
30322
30499
  [x2, y2]
30323
30500
  ];
30324
- const baseLine = (0, import_primitives5.line)(routePoints);
30501
+ const baseLine = (0, import_primitives6.line)(routePoints);
30325
30502
  const strokeWidth = coerceDimensionToMm(sl.stroke_width, 0.1);
30326
30503
  const expandedLine = (0, import_expansions3.expand)(
30327
30504
  { delta: strokeWidth / 2, corners: "round" },
@@ -30329,20 +30506,20 @@ function createSilkscreenLineGeom(sl, ctx) {
30329
30506
  );
30330
30507
  const layerSign = sl.layer === "bottom" ? -1 : 1;
30331
30508
  const zPos = layerSign * ctx.pcbThickness / 2 + layerSign * M * 1.5;
30332
- let lineGeom = (0, import_transforms4.translate)(
30509
+ let lineGeom = (0, import_transforms5.translate)(
30333
30510
  [0, 0, zPos],
30334
- (0, import_extrusions4.extrudeLinear)({ height: 0.012 }, expandedLine)
30511
+ (0, import_extrusions5.extrudeLinear)({ height: 0.012 }, expandedLine)
30335
30512
  );
30336
30513
  lineGeom = (0, import_colors4.colorize)([1, 1, 1], lineGeom);
30337
30514
  return lineGeom;
30338
30515
  }
30339
30516
 
30340
30517
  // src/geoms/create-geoms-for-silkscreen-rect.ts
30341
- var import_primitives6 = __toESM(require_primitives(), 1);
30342
- var import_extrusions5 = __toESM(require_extrusions(), 1);
30343
- var import_transforms5 = __toESM(require_transforms(), 1);
30518
+ var import_primitives7 = __toESM(require_primitives(), 1);
30519
+ var import_extrusions6 = __toESM(require_extrusions(), 1);
30520
+ var import_transforms6 = __toESM(require_transforms(), 1);
30344
30521
  var import_colors5 = __toESM(require_colors(), 1);
30345
- var import_booleans2 = __toESM(require_booleans(), 1);
30522
+ var import_booleans3 = __toESM(require_booleans(), 1);
30346
30523
  var RECT_SEGMENTS = 64;
30347
30524
  function createSilkscreenRectGeom(rect, ctx) {
30348
30525
  const width10 = coerceDimensionToMm(rect.width, 0);
@@ -30356,9 +30533,9 @@ function createSilkscreenRectGeom(rect, ctx) {
30356
30533
  height10,
30357
30534
  typeof rawBorderRadius === "string" ? parseDimensionToMm(rawBorderRadius) : rawBorderRadius
30358
30535
  );
30359
- const createRectGeom = (rectWidth, rectHeight, radius) => (0, import_extrusions5.extrudeLinear)(
30536
+ const createRectGeom = (rectWidth, rectHeight, radius) => (0, import_extrusions6.extrudeLinear)(
30360
30537
  { height: 0.012 },
30361
- (0, import_primitives6.roundedRectangle)({
30538
+ (0, import_primitives7.roundedRectangle)({
30362
30539
  size: [rectWidth, rectHeight],
30363
30540
  roundRadius: radius,
30364
30541
  segments: RECT_SEGMENTS
@@ -30383,28 +30560,28 @@ function createSilkscreenRectGeom(rect, ctx) {
30383
30560
  Math.max(borderRadius - strokeWidth, 0)
30384
30561
  );
30385
30562
  const innerGeom = createRectGeom(innerWidth, innerHeight, innerRadius);
30386
- strokeGeom = (0, import_booleans2.subtract)(outerGeom, innerGeom);
30563
+ strokeGeom = (0, import_booleans3.subtract)(outerGeom, innerGeom);
30387
30564
  } else {
30388
30565
  strokeGeom = outerGeom;
30389
30566
  }
30390
30567
  }
30391
30568
  let rectGeom = fillGeom;
30392
30569
  if (strokeGeom) {
30393
- rectGeom = rectGeom ? (0, import_booleans2.union)(rectGeom, strokeGeom) : strokeGeom;
30570
+ rectGeom = rectGeom ? (0, import_booleans3.union)(rectGeom, strokeGeom) : strokeGeom;
30394
30571
  }
30395
30572
  if (!rectGeom) return void 0;
30396
30573
  const layerSign = rect.layer === "bottom" ? -1 : 1;
30397
30574
  const zPos = layerSign * ctx.pcbThickness / 2 + layerSign * M * 1.5;
30398
- rectGeom = (0, import_transforms5.translate)([centerX, centerY, zPos], rectGeom);
30575
+ rectGeom = (0, import_transforms6.translate)([centerX, centerY, zPos], rectGeom);
30399
30576
  return (0, import_colors5.colorize)([1, 1, 1], rectGeom);
30400
30577
  }
30401
30578
 
30402
30579
  // src/geoms/create-geoms-for-silkscreen-circle.ts
30403
- var import_primitives7 = __toESM(require_primitives(), 1);
30404
- var import_extrusions6 = __toESM(require_extrusions(), 1);
30405
- var import_transforms6 = __toESM(require_transforms(), 1);
30580
+ var import_primitives8 = __toESM(require_primitives(), 1);
30581
+ var import_extrusions7 = __toESM(require_extrusions(), 1);
30582
+ var import_transforms7 = __toESM(require_transforms(), 1);
30406
30583
  var import_colors6 = __toESM(require_colors(), 1);
30407
- var import_booleans3 = __toESM(require_booleans(), 1);
30584
+ var import_booleans4 = __toESM(require_booleans(), 1);
30408
30585
  var CIRCLE_SEGMENTS = 64;
30409
30586
  function createSilkscreenCircleGeom(circleEl, ctx) {
30410
30587
  const radius = coerceDimensionToMm(circleEl.radius, 0);
@@ -30420,31 +30597,31 @@ function createSilkscreenCircleGeom(circleEl, ctx) {
30420
30597
  if (hasStroke) {
30421
30598
  const outerRadius = radius + strokeWidth / 2;
30422
30599
  const innerRadius = radius - strokeWidth / 2;
30423
- const outerCircle2d = (0, import_primitives7.circle)({
30600
+ const outerCircle2d = (0, import_primitives8.circle)({
30424
30601
  radius: outerRadius,
30425
30602
  segments: CIRCLE_SEGMENTS
30426
30603
  });
30427
- let ring3d = (0, import_extrusions6.extrudeLinear)({ height: baseHeight }, outerCircle2d);
30604
+ let ring3d = (0, import_extrusions7.extrudeLinear)({ height: baseHeight }, outerCircle2d);
30428
30605
  if (innerRadius > 0) {
30429
- const innerCircle2d = (0, import_primitives7.circle)({
30606
+ const innerCircle2d = (0, import_primitives8.circle)({
30430
30607
  radius: innerRadius,
30431
30608
  segments: CIRCLE_SEGMENTS
30432
30609
  });
30433
- const inner3d = (0, import_extrusions6.extrudeLinear)({ height: baseHeight }, innerCircle2d);
30434
- ring3d = (0, import_booleans3.subtract)(ring3d, inner3d);
30610
+ const inner3d = (0, import_extrusions7.extrudeLinear)({ height: baseHeight }, innerCircle2d);
30611
+ ring3d = (0, import_booleans4.subtract)(ring3d, inner3d);
30435
30612
  }
30436
30613
  circleGeom = ring3d;
30437
30614
  } else {
30438
- const filledCircle2d = (0, import_primitives7.circle)({ radius, segments: CIRCLE_SEGMENTS });
30439
- circleGeom = (0, import_extrusions6.extrudeLinear)({ height: baseHeight }, filledCircle2d);
30615
+ const filledCircle2d = (0, import_primitives8.circle)({ radius, segments: CIRCLE_SEGMENTS });
30616
+ circleGeom = (0, import_extrusions7.extrudeLinear)({ height: baseHeight }, filledCircle2d);
30440
30617
  }
30441
- const translatedGeom = (0, import_transforms6.translate)([centerX, centerY, zPos], circleGeom);
30618
+ const translatedGeom = (0, import_transforms7.translate)([centerX, centerY, zPos], circleGeom);
30442
30619
  return (0, import_colors6.colorize)([1, 1, 1], translatedGeom);
30443
30620
  }
30444
30621
 
30445
30622
  // src/geoms/brep-converter.ts
30446
- var import_primitives8 = __toESM(require_primitives(), 1);
30447
- var import_booleans4 = __toESM(require_booleans(), 1);
30623
+ var import_primitives9 = __toESM(require_primitives(), 1);
30624
+ var import_booleans5 = __toESM(require_booleans(), 1);
30448
30625
  function segmentToPoints(p1, p2, bulge, arcSegments) {
30449
30626
  if (!bulge || Math.abs(bulge) < 1e-9) {
30450
30627
  return [];
@@ -30512,7 +30689,7 @@ function createGeom2FromBRep(brep, arcSegments = 16) {
30512
30689
  if (arePointsClockwise2(outerPoints)) {
30513
30690
  outerPoints.reverse();
30514
30691
  }
30515
- const outerGeom = (0, import_primitives8.polygon)({ points: outerPoints });
30692
+ const outerGeom = (0, import_primitives9.polygon)({ points: outerPoints });
30516
30693
  if (!brep.inner_rings || brep.inner_rings.length === 0) {
30517
30694
  return outerGeom;
30518
30695
  }
@@ -30521,10 +30698,10 @@ function createGeom2FromBRep(brep, arcSegments = 16) {
30521
30698
  if (arePointsClockwise2(innerPoints)) {
30522
30699
  innerPoints.reverse();
30523
30700
  }
30524
- return (0, import_primitives8.polygon)({ points: innerPoints });
30701
+ return (0, import_primitives9.polygon)({ points: innerPoints });
30525
30702
  });
30526
30703
  if (innerGeoms.length === 0) return outerGeom;
30527
- return (0, import_booleans4.subtract)(outerGeom, innerGeoms);
30704
+ return (0, import_booleans5.subtract)(outerGeom, innerGeoms);
30528
30705
  }
30529
30706
 
30530
30707
  // src/BoardGeomBuilder.ts
@@ -30534,15 +30711,15 @@ var BOARD_CLIP_XY_OUTSET = 0.05;
30534
30711
  var createCenteredRectPadGeom = (width10, height10, thickness, rectBorderRadius) => {
30535
30712
  const clampedRadius = clampRectBorderRadius(width10, height10, rectBorderRadius);
30536
30713
  if (clampedRadius <= 0) {
30537
- return (0, import_primitives9.cuboid)({ center: [0, 0, 0], size: [width10, height10, thickness] });
30714
+ return (0, import_primitives10.cuboid)({ center: [0, 0, 0], size: [width10, height10, thickness] });
30538
30715
  }
30539
- const rect2d = (0, import_primitives9.roundedRectangle)({
30716
+ const rect2d = (0, import_primitives10.roundedRectangle)({
30540
30717
  size: [width10, height10],
30541
30718
  roundRadius: clampedRadius,
30542
30719
  segments: PAD_ROUNDED_SEGMENTS
30543
30720
  });
30544
- const extruded = (0, import_extrusions7.extrudeLinear)({ height: thickness }, rect2d);
30545
- return (0, import_transforms7.translate)([0, 0, -thickness / 2], extruded);
30721
+ const extruded = (0, import_extrusions8.extrudeLinear)({ height: thickness }, rect2d);
30722
+ return (0, import_transforms8.translate)([0, 0, -thickness / 2], extruded);
30546
30723
  };
30547
30724
  var buildStateOrder = [
30548
30725
  "initializing",
@@ -30669,11 +30846,11 @@ var BoardGeomBuilder = class {
30669
30846
  { xyOutset: BOARD_CLIP_XY_OUTSET }
30670
30847
  );
30671
30848
  } else {
30672
- this.boardGeom = (0, import_primitives9.cuboid)({
30849
+ this.boardGeom = (0, import_primitives10.cuboid)({
30673
30850
  size: [this.board.width, this.board.height, this.ctx.pcbThickness],
30674
30851
  center: [this.board.center.x, this.board.center.y, 0]
30675
30852
  });
30676
- this.boardClipGeom = (0, import_primitives9.cuboid)({
30853
+ this.boardClipGeom = (0, import_primitives10.cuboid)({
30677
30854
  size: [
30678
30855
  this.board.width + 2 * BOARD_CLIP_XY_OUTSET,
30679
30856
  this.board.height + 2 * BOARD_CLIP_XY_OUTSET,
@@ -30809,17 +30986,17 @@ var BoardGeomBuilder = class {
30809
30986
  const cutoutHeight = this.ctx.pcbThickness * 1.5;
30810
30987
  switch (cutout.shape) {
30811
30988
  case "rect":
30812
- cutoutGeom = (0, import_primitives9.cuboid)({
30989
+ cutoutGeom = (0, import_primitives10.cuboid)({
30813
30990
  center: [cutout.center.x, cutout.center.y, 0],
30814
30991
  size: [cutout.width, cutout.height, cutoutHeight]
30815
30992
  });
30816
30993
  if (cutout.rotation) {
30817
30994
  const rotationRadians = cutout.rotation * Math.PI / 180;
30818
- cutoutGeom = (0, import_transforms7.rotateZ)(rotationRadians, cutoutGeom);
30995
+ cutoutGeom = (0, import_transforms8.rotateZ)(rotationRadians, cutoutGeom);
30819
30996
  }
30820
30997
  break;
30821
30998
  case "circle":
30822
- cutoutGeom = (0, import_primitives9.cylinder)({
30999
+ cutoutGeom = (0, import_primitives10.cylinder)({
30823
31000
  center: [cutout.center.x, cutout.center.y, 0],
30824
31001
  radius: cutout.radius,
30825
31002
  height: cutoutHeight
@@ -30836,13 +31013,13 @@ var BoardGeomBuilder = class {
30836
31013
  if (arePointsClockwise(pointsVec2)) {
30837
31014
  pointsVec2 = pointsVec2.reverse();
30838
31015
  }
30839
- const polygon2d = (0, import_primitives9.polygon)({ points: pointsVec2 });
30840
- cutoutGeom = (0, import_extrusions7.extrudeLinear)({ height: cutoutHeight }, polygon2d);
30841
- cutoutGeom = (0, import_transforms7.translate)([0, 0, -cutoutHeight / 2], cutoutGeom);
31016
+ const polygon2d = (0, import_primitives10.polygon)({ points: pointsVec2 });
31017
+ cutoutGeom = (0, import_extrusions8.extrudeLinear)({ height: cutoutHeight }, polygon2d);
31018
+ cutoutGeom = (0, import_transforms8.translate)([0, 0, -cutoutHeight / 2], cutoutGeom);
30842
31019
  break;
30843
31020
  }
30844
31021
  if (cutoutGeom) {
30845
- this.boardGeom = (0, import_booleans5.subtract)(this.boardGeom, cutoutGeom);
31022
+ this.boardGeom = (0, import_booleans6.subtract)(this.boardGeom, cutoutGeom);
30846
31023
  }
30847
31024
  }
30848
31025
  processCopperPour(pour) {
@@ -30850,22 +31027,22 @@ var BoardGeomBuilder = class {
30850
31027
  const zPos = layerSign * this.ctx.pcbThickness / 2 + layerSign * BOARD_SURFACE_OFFSET.copper;
30851
31028
  let pourGeom = null;
30852
31029
  if (pour.shape === "rect") {
30853
- let baseGeom = (0, import_primitives9.cuboid)({
31030
+ let baseGeom = (0, import_primitives10.cuboid)({
30854
31031
  center: [0, 0, 0],
30855
31032
  // Create at origin for rotation
30856
31033
  size: [pour.width, pour.height, M]
30857
31034
  });
30858
31035
  if ("rotation" in pour && pour.rotation) {
30859
31036
  const rotationRadians = pour.rotation * Math.PI / 180;
30860
- baseGeom = (0, import_transforms7.rotateZ)(rotationRadians, baseGeom);
31037
+ baseGeom = (0, import_transforms8.rotateZ)(rotationRadians, baseGeom);
30861
31038
  }
30862
- pourGeom = (0, import_transforms7.translate)([pour.center.x, pour.center.y, zPos], baseGeom);
31039
+ pourGeom = (0, import_transforms8.translate)([pour.center.x, pour.center.y, zPos], baseGeom);
30863
31040
  } else if (pour.shape === "brep") {
30864
31041
  const brepShape = pour.brep_shape;
30865
31042
  if (brepShape && brepShape.outer_ring) {
30866
31043
  const pourGeom2 = createGeom2FromBRep(brepShape);
30867
- pourGeom = (0, import_extrusions7.extrudeLinear)({ height: M }, pourGeom2);
30868
- pourGeom = (0, import_transforms7.translate)([0, 0, zPos], pourGeom);
31044
+ pourGeom = (0, import_extrusions8.extrudeLinear)({ height: M }, pourGeom2);
31045
+ pourGeom = (0, import_transforms8.translate)([0, 0, zPos], pourGeom);
30869
31046
  }
30870
31047
  } else if (pour.shape === "polygon") {
30871
31048
  let pointsVec2 = pour.points.map((p) => [p.x, p.y]);
@@ -30878,13 +31055,13 @@ var BoardGeomBuilder = class {
30878
31055
  if (arePointsClockwise(pointsVec2)) {
30879
31056
  pointsVec2 = pointsVec2.reverse();
30880
31057
  }
30881
- const polygon2d = (0, import_primitives9.polygon)({ points: pointsVec2 });
30882
- pourGeom = (0, import_extrusions7.extrudeLinear)({ height: M }, polygon2d);
30883
- pourGeom = (0, import_transforms7.translate)([0, 0, zPos], pourGeom);
31058
+ const polygon2d = (0, import_primitives10.polygon)({ points: pointsVec2 });
31059
+ pourGeom = (0, import_extrusions8.extrudeLinear)({ height: M }, polygon2d);
31060
+ pourGeom = (0, import_transforms8.translate)([0, 0, zPos], pourGeom);
30884
31061
  }
30885
31062
  if (pourGeom) {
30886
31063
  if (this.boardClipGeom) {
30887
- pourGeom = (0, import_booleans5.intersect)(this.boardClipGeom, pourGeom);
31064
+ pourGeom = (0, import_booleans6.intersect)(this.boardClipGeom, pourGeom);
30888
31065
  }
30889
31066
  const covered = pour.covered_with_solder_mask !== false;
30890
31067
  const pourMaterialColor = covered ? tracesMaterialColors[this.board.material] ?? colors.fr4GreenSolderWithMask : colors.copper;
@@ -30897,7 +31074,7 @@ var BoardGeomBuilder = class {
30897
31074
  if (ph.shape === "circle" || ph.shape === "circular_hole_with_rect_pad") {
30898
31075
  let cyGeom = null;
30899
31076
  if (ph.shape === "circular_hole_with_rect_pad") {
30900
- cyGeom = (0, import_primitives9.cylinder)({
31077
+ cyGeom = (0, import_primitives10.cylinder)({
30901
31078
  center: [
30902
31079
  ph.x + (ph.hole_offset_x || 0),
30903
31080
  ph.y + (ph.hole_offset_y || 0),
@@ -30909,7 +31086,7 @@ var BoardGeomBuilder = class {
30909
31086
  // Ensure it cuts through
30910
31087
  });
30911
31088
  } else {
30912
- cyGeom = (0, import_primitives9.cylinder)({
31089
+ cyGeom = (0, import_primitives10.cylinder)({
30913
31090
  center: [ph.x, ph.y, 0],
30914
31091
  radius: ph.hole_diameter / 2 + M,
30915
31092
  // Add margin for subtraction
@@ -30918,10 +31095,10 @@ var BoardGeomBuilder = class {
30918
31095
  });
30919
31096
  }
30920
31097
  if (!opts.dontCutBoard) {
30921
- this.boardGeom = (0, import_booleans5.subtract)(this.boardGeom, cyGeom);
31098
+ this.boardGeom = (0, import_booleans6.subtract)(this.boardGeom, cyGeom);
30922
31099
  }
30923
31100
  this.padGeoms = this.padGeoms.map(
30924
- (pg) => (0, import_colors7.colorize)(colors.copper, (0, import_booleans5.subtract)(pg, cyGeom))
31101
+ (pg) => (0, import_colors7.colorize)(colors.copper, (0, import_booleans6.subtract)(pg, cyGeom))
30925
31102
  );
30926
31103
  const platedHoleGeom = platedHole(ph, this.ctx, {
30927
31104
  clipGeom: this.boardClipGeom
@@ -30935,8 +31112,8 @@ var BoardGeomBuilder = class {
30935
31112
  const rectLength = Math.abs(holeWidth - holeHeight);
30936
31113
  let pillHole;
30937
31114
  if (ph.shape === "pill_hole_with_rect_pad") {
30938
- pillHole = (0, import_booleans5.union)(
30939
- (0, import_primitives9.cuboid)({
31115
+ pillHole = (0, import_booleans6.union)(
31116
+ (0, import_primitives10.cuboid)({
30940
31117
  center: [
30941
31118
  ph.x + (ph.hole_offset_x || 0),
30942
31119
  ph.y + (ph.hole_offset_y || 0),
@@ -30944,7 +31121,7 @@ var BoardGeomBuilder = class {
30944
31121
  ],
30945
31122
  size: shouldRotate ? [holeHeight, rectLength, this.ctx.pcbThickness * 1.5] : [rectLength, holeHeight, this.ctx.pcbThickness * 1.5]
30946
31123
  }),
30947
- (0, import_primitives9.cylinder)({
31124
+ (0, import_primitives10.cylinder)({
30948
31125
  center: shouldRotate ? [
30949
31126
  ph.x + (ph.hole_offset_x || 0),
30950
31127
  ph.y + (ph.hole_offset_y || 0) - rectLength / 2,
@@ -30957,7 +31134,7 @@ var BoardGeomBuilder = class {
30957
31134
  radius: holeRadius,
30958
31135
  height: this.ctx.pcbThickness * 1.5
30959
31136
  }),
30960
- (0, import_primitives9.cylinder)({
31137
+ (0, import_primitives10.cylinder)({
30961
31138
  center: shouldRotate ? [
30962
31139
  ph.x + (ph.hole_offset_x || 0),
30963
31140
  ph.y + (ph.hole_offset_y || 0) + rectLength / 2,
@@ -30972,17 +31149,17 @@ var BoardGeomBuilder = class {
30972
31149
  })
30973
31150
  );
30974
31151
  } else {
30975
- pillHole = (0, import_booleans5.union)(
30976
- (0, import_primitives9.cuboid)({
31152
+ pillHole = (0, import_booleans6.union)(
31153
+ (0, import_primitives10.cuboid)({
30977
31154
  center: [ph.x, ph.y, 0],
30978
31155
  size: shouldRotate ? [holeHeight, rectLength, this.ctx.pcbThickness * 1.5] : [rectLength, holeHeight, this.ctx.pcbThickness * 1.5]
30979
31156
  }),
30980
- (0, import_primitives9.cylinder)({
31157
+ (0, import_primitives10.cylinder)({
30981
31158
  center: shouldRotate ? [ph.x, ph.y - rectLength / 2, 0] : [ph.x - rectLength / 2, ph.y, 0],
30982
31159
  radius: holeRadius,
30983
31160
  height: this.ctx.pcbThickness * 1.5
30984
31161
  }),
30985
- (0, import_primitives9.cylinder)({
31162
+ (0, import_primitives10.cylinder)({
30986
31163
  center: shouldRotate ? [ph.x, ph.y + rectLength / 2, 0] : [ph.x + rectLength / 2, ph.y, 0],
30987
31164
  radius: holeRadius,
30988
31165
  height: this.ctx.pcbThickness * 1.5
@@ -30990,10 +31167,36 @@ var BoardGeomBuilder = class {
30990
31167
  );
30991
31168
  }
30992
31169
  if (!opts.dontCutBoard) {
30993
- this.boardGeom = (0, import_booleans5.subtract)(this.boardGeom, pillHole);
31170
+ this.boardGeom = (0, import_booleans6.subtract)(this.boardGeom, pillHole);
31171
+ }
31172
+ this.padGeoms = this.padGeoms.map(
31173
+ (pg) => (0, import_colors7.colorize)(colors.copper, (0, import_booleans6.subtract)(pg, pillHole))
31174
+ );
31175
+ const platedHoleGeom = platedHole(ph, this.ctx, {
31176
+ clipGeom: this.boardClipGeom
31177
+ });
31178
+ this.platedHoleGeoms.push(platedHoleGeom);
31179
+ } else if (ph.shape === "hole_with_polygon_pad") {
31180
+ const padOutline = ph.pad_outline;
31181
+ if (!Array.isArray(padOutline) || padOutline.length < 3) {
31182
+ return;
31183
+ }
31184
+ const holeDepth = this.ctx.pcbThickness * 1.5;
31185
+ const boardHole = createHoleWithPolygonPadHoleGeom(ph, holeDepth, {
31186
+ sizeDelta: 2 * M
31187
+ });
31188
+ const copperHole = createHoleWithPolygonPadHoleGeom(ph, holeDepth, {
31189
+ sizeDelta: -2 * M
31190
+ });
31191
+ if (!boardHole || !copperHole) return;
31192
+ if (!opts.dontCutBoard) {
31193
+ this.boardGeom = (0, import_booleans6.subtract)(this.boardGeom, boardHole);
30994
31194
  }
30995
31195
  this.padGeoms = this.padGeoms.map(
30996
- (pg) => (0, import_colors7.colorize)(colors.copper, (0, import_booleans5.subtract)(pg, pillHole))
31196
+ (pg) => (0, import_colors7.colorize)(colors.copper, (0, import_booleans6.subtract)(pg, boardHole))
31197
+ );
31198
+ this.platedHoleGeoms = this.platedHoleGeoms.map(
31199
+ (phg) => (0, import_colors7.colorize)(colors.copper, (0, import_booleans6.subtract)(phg, copperHole))
30997
31200
  );
30998
31201
  const platedHoleGeom = platedHole(ph, this.ctx, {
30999
31202
  clipGeom: this.boardClipGeom
@@ -31006,22 +31209,22 @@ var BoardGeomBuilder = class {
31006
31209
  const holeDepth = this.ctx.pcbThickness * 1.5;
31007
31210
  const copperInset = 0.02;
31008
31211
  if (hole.hole_shape === "round" || hole.hole_shape === "circle") {
31009
- const cyGeom = (0, import_primitives9.cylinder)({
31212
+ const cyGeom = (0, import_primitives10.cylinder)({
31010
31213
  center: [hole.x, hole.y, 0],
31011
31214
  radius: hole.hole_diameter / 2 + M,
31012
31215
  height: holeDepth
31013
31216
  });
31014
- this.boardGeom = (0, import_booleans5.subtract)(this.boardGeom, cyGeom);
31217
+ this.boardGeom = (0, import_booleans6.subtract)(this.boardGeom, cyGeom);
31015
31218
  this.padGeoms = this.padGeoms.map(
31016
- (pg) => (0, import_colors7.colorize)(colors.copper, (0, import_booleans5.subtract)(pg, cyGeom))
31219
+ (pg) => (0, import_colors7.colorize)(colors.copper, (0, import_booleans6.subtract)(pg, cyGeom))
31017
31220
  );
31018
- const copperCut = (0, import_primitives9.cylinder)({
31221
+ const copperCut = (0, import_primitives10.cylinder)({
31019
31222
  center: [hole.x, hole.y, 0],
31020
31223
  radius: hole.hole_diameter / 2 + M / 2,
31021
31224
  height: holeDepth
31022
31225
  });
31023
31226
  this.platedHoleGeoms = this.platedHoleGeoms.map(
31024
- (phg) => (0, import_colors7.colorize)(colors.copper, (0, import_booleans5.subtract)(phg, copperCut))
31227
+ (phg) => (0, import_colors7.colorize)(colors.copper, (0, import_booleans6.subtract)(phg, copperCut))
31025
31228
  );
31026
31229
  } else if (hole.hole_shape === "pill" || hole.hole_shape === "rotated_pill") {
31027
31230
  const holeWidth = hole.hole_width;
@@ -31031,34 +31234,34 @@ var BoardGeomBuilder = class {
31031
31234
  const isRotated = hole.hole_shape === "rotated_pill";
31032
31235
  let pillHole;
31033
31236
  if (holeWidth > holeHeight) {
31034
- pillHole = (0, import_booleans5.union)(
31035
- (0, import_primitives9.cuboid)({
31237
+ pillHole = (0, import_booleans6.union)(
31238
+ (0, import_primitives10.cuboid)({
31036
31239
  center: [hole.x, hole.y, 0],
31037
31240
  size: [rectLength, holeHeight, holeDepth]
31038
31241
  }),
31039
- (0, import_primitives9.cylinder)({
31242
+ (0, import_primitives10.cylinder)({
31040
31243
  center: [hole.x - rectLength / 2, hole.y, 0],
31041
31244
  radius: holeRadius,
31042
31245
  height: holeDepth
31043
31246
  }),
31044
- (0, import_primitives9.cylinder)({
31247
+ (0, import_primitives10.cylinder)({
31045
31248
  center: [hole.x + rectLength / 2, hole.y, 0],
31046
31249
  radius: holeRadius,
31047
31250
  height: holeDepth
31048
31251
  })
31049
31252
  );
31050
31253
  } else {
31051
- pillHole = (0, import_booleans5.union)(
31052
- (0, import_primitives9.cuboid)({
31254
+ pillHole = (0, import_booleans6.union)(
31255
+ (0, import_primitives10.cuboid)({
31053
31256
  center: [hole.x, hole.y, 0],
31054
31257
  size: [holeWidth, rectLength, holeDepth]
31055
31258
  }),
31056
- (0, import_primitives9.cylinder)({
31259
+ (0, import_primitives10.cylinder)({
31057
31260
  center: [hole.x, hole.y - rectLength / 2, 0],
31058
31261
  radius: holeRadius,
31059
31262
  height: holeDepth
31060
31263
  }),
31061
- (0, import_primitives9.cylinder)({
31264
+ (0, import_primitives10.cylinder)({
31062
31265
  center: [hole.x, hole.y + rectLength / 2, 0],
31063
31266
  radius: holeRadius,
31064
31267
  height: holeDepth
@@ -31067,15 +31270,15 @@ var BoardGeomBuilder = class {
31067
31270
  }
31068
31271
  if (isRotated) {
31069
31272
  const rotationRadians = hole.ccw_rotation * Math.PI / 180;
31070
- pillHole = (0, import_transforms7.rotateZ)(rotationRadians, pillHole);
31273
+ pillHole = (0, import_transforms8.rotateZ)(rotationRadians, pillHole);
31071
31274
  }
31072
- this.boardGeom = (0, import_booleans5.subtract)(this.boardGeom, pillHole);
31275
+ this.boardGeom = (0, import_booleans6.subtract)(this.boardGeom, pillHole);
31073
31276
  this.padGeoms = this.padGeoms.map(
31074
- (pg) => (0, import_colors7.colorize)(colors.copper, (0, import_booleans5.subtract)(pg, pillHole))
31277
+ (pg) => (0, import_colors7.colorize)(colors.copper, (0, import_booleans6.subtract)(pg, pillHole))
31075
31278
  );
31076
31279
  const copperPill = (0, import_expansions4.expand)({ delta: -copperInset }, pillHole);
31077
31280
  this.platedHoleGeoms = this.platedHoleGeoms.map(
31078
- (phg) => (0, import_colors7.colorize)(colors.copper, (0, import_booleans5.subtract)(phg, copperPill))
31281
+ (phg) => (0, import_colors7.colorize)(colors.copper, (0, import_booleans6.subtract)(phg, copperPill))
31079
31282
  );
31080
31283
  }
31081
31284
  }
@@ -31090,10 +31293,10 @@ var BoardGeomBuilder = class {
31090
31293
  M,
31091
31294
  rectBorderRadius
31092
31295
  );
31093
- const positionedPadGeom = (0, import_transforms7.translate)([pad2.x, pad2.y, zPos], basePadGeom);
31296
+ const positionedPadGeom = (0, import_transforms8.translate)([pad2.x, pad2.y, zPos], basePadGeom);
31094
31297
  let finalPadGeom = positionedPadGeom;
31095
31298
  if (this.boardClipGeom) {
31096
- finalPadGeom = (0, import_booleans5.intersect)(this.boardClipGeom, finalPadGeom);
31299
+ finalPadGeom = (0, import_booleans6.intersect)(this.boardClipGeom, finalPadGeom);
31097
31300
  }
31098
31301
  finalPadGeom = (0, import_colors7.colorize)(colors.copper, finalPadGeom);
31099
31302
  this.padGeoms.push(finalPadGeom);
@@ -31105,22 +31308,22 @@ var BoardGeomBuilder = class {
31105
31308
  rectBorderRadius
31106
31309
  );
31107
31310
  const rotationRadians = pad2.ccw_rotation * Math.PI / 180;
31108
- basePadGeom = (0, import_transforms7.rotateZ)(rotationRadians, basePadGeom);
31109
- const positionedPadGeom = (0, import_transforms7.translate)([pad2.x, pad2.y, zPos], basePadGeom);
31311
+ basePadGeom = (0, import_transforms8.rotateZ)(rotationRadians, basePadGeom);
31312
+ const positionedPadGeom = (0, import_transforms8.translate)([pad2.x, pad2.y, zPos], basePadGeom);
31110
31313
  let finalPadGeom = positionedPadGeom;
31111
31314
  if (this.boardClipGeom) {
31112
- finalPadGeom = (0, import_booleans5.intersect)(this.boardClipGeom, finalPadGeom);
31315
+ finalPadGeom = (0, import_booleans6.intersect)(this.boardClipGeom, finalPadGeom);
31113
31316
  }
31114
31317
  finalPadGeom = (0, import_colors7.colorize)(colors.copper, finalPadGeom);
31115
31318
  this.padGeoms.push(finalPadGeom);
31116
31319
  } else if (pad2.shape === "circle") {
31117
- let padGeom = (0, import_primitives9.cylinder)({
31320
+ let padGeom = (0, import_primitives10.cylinder)({
31118
31321
  center: [pad2.x, pad2.y, zPos],
31119
31322
  radius: pad2.radius,
31120
31323
  height: M
31121
31324
  });
31122
31325
  if (this.boardClipGeom) {
31123
- padGeom = (0, import_booleans5.intersect)(this.boardClipGeom, padGeom);
31326
+ padGeom = (0, import_booleans6.intersect)(this.boardClipGeom, padGeom);
31124
31327
  }
31125
31328
  padGeom = (0, import_colors7.colorize)(colors.copper, padGeom);
31126
31329
  this.padGeoms.push(padGeom);
@@ -31136,14 +31339,14 @@ var BoardGeomBuilder = class {
31136
31339
  if (currentSegmentPoints.length >= 2 && currentLayer) {
31137
31340
  const layerSign = currentLayer === "bottom" ? -1 : 1;
31138
31341
  const zCenter = layerSign * this.ctx.pcbThickness / 2 + layerSign * BOARD_SURFACE_OFFSET.traces;
31139
- const linePath = (0, import_primitives9.line)(currentSegmentPoints);
31342
+ const linePath = (0, import_primitives10.line)(currentSegmentPoints);
31140
31343
  const expandedPath = (0, import_expansions4.expand)(
31141
31344
  { delta: currentWidth / 2, corners: "round" },
31142
31345
  linePath
31143
31346
  );
31144
- let traceGeom = (0, import_transforms7.translate)(
31347
+ let traceGeom = (0, import_transforms8.translate)(
31145
31348
  [0, 0, zCenter - M / 2],
31146
- (0, import_extrusions7.extrudeLinear)({ height: M }, expandedPath)
31349
+ (0, import_extrusions8.extrudeLinear)({ height: M }, expandedPath)
31147
31350
  );
31148
31351
  const startPointCoords = currentSegmentPoints[0];
31149
31352
  const endPointCoords = currentSegmentPoints[currentSegmentPoints.length - 1];
@@ -31152,25 +31355,25 @@ var BoardGeomBuilder = class {
31152
31355
  startPointCoords[1]
31153
31356
  );
31154
31357
  if (startHole) {
31155
- const cuttingCylinder = (0, import_primitives9.cylinder)({
31358
+ const cuttingCylinder = (0, import_primitives10.cylinder)({
31156
31359
  center: [startPointCoords[0], startPointCoords[1], zCenter],
31157
31360
  radius: startHole.diameter / 2 + M,
31158
31361
  height: M
31159
31362
  });
31160
- traceGeom = (0, import_booleans5.subtract)(traceGeom, cuttingCylinder);
31363
+ traceGeom = (0, import_booleans6.subtract)(traceGeom, cuttingCylinder);
31161
31364
  }
31162
31365
  const endHole = this.getHoleToCut(endPointCoords[0], endPointCoords[1]);
31163
31366
  if (endHole) {
31164
- const cuttingCylinder = (0, import_primitives9.cylinder)({
31367
+ const cuttingCylinder = (0, import_primitives10.cylinder)({
31165
31368
  center: [endPointCoords[0], endPointCoords[1], zCenter],
31166
31369
  radius: endHole.diameter / 2 + M,
31167
31370
  height: M
31168
31371
  });
31169
- traceGeom = (0, import_booleans5.subtract)(traceGeom, cuttingCylinder);
31372
+ traceGeom = (0, import_booleans6.subtract)(traceGeom, cuttingCylinder);
31170
31373
  }
31171
31374
  const tracesMaterialColor = tracesMaterialColors[this.board.material] ?? colors.fr4GreenSolderWithMask;
31172
31375
  if (this.boardClipGeom) {
31173
- traceGeom = (0, import_booleans5.intersect)(this.boardClipGeom, traceGeom);
31376
+ traceGeom = (0, import_booleans6.intersect)(this.boardClipGeom, traceGeom);
31174
31377
  }
31175
31378
  traceGeom = (0, import_colors7.colorize)(tracesMaterialColor, traceGeom);
31176
31379
  this.traceGeoms.push(traceGeom);
@@ -31239,7 +31442,7 @@ var BoardGeomBuilder = class {
31239
31442
  point2[0] + xOffset + st.anchor_position.x,
31240
31443
  point2[1] + yOffset + st.anchor_position.y
31241
31444
  ]);
31242
- const textPath = (0, import_primitives9.line)(alignedOutline);
31445
+ const textPath = (0, import_primitives10.line)(alignedOutline);
31243
31446
  const fontSize = st.font_size || 0.25;
31244
31447
  const expansionDelta = Math.min(
31245
31448
  Math.max(0.01, fontSize * 0.1),
@@ -31251,16 +31454,16 @@ var BoardGeomBuilder = class {
31251
31454
  );
31252
31455
  let textGeom;
31253
31456
  if (st.layer === "bottom") {
31254
- textGeom = (0, import_transforms7.translate)(
31457
+ textGeom = (0, import_transforms8.translate)(
31255
31458
  [0, 0, -this.ctx.pcbThickness / 2 - M],
31256
31459
  // Position above board
31257
- (0, import_extrusions7.extrudeLinear)({ height: 0.012 }, expandedPath)
31460
+ (0, import_extrusions8.extrudeLinear)({ height: 0.012 }, expandedPath)
31258
31461
  );
31259
31462
  } else {
31260
- textGeom = (0, import_transforms7.translate)(
31463
+ textGeom = (0, import_transforms8.translate)(
31261
31464
  [0, 0, this.ctx.pcbThickness / 2 + M],
31262
31465
  // Position above board
31263
- (0, import_extrusions7.extrudeLinear)({ height: 0.012 }, expandedPath)
31466
+ (0, import_extrusions8.extrudeLinear)({ height: 0.012 }, expandedPath)
31264
31467
  );
31265
31468
  }
31266
31469
  textGeom = (0, import_colors7.colorize)([1, 1, 1], textGeom);
@@ -32198,18 +32401,18 @@ function createSilkscreenTextureForLayer({
32198
32401
  let rotationDeg = textS.ccw_rotation ?? 0;
32199
32402
  if (textS.layer === "bottom") {
32200
32403
  transformMatrices.push(
32201
- translate3(textCenterX, textCenterY),
32404
+ translate4(textCenterX, textCenterY),
32202
32405
  { a: -1, b: 0, c: 0, d: 1, e: 0, f: 0 },
32203
- translate3(-textCenterX, -textCenterY)
32406
+ translate4(-textCenterX, -textCenterY)
32204
32407
  );
32205
32408
  rotationDeg = -rotationDeg;
32206
32409
  }
32207
32410
  if (rotationDeg) {
32208
32411
  const rad = rotationDeg * Math.PI / 180;
32209
32412
  transformMatrices.push(
32210
- translate3(textCenterX, textCenterY),
32413
+ translate4(textCenterX, textCenterY),
32211
32414
  rotate(rad),
32212
- translate3(-textCenterX, -textCenterY)
32415
+ translate4(-textCenterX, -textCenterY)
32213
32416
  );
32214
32417
  }
32215
32418
  const finalTransformMatrix = transformMatrices.length > 0 ? compose(...transformMatrices) : void 0;
@@ -32418,9 +32621,29 @@ function processNonPlatedHolesForManifold(Manifold, circuitJson, pcbThickness, m
32418
32621
  // src/utils/manifold/process-plated-holes.ts
32419
32622
  import { su as su10 } from "@tscircuit/circuit-json-util";
32420
32623
  import * as THREE21 from "three";
32624
+ var arePointsClockwise3 = (points) => {
32625
+ let area = 0;
32626
+ for (let i = 0; i < points.length; i++) {
32627
+ const j = (i + 1) % points.length;
32628
+ if (points[i] && points[j]) {
32629
+ area += points[i][0] * points[j][1];
32630
+ area -= points[j][0] * points[i][1];
32631
+ }
32632
+ }
32633
+ const signedArea = area / 2;
32634
+ return signedArea <= 0;
32635
+ };
32636
+ var createEllipsePoints = (width10, height10, segments) => {
32637
+ const points = [];
32638
+ for (let i = 0; i < segments; i++) {
32639
+ const theta = 2 * Math.PI * i / segments;
32640
+ points.push([width10 / 2 * Math.cos(theta), height10 / 2 * Math.sin(theta)]);
32641
+ }
32642
+ return points;
32643
+ };
32421
32644
  var COPPER_COLOR = new THREE21.Color(...colors.copper);
32422
32645
  var PLATED_HOLE_LIP_HEIGHT = 0.05;
32423
- function processPlatedHolesForManifold(Manifold, circuitJson, pcbThickness, manifoldInstancesForCleanup, boardClipVolume) {
32646
+ function processPlatedHolesForManifold(Manifold, CrossSection, circuitJson, pcbThickness, manifoldInstancesForCleanup, boardClipVolume) {
32424
32647
  const platedHoleBoardDrills = [];
32425
32648
  const pcbPlatedHoles = su10(circuitJson).pcb_plated_hole.list();
32426
32649
  const platedHoleCopperGeoms = [];
@@ -32436,6 +32659,86 @@ function processPlatedHolesForManifold(Manifold, circuitJson, pcbThickness, mani
32436
32659
  manifoldInstancesForCleanup.push(pillOp);
32437
32660
  return pillOp;
32438
32661
  };
32662
+ const createPolygonPadOp = ({
32663
+ padOutline,
32664
+ thickness
32665
+ }) => {
32666
+ if (!Array.isArray(padOutline) || padOutline.length < 3) return null;
32667
+ let points = padOutline.map((point2) => [
32668
+ point2.x,
32669
+ point2.y
32670
+ ]);
32671
+ if (arePointsClockwise3(points)) {
32672
+ points = points.reverse();
32673
+ }
32674
+ const crossSection = CrossSection.ofPolygons([points]);
32675
+ manifoldInstancesForCleanup.push(crossSection);
32676
+ const padOp = Manifold.extrude(crossSection, thickness, 0, 0, [1, 1], true);
32677
+ manifoldInstancesForCleanup.push(padOp);
32678
+ return padOp;
32679
+ };
32680
+ const createHoleOpForPolygonPad = ({
32681
+ ph,
32682
+ depth,
32683
+ sizeDelta = 0
32684
+ }) => {
32685
+ const shape = ph.shape;
32686
+ if (shape !== "hole_with_polygon_pad") {
32687
+ return null;
32688
+ }
32689
+ const padOutline = ph.pad_outline;
32690
+ if (!Array.isArray(padOutline) || padOutline.length < 3) {
32691
+ return null;
32692
+ }
32693
+ const holeShape = ph.hole_shape || "circle";
32694
+ const holeOffsetX = ph.hole_offset_x || 0;
32695
+ const holeOffsetY = ph.hole_offset_y || 0;
32696
+ let holeOp = null;
32697
+ if (holeShape === "circle") {
32698
+ const diameter = Math.max((ph.hole_diameter ?? 0) + sizeDelta, M);
32699
+ const radius = Math.max(diameter / 2, M / 2);
32700
+ holeOp = Manifold.cylinder(
32701
+ depth,
32702
+ radius,
32703
+ radius,
32704
+ SMOOTH_CIRCLE_SEGMENTS,
32705
+ true
32706
+ );
32707
+ manifoldInstancesForCleanup.push(holeOp);
32708
+ } else {
32709
+ const baseWidth = ph.hole_width ?? ph.hole_diameter;
32710
+ const baseHeight = ph.hole_height ?? ph.hole_diameter;
32711
+ if (!baseWidth || !baseHeight) return null;
32712
+ const width10 = Math.max(baseWidth + sizeDelta, M);
32713
+ const height10 = Math.max(baseHeight + sizeDelta, M);
32714
+ if (holeShape === "oval") {
32715
+ let points = createEllipsePoints(width10, height10, SMOOTH_CIRCLE_SEGMENTS);
32716
+ if (arePointsClockwise3(points)) {
32717
+ points = points.reverse();
32718
+ }
32719
+ const crossSection = CrossSection.ofPolygons([points]);
32720
+ manifoldInstancesForCleanup.push(crossSection);
32721
+ holeOp = Manifold.extrude(crossSection, depth, 0, 0, [1, 1], true);
32722
+ manifoldInstancesForCleanup.push(holeOp);
32723
+ } else if (holeShape === "pill" || holeShape === "rotated_pill") {
32724
+ holeOp = createRoundedRectPrism({
32725
+ Manifold,
32726
+ width: width10,
32727
+ height: height10,
32728
+ thickness: depth,
32729
+ borderRadius: Math.min(width10, height10) / 2
32730
+ });
32731
+ manifoldInstancesForCleanup.push(holeOp);
32732
+ }
32733
+ }
32734
+ if (!holeOp) return null;
32735
+ if (holeOffsetX || holeOffsetY) {
32736
+ const translated = holeOp.translate([holeOffsetX, holeOffsetY, 0]);
32737
+ manifoldInstancesForCleanup.push(translated);
32738
+ holeOp = translated;
32739
+ }
32740
+ return holeOp;
32741
+ };
32439
32742
  pcbPlatedHoles.forEach((ph, index2) => {
32440
32743
  if (ph.shape === "circle") {
32441
32744
  const translatedDrill = createPlatedHoleDrill({
@@ -32635,6 +32938,83 @@ function processPlatedHolesForManifold(Manifold, circuitJson, pcbThickness, mani
32635
32938
  geometry: threeGeom,
32636
32939
  color: COPPER_COLOR
32637
32940
  });
32941
+ } else if (ph.shape === "hole_with_polygon_pad") {
32942
+ const padOutline = ph.pad_outline;
32943
+ if (!Array.isArray(padOutline) || padOutline.length < 3) {
32944
+ return;
32945
+ }
32946
+ const boardHoleOp = createHoleOpForPolygonPad({
32947
+ ph,
32948
+ depth: pcbThickness * 1.2,
32949
+ sizeDelta: 2 * M
32950
+ });
32951
+ if (!boardHoleOp) return;
32952
+ const translatedBoardHole = boardHoleOp.translate([ph.x, ph.y, 0]);
32953
+ manifoldInstancesForCleanup.push(translatedBoardHole);
32954
+ platedHoleBoardDrills.push(translatedBoardHole);
32955
+ const padThickness = DEFAULT_SMT_PAD_THICKNESS;
32956
+ const fillThickness = Math.max(
32957
+ pcbThickness - 2 * padThickness - 2 * BOARD_SURFACE_OFFSET.copper + 0.1,
32958
+ M
32959
+ );
32960
+ const mainFill = createPolygonPadOp({
32961
+ padOutline,
32962
+ thickness: fillThickness
32963
+ });
32964
+ const topPad = createPolygonPadOp({ padOutline, thickness: padThickness });
32965
+ const bottomPad = createPolygonPadOp({
32966
+ padOutline,
32967
+ thickness: padThickness
32968
+ });
32969
+ if (!mainFill || !topPad || !bottomPad) return;
32970
+ const topTranslated = topPad.translate([
32971
+ 0,
32972
+ 0,
32973
+ pcbThickness / 2 / 2 + BOARD_SURFACE_OFFSET.copper
32974
+ ]);
32975
+ const bottomTranslated = bottomPad.translate([
32976
+ 0,
32977
+ 0,
32978
+ -pcbThickness / 2 / 2 - BOARD_SURFACE_OFFSET.copper
32979
+ ]);
32980
+ manifoldInstancesForCleanup.push(topTranslated, bottomTranslated);
32981
+ const barrelOp = createHoleOpForPolygonPad({
32982
+ ph,
32983
+ depth: pcbThickness * 1.02
32984
+ });
32985
+ if (!barrelOp) return;
32986
+ const holeCutOp = createHoleOpForPolygonPad({
32987
+ ph,
32988
+ depth: pcbThickness * 1.2,
32989
+ sizeDelta: -2 * M
32990
+ }) || barrelOp;
32991
+ const copperUnion = Manifold.union([
32992
+ mainFill,
32993
+ topTranslated,
32994
+ bottomTranslated,
32995
+ barrelOp
32996
+ ]);
32997
+ manifoldInstancesForCleanup.push(copperUnion);
32998
+ const finalCopper = copperUnion.subtract(holeCutOp);
32999
+ manifoldInstancesForCleanup.push(finalCopper);
33000
+ const translatedCopper = finalCopper.translate([ph.x, ph.y, 0]);
33001
+ manifoldInstancesForCleanup.push(translatedCopper);
33002
+ let finalCopperOp = translatedCopper;
33003
+ if (boardClipVolume) {
33004
+ const clipped = Manifold.intersection([
33005
+ translatedCopper,
33006
+ boardClipVolume
33007
+ ]);
33008
+ manifoldInstancesForCleanup.push(clipped);
33009
+ finalCopperOp = clipped;
33010
+ }
33011
+ platedHoleCopperOpsForSubtract.push(finalCopperOp);
33012
+ const threeGeom = manifoldMeshToThreeGeometry(finalCopperOp.getMesh());
33013
+ platedHoleCopperGeoms.push({
33014
+ key: `ph-${ph.pcb_plated_hole_id || index2}`,
33015
+ geometry: threeGeom,
33016
+ color: COPPER_COLOR
33017
+ });
32638
33018
  } else if (ph.shape === "circular_hole_with_rect_pad") {
32639
33019
  const holeOffsetX = ph.hole_offset_x || 0;
32640
33020
  const holeOffsetY = ph.hole_offset_y || 0;
@@ -32861,7 +33241,7 @@ function processSmtPadsForManifold(Manifold, circuitJson, pcbThickness, manifold
32861
33241
  }
32862
33242
 
32863
33243
  // src/utils/manifold/create-manifold-board.ts
32864
- var arePointsClockwise3 = (points) => {
33244
+ var arePointsClockwise4 = (points) => {
32865
33245
  let area = 0;
32866
33246
  for (let i = 0; i < points.length; i++) {
32867
33247
  const j = (i + 1) % points.length;
@@ -32881,7 +33261,7 @@ function createManifoldBoard(Manifold, CrossSection, boardData, pcbThickness, ma
32881
33261
  p.x,
32882
33262
  p.y
32883
33263
  ]);
32884
- if (arePointsClockwise3(outlineVec2)) {
33264
+ if (arePointsClockwise4(outlineVec2)) {
32885
33265
  outlineVec2 = outlineVec2.reverse();
32886
33266
  }
32887
33267
  const crossSection = CrossSection.ofPolygons([outlineVec2]);
@@ -32920,7 +33300,7 @@ function createManifoldBoard(Manifold, CrossSection, boardData, pcbThickness, ma
32920
33300
 
32921
33301
  // src/utils/manifold/process-copper-pours.ts
32922
33302
  import * as THREE24 from "three";
32923
- var arePointsClockwise4 = (points) => {
33303
+ var arePointsClockwise5 = (points) => {
32924
33304
  let area = 0;
32925
33305
  for (let i = 0; i < points.length; i++) {
32926
33306
  const j = (i + 1) % points.length;
@@ -33011,7 +33391,7 @@ function processCopperPoursForManifold(Manifold, CrossSection, circuitJson, pcbT
33011
33391
  p.x,
33012
33392
  p.y
33013
33393
  ]);
33014
- if (arePointsClockwise4(pointsVec2)) {
33394
+ if (arePointsClockwise5(pointsVec2)) {
33015
33395
  pointsVec2 = pointsVec2.reverse();
33016
33396
  }
33017
33397
  const crossSection = CrossSection.ofPolygons([pointsVec2]);
@@ -33036,14 +33416,14 @@ function processCopperPoursForManifold(Manifold, CrossSection, circuitJson, pcbT
33036
33416
  brepShape.outer_ring,
33037
33417
  SMOOTH_CIRCLE_SEGMENTS
33038
33418
  );
33039
- if (arePointsClockwise4(outerRingPoints)) {
33419
+ if (arePointsClockwise5(outerRingPoints)) {
33040
33420
  outerRingPoints = outerRingPoints.reverse();
33041
33421
  }
33042
33422
  const polygons = [outerRingPoints];
33043
33423
  if (brepShape.inner_rings) {
33044
33424
  const innerRingsPoints = brepShape.inner_rings.map((ring2) => {
33045
33425
  let points = ringToPoints2(ring2, SMOOTH_CIRCLE_SEGMENTS);
33046
- if (!arePointsClockwise4(points)) {
33426
+ if (!arePointsClockwise5(points)) {
33047
33427
  points = points.reverse();
33048
33428
  }
33049
33429
  return points;
@@ -33093,7 +33473,7 @@ function processCopperPoursForManifold(Manifold, CrossSection, circuitJson, pcbT
33093
33473
 
33094
33474
  // src/utils/manifold/process-cutouts.ts
33095
33475
  import { su as su13 } from "@tscircuit/circuit-json-util";
33096
- var arePointsClockwise5 = (points) => {
33476
+ var arePointsClockwise6 = (points) => {
33097
33477
  let area = 0;
33098
33478
  for (let i = 0; i < points.length; i++) {
33099
33479
  const j = (i + 1) % points.length;
@@ -33158,7 +33538,7 @@ function processCutoutsForManifold(Manifold, CrossSection, circuitJson, pcbThick
33158
33538
  p.x,
33159
33539
  p.y
33160
33540
  ]);
33161
- if (arePointsClockwise5(pointsVec2)) {
33541
+ if (arePointsClockwise6(pointsVec2)) {
33162
33542
  pointsVec2 = pointsVec2.reverse();
33163
33543
  }
33164
33544
  const crossSection = CrossSection.ofPolygons([pointsVec2]);
@@ -33322,6 +33702,7 @@ var useManifoldBoardBuilder = (manifoldJSModule, circuitJson) => {
33322
33702
  platedHoleSubtractOp
33323
33703
  } = processPlatedHolesForManifold(
33324
33704
  Manifold,
33705
+ CrossSection,
33325
33706
  circuitJson,
33326
33707
  currentPcbThickness,
33327
33708
  manifoldInstancesForCleanup.current,
@@ -39534,7 +39915,7 @@ var contentStyles = {
39534
39915
  border: "1px solid #333333",
39535
39916
  padding: "4px",
39536
39917
  minWidth: 160,
39537
- zIndex: 10001,
39918
+ zIndex: zIndexMap.appearanceMenu,
39538
39919
  fontSize: 14,
39539
39920
  fontFamily: 'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif'
39540
39921
  };
@@ -39741,7 +40122,7 @@ var contentStyles2 = {
39741
40122
  border: "1px solid #333333",
39742
40123
  padding: "4px",
39743
40124
  minWidth: 160,
39744
- zIndex: 1e4,
40125
+ zIndex: zIndexMap.contextMenu,
39745
40126
  fontSize: 14,
39746
40127
  fontWeight: 400,
39747
40128
  fontFamily: 'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif'