@tscircuit/3d-viewer 0.0.462 → 0.0.464

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 +270 -167
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1129,13 +1129,13 @@ var require_squaredLength = __commonJS({
1129
1129
  var require_subtract = __commonJS({
1130
1130
  "node_modules/@jscad/modeling/src/maths/vec3/subtract.js"(exports, module) {
1131
1131
  "use strict";
1132
- var subtract6 = (out, a, b) => {
1132
+ var subtract7 = (out, a, b) => {
1133
1133
  out[0] = a[0] - b[0];
1134
1134
  out[1] = a[1] - b[1];
1135
1135
  out[2] = a[2] - b[2];
1136
1136
  return out;
1137
1137
  };
1138
- module.exports = subtract6;
1138
+ module.exports = subtract7;
1139
1139
  }
1140
1140
  });
1141
1141
 
@@ -1676,7 +1676,7 @@ var require_scale2 = __commonJS({
1676
1676
  var require_subtract2 = __commonJS({
1677
1677
  "node_modules/@jscad/modeling/src/maths/mat4/subtract.js"(exports, module) {
1678
1678
  "use strict";
1679
- var subtract6 = (out, a, b) => {
1679
+ var subtract7 = (out, a, b) => {
1680
1680
  out[0] = a[0] - b[0];
1681
1681
  out[1] = a[1] - b[1];
1682
1682
  out[2] = a[2] - b[2];
@@ -1695,7 +1695,7 @@ var require_subtract2 = __commonJS({
1695
1695
  out[15] = a[15] - b[15];
1696
1696
  return out;
1697
1697
  };
1698
- module.exports = subtract6;
1698
+ module.exports = subtract7;
1699
1699
  }
1700
1700
  });
1701
1701
 
@@ -1712,7 +1712,7 @@ var require_toString2 = __commonJS({
1712
1712
  var require_translate = __commonJS({
1713
1713
  "node_modules/@jscad/modeling/src/maths/mat4/translate.js"(exports, module) {
1714
1714
  "use strict";
1715
- var translate10 = (out, matrix, offsets) => {
1715
+ var translate11 = (out, matrix, offsets) => {
1716
1716
  const x = offsets[0];
1717
1717
  const y = offsets[1];
1718
1718
  const z135 = offsets[2];
@@ -1765,7 +1765,7 @@ var require_translate = __commonJS({
1765
1765
  }
1766
1766
  return out;
1767
1767
  };
1768
- module.exports = translate10;
1768
+ module.exports = translate11;
1769
1769
  }
1770
1770
  });
1771
1771
 
@@ -2205,12 +2205,12 @@ var require_squaredLength2 = __commonJS({
2205
2205
  var require_subtract3 = __commonJS({
2206
2206
  "node_modules/@jscad/modeling/src/maths/vec2/subtract.js"(exports, module) {
2207
2207
  "use strict";
2208
- var subtract6 = (out, a, b) => {
2208
+ var subtract7 = (out, a, b) => {
2209
2209
  out[0] = a[0] - b[0];
2210
2210
  out[1] = a[1] - b[1];
2211
2211
  return out;
2212
2212
  };
2213
- module.exports = subtract6;
2213
+ module.exports = subtract7;
2214
2214
  }
2215
2215
  });
2216
2216
 
@@ -2671,14 +2671,14 @@ var require_point_line_distance = __commonJS({
2671
2671
  "node_modules/@jscad/modeling/src/operations/hulls/quickhull/point-line-distance.js"(exports, module) {
2672
2672
  "use strict";
2673
2673
  var cross = require_cross();
2674
- var subtract6 = require_subtract();
2674
+ var subtract7 = require_subtract();
2675
2675
  var squaredLength = require_squaredLength();
2676
2676
  var distanceSquared = (p, a, b) => {
2677
2677
  const ab = [];
2678
2678
  const ap = [];
2679
2679
  const cr = [];
2680
- subtract6(ab, b, a);
2681
- subtract6(ap, p, a);
2680
+ subtract7(ab, b, a);
2681
+ subtract7(ap, p, a);
2682
2682
  const area = squaredLength(cross(cr, ap, ab));
2683
2683
  const s = squaredLength(ab);
2684
2684
  if (s === 0) {
@@ -2697,11 +2697,11 @@ var require_get_plane_normal = __commonJS({
2697
2697
  "use strict";
2698
2698
  var cross = require_cross();
2699
2699
  var normalize = require_normalize();
2700
- var subtract6 = require_subtract();
2700
+ var subtract7 = require_subtract();
2701
2701
  var planeNormal = (out, point1, point2, point32) => {
2702
2702
  const tmp = [0, 0, 0];
2703
- subtract6(out, point1, point2);
2704
- subtract6(tmp, point2, point32);
2703
+ subtract7(out, point1, point2);
2704
+ subtract7(tmp, point2, point32);
2705
2705
  cross(out, out, tmp);
2706
2706
  return normalize(out, out);
2707
2707
  };
@@ -2915,7 +2915,7 @@ var require_Face = __commonJS({
2915
2915
  var length2 = require_length();
2916
2916
  var normalize = require_normalize();
2917
2917
  var scale3 = require_scale();
2918
- var subtract6 = require_subtract();
2918
+ var subtract7 = require_subtract();
2919
2919
  var HalfEdge = require_HalfEdge();
2920
2920
  var VISIBLE = 0;
2921
2921
  var NON_CONVEX = 1;
@@ -2949,14 +2949,14 @@ var require_Face = __commonJS({
2949
2949
  const e0 = this.edge;
2950
2950
  const e1 = e0.next;
2951
2951
  let e2 = e1.next;
2952
- const v2 = subtract6([], e1.head().point, e0.head().point);
2952
+ const v2 = subtract7([], e1.head().point, e0.head().point);
2953
2953
  const t = [];
2954
2954
  const v1 = [];
2955
2955
  this.nVertices = 2;
2956
2956
  this.normal = [0, 0, 0];
2957
2957
  while (e2 !== e0) {
2958
2958
  copy(v1, v2);
2959
- subtract6(v2, e2.head().point, e0.head().point);
2959
+ subtract7(v2, e2.head().point, e0.head().point);
2960
2960
  add(this.normal, this.normal, cross(t, v1, v2));
2961
2961
  e2 = e2.next;
2962
2962
  this.nVertices += 1;
@@ -2980,7 +2980,7 @@ var require_Face = __commonJS({
2980
2980
  } while (edge !== this.edge);
2981
2981
  const p1 = maxEdge.tail().point;
2982
2982
  const p2 = maxEdge.head().point;
2983
- const maxVector = subtract6([], p2, p1);
2983
+ const maxVector = subtract7([], p2, p1);
2984
2984
  const maxLength = Math.sqrt(maxSquaredLength);
2985
2985
  scale3(maxVector, maxVector, 1 / maxLength);
2986
2986
  const maxProjection = dot(this.normal, maxVector);
@@ -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 cylinder4 = (options) => {
7748
+ var cylinder5 = (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 = cylinder4;
7767
+ module.exports = cylinder5;
7768
7768
  }
7769
7769
  });
7770
7770
 
@@ -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 cylinder4 = require_cylinder();
8288
+ var cylinder5 = 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 cylinder4({ center, height: height10, radius });
8305
+ if (roundRadius === 0) return cylinder5({ 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);
@@ -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 translate10 = (offset4, ...objects) => {
9749
+ var translate11 = (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) => 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);
9764
+ var translateX = (offset4, ...objects) => translate11([offset4, 0, 0], objects);
9765
+ var translateY = (offset4, ...objects) => translate11([0, offset4, 0], objects);
9766
+ var translateZ = (offset4, ...objects) => translate11([0, 0, offset4], objects);
9767
9767
  module.exports = {
9768
- translate: translate10,
9768
+ translate: translate11,
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: rotate3 } = require_rotate3();
9783
- var { translate: translate10 } = require_translate2();
9783
+ var { translate: translate11 } = 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 = rotate3([0, 0, innerRotation], innerCircle);
9807
9807
  }
9808
- innerCircle = translate10([outerRadius, 0], innerCircle);
9808
+ innerCircle = translate11([outerRadius, 0], innerCircle);
9809
9809
  const extrudeOptions = {
9810
9810
  startAngle,
9811
9811
  angle: outerRotation,
@@ -11612,7 +11612,7 @@ var require_subtractGeom3 = __commonJS({
11612
11612
  var flatten = require_flatten();
11613
11613
  var retessellate = require_retessellate();
11614
11614
  var subtractSub = require_subtractGeom3Sub();
11615
- var subtract6 = (...geometries) => {
11615
+ var subtract7 = (...geometries) => {
11616
11616
  geometries = flatten(geometries);
11617
11617
  let newgeometry = geometries.shift();
11618
11618
  geometries.forEach((geometry) => {
@@ -11621,7 +11621,7 @@ var require_subtractGeom3 = __commonJS({
11621
11621
  newgeometry = retessellate(newgeometry);
11622
11622
  return newgeometry;
11623
11623
  };
11624
- module.exports = subtract6;
11624
+ module.exports = subtract7;
11625
11625
  }
11626
11626
  });
11627
11627
 
@@ -11635,14 +11635,14 @@ var require_subtractGeom2 = __commonJS({
11635
11635
  var fromFakePolygons = require_fromFakePolygons();
11636
11636
  var to3DWalls = require_to3DWalls();
11637
11637
  var subtractGeom3 = require_subtractGeom3();
11638
- var subtract6 = (...geometries) => {
11638
+ var subtract7 = (...geometries) => {
11639
11639
  geometries = flatten(geometries);
11640
11640
  const newgeometries = geometries.map((geometry) => to3DWalls({ z0: -1, z1: 1 }, geometry));
11641
11641
  const newgeom3 = subtractGeom3(newgeometries);
11642
11642
  const epsilon = measureEpsilon(newgeom3);
11643
11643
  return fromFakePolygons(epsilon, geom3.toPolygons(newgeom3));
11644
11644
  };
11645
- module.exports = subtract6;
11645
+ module.exports = subtract7;
11646
11646
  }
11647
11647
  });
11648
11648
 
@@ -11656,7 +11656,7 @@ var require_subtract4 = __commonJS({
11656
11656
  var geom3 = require_geom3();
11657
11657
  var subtractGeom2 = require_subtractGeom2();
11658
11658
  var subtractGeom3 = require_subtractGeom3();
11659
- var subtract6 = (...geometries) => {
11659
+ var subtract7 = (...geometries) => {
11660
11660
  geometries = flatten(geometries);
11661
11661
  if (geometries.length === 0) throw new Error("wrong number of arguments");
11662
11662
  if (!areAllShapesTheSameType(geometries)) {
@@ -11667,7 +11667,7 @@ var require_subtract4 = __commonJS({
11667
11667
  if (geom3.isA(geometry)) return subtractGeom3(geometries);
11668
11668
  return geometry;
11669
11669
  };
11670
- module.exports = subtract6;
11670
+ module.exports = subtract7;
11671
11671
  }
11672
11672
  });
11673
11673
 
@@ -11709,7 +11709,7 @@ var require_unionGeom3 = __commonJS({
11709
11709
  var flatten = require_flatten();
11710
11710
  var retessellate = require_retessellate();
11711
11711
  var unionSub = require_unionGeom3Sub();
11712
- var union5 = (...geometries) => {
11712
+ var union6 = (...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 = union5;
11722
+ module.exports = union6;
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 union5 = (...geometries) => {
11736
+ var union6 = (...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 = union5;
11743
+ module.exports = union6;
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 union5 = (...geometries) => {
11757
+ var union6 = (...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 = union5;
11768
+ module.exports = union6;
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 cylinder4 = geom3.create(polygons2);
12114
- result = unionGeom3Sub(result, cylinder4);
12113
+ const cylinder5 = geom3.create(polygons2);
12114
+ result = unionGeom3Sub(result, cylinder5);
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 union5 = require_union();
12158
+ var union6 = 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 union5(geometry, expanded);
12174
+ return union6(geometry, expanded);
12175
12175
  };
12176
12176
  module.exports = expandGeom3;
12177
12177
  }
@@ -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 union5 = require_union();
12889
+ var union6 = 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 union5(hulls);
12898
+ return union6(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: translate10 } = require_translate2();
13531
+ var { translate: translate11 } = 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 translate10(translation, geometry);
13568
+ return translate11(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: translate10 } = require_translate2();
13605
+ var { translate: translate11 } = 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 translate10(offset4, object);
13617
+ return translate11(offset4, object);
13618
13618
  };
13619
13619
  var center = (options, ...objects) => {
13620
13620
  const defaults = {
@@ -24526,7 +24526,7 @@ var m2host = (raw_params) => {
24526
24526
  }
24527
24527
  const centerX = (minX + maxX) / 2;
24528
24528
  const centerY = (minY + maxY) / 2;
24529
- const translate10 = (el) => {
24529
+ const translate11 = (el) => {
24530
24530
  if (typeof el.x === "number") el.x -= centerX;
24531
24531
  if (typeof el.y === "number") el.y -= centerY;
24532
24532
  if (el.center) {
@@ -24540,9 +24540,9 @@ var m2host = (raw_params) => {
24540
24540
  }));
24541
24541
  }
24542
24542
  };
24543
- for (const pad2 of pads) translate10(pad2);
24544
- translate10(cutout);
24545
- translate10(pin1Marker);
24543
+ for (const pad2 of pads) translate11(pad2);
24544
+ translate11(cutout);
24545
+ translate11(pin1Marker);
24546
24546
  return {
24547
24547
  circuitJson: [
24548
24548
  ...pads,
@@ -28509,7 +28509,7 @@ import * as THREE15 from "three";
28509
28509
  // package.json
28510
28510
  var package_default = {
28511
28511
  name: "@tscircuit/3d-viewer",
28512
- version: "0.0.461",
28512
+ version: "0.0.463",
28513
28513
  main: "./dist/index.js",
28514
28514
  module: "./dist/index.js",
28515
28515
  type: "module",
@@ -29821,10 +29821,10 @@ var createBoardGeomFromCircuitJson = (circuitJson, opts = {}) => {
29821
29821
  };
29822
29822
 
29823
29823
  // src/BoardGeomBuilder.ts
29824
- var import_transforms9 = __toESM(require_transforms(), 1);
29825
- var import_primitives10 = __toESM(require_primitives(), 1);
29824
+ var import_transforms10 = __toESM(require_transforms(), 1);
29825
+ var import_primitives11 = __toESM(require_primitives(), 1);
29826
29826
  var import_colors7 = __toESM(require_colors(), 1);
29827
- var import_booleans6 = __toESM(require_booleans(), 1);
29827
+ var import_booleans7 = __toESM(require_booleans(), 1);
29828
29828
  import { su as su3 } from "@tscircuit/circuit-json-util";
29829
29829
 
29830
29830
  // src/geoms/plated-hole.ts
@@ -30981,6 +30981,75 @@ function createGeom2FromBRep(brep, arcSegments = 16) {
30981
30981
  return (0, import_booleans5.subtract)(outerGeom, innerGeoms);
30982
30982
  }
30983
30983
 
30984
+ // src/geoms/via-geoms.ts
30985
+ var import_booleans6 = __toESM(require_booleans(), 1);
30986
+ var import_transforms9 = __toESM(require_transforms(), 1);
30987
+ var import_primitives10 = __toESM(require_primitives(), 1);
30988
+ function createViaCopper({
30989
+ x,
30990
+ y,
30991
+ outerDiameter,
30992
+ holeDiameter,
30993
+ thickness
30994
+ }) {
30995
+ if (outerDiameter <= holeDiameter) {
30996
+ throw new Error(
30997
+ `Invalid via geometry: outerDiameter (${outerDiameter}) must be > holeDiameter (${holeDiameter})`
30998
+ );
30999
+ }
31000
+ const padThickness = M;
31001
+ const platingThickness = M;
31002
+ const barrelRadius = Math.min(
31003
+ outerDiameter / 2,
31004
+ holeDiameter / 2 + platingThickness
31005
+ );
31006
+ const barrel = (0, import_primitives10.cylinder)({
31007
+ center: [0, 0, 0],
31008
+ radius: barrelRadius,
31009
+ height: thickness,
31010
+ segments: SMOOTH_CIRCLE_SEGMENTS
31011
+ });
31012
+ const topPad = (0, import_primitives10.cylinder)({
31013
+ center: [0, 0, thickness / 2],
31014
+ radius: outerDiameter / 2,
31015
+ height: padThickness,
31016
+ segments: SMOOTH_CIRCLE_SEGMENTS
31017
+ });
31018
+ const bottomPad = (0, import_primitives10.cylinder)({
31019
+ center: [0, 0, -thickness / 2],
31020
+ radius: outerDiameter / 2,
31021
+ height: padThickness,
31022
+ segments: SMOOTH_CIRCLE_SEGMENTS
31023
+ });
31024
+ const viaSolid = (0, import_booleans6.union)([barrel, topPad, bottomPad]);
31025
+ const drillHeight = thickness + padThickness * 2;
31026
+ const drill = (0, import_primitives10.cylinder)({
31027
+ center: [0, 0, 0],
31028
+ radius: holeDiameter / 2,
31029
+ height: drillHeight,
31030
+ segments: SMOOTH_CIRCLE_SEGMENTS
31031
+ });
31032
+ const finalViaCopper = (0, import_booleans6.subtract)(viaSolid, drill);
31033
+ const positionedVia = (0, import_transforms9.translate)([x, y, 0], finalViaCopper);
31034
+ return positionedVia;
31035
+ }
31036
+ function createViaBoardDrill({
31037
+ x,
31038
+ y,
31039
+ holeDiameter,
31040
+ thickness
31041
+ }) {
31042
+ const drillHeight = thickness * 1.5;
31043
+ const drillRadius = holeDiameter / 2 + M;
31044
+ const drill = (0, import_primitives10.cylinder)({
31045
+ center: [x, y, 0],
31046
+ radius: drillRadius,
31047
+ height: drillHeight,
31048
+ segments: SMOOTH_CIRCLE_SEGMENTS
31049
+ });
31050
+ return drill;
31051
+ }
31052
+
30984
31053
  // src/BoardGeomBuilder.ts
30985
31054
  var PAD_ROUNDED_SEGMENTS = 64;
30986
31055
  var BOARD_CLIP_Z_MARGIN = 1;
@@ -30988,15 +31057,15 @@ var BOARD_CLIP_XY_OUTSET = 0.05;
30988
31057
  var createCenteredRectPadGeom = (width10, height10, thickness, rectBorderRadius) => {
30989
31058
  const clampedRadius = clampRectBorderRadius(width10, height10, rectBorderRadius);
30990
31059
  if (clampedRadius <= 0) {
30991
- return (0, import_primitives10.cuboid)({ center: [0, 0, 0], size: [width10, height10, thickness] });
31060
+ return (0, import_primitives11.cuboid)({ center: [0, 0, 0], size: [width10, height10, thickness] });
30992
31061
  }
30993
- const rect2d = (0, import_primitives10.roundedRectangle)({
31062
+ const rect2d = (0, import_primitives11.roundedRectangle)({
30994
31063
  size: [width10, height10],
30995
31064
  roundRadius: clampedRadius,
30996
31065
  segments: PAD_ROUNDED_SEGMENTS
30997
31066
  });
30998
31067
  const extruded = (0, import_extrusions8.extrudeLinear)({ height: thickness }, rect2d);
30999
- return (0, import_transforms9.translate)([0, 0, -thickness / 2], extruded);
31068
+ return (0, import_transforms10.translate)([0, 0, -thickness / 2], extruded);
31000
31069
  };
31001
31070
  var buildStateOrder = [
31002
31071
  "initializing",
@@ -31032,8 +31101,6 @@ var BoardGeomBuilder = class {
31032
31101
  pcb_copper_pours;
31033
31102
  boardGeom = null;
31034
31103
  platedHoleGeoms = [];
31035
- holeGeoms = [];
31036
- // Currently only used for subtraction
31037
31104
  padGeoms = [];
31038
31105
  traceGeoms = [];
31039
31106
  viaGeoms = [];
@@ -31123,11 +31190,11 @@ var BoardGeomBuilder = class {
31123
31190
  { xyOutset: BOARD_CLIP_XY_OUTSET }
31124
31191
  );
31125
31192
  } else {
31126
- this.boardGeom = (0, import_primitives10.cuboid)({
31193
+ this.boardGeom = (0, import_primitives11.cuboid)({
31127
31194
  size: [this.board.width, this.board.height, this.ctx.pcbThickness],
31128
31195
  center: [this.board.center.x, this.board.center.y, 0]
31129
31196
  });
31130
- this.boardClipGeom = (0, import_primitives10.cuboid)({
31197
+ this.boardClipGeom = (0, import_primitives11.cuboid)({
31131
31198
  size: [
31132
31199
  this.board.width + 2 * BOARD_CLIP_XY_OUTSET,
31133
31200
  this.board.height + 2 * BOARD_CLIP_XY_OUTSET,
@@ -31262,47 +31329,48 @@ var BoardGeomBuilder = class {
31262
31329
  let cutoutGeom = null;
31263
31330
  const cutoutHeight = this.ctx.pcbThickness * 1.5;
31264
31331
  switch (cutout.shape) {
31265
- case "rect":
31332
+ case "rect": {
31266
31333
  const rectCornerRadius = clampRectBorderRadius(
31267
31334
  cutout.width,
31268
31335
  cutout.height,
31269
31336
  extractRectBorderRadius(cutout)
31270
31337
  );
31271
31338
  if (rectCornerRadius > 0) {
31272
- const rect2d = (0, import_primitives10.roundedRectangle)({
31339
+ const rect2d = (0, import_primitives11.roundedRectangle)({
31273
31340
  size: [cutout.width, cutout.height],
31274
31341
  roundRadius: rectCornerRadius,
31275
31342
  segments: PAD_ROUNDED_SEGMENTS
31276
31343
  });
31277
31344
  cutoutGeom = (0, import_extrusions8.extrudeLinear)({ height: cutoutHeight }, rect2d);
31278
- cutoutGeom = (0, import_transforms9.translate)([0, 0, -cutoutHeight / 2], cutoutGeom);
31279
- cutoutGeom = (0, import_transforms9.translate)(
31345
+ cutoutGeom = (0, import_transforms10.translate)([0, 0, -cutoutHeight / 2], cutoutGeom);
31346
+ cutoutGeom = (0, import_transforms10.translate)(
31280
31347
  [cutout.center.x, cutout.center.y, 0],
31281
31348
  cutoutGeom
31282
31349
  );
31283
31350
  } else {
31284
- const baseCutoutGeom = (0, import_primitives10.cuboid)({
31351
+ const baseCutoutGeom = (0, import_primitives11.cuboid)({
31285
31352
  center: [0, 0, 0],
31286
31353
  size: [cutout.width, cutout.height, cutoutHeight]
31287
31354
  });
31288
- cutoutGeom = (0, import_transforms9.translate)(
31355
+ cutoutGeom = (0, import_transforms10.translate)(
31289
31356
  [cutout.center.x, cutout.center.y, 0],
31290
31357
  baseCutoutGeom
31291
31358
  );
31292
31359
  }
31293
31360
  if (cutout.rotation) {
31294
31361
  const rotationRadians = cutout.rotation * Math.PI / 180;
31295
- cutoutGeom = (0, import_transforms9.rotateZ)(rotationRadians, cutoutGeom);
31362
+ cutoutGeom = (0, import_transforms10.rotateZ)(rotationRadians, cutoutGeom);
31296
31363
  }
31297
31364
  break;
31365
+ }
31298
31366
  case "circle":
31299
- cutoutGeom = (0, import_primitives10.cylinder)({
31367
+ cutoutGeom = (0, import_primitives11.cylinder)({
31300
31368
  center: [cutout.center.x, cutout.center.y, 0],
31301
31369
  radius: cutout.radius,
31302
31370
  height: cutoutHeight
31303
31371
  });
31304
31372
  break;
31305
- case "polygon":
31373
+ case "polygon": {
31306
31374
  let pointsVec2 = cutout.points.map((p) => [p.x, p.y]);
31307
31375
  if (pointsVec2.length < 3) {
31308
31376
  console.warn(
@@ -31313,13 +31381,14 @@ var BoardGeomBuilder = class {
31313
31381
  if (arePointsClockwise(pointsVec2)) {
31314
31382
  pointsVec2 = pointsVec2.reverse();
31315
31383
  }
31316
- const polygon2d = (0, import_primitives10.polygon)({ points: pointsVec2 });
31384
+ const polygon2d = (0, import_primitives11.polygon)({ points: pointsVec2 });
31317
31385
  cutoutGeom = (0, import_extrusions8.extrudeLinear)({ height: cutoutHeight }, polygon2d);
31318
- cutoutGeom = (0, import_transforms9.translate)([0, 0, -cutoutHeight / 2], cutoutGeom);
31386
+ cutoutGeom = (0, import_transforms10.translate)([0, 0, -cutoutHeight / 2], cutoutGeom);
31319
31387
  break;
31388
+ }
31320
31389
  }
31321
31390
  if (cutoutGeom) {
31322
- this.boardGeom = (0, import_booleans6.subtract)(this.boardGeom, cutoutGeom);
31391
+ this.boardGeom = (0, import_booleans7.subtract)(this.boardGeom, cutoutGeom);
31323
31392
  }
31324
31393
  }
31325
31394
  processCopperPour(pour) {
@@ -31327,22 +31396,22 @@ var BoardGeomBuilder = class {
31327
31396
  const zPos = layerSign * this.ctx.pcbThickness / 2 + layerSign * BOARD_SURFACE_OFFSET.copper;
31328
31397
  let pourGeom = null;
31329
31398
  if (pour.shape === "rect") {
31330
- let baseGeom = (0, import_primitives10.cuboid)({
31399
+ let baseGeom = (0, import_primitives11.cuboid)({
31331
31400
  center: [0, 0, 0],
31332
31401
  // Create at origin for rotation
31333
31402
  size: [pour.width, pour.height, M]
31334
31403
  });
31335
31404
  if ("rotation" in pour && pour.rotation) {
31336
31405
  const rotationRadians = pour.rotation * Math.PI / 180;
31337
- baseGeom = (0, import_transforms9.rotateZ)(rotationRadians, baseGeom);
31406
+ baseGeom = (0, import_transforms10.rotateZ)(rotationRadians, baseGeom);
31338
31407
  }
31339
- pourGeom = (0, import_transforms9.translate)([pour.center.x, pour.center.y, zPos], baseGeom);
31408
+ pourGeom = (0, import_transforms10.translate)([pour.center.x, pour.center.y, zPos], baseGeom);
31340
31409
  } else if (pour.shape === "brep") {
31341
31410
  const brepShape = pour.brep_shape;
31342
- if (brepShape && brepShape.outer_ring) {
31411
+ if (brepShape?.outer_ring) {
31343
31412
  const pourGeom2 = createGeom2FromBRep(brepShape);
31344
31413
  pourGeom = (0, import_extrusions8.extrudeLinear)({ height: M }, pourGeom2);
31345
- pourGeom = (0, import_transforms9.translate)([0, 0, zPos], pourGeom);
31414
+ pourGeom = (0, import_transforms10.translate)([0, 0, zPos], pourGeom);
31346
31415
  }
31347
31416
  } else if (pour.shape === "polygon") {
31348
31417
  let pointsVec2 = pour.points.map((p) => [p.x, p.y]);
@@ -31355,13 +31424,13 @@ var BoardGeomBuilder = class {
31355
31424
  if (arePointsClockwise(pointsVec2)) {
31356
31425
  pointsVec2 = pointsVec2.reverse();
31357
31426
  }
31358
- const polygon2d = (0, import_primitives10.polygon)({ points: pointsVec2 });
31427
+ const polygon2d = (0, import_primitives11.polygon)({ points: pointsVec2 });
31359
31428
  pourGeom = (0, import_extrusions8.extrudeLinear)({ height: M }, polygon2d);
31360
- pourGeom = (0, import_transforms9.translate)([0, 0, zPos], pourGeom);
31429
+ pourGeom = (0, import_transforms10.translate)([0, 0, zPos], pourGeom);
31361
31430
  }
31362
31431
  if (pourGeom) {
31363
31432
  if (this.boardClipGeom) {
31364
- pourGeom = (0, import_booleans6.intersect)(this.boardClipGeom, pourGeom);
31433
+ pourGeom = (0, import_booleans7.intersect)(this.boardClipGeom, pourGeom);
31365
31434
  }
31366
31435
  const covered = pour.covered_with_solder_mask !== false;
31367
31436
  const pourMaterialColor = covered ? tracesMaterialColors[this.board.material] ?? colors.fr4TracesWithoutMaskTan : colors.copper;
@@ -31374,7 +31443,7 @@ var BoardGeomBuilder = class {
31374
31443
  if (ph.shape === "circle" || ph.shape === "circular_hole_with_rect_pad") {
31375
31444
  let cyGeom = null;
31376
31445
  if (ph.shape === "circular_hole_with_rect_pad") {
31377
- cyGeom = (0, import_primitives10.cylinder)({
31446
+ cyGeom = (0, import_primitives11.cylinder)({
31378
31447
  center: [
31379
31448
  ph.x + (ph.hole_offset_x || 0),
31380
31449
  ph.y + (ph.hole_offset_y || 0),
@@ -31386,7 +31455,7 @@ var BoardGeomBuilder = class {
31386
31455
  // Ensure it cuts through
31387
31456
  });
31388
31457
  } else {
31389
- cyGeom = (0, import_primitives10.cylinder)({
31458
+ cyGeom = (0, import_primitives11.cylinder)({
31390
31459
  center: [ph.x, ph.y, 0],
31391
31460
  radius: ph.hole_diameter / 2 + M,
31392
31461
  // Add margin for subtraction
@@ -31395,10 +31464,10 @@ var BoardGeomBuilder = class {
31395
31464
  });
31396
31465
  }
31397
31466
  if (!opts.dontCutBoard) {
31398
- this.boardGeom = (0, import_booleans6.subtract)(this.boardGeom, cyGeom);
31467
+ this.boardGeom = (0, import_booleans7.subtract)(this.boardGeom, cyGeom);
31399
31468
  }
31400
31469
  this.padGeoms = this.padGeoms.map(
31401
- (pg) => (0, import_colors7.colorize)(colors.copper, (0, import_booleans6.subtract)(pg, cyGeom))
31470
+ (pg) => (0, import_colors7.colorize)(colors.copper, (0, import_booleans7.subtract)(pg, cyGeom))
31402
31471
  );
31403
31472
  const platedHoleGeom = platedHole(ph, this.ctx, {
31404
31473
  clipGeom: this.boardClipGeom
@@ -31411,17 +31480,17 @@ var BoardGeomBuilder = class {
31411
31480
  const holeRadius = holeHeight / 2;
31412
31481
  const rectLength = Math.abs(holeWidth - holeHeight);
31413
31482
  let pillHole;
31414
- pillHole = (0, import_booleans6.union)(
31415
- (0, import_primitives10.cuboid)({
31483
+ pillHole = (0, import_booleans7.union)(
31484
+ (0, import_primitives11.cuboid)({
31416
31485
  center: [ph.x, ph.y, 0],
31417
31486
  size: shouldRotate ? [holeHeight, rectLength, this.ctx.pcbThickness * 1.5] : [rectLength, holeHeight, this.ctx.pcbThickness * 1.5]
31418
31487
  }),
31419
- (0, import_primitives10.cylinder)({
31488
+ (0, import_primitives11.cylinder)({
31420
31489
  center: shouldRotate ? [ph.x, ph.y - rectLength / 2, 0] : [ph.x - rectLength / 2, ph.y, 0],
31421
31490
  radius: holeRadius,
31422
31491
  height: this.ctx.pcbThickness * 1.5
31423
31492
  }),
31424
- (0, import_primitives10.cylinder)({
31493
+ (0, import_primitives11.cylinder)({
31425
31494
  center: shouldRotate ? [ph.x, ph.y + rectLength / 2, 0] : [ph.x + rectLength / 2, ph.y, 0],
31426
31495
  radius: holeRadius,
31427
31496
  height: this.ctx.pcbThickness * 1.5
@@ -31429,16 +31498,16 @@ var BoardGeomBuilder = class {
31429
31498
  );
31430
31499
  if (ph.ccw_rotation) {
31431
31500
  const rotationRadians = ph.ccw_rotation * Math.PI / 180;
31432
- pillHole = (0, import_transforms9.translate)(
31501
+ pillHole = (0, import_transforms10.translate)(
31433
31502
  [ph.x, ph.y, 0],
31434
- (0, import_transforms9.rotateZ)(rotationRadians, (0, import_transforms9.translate)([-ph.x, -ph.y, 0], pillHole))
31503
+ (0, import_transforms10.rotateZ)(rotationRadians, (0, import_transforms10.translate)([-ph.x, -ph.y, 0], pillHole))
31435
31504
  );
31436
31505
  }
31437
31506
  if (!opts.dontCutBoard) {
31438
- this.boardGeom = (0, import_booleans6.subtract)(this.boardGeom, pillHole);
31507
+ this.boardGeom = (0, import_booleans7.subtract)(this.boardGeom, pillHole);
31439
31508
  }
31440
31509
  this.padGeoms = this.padGeoms.map(
31441
- (pg) => (0, import_colors7.colorize)(colors.copper, (0, import_booleans6.subtract)(pg, pillHole))
31510
+ (pg) => (0, import_colors7.colorize)(colors.copper, (0, import_booleans7.subtract)(pg, pillHole))
31442
31511
  );
31443
31512
  const platedHoleGeom = platedHole(ph, this.ctx, {
31444
31513
  clipGeom: this.boardClipGeom
@@ -31451,8 +31520,8 @@ var BoardGeomBuilder = class {
31451
31520
  const holeRadius = holeHeight / 2;
31452
31521
  const rectLength = Math.abs(holeWidth - holeHeight);
31453
31522
  let pillHole;
31454
- pillHole = (0, import_booleans6.union)(
31455
- (0, import_primitives10.cuboid)({
31523
+ pillHole = (0, import_booleans7.union)(
31524
+ (0, import_primitives11.cuboid)({
31456
31525
  center: [
31457
31526
  ph.x + (ph.hole_offset_x || 0),
31458
31527
  ph.y + (ph.hole_offset_y || 0),
@@ -31460,7 +31529,7 @@ var BoardGeomBuilder = class {
31460
31529
  ],
31461
31530
  size: shouldRotate ? [holeHeight, rectLength, this.ctx.pcbThickness * 1.5] : [rectLength, holeHeight, this.ctx.pcbThickness * 1.5]
31462
31531
  }),
31463
- (0, import_primitives10.cylinder)({
31532
+ (0, import_primitives11.cylinder)({
31464
31533
  center: shouldRotate ? [
31465
31534
  ph.x + (ph.hole_offset_x || 0),
31466
31535
  ph.y + (ph.hole_offset_y || 0) - rectLength / 2,
@@ -31473,7 +31542,7 @@ var BoardGeomBuilder = class {
31473
31542
  radius: holeRadius,
31474
31543
  height: this.ctx.pcbThickness * 1.5
31475
31544
  }),
31476
- (0, import_primitives10.cylinder)({
31545
+ (0, import_primitives11.cylinder)({
31477
31546
  center: shouldRotate ? [
31478
31547
  ph.x + (ph.hole_offset_x || 0),
31479
31548
  ph.y + (ph.hole_offset_y || 0) + rectLength / 2,
@@ -31501,13 +31570,13 @@ var BoardGeomBuilder = class {
31501
31570
  });
31502
31571
  if (!boardHole || !copperHole) return;
31503
31572
  if (!opts.dontCutBoard) {
31504
- this.boardGeom = (0, import_booleans6.subtract)(this.boardGeom, boardHole);
31573
+ this.boardGeom = (0, import_booleans7.subtract)(this.boardGeom, boardHole);
31505
31574
  }
31506
31575
  this.padGeoms = this.padGeoms.map(
31507
- (pg) => (0, import_colors7.colorize)(colors.copper, (0, import_booleans6.subtract)(pg, boardHole))
31576
+ (pg) => (0, import_colors7.colorize)(colors.copper, (0, import_booleans7.subtract)(pg, boardHole))
31508
31577
  );
31509
31578
  this.platedHoleGeoms = this.platedHoleGeoms.map(
31510
- (phg) => (0, import_colors7.colorize)(colors.copper, (0, import_booleans6.subtract)(phg, copperHole))
31579
+ (phg) => (0, import_colors7.colorize)(colors.copper, (0, import_booleans7.subtract)(phg, copperHole))
31511
31580
  );
31512
31581
  const platedHoleGeom = platedHole(ph, this.ctx, {
31513
31582
  clipGeom: this.boardClipGeom
@@ -31520,22 +31589,22 @@ var BoardGeomBuilder = class {
31520
31589
  const holeDepth = this.ctx.pcbThickness * 1.5;
31521
31590
  const copperInset = 0.02;
31522
31591
  if (hole.hole_shape === "round" || hole.hole_shape === "circle") {
31523
- const cyGeom = (0, import_primitives10.cylinder)({
31592
+ const cyGeom = (0, import_primitives11.cylinder)({
31524
31593
  center: [hole.x, hole.y, 0],
31525
31594
  radius: hole.hole_diameter / 2 + M,
31526
31595
  height: holeDepth
31527
31596
  });
31528
- this.boardGeom = (0, import_booleans6.subtract)(this.boardGeom, cyGeom);
31597
+ this.boardGeom = (0, import_booleans7.subtract)(this.boardGeom, cyGeom);
31529
31598
  this.padGeoms = this.padGeoms.map(
31530
- (pg) => (0, import_colors7.colorize)(colors.copper, (0, import_booleans6.subtract)(pg, cyGeom))
31599
+ (pg) => (0, import_colors7.colorize)(colors.copper, (0, import_booleans7.subtract)(pg, cyGeom))
31531
31600
  );
31532
- const copperCut = (0, import_primitives10.cylinder)({
31601
+ const copperCut = (0, import_primitives11.cylinder)({
31533
31602
  center: [hole.x, hole.y, 0],
31534
31603
  radius: hole.hole_diameter / 2 + M / 2,
31535
31604
  height: holeDepth
31536
31605
  });
31537
31606
  this.platedHoleGeoms = this.platedHoleGeoms.map(
31538
- (phg) => (0, import_colors7.colorize)(colors.copper, (0, import_booleans6.subtract)(phg, copperCut))
31607
+ (phg) => (0, import_colors7.colorize)(colors.copper, (0, import_booleans7.subtract)(phg, copperCut))
31539
31608
  );
31540
31609
  } else if (hole.hole_shape === "pill" || hole.hole_shape === "rotated_pill") {
31541
31610
  const holeWidth = hole.hole_width;
@@ -31545,34 +31614,34 @@ var BoardGeomBuilder = class {
31545
31614
  const isRotated = hole.hole_shape === "rotated_pill";
31546
31615
  let pillHole;
31547
31616
  if (holeWidth > holeHeight) {
31548
- pillHole = (0, import_booleans6.union)(
31549
- (0, import_primitives10.cuboid)({
31617
+ pillHole = (0, import_booleans7.union)(
31618
+ (0, import_primitives11.cuboid)({
31550
31619
  center: [hole.x, hole.y, 0],
31551
31620
  size: [rectLength, holeHeight, holeDepth]
31552
31621
  }),
31553
- (0, import_primitives10.cylinder)({
31622
+ (0, import_primitives11.cylinder)({
31554
31623
  center: [hole.x - rectLength / 2, hole.y, 0],
31555
31624
  radius: holeRadius,
31556
31625
  height: holeDepth
31557
31626
  }),
31558
- (0, import_primitives10.cylinder)({
31627
+ (0, import_primitives11.cylinder)({
31559
31628
  center: [hole.x + rectLength / 2, hole.y, 0],
31560
31629
  radius: holeRadius,
31561
31630
  height: holeDepth
31562
31631
  })
31563
31632
  );
31564
31633
  } else {
31565
- pillHole = (0, import_booleans6.union)(
31566
- (0, import_primitives10.cuboid)({
31634
+ pillHole = (0, import_booleans7.union)(
31635
+ (0, import_primitives11.cuboid)({
31567
31636
  center: [hole.x, hole.y, 0],
31568
31637
  size: [holeWidth, rectLength, holeDepth]
31569
31638
  }),
31570
- (0, import_primitives10.cylinder)({
31639
+ (0, import_primitives11.cylinder)({
31571
31640
  center: [hole.x, hole.y - rectLength / 2, 0],
31572
31641
  radius: holeRadius,
31573
31642
  height: holeDepth
31574
31643
  }),
31575
- (0, import_primitives10.cylinder)({
31644
+ (0, import_primitives11.cylinder)({
31576
31645
  center: [hole.x, hole.y + rectLength / 2, 0],
31577
31646
  radius: holeRadius,
31578
31647
  height: holeDepth
@@ -31581,15 +31650,15 @@ var BoardGeomBuilder = class {
31581
31650
  }
31582
31651
  if (isRotated) {
31583
31652
  const rotationRadians = hole.ccw_rotation * Math.PI / 180;
31584
- pillHole = (0, import_transforms9.rotateZ)(rotationRadians, pillHole);
31653
+ pillHole = (0, import_transforms10.rotateZ)(rotationRadians, pillHole);
31585
31654
  }
31586
- this.boardGeom = (0, import_booleans6.subtract)(this.boardGeom, pillHole);
31655
+ this.boardGeom = (0, import_booleans7.subtract)(this.boardGeom, pillHole);
31587
31656
  this.padGeoms = this.padGeoms.map(
31588
- (pg) => (0, import_colors7.colorize)(colors.copper, (0, import_booleans6.subtract)(pg, pillHole))
31657
+ (pg) => (0, import_colors7.colorize)(colors.copper, (0, import_booleans7.subtract)(pg, pillHole))
31589
31658
  );
31590
31659
  const copperPill = (0, import_expansions4.expand)({ delta: -copperInset }, pillHole);
31591
31660
  this.platedHoleGeoms = this.platedHoleGeoms.map(
31592
- (phg) => (0, import_colors7.colorize)(colors.copper, (0, import_booleans6.subtract)(phg, copperPill))
31661
+ (phg) => (0, import_colors7.colorize)(colors.copper, (0, import_booleans7.subtract)(phg, copperPill))
31593
31662
  );
31594
31663
  }
31595
31664
  }
@@ -31604,10 +31673,10 @@ var BoardGeomBuilder = class {
31604
31673
  M,
31605
31674
  rectBorderRadius
31606
31675
  );
31607
- const positionedPadGeom = (0, import_transforms9.translate)([pad2.x, pad2.y, zPos], basePadGeom);
31676
+ const positionedPadGeom = (0, import_transforms10.translate)([pad2.x, pad2.y, zPos], basePadGeom);
31608
31677
  let finalPadGeom = positionedPadGeom;
31609
31678
  if (this.boardClipGeom) {
31610
- finalPadGeom = (0, import_booleans6.intersect)(this.boardClipGeom, finalPadGeom);
31679
+ finalPadGeom = (0, import_booleans7.intersect)(this.boardClipGeom, finalPadGeom);
31611
31680
  }
31612
31681
  finalPadGeom = (0, import_colors7.colorize)(colors.copper, finalPadGeom);
31613
31682
  this.padGeoms.push(finalPadGeom);
@@ -31619,22 +31688,22 @@ var BoardGeomBuilder = class {
31619
31688
  rectBorderRadius
31620
31689
  );
31621
31690
  const rotationRadians = pad2.ccw_rotation * Math.PI / 180;
31622
- basePadGeom = (0, import_transforms9.rotateZ)(rotationRadians, basePadGeom);
31623
- const positionedPadGeom = (0, import_transforms9.translate)([pad2.x, pad2.y, zPos], basePadGeom);
31691
+ basePadGeom = (0, import_transforms10.rotateZ)(rotationRadians, basePadGeom);
31692
+ const positionedPadGeom = (0, import_transforms10.translate)([pad2.x, pad2.y, zPos], basePadGeom);
31624
31693
  let finalPadGeom = positionedPadGeom;
31625
31694
  if (this.boardClipGeom) {
31626
- finalPadGeom = (0, import_booleans6.intersect)(this.boardClipGeom, finalPadGeom);
31695
+ finalPadGeom = (0, import_booleans7.intersect)(this.boardClipGeom, finalPadGeom);
31627
31696
  }
31628
31697
  finalPadGeom = (0, import_colors7.colorize)(colors.copper, finalPadGeom);
31629
31698
  this.padGeoms.push(finalPadGeom);
31630
31699
  } else if (pad2.shape === "circle") {
31631
- let padGeom = (0, import_primitives10.cylinder)({
31700
+ let padGeom = (0, import_primitives11.cylinder)({
31632
31701
  center: [pad2.x, pad2.y, zPos],
31633
31702
  radius: pad2.radius,
31634
31703
  height: M
31635
31704
  });
31636
31705
  if (this.boardClipGeom) {
31637
- padGeom = (0, import_booleans6.intersect)(this.boardClipGeom, padGeom);
31706
+ padGeom = (0, import_booleans7.intersect)(this.boardClipGeom, padGeom);
31638
31707
  }
31639
31708
  padGeom = (0, import_colors7.colorize)(colors.copper, padGeom);
31640
31709
  this.padGeoms.push(padGeom);
@@ -31650,12 +31719,12 @@ var BoardGeomBuilder = class {
31650
31719
  if (currentSegmentPoints.length >= 2 && currentLayer) {
31651
31720
  const layerSign = currentLayer === "bottom" ? -1 : 1;
31652
31721
  const zCenter = layerSign * this.ctx.pcbThickness / 2 + layerSign * BOARD_SURFACE_OFFSET.traces;
31653
- const linePath = (0, import_primitives10.line)(currentSegmentPoints);
31722
+ const linePath = (0, import_primitives11.line)(currentSegmentPoints);
31654
31723
  const expandedPath = (0, import_expansions4.expand)(
31655
31724
  { delta: currentWidth / 2, corners: "round" },
31656
31725
  linePath
31657
31726
  );
31658
- let traceGeom = (0, import_transforms9.translate)(
31727
+ let traceGeom = (0, import_transforms10.translate)(
31659
31728
  [0, 0, zCenter - M / 2],
31660
31729
  (0, import_extrusions8.extrudeLinear)({ height: M }, expandedPath)
31661
31730
  );
@@ -31666,25 +31735,25 @@ var BoardGeomBuilder = class {
31666
31735
  startPointCoords[1]
31667
31736
  );
31668
31737
  if (startHole) {
31669
- const cuttingCylinder = (0, import_primitives10.cylinder)({
31738
+ const cuttingCylinder = (0, import_primitives11.cylinder)({
31670
31739
  center: [startPointCoords[0], startPointCoords[1], zCenter],
31671
31740
  radius: startHole.diameter / 2 + M,
31672
31741
  height: M
31673
31742
  });
31674
- traceGeom = (0, import_booleans6.subtract)(traceGeom, cuttingCylinder);
31743
+ traceGeom = (0, import_booleans7.subtract)(traceGeom, cuttingCylinder);
31675
31744
  }
31676
31745
  const endHole = this.getHoleToCut(endPointCoords[0], endPointCoords[1]);
31677
31746
  if (endHole) {
31678
- const cuttingCylinder = (0, import_primitives10.cylinder)({
31747
+ const cuttingCylinder = (0, import_primitives11.cylinder)({
31679
31748
  center: [endPointCoords[0], endPointCoords[1], zCenter],
31680
31749
  radius: endHole.diameter / 2 + M,
31681
31750
  height: M
31682
31751
  });
31683
- traceGeom = (0, import_booleans6.subtract)(traceGeom, cuttingCylinder);
31752
+ traceGeom = (0, import_booleans7.subtract)(traceGeom, cuttingCylinder);
31684
31753
  }
31685
31754
  const tracesMaterialColor = tracesMaterialColors[this.board.material] ?? colors.fr4TracesWithoutMaskTan;
31686
31755
  if (this.boardClipGeom) {
31687
- traceGeom = (0, import_booleans6.intersect)(this.boardClipGeom, traceGeom);
31756
+ traceGeom = (0, import_booleans7.intersect)(this.boardClipGeom, traceGeom);
31688
31757
  }
31689
31758
  traceGeom = (0, import_colors7.colorize)(tracesMaterialColor, traceGeom);
31690
31759
  this.traceGeoms.push(traceGeom);
@@ -31727,24 +31796,34 @@ var BoardGeomBuilder = class {
31727
31796
  finishSegment();
31728
31797
  }
31729
31798
  processVia(via) {
31730
- this.processPlatedHole(
31731
- {
31799
+ if (!this.boardGeom) return;
31800
+ if (typeof via.outer_diameter === "number" && typeof via.hole_diameter === "number") {
31801
+ const viaCopperGeom = createViaCopper({
31732
31802
  x: via.x,
31733
31803
  y: via.y,
31734
- hole_diameter: via.hole_diameter,
31735
- outer_diameter: via.outer_diameter,
31736
- shape: "circle",
31737
- layers: ["top", "bottom"],
31738
- // Assume through-hole via
31739
- type: "pcb_plated_hole",
31740
- pcb_plated_hole_id: `via_${via.pcb_via_id}`
31741
- // Create a unique-ish ID
31742
- },
31743
- {
31744
- dontCutBoard: true
31745
- // Board cut should happen via trace logic or dedicated via cut
31804
+ outerDiameter: via.outer_diameter,
31805
+ holeDiameter: via.hole_diameter,
31806
+ thickness: this.ctx.pcbThickness
31807
+ });
31808
+ let finalViaGeom = viaCopperGeom;
31809
+ if (this.boardClipGeom) {
31810
+ finalViaGeom = (0, import_booleans7.intersect)(this.boardClipGeom, viaCopperGeom);
31811
+ finalViaGeom = (0, import_colors7.colorize)(colors.copper, finalViaGeom);
31746
31812
  }
31747
- );
31813
+ this.viaGeoms.push(finalViaGeom);
31814
+ }
31815
+ if (typeof via.hole_diameter === "number") {
31816
+ const viaDrill = createViaBoardDrill({
31817
+ x: via.x,
31818
+ y: via.y,
31819
+ holeDiameter: via.hole_diameter,
31820
+ thickness: this.ctx.pcbThickness
31821
+ });
31822
+ this.boardGeom = (0, import_booleans7.subtract)(this.boardGeom, viaDrill);
31823
+ this.padGeoms = this.padGeoms.map(
31824
+ (pg) => (0, import_colors7.colorize)(colors.copper, (0, import_booleans7.subtract)(pg, viaDrill))
31825
+ );
31826
+ }
31748
31827
  }
31749
31828
  processSilkscreenText(st) {
31750
31829
  const { textOutlines, xOffset, yOffset } = createSilkscreenTextGeoms(st);
@@ -31753,7 +31832,7 @@ var BoardGeomBuilder = class {
31753
31832
  point2[0] + xOffset + st.anchor_position.x,
31754
31833
  point2[1] + yOffset + st.anchor_position.y
31755
31834
  ]);
31756
- const textPath = (0, import_primitives10.line)(alignedOutline);
31835
+ const textPath = (0, import_primitives11.line)(alignedOutline);
31757
31836
  const fontSize = st.font_size || 0.25;
31758
31837
  const expansionDelta = Math.min(
31759
31838
  Math.max(0.01, fontSize * 0.1),
@@ -31765,13 +31844,13 @@ var BoardGeomBuilder = class {
31765
31844
  );
31766
31845
  let textGeom;
31767
31846
  if (st.layer === "bottom") {
31768
- textGeom = (0, import_transforms9.translate)(
31847
+ textGeom = (0, import_transforms10.translate)(
31769
31848
  [0, 0, -this.ctx.pcbThickness / 2 - M],
31770
31849
  // Position above board
31771
31850
  (0, import_extrusions8.extrudeLinear)({ height: 0.012 }, expandedPath)
31772
31851
  );
31773
31852
  } else {
31774
- textGeom = (0, import_transforms9.translate)(
31853
+ textGeom = (0, import_transforms10.translate)(
31775
31854
  [0, 0, this.ctx.pcbThickness / 2 + M],
31776
31855
  // Position above board
31777
31856
  (0, import_extrusions8.extrudeLinear)({ height: 0.012 }, expandedPath)
@@ -33553,7 +33632,7 @@ import { su as su11 } from "@tscircuit/circuit-json-util";
33553
33632
  import * as THREE22 from "three";
33554
33633
 
33555
33634
  // src/utils/via-geoms.ts
33556
- function createViaCopper({
33635
+ function createViaCopper2({
33557
33636
  Manifold,
33558
33637
  x,
33559
33638
  y,
@@ -33623,7 +33702,7 @@ function processViasForManifold(Manifold, circuitJson, pcbThickness, manifoldIns
33623
33702
  viaBoardDrills.push(translatedDrill);
33624
33703
  }
33625
33704
  if (typeof via.outer_diameter === "number" && typeof via.hole_diameter === "number") {
33626
- const translatedViaCopper = createViaCopper({
33705
+ const translatedViaCopper = createViaCopper2({
33627
33706
  Manifold,
33628
33707
  x: via.x,
33629
33708
  y: via.y,
@@ -35020,7 +35099,7 @@ import * as THREE29 from "three";
35020
35099
  function createTextureMeshes(textures, boardData, pcbThickness) {
35021
35100
  const meshes = [];
35022
35101
  if (!textures || !boardData || pcbThickness === null) return meshes;
35023
- const createTexturePlane = (texture, yOffset, isBottomLayer, keySuffix, usePolygonOffset = false) => {
35102
+ const createTexturePlane = (texture, yOffset, isBottomLayer, keySuffix, usePolygonOffset = false, renderOrder = 0) => {
35024
35103
  if (!texture) return null;
35025
35104
  const planeGeom = new THREE29.PlaneGeometry(boardData.width, boardData.height);
35026
35105
  const material = new THREE29.MeshBasicMaterial({
@@ -35030,8 +35109,9 @@ function createTextureMeshes(textures, boardData, pcbThickness) {
35030
35109
  depthWrite: false,
35031
35110
  // Important for layers to avoid z-fighting issues with board itself
35032
35111
  polygonOffset: usePolygonOffset,
35033
- polygonOffsetFactor: usePolygonOffset ? -1 : 0,
35034
- polygonOffsetUnits: usePolygonOffset ? -1 : 0
35112
+ polygonOffsetFactor: usePolygonOffset ? -4 : 0,
35113
+ // Increased for better z-fighting prevention
35114
+ polygonOffsetUnits: usePolygonOffset ? -4 : 0
35035
35115
  });
35036
35116
  const mesh = new THREE29.Mesh(planeGeom, material);
35037
35117
  mesh.position.set(boardData.center.x, boardData.center.y, yOffset);
@@ -35039,6 +35119,7 @@ function createTextureMeshes(textures, boardData, pcbThickness) {
35039
35119
  mesh.rotation.set(Math.PI, 0, 0);
35040
35120
  }
35041
35121
  mesh.name = `${isBottomLayer ? "bottom" : "top"}-${keySuffix}-texture-plane`;
35122
+ mesh.renderOrder = renderOrder;
35042
35123
  return mesh;
35043
35124
  };
35044
35125
  const topTraceMesh = createTexturePlane(
@@ -35046,14 +35127,20 @@ function createTextureMeshes(textures, boardData, pcbThickness) {
35046
35127
  pcbThickness / 2 + BOARD_SURFACE_OFFSET.traces,
35047
35128
  // Use consistent copper offset
35048
35129
  false,
35049
- "trace"
35130
+ "trace",
35131
+ false,
35132
+ 2
35133
+ // Render after soldermask
35050
35134
  );
35051
35135
  if (topTraceMesh) meshes.push(topTraceMesh);
35052
35136
  const topTraceWithMaskMesh = createTexturePlane(
35053
35137
  textures.topTraceWithMask,
35054
35138
  pcbThickness / 2 + BOARD_SURFACE_OFFSET.traces,
35055
35139
  false,
35056
- "trace-with-mask"
35140
+ "trace-with-mask",
35141
+ false,
35142
+ 2
35143
+ // Render after soldermask
35057
35144
  );
35058
35145
  if (topTraceWithMaskMesh) meshes.push(topTraceWithMaskMesh);
35059
35146
  const topSilkscreenMesh = createTexturePlane(
@@ -35061,7 +35148,10 @@ function createTextureMeshes(textures, boardData, pcbThickness) {
35061
35148
  pcbThickness / 2 + 0.017,
35062
35149
  // Slightly above trace
35063
35150
  false,
35064
- "silkscreen"
35151
+ "silkscreen",
35152
+ false,
35153
+ 3
35154
+ // Render after traces
35065
35155
  );
35066
35156
  if (topSilkscreenMesh) meshes.push(topSilkscreenMesh);
35067
35157
  const bottomTraceMesh = createTexturePlane(
@@ -35069,21 +35159,30 @@ function createTextureMeshes(textures, boardData, pcbThickness) {
35069
35159
  -pcbThickness / 2 - BOARD_SURFACE_OFFSET.traces,
35070
35160
  // Use consistent copper offset
35071
35161
  true,
35072
- "trace"
35162
+ "trace",
35163
+ false,
35164
+ 2
35165
+ // Render after soldermask
35073
35166
  );
35074
35167
  if (bottomTraceMesh) meshes.push(bottomTraceMesh);
35075
35168
  const bottomTraceWithMaskMesh = createTexturePlane(
35076
35169
  textures.bottomTraceWithMask,
35077
35170
  -pcbThickness / 2 - BOARD_SURFACE_OFFSET.traces,
35078
35171
  true,
35079
- "trace-with-mask"
35172
+ "trace-with-mask",
35173
+ false,
35174
+ 2
35175
+ // Render after soldermask
35080
35176
  );
35081
35177
  if (bottomTraceWithMaskMesh) meshes.push(bottomTraceWithMaskMesh);
35082
35178
  const bottomSilkscreenMesh = createTexturePlane(
35083
35179
  textures.bottomSilkscreen,
35084
35180
  -pcbThickness / 2 - 0.017,
35085
35181
  true,
35086
- "silkscreen"
35182
+ "silkscreen",
35183
+ false,
35184
+ 3
35185
+ // Render after traces
35087
35186
  );
35088
35187
  if (bottomSilkscreenMesh) meshes.push(bottomSilkscreenMesh);
35089
35188
  const topSoldermaskMesh = createTexturePlane(
@@ -35092,8 +35191,10 @@ function createTextureMeshes(textures, boardData, pcbThickness) {
35092
35191
  // Just above board surface, below traces
35093
35192
  false,
35094
35193
  "soldermask",
35095
- true
35194
+ true,
35096
35195
  // Enable polygon offset
35196
+ 1
35197
+ // Render after board (renderOrder)
35097
35198
  );
35098
35199
  if (topSoldermaskMesh) meshes.push(topSoldermaskMesh);
35099
35200
  const bottomSoldermaskMesh = createTexturePlane(
@@ -35102,8 +35203,10 @@ function createTextureMeshes(textures, boardData, pcbThickness) {
35102
35203
  // Just below board surface (bottom side)
35103
35204
  true,
35104
35205
  "soldermask",
35105
- true
35206
+ true,
35106
35207
  // Enable polygon offset
35208
+ 1
35209
+ // Render after board (renderOrder)
35107
35210
  );
35108
35211
  if (bottomSoldermaskMesh) meshes.push(bottomSoldermaskMesh);
35109
35212
  return meshes;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tscircuit/3d-viewer",
3
- "version": "0.0.462",
3
+ "version": "0.0.464",
4
4
  "main": "./dist/index.js",
5
5
  "module": "./dist/index.js",
6
6
  "type": "module",