@tscircuit/3d-viewer 0.0.494 → 0.0.496

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 +397 -2
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -30825,7 +30825,7 @@ import * as THREE16 from "three";
30825
30825
  // package.json
30826
30826
  var package_default = {
30827
30827
  name: "@tscircuit/3d-viewer",
30828
- version: "0.0.493",
30828
+ version: "0.0.495",
30829
30829
  main: "./dist/index.js",
30830
30830
  module: "./dist/index.js",
30831
30831
  type: "module",
@@ -32663,6 +32663,149 @@ var platedHole = (plated_hole, ctx, options = {}) => {
32663
32663
  clipGeom
32664
32664
  );
32665
32665
  return (0, import_colors2.colorize)(colors.copper, finalCopper);
32666
+ } else if (plated_hole.shape === "rotated_pill_hole_with_rect_pad") {
32667
+ if (plated_hole.hole_shape && plated_hole.hole_shape !== "rotated_pill" || plated_hole.pad_shape && plated_hole.pad_shape !== "rect") {
32668
+ throw new Error(
32669
+ `Invalid hole_shape or pad_shape for rotated_pill_hole_with_rect_pad`
32670
+ );
32671
+ }
32672
+ const holeOffsetX = plated_hole.hole_offset_x || 0;
32673
+ const holeOffsetY = plated_hole.hole_offset_y || 0;
32674
+ const holeWidth = plated_hole.hole_width;
32675
+ const holeHeight = plated_hole.hole_height;
32676
+ const isHorizontal = holeWidth >= holeHeight;
32677
+ const longDim = isHorizontal ? holeWidth : holeHeight;
32678
+ const shortDim = isHorizontal ? holeHeight : holeWidth;
32679
+ const holeRadius = shortDim / 2;
32680
+ const rectLength = Math.abs(longDim - shortDim);
32681
+ const padWidth = plated_hole.rect_pad_width || holeWidth + 0.2;
32682
+ const padHeight = plated_hole.rect_pad_height || holeHeight + 0.2;
32683
+ const rectBorderRadius = extractRectBorderRadius(plated_hole);
32684
+ const barrelMargin = 0.03;
32685
+ const holeRotationRadians = (plated_hole.hole_ccw_rotation || 0) * Math.PI / 180;
32686
+ const rectRotationRadians = (plated_hole.rect_ccw_rotation || 0) * Math.PI / 180;
32687
+ const rotateHole = (geom) => {
32688
+ const rotatedOffsetX = holeOffsetX * Math.cos(holeRotationRadians) - holeOffsetY * Math.sin(holeRotationRadians);
32689
+ const rotatedOffsetY = holeOffsetX * Math.sin(holeRotationRadians) + holeOffsetY * Math.cos(holeRotationRadians);
32690
+ const rotated = (0, import_transforms4.rotate)([0, 0, holeRotationRadians], geom);
32691
+ return (0, import_transforms4.translate)(
32692
+ [plated_hole.x + rotatedOffsetX, plated_hole.y + rotatedOffsetY, 0],
32693
+ rotated
32694
+ );
32695
+ };
32696
+ const rotateRectPad = (geom) => {
32697
+ if (!rectRotationRadians) return geom;
32698
+ const toOrigin = (0, import_transforms4.translate)([-plated_hole.x, -plated_hole.y, 0], geom);
32699
+ const rotated = (0, import_transforms4.rotate)([0, 0, rectRotationRadians], toOrigin);
32700
+ return (0, import_transforms4.translate)([plated_hole.x, plated_hole.y, 0], rotated);
32701
+ };
32702
+ const barrel = rotateHole(
32703
+ (0, import_booleans2.union)(
32704
+ (0, import_primitives4.cuboid)({
32705
+ center: [0, 0, 0],
32706
+ size: isHorizontal ? [
32707
+ rectLength + 2 * barrelMargin,
32708
+ shortDim + 2 * barrelMargin,
32709
+ copperSpan
32710
+ ] : [
32711
+ shortDim + 2 * barrelMargin,
32712
+ rectLength + 2 * barrelMargin,
32713
+ copperSpan
32714
+ ]
32715
+ }),
32716
+ (0, import_primitives4.cylinder)({
32717
+ center: isHorizontal ? [-rectLength / 2, 0, 0] : [0, -rectLength / 2, 0],
32718
+ radius: holeRadius + barrelMargin,
32719
+ height: copperSpan
32720
+ }),
32721
+ (0, import_primitives4.cylinder)({
32722
+ center: isHorizontal ? [rectLength / 2, 0, 0] : [0, rectLength / 2, 0],
32723
+ radius: holeRadius + barrelMargin,
32724
+ height: copperSpan
32725
+ })
32726
+ )
32727
+ );
32728
+ const holeCut = rotateHole(
32729
+ (0, import_booleans2.union)(
32730
+ (0, import_primitives4.cuboid)({
32731
+ center: [0, 0, 0],
32732
+ size: isHorizontal ? [rectLength, shortDim, throughDrillHeight * 1.1] : [shortDim, rectLength, throughDrillHeight * 1.1]
32733
+ }),
32734
+ (0, import_primitives4.cylinder)({
32735
+ center: isHorizontal ? [-rectLength / 2, 0, 0] : [0, -rectLength / 2, 0],
32736
+ radius: holeRadius,
32737
+ height: throughDrillHeight * 1.1
32738
+ }),
32739
+ (0, import_primitives4.cylinder)({
32740
+ center: isHorizontal ? [rectLength / 2, 0, 0] : [0, rectLength / 2, 0],
32741
+ radius: holeRadius,
32742
+ height: throughDrillHeight * 1.1
32743
+ })
32744
+ )
32745
+ );
32746
+ const copperTopPad = rotateRectPad(
32747
+ createRectPadGeom({
32748
+ width: padWidth,
32749
+ height: padHeight,
32750
+ thickness: platedHoleLipHeight,
32751
+ center: [plated_hole.x, plated_hole.y, topSurfaceZ],
32752
+ borderRadius: rectBorderRadius
32753
+ })
32754
+ );
32755
+ const copperBottomPad = rotateRectPad(
32756
+ createRectPadGeom({
32757
+ width: padWidth,
32758
+ height: padHeight,
32759
+ thickness: platedHoleLipHeight,
32760
+ center: [plated_hole.x, plated_hole.y, bottomSurfaceZ],
32761
+ borderRadius: rectBorderRadius
32762
+ })
32763
+ );
32764
+ const copperFill = rotateRectPad(
32765
+ (() => {
32766
+ const height10 = Math.max(copperSpan - platedHoleLipHeight * 2, M);
32767
+ const topPadBottom = topSurfaceZ;
32768
+ const bottomPadTop = bottomSurfaceZ;
32769
+ const centerZ = (topPadBottom + bottomPadTop) / 2;
32770
+ const rect2d = (0, import_primitives4.roundedRectangle)({
32771
+ size: [padWidth, padHeight],
32772
+ roundRadius: rectBorderRadius || 0,
32773
+ segments: RECT_PAD_SEGMENTS
32774
+ });
32775
+ const extruded = (0, import_extrusions3.extrudeLinear)({ height: height10 }, rect2d);
32776
+ return (0, import_transforms4.translate)(
32777
+ [plated_hole.x, plated_hole.y, centerZ - height10 / 2],
32778
+ extruded
32779
+ );
32780
+ })()
32781
+ );
32782
+ const copperTopPadCut = (0, import_booleans2.subtract)(copperTopPad, holeCut);
32783
+ const copperBottomPadCut = (0, import_booleans2.subtract)(copperBottomPad, holeCut);
32784
+ const copperFillCut = (0, import_booleans2.subtract)(copperFill, holeCut);
32785
+ const barrelHoleCut = rotateHole(
32786
+ (0, import_booleans2.union)(
32787
+ (0, import_primitives4.cuboid)({
32788
+ center: [0, 0, 0],
32789
+ size: isHorizontal ? [rectLength - 2 * M, shortDim - 2 * M, throughDrillHeight * 1.1] : [shortDim - 2 * M, rectLength - 2 * M, throughDrillHeight * 1.1]
32790
+ }),
32791
+ (0, import_primitives4.cylinder)({
32792
+ center: isHorizontal ? [-rectLength / 2, 0, 0] : [0, -rectLength / 2, 0],
32793
+ radius: holeRadius - M,
32794
+ height: throughDrillHeight * 1.1
32795
+ }),
32796
+ (0, import_primitives4.cylinder)({
32797
+ center: isHorizontal ? [rectLength / 2, 0, 0] : [0, rectLength / 2, 0],
32798
+ radius: holeRadius - M,
32799
+ height: throughDrillHeight * 1.1
32800
+ })
32801
+ )
32802
+ );
32803
+ const barrelWithHole = (0, import_booleans2.subtract)(barrel, barrelHoleCut);
32804
+ const finalCopper = maybeClip(
32805
+ (0, import_booleans2.union)(copperTopPadCut, copperBottomPadCut, copperFillCut, barrelWithHole),
32806
+ clipGeom
32807
+ );
32808
+ return (0, import_colors2.colorize)(colors.copper, finalCopper);
32666
32809
  } else if (plated_hole.shape === "hole_with_polygon_pad") {
32667
32810
  const padOutline = plated_hole.pad_outline;
32668
32811
  if (!Array.isArray(padOutline) || padOutline.length < 3) {
@@ -33313,6 +33456,53 @@ var BoardGeomBuilder = class {
33313
33456
  clipGeom: this.boardClipGeom
33314
33457
  });
33315
33458
  this.platedHoleGeoms.push(platedHoleGeom);
33459
+ } else if (ph.shape === "rotated_pill_hole_with_rect_pad") {
33460
+ if (ph.hole_shape && ph.hole_shape !== "rotated_pill" || ph.pad_shape && ph.pad_shape !== "rect") {
33461
+ return;
33462
+ }
33463
+ const rphHoleWidth = ph.hole_width;
33464
+ const rphHoleHeight = ph.hole_height;
33465
+ const rphIsHorizontal = rphHoleWidth >= rphHoleHeight;
33466
+ const rphLongDim = rphIsHorizontal ? rphHoleWidth : rphHoleHeight;
33467
+ const rphShortDim = rphIsHorizontal ? rphHoleHeight : rphHoleWidth;
33468
+ const rphHoleRadius = rphShortDim / 2;
33469
+ const rphRectLength = Math.abs(rphLongDim - rphShortDim);
33470
+ const rphHoleOffsetX = ph.hole_offset_x || 0;
33471
+ const rphHoleOffsetY = ph.hole_offset_y || 0;
33472
+ let rphPillHole = (0, import_booleans5.union)(
33473
+ (0, import_primitives7.cuboid)({
33474
+ center: [0, 0, 0],
33475
+ size: rphIsHorizontal ? [rphRectLength, rphShortDim, this.ctx.pcbThickness * 1.5] : [rphShortDim, rphRectLength, this.ctx.pcbThickness * 1.5]
33476
+ }),
33477
+ (0, import_primitives7.cylinder)({
33478
+ center: rphIsHorizontal ? [-rphRectLength / 2, 0, 0] : [0, -rphRectLength / 2, 0],
33479
+ radius: rphHoleRadius,
33480
+ height: this.ctx.pcbThickness * 1.5
33481
+ }),
33482
+ (0, import_primitives7.cylinder)({
33483
+ center: rphIsHorizontal ? [rphRectLength / 2, 0, 0] : [0, rphRectLength / 2, 0],
33484
+ radius: rphHoleRadius,
33485
+ height: this.ctx.pcbThickness * 1.5
33486
+ })
33487
+ );
33488
+ const rphHoleRotationRadians = (ph.hole_ccw_rotation || 0) * Math.PI / 180;
33489
+ const rphRotatedOffsetX = rphHoleOffsetX * Math.cos(rphHoleRotationRadians) - rphHoleOffsetY * Math.sin(rphHoleRotationRadians);
33490
+ const rphRotatedOffsetY = rphHoleOffsetX * Math.sin(rphHoleRotationRadians) + rphHoleOffsetY * Math.cos(rphHoleRotationRadians);
33491
+ rphPillHole = (0, import_transforms6.rotateZ)(rphHoleRotationRadians, rphPillHole);
33492
+ const pillHole = (0, import_transforms6.translate)(
33493
+ [ph.x + rphRotatedOffsetX, ph.y + rphRotatedOffsetY, 0],
33494
+ rphPillHole
33495
+ );
33496
+ if (!opts.dontCutBoard) {
33497
+ this.boardGeom = (0, import_booleans5.subtract)(this.boardGeom, pillHole);
33498
+ }
33499
+ this.padGeoms = this.padGeoms.map(
33500
+ (pg) => (0, import_colors3.colorize)(colors.copper, (0, import_booleans5.subtract)(pg, pillHole))
33501
+ );
33502
+ const platedHoleGeom = platedHole(ph, this.ctx, {
33503
+ clipGeom: this.boardClipGeom
33504
+ });
33505
+ this.platedHoleGeoms.push(platedHoleGeom);
33316
33506
  } else if (ph.shape === "hole_with_polygon_pad") {
33317
33507
  const padOutline = ph.pad_outline;
33318
33508
  if (!Array.isArray(padOutline) || padOutline.length < 3) {
@@ -33869,8 +34059,8 @@ import * as THREE24 from "three";
33869
34059
  import { su as su9 } from "@tscircuit/circuit-json-util";
33870
34060
 
33871
34061
  // src/utils/soldermask-texture.ts
33872
- import * as THREE19 from "three";
33873
34062
  import { su as su5 } from "@tscircuit/circuit-json-util";
34063
+ import * as THREE19 from "three";
33874
34064
 
33875
34065
  // node_modules/@tscircuit/math-utils/dist/chunk-5N7UJNVK.js
33876
34066
  var getBoundsFromPoints = (points) => {
@@ -34191,6 +34381,22 @@ function createSoldermaskTextureForLayer({
34191
34381
  ctx.arc(adjustedCanvasX, adjustedCanvasY, canvasRadius, 0, 2 * Math.PI);
34192
34382
  ctx.fill();
34193
34383
  }
34384
+ if (hole.pad_outline && hole.pad_outline.length >= 3) {
34385
+ ctx.beginPath();
34386
+ hole.pad_outline.forEach(
34387
+ (point2, index2) => {
34388
+ const px = canvasXFromPcb(hole.x + point2.x);
34389
+ const py = canvasYFromPcb(hole.y + point2.y);
34390
+ if (index2 === 0) {
34391
+ ctx.moveTo(px, py);
34392
+ } else {
34393
+ ctx.lineTo(px, py);
34394
+ }
34395
+ }
34396
+ );
34397
+ ctx.closePath();
34398
+ ctx.fill();
34399
+ }
34194
34400
  } else if (hole.shape === "circular_hole_with_rect_pad") {
34195
34401
  const padWidth = (hole.rect_pad_width ?? hole.hole_diameter ?? 0) * traceTextureResolution;
34196
34402
  const padHeight = (hole.rect_pad_height ?? hole.hole_diameter ?? 0) * traceTextureResolution;
@@ -34254,6 +34460,42 @@ function createSoldermaskTextureForLayer({
34254
34460
  );
34255
34461
  ctx.fill();
34256
34462
  }
34463
+ } else if (hole.shape === "rotated_pill_hole_with_rect_pad") {
34464
+ const padWidth = (hole.rect_pad_width ?? hole.hole_width ?? 0) * traceTextureResolution;
34465
+ const padHeight = (hole.rect_pad_height ?? hole.hole_height ?? 0) * traceTextureResolution;
34466
+ const rawRadius = extractRectBorderRadius(hole);
34467
+ const borderRadius = clampRectBorderRadius(
34468
+ hole.rect_pad_width ?? hole.hole_width ?? 0,
34469
+ hole.rect_pad_height ?? hole.hole_height ?? 0,
34470
+ rawRadius
34471
+ ) * traceTextureResolution;
34472
+ const rectCcwRotationDeg = hole.rect_ccw_rotation || 0;
34473
+ const rectRotation = -rectCcwRotationDeg;
34474
+ if (rectRotation) {
34475
+ ctx.save();
34476
+ ctx.translate(canvasX, canvasY);
34477
+ ctx.rotate(rectRotation * Math.PI / 180);
34478
+ ctx.beginPath();
34479
+ ctx.roundRect(
34480
+ -padWidth / 2,
34481
+ -padHeight / 2,
34482
+ padWidth,
34483
+ padHeight,
34484
+ borderRadius
34485
+ );
34486
+ ctx.fill();
34487
+ ctx.restore();
34488
+ } else {
34489
+ ctx.beginPath();
34490
+ ctx.roundRect(
34491
+ canvasX - padWidth / 2,
34492
+ canvasY - padHeight / 2,
34493
+ padWidth,
34494
+ padHeight,
34495
+ borderRadius
34496
+ );
34497
+ ctx.fill();
34498
+ }
34257
34499
  }
34258
34500
  });
34259
34501
  const pcbHoles = su5(circuitJson).pcb_hole.list();
@@ -35200,6 +35442,31 @@ function createTraceTextureForLayer({
35200
35442
  ctx.beginPath();
35201
35443
  ctx.arc(canvasX, canvasY, canvasRadius, 0, 2 * Math.PI, false);
35202
35444
  ctx.fill();
35445
+ } else if (ph.layers.includes(layer) && ph.shape === "rotated_pill_hole_with_rect_pad") {
35446
+ const canvasX = (ph.x - boardOutlineBounds.minX) * traceTextureResolution;
35447
+ const canvasY = (boardOutlineBounds.maxY - ph.y) * traceTextureResolution;
35448
+ const padWidth = (ph.rect_pad_width ?? ph.hole_width ?? 0) * traceTextureResolution;
35449
+ const padHeight = (ph.rect_pad_height ?? ph.hole_height ?? 0) * traceTextureResolution;
35450
+ const rectCcwRotationDeg = ph.rect_ccw_rotation || 0;
35451
+ const rectRotation = -rectCcwRotationDeg;
35452
+ if (rectRotation) {
35453
+ ctx.save();
35454
+ ctx.translate(canvasX, canvasY);
35455
+ ctx.rotate(rectRotation * Math.PI / 180);
35456
+ ctx.beginPath();
35457
+ ctx.rect(-padWidth / 2, -padHeight / 2, padWidth, padHeight);
35458
+ ctx.fill();
35459
+ ctx.restore();
35460
+ } else {
35461
+ ctx.beginPath();
35462
+ ctx.rect(
35463
+ canvasX - padWidth / 2,
35464
+ canvasY - padHeight / 2,
35465
+ padWidth,
35466
+ padHeight
35467
+ );
35468
+ ctx.fill();
35469
+ }
35203
35470
  }
35204
35471
  });
