@tscircuit/3d-viewer 0.0.437 → 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 +635 -265
  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,
@@ -28252,7 +28287,7 @@ import * as THREE15 from "three";
28252
28287
  // package.json
28253
28288
  var package_default = {
28254
28289
  name: "@tscircuit/3d-viewer",
28255
- version: "0.0.436",
28290
+ version: "0.0.437",
28256
28291
  main: "./dist/index.js",
28257
28292
  module: "./dist/index.js",
28258
28293
  type: "module",
@@ -28313,7 +28348,7 @@ var package_default = {
28313
28348
  "@vitejs/plugin-react": "^4.3.4",
28314
28349
  "bun-match-svg": "^0.0.9",
28315
28350
  "bun-types": "1.2.1",
28316
- "circuit-json": "0.0.311",
28351
+ "circuit-json": "0.0.316",
28317
28352
  "circuit-to-svg": "^0.0.179",
28318
28353
  debug: "^4.4.0",
28319
28354
  "jscad-electronics": "^0.0.89",
@@ -29550,18 +29585,18 @@ var createBoardGeomFromCircuitJson = (circuitJson, opts = {}) => {
29550
29585
  };
29551
29586
 
29552
29587
  // src/BoardGeomBuilder.ts
29553
- var import_transforms7 = __toESM(require_transforms(), 1);
29554
- var import_primitives9 = __toESM(require_primitives(), 1);
29588
+ var import_transforms8 = __toESM(require_transforms(), 1);
29589
+ var import_primitives10 = __toESM(require_primitives(), 1);
29555
29590
  var import_colors7 = __toESM(require_colors(), 1);
29556
- var import_booleans5 = __toESM(require_booleans(), 1);
29591
+ var import_booleans6 = __toESM(require_booleans(), 1);
29557
29592
  import { su as su3 } from "@tscircuit/circuit-json-util";
29558
29593
 
29559
29594
  // src/geoms/plated-hole.ts
29560
- var import_primitives3 = __toESM(require_primitives(), 1);
29595
+ var import_primitives4 = __toESM(require_primitives(), 1);
29561
29596
  var import_colors2 = __toESM(require_colors(), 1);
29562
- var import_booleans = __toESM(require_booleans(), 1);
29563
- var import_extrusions2 = __toESM(require_extrusions(), 1);
29564
- 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);
29565
29600
 
29566
29601
  // src/utils/rect-border-radius.ts
29567
29602
  function clampRectBorderRadius(width10, height10, rawRadius) {
@@ -29580,10 +29615,101 @@ function extractRectBorderRadius(source) {
29580
29615
  return source.corner_radius ?? source.cornerRadius ?? source.rect_pad_border_radius ?? source.rectPadBorderRadius ?? source.rect_border_radius ?? source.rectBorderRadius ?? void 0;
29581
29616
  }
29582
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
+
29583
29709
  // src/geoms/plated-hole.ts
29584
29710
  var platedHoleLipHeight = 0.02;
29585
29711
  var RECT_PAD_SEGMENTS = 64;
29586
- 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;
29587
29713
  var createRectPadGeom = ({
29588
29714
  width: width10,
29589
29715
  height: height10,
@@ -29593,16 +29719,16 @@ var createRectPadGeom = ({
29593
29719
  }) => {
29594
29720
  const clampedRadius = clampRectBorderRadius(width10, height10, borderRadius);
29595
29721
  if (clampedRadius <= 0) {
29596
- return (0, import_primitives3.cuboid)({ center, size: [width10, height10, thickness] });
29722
+ return (0, import_primitives4.cuboid)({ center, size: [width10, height10, thickness] });
29597
29723
  }
29598
- const rect2d = (0, import_primitives3.roundedRectangle)({
29724
+ const rect2d = (0, import_primitives4.roundedRectangle)({
29599
29725
  size: [width10, height10],
29600
29726
  roundRadius: clampedRadius,
29601
29727
  segments: RECT_PAD_SEGMENTS
29602
29728
  });
29603
- const extruded = (0, import_extrusions2.extrudeLinear)({ height: thickness }, rect2d);
29729
+ const extruded = (0, import_extrusions3.extrudeLinear)({ height: thickness }, rect2d);
29604
29730
  const offsetZ = center[2] - thickness / 2;
29605
- return (0, import_transforms2.translate)([center[0], center[1], offsetZ], extruded);
29731
+ return (0, import_transforms3.translate)([center[0], center[1], offsetZ], extruded);
29606
29732
  };
29607
29733
  var platedHole = (plated_hole, ctx, options = {}) => {
29608
29734
  const { clipGeom } = options;
@@ -29614,18 +29740,18 @@ var platedHole = (plated_hole, ctx, options = {}) => {
29614
29740
  if (plated_hole.shape === "circle") {
29615
29741
  const outerDiameter = plated_hole.outer_diameter ?? Math.max(plated_hole.hole_diameter, 0);
29616
29742
  const copperHeight = copperSpan + 0.01;
29617
- const copperBody = (0, import_primitives3.cylinder)({
29743
+ const copperBody = (0, import_primitives4.cylinder)({
29618
29744
  center: [plated_hole.x, plated_hole.y, 0],
29619
29745
  radius: outerDiameter / 2,
29620
29746
  height: copperHeight
29621
29747
  });
29622
29748
  const copperSolid = maybeClip(copperBody, clipGeom);
29623
- const drill = (0, import_primitives3.cylinder)({
29749
+ const drill = (0, import_primitives4.cylinder)({
29624
29750
  center: [plated_hole.x, plated_hole.y, 0],
29625
29751
  radius: Math.max(plated_hole.hole_diameter / 2, 0.01),
29626
29752
  height: throughDrillHeight
29627
29753
  });
29628
- 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));
29629
29755
  }
29630
29756
  if (plated_hole.shape === "circular_hole_with_rect_pad") {
29631
29757
  const holeOffsetX = plated_hole.hole_offset_x || 0;
@@ -29634,7 +29760,7 @@ var platedHole = (plated_hole, ctx, options = {}) => {
29634
29760
  const padHeight = plated_hole.rect_pad_height || plated_hole.hole_diameter;
29635
29761
  const rectBorderRadius = extractRectBorderRadius(plated_hole);
29636
29762
  const copperSolid = maybeClip(
29637
- (0, import_booleans.union)(
29763
+ (0, import_booleans2.union)(
29638
29764
  // Top rectangular pad (thicker to ensure connection)
29639
29765
  createRectPadGeom({
29640
29766
  width: padWidth,
@@ -29659,19 +29785,19 @@ var platedHole = (plated_hole, ctx, options = {}) => {
29659
29785
  const topPadBottom = topSurfaceZ;
29660
29786
  const bottomPadTop = bottomSurfaceZ;
29661
29787
  const centerZ = (topPadBottom + bottomPadTop) / 2;
29662
- const rect2d = (0, import_primitives3.roundedRectangle)({
29788
+ const rect2d = (0, import_primitives4.roundedRectangle)({
29663
29789
  size: [padWidth, padHeight],
29664
29790
  roundRadius: rectBorderRadius || 0,
29665
29791
  segments: RECT_PAD_SEGMENTS
29666
29792
  });
29667
- const extruded = (0, import_extrusions2.extrudeLinear)({ height: height10 }, rect2d);
29668
- return (0, import_transforms2.translate)(
29793
+ const extruded = (0, import_extrusions3.extrudeLinear)({ height: height10 }, rect2d);
29794
+ return (0, import_transforms3.translate)(
29669
29795
  [plated_hole.x, plated_hole.y, centerZ - height10 / 2],
29670
29796
  extruded
29671
29797
  );
29672
29798
  })(),
29673
29799
  // Plated barrel around hole (ensured connection with pads)
29674
- (0, import_primitives3.cylinder)({
29800
+ (0, import_primitives4.cylinder)({
29675
29801
  center: [
29676
29802
  plated_hole.x + (holeOffsetX || 0),
29677
29803
  plated_hole.y + (holeOffsetY || 0),
@@ -29683,7 +29809,7 @@ var platedHole = (plated_hole, ctx, options = {}) => {
29683
29809
  ),
29684
29810
  clipGeom
29685
29811
  );
29686
- const drill = (0, import_primitives3.cylinder)({
29812
+ const drill = (0, import_primitives4.cylinder)({
29687
29813
  center: [
29688
29814
  plated_hole.x + (holeOffsetX || 0),
29689
29815
  plated_hole.y + (holeOffsetY || 0),
@@ -29692,7 +29818,7 @@ var platedHole = (plated_hole, ctx, options = {}) => {
29692
29818
  radius: Math.max(plated_hole.hole_diameter / 2 - M, 0.01),
29693
29819
  height: throughDrillHeight
29694
29820
  });
29695
- const barrel = (0, import_primitives3.cylinder)({
29821
+ const barrel = (0, import_primitives4.cylinder)({
29696
29822
  center: [
29697
29823
  plated_hole.x + (holeOffsetX || 0),
29698
29824
  plated_hole.y + (holeOffsetY || 0),
@@ -29701,18 +29827,18 @@ var platedHole = (plated_hole, ctx, options = {}) => {
29701
29827
  radius: plated_hole.hole_diameter / 2,
29702
29828
  height: copperSpan
29703
29829
  });
29704
- let finalCopper = (0, import_booleans.union)(
29705
- (0, import_booleans.subtract)(copperSolid, barrel),
29830
+ let finalCopper = (0, import_booleans2.union)(
29831
+ (0, import_booleans2.subtract)(copperSolid, barrel),
29706
29832
  // Subtract the barrel from the main shape
29707
29833
  barrel
29708
29834
  // Add the barrel back to ensure proper connection
29709
29835
  );
29710
29836
  if (options.clipGeom) {
29711
- finalCopper = (0, import_booleans.subtract)(finalCopper, drill);
29712
- 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);
29713
29839
  return (0, import_colors2.colorize)(colors.copper, finalCopper);
29714
29840
  }
29715
- 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));
29716
29842
  }
29717
29843
  if (plated_hole.shape === "pill") {
29718
29844
  const shouldRotate = plated_hole.hole_height > plated_hole.hole_width;
@@ -29729,51 +29855,51 @@ var platedHole = (plated_hole, ctx, options = {}) => {
29729
29855
  const radius = height10 / 2;
29730
29856
  const length2 = Math.abs(width10 - height10);
29731
29857
  if (length2 <= 1e-6) {
29732
- return (0, import_primitives3.cylinder)({
29858
+ return (0, import_primitives4.cylinder)({
29733
29859
  center: [plated_hole.x, plated_hole.y, 0],
29734
29860
  radius,
29735
29861
  height: thickness
29736
29862
  });
29737
29863
  }
29738
- const rect = (0, import_primitives3.cuboid)({
29864
+ const rect = (0, import_primitives4.cuboid)({
29739
29865
  center: [plated_hole.x, plated_hole.y, 0],
29740
29866
  size: shouldRotate ? [height10, length2, thickness] : [length2, height10, thickness]
29741
29867
  });
29742
- const leftCap = (0, import_primitives3.cylinder)({
29868
+ const leftCap = (0, import_primitives4.cylinder)({
29743
29869
  center: shouldRotate ? [plated_hole.x, plated_hole.y - length2 / 2, 0] : [plated_hole.x - length2 / 2, plated_hole.y, 0],
29744
29870
  radius,
29745
29871
  height: thickness
29746
29872
  });
29747
- const rightCap = (0, import_primitives3.cylinder)({
29873
+ const rightCap = (0, import_primitives4.cylinder)({
29748
29874
  center: shouldRotate ? [plated_hole.x, plated_hole.y + length2 / 2, 0] : [plated_hole.x + length2 / 2, plated_hole.y, 0],
29749
29875
  radius,
29750
29876
  height: thickness
29751
29877
  });
29752
- return (0, import_booleans.union)(rect, leftCap, rightCap);
29878
+ return (0, import_booleans2.union)(rect, leftCap, rightCap);
29753
29879
  };
29754
29880
  const outerBarrel = createPillSection(
29755
29881
  outerPillWidth,
29756
29882
  outerPillHeight,
29757
29883
  copperHeight
29758
29884
  );
29759
- const drillRect = (0, import_primitives3.cuboid)({
29885
+ const drillRect = (0, import_primitives4.cuboid)({
29760
29886
  center: [plated_hole.x, plated_hole.y, 0],
29761
29887
  size: shouldRotate ? [holeHeight - 2 * M, rectLength, throughDrillHeight] : [rectLength, holeHeight - 2 * M, throughDrillHeight]
29762
29888
  });
29763
- const drillLeftCap = (0, import_primitives3.cylinder)({
29889
+ const drillLeftCap = (0, import_primitives4.cylinder)({
29764
29890
  center: shouldRotate ? [plated_hole.x, plated_hole.y - rectLength / 2, 0] : [plated_hole.x - rectLength / 2, plated_hole.y, 0],
29765
29891
  radius: holeRadius - M,
29766
29892
  height: throughDrillHeight
29767
29893
  });
29768
- const drillRightCap = (0, import_primitives3.cylinder)({
29894
+ const drillRightCap = (0, import_primitives4.cylinder)({
29769
29895
  center: shouldRotate ? [plated_hole.x, plated_hole.y + rectLength / 2, 0] : [plated_hole.x + rectLength / 2, plated_hole.y, 0],
29770
29896
  radius: holeRadius - M,
29771
29897
  height: throughDrillHeight
29772
29898
  });
29773
- const drillUnion = (0, import_booleans.union)(drillRect, drillLeftCap, drillRightCap);
29899
+ const drillUnion = (0, import_booleans2.union)(drillRect, drillLeftCap, drillRightCap);
29774
29900
  const copperSolid = maybeClip(outerBarrel, clipGeom);
29775
29901
  const drill = drillUnion;
29776
- 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));
29777
29903
  }
29778
29904
  if (plated_hole.shape === "pill_hole_with_rect_pad") {
29779
29905
  const holeOffsetX = plated_hole.hole_offset_x || 0;
@@ -29787,8 +29913,8 @@ var platedHole = (plated_hole, ctx, options = {}) => {
29787
29913
  const padHeight = plated_hole.rect_pad_height || holeHeight + 0.2;
29788
29914
  const rectBorderRadius = extractRectBorderRadius(plated_hole);
29789
29915
  const barrelMargin = 0.03;
29790
- const barrel = (0, import_booleans.union)(
29791
- (0, import_primitives3.cuboid)({
29916
+ const barrel = (0, import_booleans2.union)(
29917
+ (0, import_primitives4.cuboid)({
29792
29918
  center: [plated_hole.x + holeOffsetX, plated_hole.y + holeOffsetY, 0],
29793
29919
  size: shouldRotate ? [
29794
29920
  holeHeight + 2 * barrelMargin,
@@ -29800,7 +29926,7 @@ var platedHole = (plated_hole, ctx, options = {}) => {
29800
29926
  copperSpan
29801
29927
  ]
29802
29928
  }),
29803
- (0, import_primitives3.cylinder)({
29929
+ (0, import_primitives4.cylinder)({
29804
29930
  center: shouldRotate ? [
29805
29931
  plated_hole.x + holeOffsetX,
29806
29932
  plated_hole.y + holeOffsetY - rectLength / 2,
@@ -29813,7 +29939,7 @@ var platedHole = (plated_hole, ctx, options = {}) => {
29813
29939
  radius: holeRadius + barrelMargin,
29814
29940
  height: copperSpan
29815
29941
  }),
29816
- (0, import_primitives3.cylinder)({
29942
+ (0, import_primitives4.cylinder)({
29817
29943
  center: shouldRotate ? [
29818
29944
  plated_hole.x + holeOffsetX,
29819
29945
  plated_hole.y + holeOffsetY + rectLength / 2,
@@ -29827,12 +29953,12 @@ var platedHole = (plated_hole, ctx, options = {}) => {
29827
29953
  height: copperSpan
29828
29954
  })
29829
29955
  );
29830
- const holeCut = (0, import_booleans.union)(
29831
- (0, import_primitives3.cuboid)({
29956
+ const holeCut = (0, import_booleans2.union)(
29957
+ (0, import_primitives4.cuboid)({
29832
29958
  center: [plated_hole.x + holeOffsetX, plated_hole.y + holeOffsetY, 0],
29833
29959
  size: shouldRotate ? [holeHeight, rectLength, throughDrillHeight * 1.1] : [rectLength, holeHeight, throughDrillHeight * 1.1]
29834
29960
  }),
29835
- (0, import_primitives3.cylinder)({
29961
+ (0, import_primitives4.cylinder)({
29836
29962
  center: shouldRotate ? [
29837
29963
  plated_hole.x + holeOffsetX,
29838
29964
  plated_hole.y + holeOffsetY - rectLength / 2,
@@ -29845,7 +29971,7 @@ var platedHole = (plated_hole, ctx, options = {}) => {
29845
29971
  radius: holeRadius,
29846
29972
  height: throughDrillHeight * 1.1
29847
29973
  }),
29848
- (0, import_primitives3.cylinder)({
29974
+ (0, import_primitives4.cylinder)({
29849
29975
  center: shouldRotate ? [
29850
29976
  plated_hole.x + holeOffsetX,
29851
29977
  plated_hole.y + holeOffsetY + rectLength / 2,
@@ -29878,26 +30004,26 @@ var platedHole = (plated_hole, ctx, options = {}) => {
29878
30004
  const topPadBottom = topSurfaceZ;
29879
30005
  const bottomPadTop = bottomSurfaceZ;
29880
30006
  const centerZ = (topPadBottom + bottomPadTop) / 2;
29881
- const rect2d = (0, import_primitives3.roundedRectangle)({
30007
+ const rect2d = (0, import_primitives4.roundedRectangle)({
29882
30008
  size: [padWidth, padHeight],
29883
30009
  roundRadius: rectBorderRadius || 0,
29884
30010
  segments: RECT_PAD_SEGMENTS
29885
30011
  });
29886
- const extruded = (0, import_extrusions2.extrudeLinear)({ height: height10 }, rect2d);
29887
- return (0, import_transforms2.translate)(
30012
+ const extruded = (0, import_extrusions3.extrudeLinear)({ height: height10 }, rect2d);
30013
+ return (0, import_transforms3.translate)(
29888
30014
  [plated_hole.x, plated_hole.y, centerZ - height10 / 2],
29889
30015
  extruded
29890
30016
  );
29891
30017
  })();
29892
- const copperTopPadCut = (0, import_booleans.subtract)(copperTopPad, holeCut);
29893
- const copperBottomPadCut = (0, import_booleans.subtract)(copperBottomPad, holeCut);
29894
- const copperFillCut = (0, import_booleans.subtract)(copperFill, holeCut);
29895
- const barrelHoleCut = (0, import_booleans.union)(
29896
- (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)({
29897
30023
  center: [plated_hole.x + holeOffsetX, plated_hole.y + holeOffsetY, 0],
29898
30024
  size: shouldRotate ? [holeHeight - 2 * M, rectLength - 2 * M, throughDrillHeight * 1.1] : [rectLength - 2 * M, holeHeight - 2 * M, throughDrillHeight * 1.1]
29899
30025
  }),
29900
- (0, import_primitives3.cylinder)({
30026
+ (0, import_primitives4.cylinder)({
29901
30027
  center: shouldRotate ? [
29902
30028
  plated_hole.x + holeOffsetX,
29903
30029
  plated_hole.y + holeOffsetY - rectLength / 2,
@@ -29910,7 +30036,7 @@ var platedHole = (plated_hole, ctx, options = {}) => {
29910
30036
  radius: holeRadius - M,
29911
30037
  height: throughDrillHeight * 1.1
29912
30038
  }),
29913
- (0, import_primitives3.cylinder)({
30039
+ (0, import_primitives4.cylinder)({
29914
30040
  center: shouldRotate ? [
29915
30041
  plated_hole.x + holeOffsetX,
29916
30042
  plated_hole.y + holeOffsetY + rectLength / 2,
@@ -29924,19 +30050,59 @@ var platedHole = (plated_hole, ctx, options = {}) => {
29924
30050
  height: throughDrillHeight * 1.1
29925
30051
  })
29926
30052
  );
29927
- const barrelWithHole = (0, import_booleans.subtract)(barrel, barrelHoleCut);
30053
+ const barrelWithHole = (0, import_booleans2.subtract)(barrel, barrelHoleCut);
29928
30054
  const finalCopper = maybeClip(
29929
- (0, import_booleans.union)(copperTopPadCut, copperBottomPadCut, copperFillCut, barrelWithHole),
30055
+ (0, import_booleans2.union)(copperTopPadCut, copperBottomPadCut, copperFillCut, barrelWithHole),
29930
30056
  clipGeom
29931
30057
  );
29932
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));
29933
30099
  } else {
29934
30100
  throw new Error(`Unsupported plated hole shape: ${plated_hole.shape}`);
29935
30101
  }
29936
30102
  };
29937
30103
 
29938
30104
  // src/BoardGeomBuilder.ts
29939
- var import_extrusions7 = __toESM(require_extrusions(), 1);
30105
+ var import_extrusions8 = __toESM(require_extrusions(), 1);
29940
30106
  var import_expansions4 = __toESM(require_expansions(), 1);
29941
30107
 
29942
30108
  // src/geoms/create-geoms-for-silkscreen-text.ts
@@ -29959,7 +30125,7 @@ function isUndefined(val) {
29959
30125
  }
29960
30126
 
29961
30127
  // node_modules/transformation-matrix/src/translate.js
29962
- function translate3(tx, ty = 0) {
30128
+ function translate4(tx, ty = 0) {
29963
30129
  return {
29964
30130
  a: 1,
29965
30131
  c: 0,
@@ -30018,9 +30184,9 @@ function rotate(angle, cx, cy) {
30018
30184
  return rotationMatrix;
30019
30185
  }
30020
30186
  return transform([
30021
- translate3(cx, cy),
30187
+ translate4(cx, cy),
30022
30188
  rotationMatrix,
30023
- translate3(-cx, -cy)
30189
+ translate4(-cx, -cy)
30024
30190
  ]);
30025
30191
  }
30026
30192
 
@@ -30208,19 +30374,19 @@ function createSilkscreenTextGeoms(silkscreenText) {
30208
30374
  const transforms = [];
30209
30375
  if (silkscreenText.layer === "bottom") {
30210
30376
  transforms.push(
30211
- translate3(centerX, centerY),
30377
+ translate4(centerX, centerY),
30212
30378
  { a: -1, b: 0, c: 0, d: 1, e: 0, f: 0 },
30213
30379
  // horizontal flip matrix
30214
- translate3(-centerX, -centerY)
30380
+ translate4(-centerX, -centerY)
30215
30381
  );
30216
30382
  rotationDegrees = -rotationDegrees;
30217
30383
  }
30218
30384
  if (rotationDegrees) {
30219
30385
  const rad = rotationDegrees * Math.PI / 180;
30220
30386
  transforms.push(
30221
- translate3(centerX, centerY),
30387
+ translate4(centerX, centerY),
30222
30388
  rotate(rad),
30223
- translate3(-centerX, -centerY)
30389
+ translate4(-centerX, -centerY)
30224
30390
  );
30225
30391
  }
30226
30392
  let transformedOutlines = textOutlines;
@@ -30241,10 +30407,10 @@ function createSilkscreenTextGeoms(silkscreenText) {
30241
30407
  }
30242
30408
 
30243
30409
  // src/geoms/create-geoms-for-silkscreen-path.ts
30244
- var import_primitives4 = __toESM(require_primitives(), 1);
30410
+ var import_primitives5 = __toESM(require_primitives(), 1);
30245
30411
  var import_expansions2 = __toESM(require_expansions(), 1);
30246
- var import_extrusions3 = __toESM(require_extrusions(), 1);
30247
- var import_transforms3 = __toESM(require_transforms(), 1);
30412
+ var import_extrusions4 = __toESM(require_extrusions(), 1);
30413
+ var import_transforms4 = __toESM(require_transforms(), 1);
30248
30414
  var import_colors3 = __toESM(require_colors(), 1);
30249
30415
 
30250
30416
  // src/utils/units.ts
@@ -30299,7 +30465,7 @@ function createSilkscreenPathGeom(sp, ctx) {
30299
30465
  parseDimensionToMm(p.x) ?? 0,
30300
30466
  parseDimensionToMm(p.y) ?? 0
30301
30467
  ]);
30302
- const pathLine = (0, import_primitives4.line)(routePoints);
30468
+ const pathLine = (0, import_primitives5.line)(routePoints);
30303
30469
  const strokeWidth = coerceDimensionToMm(sp.stroke_width, 0.1);
30304
30470
  const expandedPath = (0, import_expansions2.expand)(
30305
30471
  { delta: strokeWidth / 2, corners: "round" },
@@ -30307,9 +30473,9 @@ function createSilkscreenPathGeom(sp, ctx) {
30307
30473
  );
30308
30474
  const layerSign = sp.layer === "bottom" ? -1 : 1;
30309
30475
  const zPos = layerSign * ctx.pcbThickness / 2 + layerSign * M * 1.5;
30310
- let pathGeom = (0, import_transforms3.translate)(
30476
+ let pathGeom = (0, import_transforms4.translate)(
30311
30477
  [0, 0, zPos],
30312
- (0, import_extrusions3.extrudeLinear)({ height: 0.012 }, expandedPath)
30478
+ (0, import_extrusions4.extrudeLinear)({ height: 0.012 }, expandedPath)
30313
30479
  // Standard silkscreen thickness
30314
30480
  );
30315
30481
  pathGeom = (0, import_colors3.colorize)([1, 1, 1], pathGeom);
@@ -30317,10 +30483,10 @@ function createSilkscreenPathGeom(sp, ctx) {
30317
30483
  }
30318
30484
 
30319
30485
  // src/geoms/create-geoms-for-silkscreen-line.ts
30320
- var import_primitives5 = __toESM(require_primitives(), 1);
30486
+ var import_primitives6 = __toESM(require_primitives(), 1);
30321
30487
  var import_expansions3 = __toESM(require_expansions(), 1);
30322
- var import_extrusions4 = __toESM(require_extrusions(), 1);
30323
- var import_transforms4 = __toESM(require_transforms(), 1);
30488
+ var import_extrusions5 = __toESM(require_extrusions(), 1);
30489
+ var import_transforms5 = __toESM(require_transforms(), 1);
30324
30490
  var import_colors4 = __toESM(require_colors(), 1);
30325
30491
  function createSilkscreenLineGeom(sl, ctx) {
30326
30492
  const x1 = parseDimensionToMm(sl.x1) ?? 0;
@@ -30332,7 +30498,7 @@ function createSilkscreenLineGeom(sl, ctx) {
30332
30498
  [x1, y1],
30333
30499
  [x2, y2]
30334
30500
  ];
30335
- const baseLine = (0, import_primitives5.line)(routePoints);
30501
+ const baseLine = (0, import_primitives6.line)(routePoints);
30336
30502
  const strokeWidth = coerceDimensionToMm(sl.stroke_width, 0.1);
30337
30503
  const expandedLine = (0, import_expansions3.expand)(
30338
30504
  { delta: strokeWidth / 2, corners: "round" },
@@ -30340,20 +30506,20 @@ function createSilkscreenLineGeom(sl, ctx) {
30340
30506
  );
30341
30507
  const layerSign = sl.layer === "bottom" ? -1 : 1;
30342
30508
  const zPos = layerSign * ctx.pcbThickness / 2 + layerSign * M * 1.5;
30343
- let lineGeom = (0, import_transforms4.translate)(
30509
+ let lineGeom = (0, import_transforms5.translate)(
30344
30510
  [0, 0, zPos],
30345
- (0, import_extrusions4.extrudeLinear)({ height: 0.012 }, expandedLine)
30511
+ (0, import_extrusions5.extrudeLinear)({ height: 0.012 }, expandedLine)
30346
30512
  );
30347
30513
  lineGeom = (0, import_colors4.colorize)([1, 1, 1], lineGeom);
30348
30514
  return lineGeom;
30349
30515
  }
30350
30516
 
30351
30517
  // src/geoms/create-geoms-for-silkscreen-rect.ts
30352
- var import_primitives6 = __toESM(require_primitives(), 1);
30353
- var import_extrusions5 = __toESM(require_extrusions(), 1);
30354
- 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);
30355
30521
  var import_colors5 = __toESM(require_colors(), 1);
30356
- var import_booleans2 = __toESM(require_booleans(), 1);
30522
+ var import_booleans3 = __toESM(require_booleans(), 1);
30357
30523
  var RECT_SEGMENTS = 64;
30358
30524
  function createSilkscreenRectGeom(rect, ctx) {
30359
30525
  const width10 = coerceDimensionToMm(rect.width, 0);
@@ -30367,9 +30533,9 @@ function createSilkscreenRectGeom(rect, ctx) {
30367
30533
  height10,
30368
30534
  typeof rawBorderRadius === "string" ? parseDimensionToMm(rawBorderRadius) : rawBorderRadius
30369
30535
  );
30370
- const createRectGeom = (rectWidth, rectHeight, radius) => (0, import_extrusions5.extrudeLinear)(
30536
+ const createRectGeom = (rectWidth, rectHeight, radius) => (0, import_extrusions6.extrudeLinear)(
30371
30537
  { height: 0.012 },
30372
- (0, import_primitives6.roundedRectangle)({
30538
+ (0, import_primitives7.roundedRectangle)({
30373
30539
  size: [rectWidth, rectHeight],
30374
30540
  roundRadius: radius,
30375
30541
  segments: RECT_SEGMENTS
@@ -30394,28 +30560,28 @@ function createSilkscreenRectGeom(rect, ctx) {
30394
30560
  Math.max(borderRadius - strokeWidth, 0)
30395
30561
  );
30396
30562
  const innerGeom = createRectGeom(innerWidth, innerHeight, innerRadius);
30397
- strokeGeom = (0, import_booleans2.subtract)(outerGeom, innerGeom);
30563
+ strokeGeom = (0, import_booleans3.subtract)(outerGeom, innerGeom);
30398
30564
  } else {
30399
30565
  strokeGeom = outerGeom;
30400
30566
  }
30401
30567
  }
30402
30568
  let rectGeom = fillGeom;
30403
30569
  if (strokeGeom) {
30404
- rectGeom = rectGeom ? (0, import_booleans2.union)(rectGeom, strokeGeom) : strokeGeom;
30570
+ rectGeom = rectGeom ? (0, import_booleans3.union)(rectGeom, strokeGeom) : strokeGeom;
30405
30571
  }
30406
30572
  if (!rectGeom) return void 0;
30407
30573
  const layerSign = rect.layer === "bottom" ? -1 : 1;
30408
30574
  const zPos = layerSign * ctx.pcbThickness / 2 + layerSign * M * 1.5;
30409
- rectGeom = (0, import_transforms5.translate)([centerX, centerY, zPos], rectGeom);
30575
+ rectGeom = (0, import_transforms6.translate)([centerX, centerY, zPos], rectGeom);
30410
30576
  return (0, import_colors5.colorize)([1, 1, 1], rectGeom);
30411
30577
  }
30412
30578
 
30413
30579
  // src/geoms/create-geoms-for-silkscreen-circle.ts
30414
- var import_primitives7 = __toESM(require_primitives(), 1);
30415
- var import_extrusions6 = __toESM(require_extrusions(), 1);
30416
- 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);
30417
30583
  var import_colors6 = __toESM(require_colors(), 1);
30418
- var import_booleans3 = __toESM(require_booleans(), 1);
30584
+ var import_booleans4 = __toESM(require_booleans(), 1);
30419
30585
  var CIRCLE_SEGMENTS = 64;
30420
30586
  function createSilkscreenCircleGeom(circleEl, ctx) {
30421
30587
  const radius = coerceDimensionToMm(circleEl.radius, 0);
@@ -30431,31 +30597,31 @@ function createSilkscreenCircleGeom(circleEl, ctx) {
30431
30597
  if (hasStroke) {
30432
30598
  const outerRadius = radius + strokeWidth / 2;
30433
30599
  const innerRadius = radius - strokeWidth / 2;
30434
- const outerCircle2d = (0, import_primitives7.circle)({
30600
+ const outerCircle2d = (0, import_primitives8.circle)({
30435
30601
  radius: outerRadius,
30436
30602
  segments: CIRCLE_SEGMENTS
30437
30603
  });
30438
- let ring3d = (0, import_extrusions6.extrudeLinear)({ height: baseHeight }, outerCircle2d);
30604
+ let ring3d = (0, import_extrusions7.extrudeLinear)({ height: baseHeight }, outerCircle2d);
30439
30605
  if (innerRadius > 0) {
30440
- const innerCircle2d = (0, import_primitives7.circle)({
30606
+ const innerCircle2d = (0, import_primitives8.circle)({
30441
30607
  radius: innerRadius,
30442
30608
  segments: CIRCLE_SEGMENTS
30443
30609
  });
30444
- const inner3d = (0, import_extrusions6.extrudeLinear)({ height: baseHeight }, innerCircle2d);
30445
- 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);
30446
30612
  }
30447
30613
  circleGeom = ring3d;
30448
30614
  } else {
30449
- const filledCircle2d = (0, import_primitives7.circle)({ radius, segments: CIRCLE_SEGMENTS });
30450
- 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);
30451
30617
  }
30452
- const translatedGeom = (0, import_transforms6.translate)([centerX, centerY, zPos], circleGeom);
30618
+ const translatedGeom = (0, import_transforms7.translate)([centerX, centerY, zPos], circleGeom);
30453
30619
  return (0, import_colors6.colorize)([1, 1, 1], translatedGeom);
30454
30620
  }
30455
30621
 
30456
30622
  // src/geoms/brep-converter.ts
30457
- var import_primitives8 = __toESM(require_primitives(), 1);
30458
- var import_booleans4 = __toESM(require_booleans(), 1);
30623
+ var import_primitives9 = __toESM(require_primitives(), 1);
30624
+ var import_booleans5 = __toESM(require_booleans(), 1);
30459
30625
  function segmentToPoints(p1, p2, bulge, arcSegments) {
30460
30626
  if (!bulge || Math.abs(bulge) < 1e-9) {
30461
30627
  return [];
@@ -30523,7 +30689,7 @@ function createGeom2FromBRep(brep, arcSegments = 16) {
30523
30689
  if (arePointsClockwise2(outerPoints)) {
30524
30690
  outerPoints.reverse();
30525
30691
  }
30526
- const outerGeom = (0, import_primitives8.polygon)({ points: outerPoints });
30692
+ const outerGeom = (0, import_primitives9.polygon)({ points: outerPoints });
30527
30693
  if (!brep.inner_rings || brep.inner_rings.length === 0) {
30528
30694
  return outerGeom;
30529
30695
  }
@@ -30532,10 +30698,10 @@ function createGeom2FromBRep(brep, arcSegments = 16) {
30532
30698
  if (arePointsClockwise2(innerPoints)) {
30533
30699
  innerPoints.reverse();
30534
30700
  }
30535
- return (0, import_primitives8.polygon)({ points: innerPoints });
30701
+ return (0, import_primitives9.polygon)({ points: innerPoints });
30536
30702
  });
30537
30703
  if (innerGeoms.length === 0) return outerGeom;
30538
- return (0, import_booleans4.subtract)(outerGeom, innerGeoms);
30704
+ return (0, import_booleans5.subtract)(outerGeom, innerGeoms);
30539
30705
  }
30540
30706
 
30541
30707
  // src/BoardGeomBuilder.ts
@@ -30545,15 +30711,15 @@ var BOARD_CLIP_XY_OUTSET = 0.05;
30545
30711
  var createCenteredRectPadGeom = (width10, height10, thickness, rectBorderRadius) => {
30546
30712
  const clampedRadius = clampRectBorderRadius(width10, height10, rectBorderRadius);
30547
30713
  if (clampedRadius <= 0) {
30548
- 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] });
30549
30715
  }
30550
- const rect2d = (0, import_primitives9.roundedRectangle)({
30716
+ const rect2d = (0, import_primitives10.roundedRectangle)({
30551
30717
  size: [width10, height10],
30552
30718
  roundRadius: clampedRadius,
30553
30719
  segments: PAD_ROUNDED_SEGMENTS
30554
30720
  });
30555
- const extruded = (0, import_extrusions7.extrudeLinear)({ height: thickness }, rect2d);
30556
- 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);
30557
30723
  };
30558
30724
  var buildStateOrder = [
30559
30725
  "initializing",
@@ -30680,11 +30846,11 @@ var BoardGeomBuilder = class {
30680
30846
  { xyOutset: BOARD_CLIP_XY_OUTSET }
30681
30847
  );
30682
30848
  } else {
30683
- this.boardGeom = (0, import_primitives9.cuboid)({
30849
+ this.boardGeom = (0, import_primitives10.cuboid)({
30684
30850
  size: [this.board.width, this.board.height, this.ctx.pcbThickness],
30685
30851
  center: [this.board.center.x, this.board.center.y, 0]
30686
30852
  });
30687
- this.boardClipGeom = (0, import_primitives9.cuboid)({
30853
+ this.boardClipGeom = (0, import_primitives10.cuboid)({
30688
30854
  size: [
30689
30855
  this.board.width + 2 * BOARD_CLIP_XY_OUTSET,
30690
30856
  this.board.height + 2 * BOARD_CLIP_XY_OUTSET,
@@ -30820,17 +30986,17 @@ var BoardGeomBuilder = class {
30820
30986
  const cutoutHeight = this.ctx.pcbThickness * 1.5;
30821
30987
  switch (cutout.shape) {
30822
30988
  case "rect":
30823
- cutoutGeom = (0, import_primitives9.cuboid)({
30989
+ cutoutGeom = (0, import_primitives10.cuboid)({
30824
30990
  center: [cutout.center.x, cutout.center.y, 0],
30825
30991
  size: [cutout.width, cutout.height, cutoutHeight]
30826
30992
  });
30827
30993
  if (cutout.rotation) {
30828
30994
  const rotationRadians = cutout.rotation * Math.PI / 180;
30829
- cutoutGeom = (0, import_transforms7.rotateZ)(rotationRadians, cutoutGeom);
30995
+ cutoutGeom = (0, import_transforms8.rotateZ)(rotationRadians, cutoutGeom);
30830
30996
  }
30831
30997
  break;
30832
30998
  case "circle":
30833
- cutoutGeom = (0, import_primitives9.cylinder)({
30999
+ cutoutGeom = (0, import_primitives10.cylinder)({
30834
31000
  center: [cutout.center.x, cutout.center.y, 0],
30835
31001
  radius: cutout.radius,
30836
31002
  height: cutoutHeight
@@ -30847,13 +31013,13 @@ var BoardGeomBuilder = class {
30847
31013
  if (arePointsClockwise(pointsVec2)) {
30848
31014
  pointsVec2 = pointsVec2.reverse();
30849
31015
  }
30850
- const polygon2d = (0, import_primitives9.polygon)({ points: pointsVec2 });
30851
- cutoutGeom = (0, import_extrusions7.extrudeLinear)({ height: cutoutHeight }, polygon2d);
30852
- 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);
30853
31019
  break;
30854
31020
  }
30855
31021
  if (cutoutGeom) {
30856
- this.boardGeom = (0, import_booleans5.subtract)(this.boardGeom, cutoutGeom);
31022
+ this.boardGeom = (0, import_booleans6.subtract)(this.boardGeom, cutoutGeom);
30857
31023
  }
30858
31024
  }
30859
31025
  processCopperPour(pour) {
@@ -30861,22 +31027,22 @@ var BoardGeomBuilder = class {
30861
31027
  const zPos = layerSign * this.ctx.pcbThickness / 2 + layerSign * BOARD_SURFACE_OFFSET.copper;
30862
31028
  let pourGeom = null;
30863
31029
  if (pour.shape === "rect") {
30864
- let baseGeom = (0, import_primitives9.cuboid)({
31030
+ let baseGeom = (0, import_primitives10.cuboid)({
30865
31031
  center: [0, 0, 0],
30866
31032
  // Create at origin for rotation
30867
31033
  size: [pour.width, pour.height, M]
30868
31034
  });
30869
31035
  if ("rotation" in pour && pour.rotation) {
30870
31036
  const rotationRadians = pour.rotation * Math.PI / 180;
30871
- baseGeom = (0, import_transforms7.rotateZ)(rotationRadians, baseGeom);
31037
+ baseGeom = (0, import_transforms8.rotateZ)(rotationRadians, baseGeom);
30872
31038
  }
30873
- 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);
30874
31040
  } else if (pour.shape === "brep") {
30875
31041
  const brepShape = pour.brep_shape;
30876
31042
  if (brepShape && brepShape.outer_ring) {
30877
31043
  const pourGeom2 = createGeom2FromBRep(brepShape);
30878
- pourGeom = (0, import_extrusions7.extrudeLinear)({ height: M }, pourGeom2);
30879
- 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);
30880
31046
  }
30881
31047
  } else if (pour.shape === "polygon") {
30882
31048
  let pointsVec2 = pour.points.map((p) => [p.x, p.y]);
@@ -30889,13 +31055,13 @@ var BoardGeomBuilder = class {
30889
31055
  if (arePointsClockwise(pointsVec2)) {
30890
31056
  pointsVec2 = pointsVec2.reverse();
30891
31057
  }
30892
- const polygon2d = (0, import_primitives9.polygon)({ points: pointsVec2 });
30893
- pourGeom = (0, import_extrusions7.extrudeLinear)({ height: M }, polygon2d);
30894
- 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);
30895
31061
  }
30896
31062
  if (pourGeom) {
30897
31063
  if (this.boardClipGeom) {
30898
- pourGeom = (0, import_booleans5.intersect)(this.boardClipGeom, pourGeom);
31064
+ pourGeom = (0, import_booleans6.intersect)(this.boardClipGeom, pourGeom);
30899
31065
  }
30900
31066
  const covered = pour.covered_with_solder_mask !== false;
30901
31067
  const pourMaterialColor = covered ? tracesMaterialColors[this.board.material] ?? colors.fr4GreenSolderWithMask : colors.copper;
@@ -30908,7 +31074,7 @@ var BoardGeomBuilder = class {
30908
31074
  if (ph.shape === "circle" || ph.shape === "circular_hole_with_rect_pad") {
30909
31075
  let cyGeom = null;
30910
31076
  if (ph.shape === "circular_hole_with_rect_pad") {
30911
- cyGeom = (0, import_primitives9.cylinder)({
31077
+ cyGeom = (0, import_primitives10.cylinder)({
30912
31078
  center: [
30913
31079
  ph.x + (ph.hole_offset_x || 0),
30914
31080
  ph.y + (ph.hole_offset_y || 0),
@@ -30920,7 +31086,7 @@ var BoardGeomBuilder = class {
30920
31086
  // Ensure it cuts through
30921
31087
  });
30922
31088
  } else {
30923
- cyGeom = (0, import_primitives9.cylinder)({
31089
+ cyGeom = (0, import_primitives10.cylinder)({
30924
31090
  center: [ph.x, ph.y, 0],
30925
31091
  radius: ph.hole_diameter / 2 + M,
30926
31092
  // Add margin for subtraction
@@ -30929,10 +31095,10 @@ var BoardGeomBuilder = class {
30929
31095
  });
30930
31096
  }
30931
31097
  if (!opts.dontCutBoard) {
30932
- this.boardGeom = (0, import_booleans5.subtract)(this.boardGeom, cyGeom);
31098
+ this.boardGeom = (0, import_booleans6.subtract)(this.boardGeom, cyGeom);
30933
31099
  }
30934
31100
  this.padGeoms = this.padGeoms.map(
30935
- (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))
30936
31102
  );
30937
31103
  const platedHoleGeom = platedHole(ph, this.ctx, {
30938
31104
  clipGeom: this.boardClipGeom
@@ -30946,8 +31112,8 @@ var BoardGeomBuilder = class {
30946
31112
  const rectLength = Math.abs(holeWidth - holeHeight);
30947
31113
  let pillHole;
30948
31114
  if (ph.shape === "pill_hole_with_rect_pad") {
30949
- pillHole = (0, import_booleans5.union)(
30950
- (0, import_primitives9.cuboid)({
31115
+ pillHole = (0, import_booleans6.union)(
31116
+ (0, import_primitives10.cuboid)({
30951
31117
  center: [
30952
31118
  ph.x + (ph.hole_offset_x || 0),
30953
31119
  ph.y + (ph.hole_offset_y || 0),
@@ -30955,7 +31121,7 @@ var BoardGeomBuilder = class {
30955
31121
  ],
30956
31122
  size: shouldRotate ? [holeHeight, rectLength, this.ctx.pcbThickness * 1.5] : [rectLength, holeHeight, this.ctx.pcbThickness * 1.5]
30957
31123
  }),
30958
- (0, import_primitives9.cylinder)({
31124
+ (0, import_primitives10.cylinder)({
30959
31125
  center: shouldRotate ? [
30960
31126
  ph.x + (ph.hole_offset_x || 0),
30961
31127
  ph.y + (ph.hole_offset_y || 0) - rectLength / 2,
@@ -30968,7 +31134,7 @@ var BoardGeomBuilder = class {
30968
31134
  radius: holeRadius,
30969
31135
  height: this.ctx.pcbThickness * 1.5
30970
31136
  }),
30971
- (0, import_primitives9.cylinder)({
31137
+ (0, import_primitives10.cylinder)({
30972
31138
  center: shouldRotate ? [
30973
31139
  ph.x + (ph.hole_offset_x || 0),
30974
31140
  ph.y + (ph.hole_offset_y || 0) + rectLength / 2,
@@ -30983,17 +31149,17 @@ var BoardGeomBuilder = class {
30983
31149
  })
30984
31150
  );
30985
31151
  } else {
30986
- pillHole = (0, import_booleans5.union)(
30987
- (0, import_primitives9.cuboid)({
31152
+ pillHole = (0, import_booleans6.union)(
31153
+ (0, import_primitives10.cuboid)({
30988
31154
  center: [ph.x, ph.y, 0],
30989
31155
  size: shouldRotate ? [holeHeight, rectLength, this.ctx.pcbThickness * 1.5] : [rectLength, holeHeight, this.ctx.pcbThickness * 1.5]
30990
31156
  }),
30991
- (0, import_primitives9.cylinder)({
31157
+ (0, import_primitives10.cylinder)({
30992
31158
  center: shouldRotate ? [ph.x, ph.y - rectLength / 2, 0] : [ph.x - rectLength / 2, ph.y, 0],
30993
31159
  radius: holeRadius,
30994
31160
  height: this.ctx.pcbThickness * 1.5
30995
31161
  }),
30996
- (0, import_primitives9.cylinder)({
31162
+ (0, import_primitives10.cylinder)({
30997
31163
  center: shouldRotate ? [ph.x, ph.y + rectLength / 2, 0] : [ph.x + rectLength / 2, ph.y, 0],
30998
31164
  radius: holeRadius,
30999
31165
  height: this.ctx.pcbThickness * 1.5
@@ -31001,10 +31167,36 @@ var BoardGeomBuilder = class {
31001
31167
  );
31002
31168
  }
31003
31169
  if (!opts.dontCutBoard) {
31004
- 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);
31005
31194
  }
31006
31195
  this.padGeoms = this.padGeoms.map(
31007
- (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))
31008
31200
  );
31009
31201
  const platedHoleGeom = platedHole(ph, this.ctx, {
31010
31202
  clipGeom: this.boardClipGeom
@@ -31017,22 +31209,22 @@ var BoardGeomBuilder = class {
31017
31209
  const holeDepth = this.ctx.pcbThickness * 1.5;
31018
31210
  const copperInset = 0.02;
31019
31211
  if (hole.hole_shape === "round" || hole.hole_shape === "circle") {
31020
- const cyGeom = (0, import_primitives9.cylinder)({
31212
+ const cyGeom = (0, import_primitives10.cylinder)({
31021
31213
  center: [hole.x, hole.y, 0],
31022
31214
  radius: hole.hole_diameter / 2 + M,
31023
31215
  height: holeDepth
31024
31216
  });
31025
- this.boardGeom = (0, import_booleans5.subtract)(this.boardGeom, cyGeom);
31217
+ this.boardGeom = (0, import_booleans6.subtract)(this.boardGeom, cyGeom);
31026
31218
  this.padGeoms = this.padGeoms.map(
31027
- (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))
31028
31220
  );
31029
- const copperCut = (0, import_primitives9.cylinder)({
31221
+ const copperCut = (0, import_primitives10.cylinder)({
31030
31222
  center: [hole.x, hole.y, 0],
31031
31223
  radius: hole.hole_diameter / 2 + M / 2,
31032
31224
  height: holeDepth
31033
31225
  });
31034
31226
  this.platedHoleGeoms = this.platedHoleGeoms.map(
31035
- (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))
31036
31228
  );
31037
31229
  } else if (hole.hole_shape === "pill" || hole.hole_shape === "rotated_pill") {
31038
31230
  const holeWidth = hole.hole_width;
@@ -31042,34 +31234,34 @@ var BoardGeomBuilder = class {
31042
31234
  const isRotated = hole.hole_shape === "rotated_pill";
31043
31235
  let pillHole;
31044
31236
  if (holeWidth > holeHeight) {
31045
- pillHole = (0, import_booleans5.union)(
31046
- (0, import_primitives9.cuboid)({
31237
+ pillHole = (0, import_booleans6.union)(
31238
+ (0, import_primitives10.cuboid)({
31047
31239
  center: [hole.x, hole.y, 0],
31048
31240
  size: [rectLength, holeHeight, holeDepth]
31049
31241
  }),
31050
- (0, import_primitives9.cylinder)({
31242
+ (0, import_primitives10.cylinder)({
31051
31243
  center: [hole.x - rectLength / 2, hole.y, 0],
31052
31244
  radius: holeRadius,
31053
31245
  height: holeDepth
31054
31246
  }),
31055
- (0, import_primitives9.cylinder)({
31247
+ (0, import_primitives10.cylinder)({
31056
31248
  center: [hole.x + rectLength / 2, hole.y, 0],
31057
31249
  radius: holeRadius,
31058
31250
  height: holeDepth
31059
31251
  })
31060
31252
  );
31061
31253
  } else {
31062
- pillHole = (0, import_booleans5.union)(
31063
- (0, import_primitives9.cuboid)({
31254
+ pillHole = (0, import_booleans6.union)(
31255
+ (0, import_primitives10.cuboid)({
31064
31256
  center: [hole.x, hole.y, 0],
31065
31257
  size: [holeWidth, rectLength, holeDepth]
31066
31258
  }),
31067
- (0, import_primitives9.cylinder)({
31259
+ (0, import_primitives10.cylinder)({
31068
31260
  center: [hole.x, hole.y - rectLength / 2, 0],
31069
31261
  radius: holeRadius,
31070
31262
  height: holeDepth
31071
31263
  }),
31072
- (0, import_primitives9.cylinder)({
31264
+ (0, import_primitives10.cylinder)({
31073
31265
  center: [hole.x, hole.y + rectLength / 2, 0],
31074
31266
  radius: holeRadius,
31075
31267
  height: holeDepth
@@ -31078,15 +31270,15 @@ var BoardGeomBuilder = class {
31078
31270
  }
31079
31271
  if (isRotated) {
31080
31272
  const rotationRadians = hole.ccw_rotation * Math.PI / 180;
31081
- pillHole = (0, import_transforms7.rotateZ)(rotationRadians, pillHole);
31273
+ pillHole = (0, import_transforms8.rotateZ)(rotationRadians, pillHole);
31082
31274
  }
31083
- this.boardGeom = (0, import_booleans5.subtract)(this.boardGeom, pillHole);
31275
+ this.boardGeom = (0, import_booleans6.subtract)(this.boardGeom, pillHole);
31084
31276
  this.padGeoms = this.padGeoms.map(
31085
- (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))
31086
31278
  );
31087
31279
  const copperPill = (0, import_expansions4.expand)({ delta: -copperInset }, pillHole);
31088
31280
  this.platedHoleGeoms = this.platedHoleGeoms.map(
31089
- (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))
31090
31282
  );
31091
31283
  }
31092
31284
  }
@@ -31101,10 +31293,10 @@ var BoardGeomBuilder = class {
31101
31293
  M,
31102
31294
  rectBorderRadius
31103
31295
  );
31104
- 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);
31105
31297
  let finalPadGeom = positionedPadGeom;
31106
31298
  if (this.boardClipGeom) {
31107
- finalPadGeom = (0, import_booleans5.intersect)(this.boardClipGeom, finalPadGeom);
31299
+ finalPadGeom = (0, import_booleans6.intersect)(this.boardClipGeom, finalPadGeom);
31108
31300
  }
31109
31301
  finalPadGeom = (0, import_colors7.colorize)(colors.copper, finalPadGeom);
31110
31302
  this.padGeoms.push(finalPadGeom);
@@ -31116,22 +31308,22 @@ var BoardGeomBuilder = class {
31116
31308
  rectBorderRadius
31117
31309
  );
31118
31310
  const rotationRadians = pad2.ccw_rotation * Math.PI / 180;
31119
- basePadGeom = (0, import_transforms7.rotateZ)(rotationRadians, basePadGeom);
31120
- 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);
31121
31313
  let finalPadGeom = positionedPadGeom;
31122
31314
  if (this.boardClipGeom) {
31123
- finalPadGeom = (0, import_booleans5.intersect)(this.boardClipGeom, finalPadGeom);
31315
+ finalPadGeom = (0, import_booleans6.intersect)(this.boardClipGeom, finalPadGeom);
31124
31316
  }
31125
31317
  finalPadGeom = (0, import_colors7.colorize)(colors.copper, finalPadGeom);
31126
31318
  this.padGeoms.push(finalPadGeom);
31127
31319
  } else if (pad2.shape === "circle") {
31128
- let padGeom = (0, import_primitives9.cylinder)({
31320
+ let padGeom = (0, import_primitives10.cylinder)({
31129
31321
  center: [pad2.x, pad2.y, zPos],
31130
31322
  radius: pad2.radius,
31131
31323
  height: M
31132
31324
  });
31133
31325
  if (this.boardClipGeom) {
31134
- padGeom = (0, import_booleans5.intersect)(this.boardClipGeom, padGeom);
31326
+ padGeom = (0, import_booleans6.intersect)(this.boardClipGeom, padGeom);
31135
31327
  }
31136
31328
  padGeom = (0, import_colors7.colorize)(colors.copper, padGeom);
31137
31329
  this.padGeoms.push(padGeom);
@@ -31147,14 +31339,14 @@ var BoardGeomBuilder = class {
31147
31339
  if (currentSegmentPoints.length >= 2 && currentLayer) {
31148
31340
  const layerSign = currentLayer === "bottom" ? -1 : 1;
31149
31341
  const zCenter = layerSign * this.ctx.pcbThickness / 2 + layerSign * BOARD_SURFACE_OFFSET.traces;
31150
- const linePath = (0, import_primitives9.line)(currentSegmentPoints);
31342
+ const linePath = (0, import_primitives10.line)(currentSegmentPoints);
31151
31343
  const expandedPath = (0, import_expansions4.expand)(
31152
31344
  { delta: currentWidth / 2, corners: "round" },
31153
31345
  linePath
31154
31346
  );
31155
- let traceGeom = (0, import_transforms7.translate)(
31347
+ let traceGeom = (0, import_transforms8.translate)(
31156
31348
  [0, 0, zCenter - M / 2],
31157
- (0, import_extrusions7.extrudeLinear)({ height: M }, expandedPath)
31349
+ (0, import_extrusions8.extrudeLinear)({ height: M }, expandedPath)
31158
31350
  );
31159
31351
  const startPointCoords = currentSegmentPoints[0];
31160
31352
  const endPointCoords = currentSegmentPoints[currentSegmentPoints.length - 1];
@@ -31163,25 +31355,25 @@ var BoardGeomBuilder = class {
31163
31355
  startPointCoords[1]
31164
31356
  );
31165
31357
  if (startHole) {
31166
- const cuttingCylinder = (0, import_primitives9.cylinder)({
31358
+ const cuttingCylinder = (0, import_primitives10.cylinder)({
31167
31359
  center: [startPointCoords[0], startPointCoords[1], zCenter],
31168
31360
  radius: startHole.diameter / 2 + M,
31169
31361
  height: M
31170
31362
  });
31171
- traceGeom = (0, import_booleans5.subtract)(traceGeom, cuttingCylinder);
31363
+ traceGeom = (0, import_booleans6.subtract)(traceGeom, cuttingCylinder);
31172
31364
  }
31173
31365
  const endHole = this.getHoleToCut(endPointCoords[0], endPointCoords[1]);
31174
31366
  if (endHole) {
31175
- const cuttingCylinder = (0, import_primitives9.cylinder)({
31367
+ const cuttingCylinder = (0, import_primitives10.cylinder)({
31176
31368
  center: [endPointCoords[0], endPointCoords[1], zCenter],
31177
31369
  radius: endHole.diameter / 2 + M,
31178
31370
  height: M
31179
31371
  });
31180
- traceGeom = (0, import_booleans5.subtract)(traceGeom, cuttingCylinder);
31372
+ traceGeom = (0, import_booleans6.subtract)(traceGeom, cuttingCylinder);
31181
31373
  }
31182
31374
  const tracesMaterialColor = tracesMaterialColors[this.board.material] ?? colors.fr4GreenSolderWithMask;
31183
31375
  if (this.boardClipGeom) {
31184
- traceGeom = (0, import_booleans5.intersect)(this.boardClipGeom, traceGeom);
31376
+ traceGeom = (0, import_booleans6.intersect)(this.boardClipGeom, traceGeom);
31185
31377
  }
31186
31378
  traceGeom = (0, import_colors7.colorize)(tracesMaterialColor, traceGeom);
31187
31379
  this.traceGeoms.push(traceGeom);
@@ -31250,7 +31442,7 @@ var BoardGeomBuilder = class {
31250
31442
  point2[0] + xOffset + st.anchor_position.x,
31251
31443
  point2[1] + yOffset + st.anchor_position.y
31252
31444
  ]);
31253
- const textPath = (0, import_primitives9.line)(alignedOutline);
31445
+ const textPath = (0, import_primitives10.line)(alignedOutline);
31254
31446
  const fontSize = st.font_size || 0.25;
31255
31447
  const expansionDelta = Math.min(
31256
31448
  Math.max(0.01, fontSize * 0.1),
@@ -31262,16 +31454,16 @@ var BoardGeomBuilder = class {
31262
31454
  );
31263
31455
  let textGeom;
31264
31456
  if (st.layer === "bottom") {
31265
- textGeom = (0, import_transforms7.translate)(
31457
+ textGeom = (0, import_transforms8.translate)(
31266
31458
  [0, 0, -this.ctx.pcbThickness / 2 - M],
31267
31459
  // Position above board
31268
- (0, import_extrusions7.extrudeLinear)({ height: 0.012 }, expandedPath)
31460
+ (0, import_extrusions8.extrudeLinear)({ height: 0.012 }, expandedPath)
31269
31461
  );
31270
31462
  } else {
31271
- textGeom = (0, import_transforms7.translate)(
31463
+ textGeom = (0, import_transforms8.translate)(
31272
31464
  [0, 0, this.ctx.pcbThickness / 2 + M],
31273
31465
  // Position above board
31274
- (0, import_extrusions7.extrudeLinear)({ height: 0.012 }, expandedPath)
31466
+ (0, import_extrusions8.extrudeLinear)({ height: 0.012 }, expandedPath)
31275
31467
  );
31276
31468
  }
31277
31469
  textGeom = (0, import_colors7.colorize)([1, 1, 1], textGeom);
@@ -32209,18 +32401,18 @@ function createSilkscreenTextureForLayer({
32209
32401
  let rotationDeg = textS.ccw_rotation ?? 0;
32210
32402
  if (textS.layer === "bottom") {
32211
32403
  transformMatrices.push(
32212
- translate3(textCenterX, textCenterY),
32404
+ translate4(textCenterX, textCenterY),
32213
32405
  { a: -1, b: 0, c: 0, d: 1, e: 0, f: 0 },
32214
- translate3(-textCenterX, -textCenterY)
32406
+ translate4(-textCenterX, -textCenterY)
32215
32407
  );
32216
32408
  rotationDeg = -rotationDeg;
32217
32409
  }
32218
32410
  if (rotationDeg) {
32219
32411
  const rad = rotationDeg * Math.PI / 180;
32220
32412
  transformMatrices.push(
32221
- translate3(textCenterX, textCenterY),
32413
+ translate4(textCenterX, textCenterY),
32222
32414
  rotate(rad),
32223
- translate3(-textCenterX, -textCenterY)
32415
+ translate4(-textCenterX, -textCenterY)
32224
32416
  );
32225
32417
  }
32226
32418
  const finalTransformMatrix = transformMatrices.length > 0 ? compose(...transformMatrices) : void 0;
@@ -32429,9 +32621,29 @@ function processNonPlatedHolesForManifold(Manifold, circuitJson, pcbThickness, m
32429
32621
  // src/utils/manifold/process-plated-holes.ts
32430
32622
  import { su as su10 } from "@tscircuit/circuit-json-util";
32431
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
+ };
32432
32644
  var COPPER_COLOR = new THREE21.Color(...colors.copper);
32433
32645
  var PLATED_HOLE_LIP_HEIGHT = 0.05;
32434
- function processPlatedHolesForManifold(Manifold, circuitJson, pcbThickness, manifoldInstancesForCleanup, boardClipVolume) {
32646
+ function processPlatedHolesForManifold(Manifold, CrossSection, circuitJson, pcbThickness, manifoldInstancesForCleanup, boardClipVolume) {
32435
32647
  const platedHoleBoardDrills = [];
32436
32648
  const pcbPlatedHoles = su10(circuitJson).pcb_plated_hole.list();
32437
32649
  const platedHoleCopperGeoms = [];
@@ -32447,6 +32659,86 @@ function processPlatedHolesForManifold(Manifold, circuitJson, pcbThickness, mani
32447
32659
  manifoldInstancesForCleanup.push(pillOp);
32448
32660
  return pillOp;
32449
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
+ };
32450
32742
  pcbPlatedHoles.forEach((ph, index2) => {
32451
32743
  if (ph.shape === "circle") {
32452
32744
  const translatedDrill = createPlatedHoleDrill({
@@ -32646,6 +32938,83 @@ function processPlatedHolesForManifold(Manifold, circuitJson, pcbThickness, mani
32646
32938
  geometry: threeGeom,
32647
32939
  color: COPPER_COLOR
32648
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
+ });
32649
33018
  } else if (ph.shape === "circular_hole_with_rect_pad") {
32650
33019
  const holeOffsetX = ph.hole_offset_x || 0;
32651
33020
  const holeOffsetY = ph.hole_offset_y || 0;
@@ -32872,7 +33241,7 @@ function processSmtPadsForManifold(Manifold, circuitJson, pcbThickness, manifold
32872
33241
  }
32873
33242
 
32874
33243
  // src/utils/manifold/create-manifold-board.ts
32875
- var arePointsClockwise3 = (points) => {
33244
+ var arePointsClockwise4 = (points) => {
32876
33245
  let area = 0;
32877
33246
  for (let i = 0; i < points.length; i++) {
32878
33247
  const j = (i + 1) % points.length;
@@ -32892,7 +33261,7 @@ function createManifoldBoard(Manifold, CrossSection, boardData, pcbThickness, ma
32892
33261
  p.x,
32893
33262
  p.y
32894
33263
  ]);
32895
- if (arePointsClockwise3(outlineVec2)) {
33264
+ if (arePointsClockwise4(outlineVec2)) {
32896
33265
  outlineVec2 = outlineVec2.reverse();
32897
33266
  }
32898
33267
  const crossSection = CrossSection.ofPolygons([outlineVec2]);
@@ -32931,7 +33300,7 @@ function createManifoldBoard(Manifold, CrossSection, boardData, pcbThickness, ma
32931
33300
 
32932
33301
  // src/utils/manifold/process-copper-pours.ts
32933
33302
  import * as THREE24 from "three";
32934
- var arePointsClockwise4 = (points) => {
33303
+ var arePointsClockwise5 = (points) => {
32935
33304
  let area = 0;
32936
33305
  for (let i = 0; i < points.length; i++) {
32937
33306
  const j = (i + 1) % points.length;
@@ -33022,7 +33391,7 @@ function processCopperPoursForManifold(Manifold, CrossSection, circuitJson, pcbT
33022
33391
  p.x,
33023
33392
  p.y
33024
33393
  ]);
33025
- if (arePointsClockwise4(pointsVec2)) {
33394
+ if (arePointsClockwise5(pointsVec2)) {
33026
33395
  pointsVec2 = pointsVec2.reverse();
33027
33396
  }
33028
33397
  const crossSection = CrossSection.ofPolygons([pointsVec2]);
@@ -33047,14 +33416,14 @@ function processCopperPoursForManifold(Manifold, CrossSection, circuitJson, pcbT
33047
33416
  brepShape.outer_ring,
33048
33417
  SMOOTH_CIRCLE_SEGMENTS
33049
33418
  );
33050
- if (arePointsClockwise4(outerRingPoints)) {
33419
+ if (arePointsClockwise5(outerRingPoints)) {
33051
33420
  outerRingPoints = outerRingPoints.reverse();
33052
33421
  }
33053
33422
  const polygons = [outerRingPoints];
33054
33423
  if (brepShape.inner_rings) {
33055
33424
  const innerRingsPoints = brepShape.inner_rings.map((ring2) => {
33056
33425
  let points = ringToPoints2(ring2, SMOOTH_CIRCLE_SEGMENTS);
33057
- if (!arePointsClockwise4(points)) {
33426
+ if (!arePointsClockwise5(points)) {
33058
33427
  points = points.reverse();
33059
33428
  }
33060
33429
  return points;
@@ -33104,7 +33473,7 @@ function processCopperPoursForManifold(Manifold, CrossSection, circuitJson, pcbT
33104
33473
 
33105
33474
  // src/utils/manifold/process-cutouts.ts
33106
33475
  import { su as su13 } from "@tscircuit/circuit-json-util";
33107
- var arePointsClockwise5 = (points) => {
33476
+ var arePointsClockwise6 = (points) => {
33108
33477
  let area = 0;
33109
33478
  for (let i = 0; i < points.length; i++) {
33110
33479
  const j = (i + 1) % points.length;
@@ -33169,7 +33538,7 @@ function processCutoutsForManifold(Manifold, CrossSection, circuitJson, pcbThick
33169
33538
  p.x,
33170
33539
  p.y
33171
33540
  ]);
33172
- if (arePointsClockwise5(pointsVec2)) {
33541
+ if (arePointsClockwise6(pointsVec2)) {
33173
33542
  pointsVec2 = pointsVec2.reverse();
33174
33543
  }
33175
33544
  const crossSection = CrossSection.ofPolygons([pointsVec2]);
@@ -33333,6 +33702,7 @@ var useManifoldBoardBuilder = (manifoldJSModule, circuitJson) => {
33333
33702
  platedHoleSubtractOp
33334
33703
  } = processPlatedHolesForManifold(
33335
33704
  Manifold,
33705
+ CrossSection,
33336
33706
  circuitJson,
33337
33707
  currentPcbThickness,
33338
33708
  manifoldInstancesForCleanup.current,