35205
35472
  ctx.globalCompositeOperation = "source-over";
@@ -36759,6 +37026,134 @@ function processPlatedHolesForManifold(Manifold, CrossSection, circuitJson, pcbT
36759
37026
  geometry: threeGeom,
36760
37027
  color: COPPER_COLOR
36761
37028
  });
37029
+ } else if (ph.shape === "rotated_pill_hole_with_rect_pad") {
37030
+ if (ph.hole_shape && ph.hole_shape !== "rotated_pill" || ph.pad_shape && ph.pad_shape !== "rect") {
37031
+ return;
37032
+ }
37033
+ const holeW = ph.hole_width;
37034
+ const holeH = ph.hole_height;
37035
+ const holeOffsetX = ph.hole_offset_x || 0;
37036
+ const holeOffsetY = ph.hole_offset_y || 0;
37037
+ const padWidth = ph.rect_pad_width;
37038
+ const padHeight = ph.rect_pad_height;
37039
+ const rectBorderRadius = extractRectBorderRadius(ph);
37040
+ const padThickness = DEFAULT_SMT_PAD_THICKNESS;
37041
+ const drillW = holeW + 2 * MANIFOLD_Z_OFFSET;
37042
+ const drillH = holeH + 2 * MANIFOLD_Z_OFFSET;
37043
+ const drillDepth = pcbThickness * 1.2;
37044
+ let boardPillDrillOp = createPillOp(drillW, drillH, drillDepth).translate(
37045
+ [holeOffsetX, holeOffsetY, 0]
37046
+ );
37047
+ if (ph.hole_ccw_rotation) {
37048
+ const rotatedDrill = boardPillDrillOp.rotate([
37049
+ 0,
37050
+ 0,
37051
+ ph.hole_ccw_rotation
37052
+ ]);
37053
+ manifoldInstancesForCleanup.push(rotatedDrill);
37054
+ boardPillDrillOp = rotatedDrill;
37055
+ }
37056
+ const translatedBoardPillDrill = boardPillDrillOp.translate([
37057
+ ph.x,
37058
+ ph.y,
37059
+ 0
37060
+ ]);
37061
+ manifoldInstancesForCleanup.push(translatedBoardPillDrill);
37062
+ platedHoleBoardDrills.push(translatedBoardPillDrill);
37063
+ let mainFill = createRoundedRectPrism({
37064
+ Manifold,
37065
+ width: padWidth,
37066
+ height: padHeight,
37067
+ thickness: pcbThickness - 2 * padThickness - 2 * BOARD_SURFACE_OFFSET.copper + 0.1,
37068
+ // Fill between pads
37069
+ borderRadius: rectBorderRadius
37070
+ });
37071
+ manifoldInstancesForCleanup.push(mainFill);
37072
+ if (ph.rect_ccw_rotation) {
37073
+ const rotatedMainFill = mainFill.rotate([0, 0, ph.rect_ccw_rotation]);
37074
+ manifoldInstancesForCleanup.push(rotatedMainFill);
37075
+ mainFill = rotatedMainFill;
37076
+ }
37077
+ let topPad = createRoundedRectPrism({
37078
+ Manifold,
37079
+ width: padWidth,
37080
+ height: padHeight,
37081
+ thickness: padThickness,
37082
+ borderRadius: rectBorderRadius
37083
+ }).translate([0, 0, pcbThickness / 2 / 2 + BOARD_SURFACE_OFFSET.copper]);
37084
+ if (ph.rect_ccw_rotation) {
37085
+ const rotatedTopPad = topPad.rotate([0, 0, ph.rect_ccw_rotation]);
37086
+ manifoldInstancesForCleanup.push(rotatedTopPad);
37087
+ topPad = rotatedTopPad;
37088
+ }
37089
+ let bottomPad = createRoundedRectPrism({
37090
+ Manifold,
37091
+ width: padWidth,
37092
+ height: padHeight,
37093
+ thickness: padThickness,
37094
+ borderRadius: rectBorderRadius
37095
+ }).translate([0, 0, -pcbThickness / 2 / 2 - BOARD_SURFACE_OFFSET.copper]);
37096
+ if (ph.rect_ccw_rotation) {
37097
+ const rotatedBottomPad = bottomPad.rotate([0, 0, ph.rect_ccw_rotation]);
37098
+ manifoldInstancesForCleanup.push(rotatedBottomPad);
37099
+ bottomPad = rotatedBottomPad;
37100
+ }
37101
+ manifoldInstancesForCleanup.push(topPad, bottomPad);
37102
+ const barrelPill = createPillOp(
37103
+ holeW,
37104
+ holeH,
37105
+ pcbThickness * 1.02
37106
+ // Slightly taller than board
37107
+ ).translate([holeOffsetX, holeOffsetY, 0]);
37108
+ if (ph.hole_ccw_rotation) {
37109
+ const rotatedDrill = boardPillDrillOp.rotate([
37110
+ 0,
37111
+ 0,
37112
+ ph.hole_ccw_rotation
37113
+ ]);
37114
+ manifoldInstancesForCleanup.push(rotatedDrill);
37115
+ boardPillDrillOp = rotatedDrill;
37116
+ }
37117
+ manifoldInstancesForCleanup.push(barrelPill);
37118
+ const copperUnion = Manifold.union([
37119
+ mainFill,
37120
+ topPad,
37121
+ bottomPad,
37122
+ barrelPill
37123
+ ]);
37124
+ manifoldInstancesForCleanup.push(copperUnion);
37125
+ let holeCutOp = createPillOp(
37126
+ Math.max(holeW - 2 * PLATED_HOLE_LIP_HEIGHT, 0.01),
37127
+ Math.max(holeH - 2 * PLATED_HOLE_LIP_HEIGHT, 0.01),
37128
+ pcbThickness * 1.2
37129
+ // Ensure it cuts through
37130
+ ).translate([holeOffsetX, holeOffsetY, 0]);
37131
+ if (ph.hole_ccw_rotation) {
37132
+ const rotatedHoleCut = holeCutOp.rotate([0, 0, ph.hole_ccw_rotation]);
37133
+ manifoldInstancesForCleanup.push(rotatedHoleCut);
37134
+ holeCutOp = rotatedHoleCut;
37135
+ }
37136
+ manifoldInstancesForCleanup.push(holeCutOp);
37137
+ const finalCopper = copperUnion.subtract(holeCutOp);
37138
+ manifoldInstancesForCleanup.push(finalCopper);
37139
+ const translatedCopper = finalCopper.translate([ph.x, ph.y, 0]);
37140
+ manifoldInstancesForCleanup.push(translatedCopper);
37141
+ let finalCopperOp = translatedCopper;
37142
+ if (boardClipVolume) {
37143
+ const clipped = Manifold.intersection([
37144
+ translatedCopper,
37145
+ boardClipVolume
37146
+ ]);
37147
+ manifoldInstancesForCleanup.push(clipped);
37148
+ finalCopperOp = clipped;
37149
+ }
37150
+ platedHoleCopperOpsForSubtract.push(finalCopperOp);
37151
+ const threeGeom = manifoldMeshToThreeGeometry(finalCopperOp.getMesh());
37152
+ platedHoleCopperGeoms.push({
37153
+ key: `ph-${ph.pcb_plated_hole_id || index2}`,
37154
+ geometry: threeGeom,
37155
+ color: COPPER_COLOR
37156
+ });
36762
37157
  } else if (ph.shape === "hole_with_polygon_pad") {
36763
37158
  const padOutline = ph.pad_outline;
36764
37159
  if (!Array.isArray(padOutline) || padOutline.length < 3) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tscircuit/3d-viewer",
3
- "version": "0.0.494",
3
+ "version": "0.0.496",
4
4
  "main": "./dist/index.js",
5
5
  "module": "./dist/index.js",
6
6
  "type": "module",