@tscircuit/3d-viewer 0.0.411 → 0.0.413
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.
- package/dist/index.js +509 -186
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -16636,8 +16636,8 @@ var pcb_fabrication_note_dimension = z93.object({
|
|
|
16636
16636
|
pcb_group_id: z93.string().optional(),
|
|
16637
16637
|
subcircuit_id: z93.string().optional(),
|
|
16638
16638
|
layer: visible_layer,
|
|
16639
|
-
from: point
|
|
16640
|
-
to: point
|
|
16639
|
+
from: point,
|
|
16640
|
+
to: point,
|
|
16641
16641
|
text: z93.string().optional(),
|
|
16642
16642
|
offset: length.optional(),
|
|
16643
16643
|
font: z93.literal("tscircuit2024").default("tscircuit2024"),
|
|
@@ -26576,7 +26576,7 @@ import * as THREE13 from "three";
|
|
|
26576
26576
|
// package.json
|
|
26577
26577
|
var package_default = {
|
|
26578
26578
|
name: "@tscircuit/3d-viewer",
|
|
26579
|
-
version: "0.0.
|
|
26579
|
+
version: "0.0.412",
|
|
26580
26580
|
main: "./dist/index.js",
|
|
26581
26581
|
module: "./dist/index.js",
|
|
26582
26582
|
type: "module",
|
|
@@ -26623,8 +26623,8 @@ var package_default = {
|
|
|
26623
26623
|
"@storybook/blocks": "9.0.0-alpha.17",
|
|
26624
26624
|
"@storybook/react-vite": "^9.1.5",
|
|
26625
26625
|
"@tscircuit/circuit-json-util": "^0.0.72",
|
|
26626
|
-
"@tscircuit/core": "^0.0.
|
|
26627
|
-
"@tscircuit/props": "^0.0.
|
|
26626
|
+
"@tscircuit/core": "^0.0.787",
|
|
26627
|
+
"@tscircuit/props": "^0.0.364",
|
|
26628
26628
|
"@tscircuit/checks": "^0.0.85",
|
|
26629
26629
|
"@tscircuit/math-utils": "^0.0.27",
|
|
26630
26630
|
"@tscircuit/capacity-autorouter": "^0.0.131",
|
|
@@ -26636,7 +26636,7 @@ var package_default = {
|
|
|
26636
26636
|
"@vitejs/plugin-react": "^4.3.4",
|
|
26637
26637
|
"bun-match-svg": "^0.0.9",
|
|
26638
26638
|
"bun-types": "1.2.1",
|
|
26639
|
-
"circuit-json": "0.0.
|
|
26639
|
+
"circuit-json": "0.0.279",
|
|
26640
26640
|
"circuit-to-svg": "^0.0.179",
|
|
26641
26641
|
debug: "^4.4.0",
|
|
26642
26642
|
"jscad-electronics": "^0.0.48",
|
|
@@ -27519,38 +27519,67 @@ var platedHole = (plated_hole, ctx, options = {}) => {
|
|
|
27519
27519
|
return (0, import_colors2.colorize)(colors.copper, (0, import_booleans.subtract)(copperSolid, drill));
|
|
27520
27520
|
}
|
|
27521
27521
|
if (plated_hole.shape === "circular_hole_with_rect_pad") {
|
|
27522
|
+
const holeOffsetX = plated_hole.hole_offset_x || 0;
|
|
27523
|
+
const holeOffsetY = plated_hole.hole_offset_y || 0;
|
|
27522
27524
|
const padWidth = plated_hole.rect_pad_width || plated_hole.hole_diameter;
|
|
27523
27525
|
const padHeight = plated_hole.rect_pad_height || plated_hole.hole_diameter;
|
|
27524
27526
|
const rectBorderRadius = extractRectBorderRadius(plated_hole);
|
|
27525
27527
|
const copperSolid = maybeClip(
|
|
27526
27528
|
(0, import_booleans.union)(
|
|
27527
|
-
// Top rectangular pad
|
|
27529
|
+
// Top rectangular pad (thicker to ensure connection)
|
|
27528
27530
|
createRectPadGeom({
|
|
27529
27531
|
width: padWidth,
|
|
27530
27532
|
height: padHeight,
|
|
27531
|
-
thickness: platedHoleLipHeight,
|
|
27533
|
+
thickness: platedHoleLipHeight + 0.1,
|
|
27534
|
+
// Slightly thicker to ensure connection
|
|
27532
27535
|
center: [
|
|
27533
27536
|
plated_hole.x,
|
|
27534
27537
|
plated_hole.y,
|
|
27535
|
-
ctx.pcbThickness / 2 + platedHoleLipHeight / 2 + M
|
|
27538
|
+
ctx.pcbThickness / 2 + platedHoleLipHeight / 2 + M - 0.05
|
|
27539
|
+
// Adjusted for thickness
|
|
27536
27540
|
],
|
|
27537
27541
|
borderRadius: rectBorderRadius
|
|
27538
27542
|
}),
|
|
27539
|
-
// Bottom rectangular pad
|
|
27543
|
+
// Bottom rectangular pad (thicker to ensure connection)
|
|
27540
27544
|
createRectPadGeom({
|
|
27541
27545
|
width: padWidth,
|
|
27542
27546
|
height: padHeight,
|
|
27543
|
-
thickness: platedHoleLipHeight,
|
|
27547
|
+
thickness: platedHoleLipHeight + 0.1,
|
|
27548
|
+
// Slightly thicker to ensure connection
|
|
27544
27549
|
center: [
|
|
27545
27550
|
plated_hole.x,
|
|
27546
27551
|
plated_hole.y,
|
|
27547
|
-
-ctx.pcbThickness / 2 - platedHoleLipHeight / 2 - M
|
|
27552
|
+
-ctx.pcbThickness / 2 - platedHoleLipHeight / 2 - M + 0.05
|
|
27553
|
+
// Adjusted for thickness
|
|
27548
27554
|
],
|
|
27549
27555
|
borderRadius: rectBorderRadius
|
|
27550
27556
|
}),
|
|
27551
|
-
//
|
|
27557
|
+
// Main copper fill between pads with rounded corners
|
|
27558
|
+
(() => {
|
|
27559
|
+
const height10 = ctx.pcbThickness - platedHoleLipHeight * 2 - M * 2 + 0.1;
|
|
27560
|
+
const rect2d = (0, import_primitives3.roundedRectangle)({
|
|
27561
|
+
size: [padWidth, padHeight],
|
|
27562
|
+
roundRadius: rectBorderRadius || 0,
|
|
27563
|
+
segments: RECT_PAD_SEGMENTS
|
|
27564
|
+
});
|
|
27565
|
+
const extruded = (0, import_extrusions2.extrudeLinear)({ height: height10 }, rect2d);
|
|
27566
|
+
return (0, import_transforms2.translate)(
|
|
27567
|
+
[
|
|
27568
|
+
plated_hole.x,
|
|
27569
|
+
plated_hole.y,
|
|
27570
|
+
-height10 / 2
|
|
27571
|
+
// Center vertically
|
|
27572
|
+
],
|
|
27573
|
+
extruded
|
|
27574
|
+
);
|
|
27575
|
+
})(),
|
|
27576
|
+
// Plated barrel around hole (ensured connection with pads)
|
|
27552
27577
|
(0, import_primitives3.cylinder)({
|
|
27553
|
-
center: [
|
|
27578
|
+
center: [
|
|
27579
|
+
plated_hole.x + (holeOffsetX || 0),
|
|
27580
|
+
plated_hole.y + (holeOffsetY || 0),
|
|
27581
|
+
0
|
|
27582
|
+
],
|
|
27554
27583
|
radius: plated_hole.hole_diameter / 2,
|
|
27555
27584
|
height: ctx.pcbThickness
|
|
27556
27585
|
})
|
|
@@ -27558,11 +27587,35 @@ var platedHole = (plated_hole, ctx, options = {}) => {
|
|
|
27558
27587
|
clipGeom
|
|
27559
27588
|
);
|
|
27560
27589
|
const drill = (0, import_primitives3.cylinder)({
|
|
27561
|
-
center: [
|
|
27590
|
+
center: [
|
|
27591
|
+
plated_hole.x + (holeOffsetX || 0),
|
|
27592
|
+
plated_hole.y + (holeOffsetY || 0),
|
|
27593
|
+
0
|
|
27594
|
+
],
|
|
27562
27595
|
radius: Math.max(plated_hole.hole_diameter / 2 - M, 0.01),
|
|
27563
27596
|
height: throughDrillHeight
|
|
27564
27597
|
});
|
|
27565
|
-
|
|
27598
|
+
const barrel = (0, import_primitives3.cylinder)({
|
|
27599
|
+
center: [
|
|
27600
|
+
plated_hole.x + (holeOffsetX || 0),
|
|
27601
|
+
plated_hole.y + (holeOffsetY || 0),
|
|
27602
|
+
0
|
|
27603
|
+
],
|
|
27604
|
+
radius: plated_hole.hole_diameter / 2,
|
|
27605
|
+
height: ctx.pcbThickness
|
|
27606
|
+
});
|
|
27607
|
+
let finalCopper = (0, import_booleans.union)(
|
|
27608
|
+
(0, import_booleans.subtract)(copperSolid, barrel),
|
|
27609
|
+
// Subtract the barrel from the main shape
|
|
27610
|
+
barrel
|
|
27611
|
+
// Add the barrel back to ensure proper connection
|
|
27612
|
+
);
|
|
27613
|
+
if (options.clipGeom) {
|
|
27614
|
+
finalCopper = (0, import_booleans.subtract)(finalCopper, drill);
|
|
27615
|
+
finalCopper = (0, import_booleans.intersect)(finalCopper, options.clipGeom);
|
|
27616
|
+
return (0, import_colors2.colorize)(colors.copper, finalCopper);
|
|
27617
|
+
}
|
|
27618
|
+
return (0, import_colors2.colorize)(colors.copper, (0, import_booleans.subtract)(finalCopper, drill));
|
|
27566
27619
|
}
|
|
27567
27620
|
if (plated_hole.shape === "pill") {
|
|
27568
27621
|
const shouldRotate = plated_hole.hole_height > plated_hole.hole_width;
|
|
@@ -27626,6 +27679,8 @@ var platedHole = (plated_hole, ctx, options = {}) => {
|
|
|
27626
27679
|
return (0, import_colors2.colorize)(colors.copper, (0, import_booleans.subtract)(copperSolid, drill));
|
|
27627
27680
|
}
|
|
27628
27681
|
if (plated_hole.shape === "pill_hole_with_rect_pad") {
|
|
27682
|
+
const holeOffsetX = plated_hole.hole_offset_x || 0;
|
|
27683
|
+
const holeOffsetY = plated_hole.hole_offset_y || 0;
|
|
27629
27684
|
const shouldRotate = plated_hole.hole_height > plated_hole.hole_width;
|
|
27630
27685
|
const holeWidth = shouldRotate ? plated_hole.hole_height : plated_hole.hole_width;
|
|
27631
27686
|
const holeHeight = shouldRotate ? plated_hole.hole_width : plated_hole.hole_height;
|
|
@@ -27634,64 +27689,140 @@ var platedHole = (plated_hole, ctx, options = {}) => {
|
|
|
27634
27689
|
const padWidth = plated_hole.rect_pad_width || holeWidth + 0.2;
|
|
27635
27690
|
const padHeight = plated_hole.rect_pad_height || holeHeight + 0.2;
|
|
27636
27691
|
const rectBorderRadius = extractRectBorderRadius(plated_hole);
|
|
27637
|
-
const
|
|
27638
|
-
|
|
27639
|
-
|
|
27640
|
-
|
|
27641
|
-
|
|
27642
|
-
|
|
27643
|
-
|
|
27644
|
-
|
|
27645
|
-
|
|
27646
|
-
|
|
27647
|
-
|
|
27648
|
-
|
|
27649
|
-
|
|
27650
|
-
|
|
27651
|
-
|
|
27652
|
-
|
|
27653
|
-
|
|
27654
|
-
|
|
27655
|
-
|
|
27656
|
-
|
|
27657
|
-
|
|
27658
|
-
|
|
27659
|
-
|
|
27660
|
-
|
|
27661
|
-
|
|
27662
|
-
|
|
27692
|
+
const barrelMargin = 0.03;
|
|
27693
|
+
const barrel = (0, import_booleans.union)(
|
|
27694
|
+
(0, import_primitives3.cuboid)({
|
|
27695
|
+
center: [plated_hole.x + holeOffsetX, plated_hole.y + holeOffsetY, 0],
|
|
27696
|
+
size: shouldRotate ? [
|
|
27697
|
+
holeHeight + 2 * barrelMargin,
|
|
27698
|
+
rectLength + 2 * barrelMargin,
|
|
27699
|
+
ctx.pcbThickness + 0.2
|
|
27700
|
+
] : [
|
|
27701
|
+
rectLength + 2 * barrelMargin,
|
|
27702
|
+
holeHeight + 2 * barrelMargin,
|
|
27703
|
+
ctx.pcbThickness + 0.2
|
|
27704
|
+
]
|
|
27705
|
+
}),
|
|
27706
|
+
(0, import_primitives3.cylinder)({
|
|
27707
|
+
center: shouldRotate ? [
|
|
27708
|
+
plated_hole.x + holeOffsetX,
|
|
27709
|
+
plated_hole.y + holeOffsetY - rectLength / 2,
|
|
27710
|
+
0
|
|
27711
|
+
] : [
|
|
27712
|
+
plated_hole.x + holeOffsetX - rectLength / 2,
|
|
27713
|
+
plated_hole.y + holeOffsetY,
|
|
27714
|
+
0
|
|
27715
|
+
],
|
|
27716
|
+
radius: holeRadius + barrelMargin,
|
|
27717
|
+
height: ctx.pcbThickness + 0.2
|
|
27718
|
+
// extend slightly above/below PCB
|
|
27719
|
+
}),
|
|
27720
|
+
(0, import_primitives3.cylinder)({
|
|
27721
|
+
center: shouldRotate ? [
|
|
27722
|
+
plated_hole.x + holeOffsetX,
|
|
27723
|
+
plated_hole.y + holeOffsetY + rectLength / 2,
|
|
27724
|
+
0
|
|
27725
|
+
] : [
|
|
27726
|
+
plated_hole.x + holeOffsetX + rectLength / 2,
|
|
27727
|
+
plated_hole.y + holeOffsetY,
|
|
27728
|
+
0
|
|
27729
|
+
],
|
|
27730
|
+
radius: holeRadius + barrelMargin,
|
|
27731
|
+
height: ctx.pcbThickness + 0.2
|
|
27732
|
+
})
|
|
27733
|
+
);
|
|
27734
|
+
const holeCut = (0, import_booleans.union)(
|
|
27735
|
+
(0, import_primitives3.cuboid)({
|
|
27736
|
+
center: [plated_hole.x + holeOffsetX, plated_hole.y + holeOffsetY, 0],
|
|
27737
|
+
size: shouldRotate ? [holeHeight, rectLength, throughDrillHeight * 1.1] : [rectLength, holeHeight, throughDrillHeight * 1.1]
|
|
27738
|
+
}),
|
|
27739
|
+
(0, import_primitives3.cylinder)({
|
|
27740
|
+
center: shouldRotate ? [
|
|
27741
|
+
plated_hole.x + holeOffsetX,
|
|
27742
|
+
plated_hole.y + holeOffsetY - rectLength / 2,
|
|
27743
|
+
0
|
|
27744
|
+
] : [
|
|
27745
|
+
plated_hole.x + holeOffsetX - rectLength / 2,
|
|
27746
|
+
plated_hole.y + holeOffsetY,
|
|
27747
|
+
0
|
|
27748
|
+
],
|
|
27749
|
+
radius: holeRadius,
|
|
27750
|
+
height: throughDrillHeight * 1.1
|
|
27751
|
+
}),
|
|
27752
|
+
(0, import_primitives3.cylinder)({
|
|
27753
|
+
center: shouldRotate ? [
|
|
27754
|
+
plated_hole.x + holeOffsetX,
|
|
27755
|
+
plated_hole.y + holeOffsetY + rectLength / 2,
|
|
27756
|
+
0
|
|
27757
|
+
] : [
|
|
27758
|
+
plated_hole.x + holeOffsetX + rectLength / 2,
|
|
27759
|
+
plated_hole.y + holeOffsetY,
|
|
27760
|
+
0
|
|
27761
|
+
],
|
|
27762
|
+
radius: holeRadius,
|
|
27763
|
+
height: throughDrillHeight * 1.1
|
|
27764
|
+
})
|
|
27765
|
+
);
|
|
27766
|
+
const mainFill = createRectPadGeom({
|
|
27663
27767
|
width: padWidth,
|
|
27664
27768
|
height: padHeight,
|
|
27665
|
-
thickness: platedHoleLipHeight,
|
|
27666
|
-
center: [
|
|
27667
|
-
plated_hole.x,
|
|
27668
|
-
plated_hole.y,
|
|
27669
|
-
-ctx.pcbThickness / 2 - platedHoleLipHeight / 2 - M
|
|
27670
|
-
],
|
|
27769
|
+
thickness: ctx.pcbThickness - 2 * platedHoleLipHeight - M * 2 + 0.1,
|
|
27770
|
+
center: [plated_hole.x, plated_hole.y, 0],
|
|
27671
27771
|
borderRadius: rectBorderRadius
|
|
27672
27772
|
});
|
|
27673
|
-
const
|
|
27773
|
+
const createPadWithHole = (zOffset) => {
|
|
27774
|
+
const pad2 = createRectPadGeom({
|
|
27775
|
+
width: padWidth,
|
|
27776
|
+
height: padHeight,
|
|
27777
|
+
thickness: platedHoleLipHeight + 0.1,
|
|
27778
|
+
center: [plated_hole.x, plated_hole.y, zOffset],
|
|
27779
|
+
borderRadius: rectBorderRadius
|
|
27780
|
+
});
|
|
27781
|
+
return (0, import_booleans.subtract)(pad2, holeCut);
|
|
27782
|
+
};
|
|
27783
|
+
const topPad = createPadWithHole(
|
|
27784
|
+
ctx.pcbThickness / 2 - platedHoleLipHeight / 2 + 0.05
|
|
27785
|
+
);
|
|
27786
|
+
const bottomPad = createPadWithHole(
|
|
27787
|
+
-ctx.pcbThickness / 2 + platedHoleLipHeight / 2 - 0.05
|
|
27788
|
+
);
|
|
27789
|
+
const filledArea = (0, import_booleans.subtract)(mainFill, holeCut);
|
|
27790
|
+
const barrelHoleCut = (0, import_booleans.union)(
|
|
27674
27791
|
(0, import_primitives3.cuboid)({
|
|
27675
|
-
center: [plated_hole.x, plated_hole.y, 0],
|
|
27676
|
-
size: shouldRotate ? [holeHeight -
|
|
27792
|
+
center: [plated_hole.x + holeOffsetX, plated_hole.y + holeOffsetY, 0],
|
|
27793
|
+
size: shouldRotate ? [holeHeight - 2 * M, rectLength - 2 * M, throughDrillHeight * 1.1] : [rectLength - 2 * M, holeHeight - 2 * M, throughDrillHeight * 1.1]
|
|
27677
27794
|
}),
|
|
27678
27795
|
(0, import_primitives3.cylinder)({
|
|
27679
|
-
center: shouldRotate ? [
|
|
27680
|
-
|
|
27681
|
-
|
|
27796
|
+
center: shouldRotate ? [
|
|
27797
|
+
plated_hole.x + holeOffsetX,
|
|
27798
|
+
plated_hole.y + holeOffsetY - rectLength / 2,
|
|
27799
|
+
0
|
|
27800
|
+
] : [
|
|
27801
|
+
plated_hole.x + holeOffsetX - rectLength / 2,
|
|
27802
|
+
plated_hole.y + holeOffsetY,
|
|
27803
|
+
0
|
|
27804
|
+
],
|
|
27805
|
+
radius: holeRadius - M,
|
|
27806
|
+
height: throughDrillHeight * 1.1
|
|
27682
27807
|
}),
|
|
27683
27808
|
(0, import_primitives3.cylinder)({
|
|
27684
|
-
center: shouldRotate ? [
|
|
27685
|
-
|
|
27686
|
-
|
|
27809
|
+
center: shouldRotate ? [
|
|
27810
|
+
plated_hole.x + holeOffsetX,
|
|
27811
|
+
plated_hole.y + holeOffsetY + rectLength / 2,
|
|
27812
|
+
0
|
|
27813
|
+
] : [
|
|
27814
|
+
plated_hole.x + holeOffsetX + rectLength / 2,
|
|
27815
|
+
plated_hole.y + holeOffsetY,
|
|
27816
|
+
0
|
|
27817
|
+
],
|
|
27818
|
+
radius: holeRadius - M,
|
|
27819
|
+
height: throughDrillHeight * 1.1
|
|
27687
27820
|
})
|
|
27688
27821
|
);
|
|
27689
|
-
const
|
|
27690
|
-
|
|
27691
|
-
|
|
27692
|
-
);
|
|
27693
|
-
const drill = holeCut;
|
|
27694
|
-
return (0, import_colors2.colorize)(colors.copper, (0, import_booleans.subtract)(copperSolid, drill));
|
|
27822
|
+
const barrelWithHole = (0, import_booleans.subtract)(barrel, barrelHoleCut);
|
|
27823
|
+
const finalCopper = (0, import_booleans.union)(filledArea, barrelWithHole, topPad, bottomPad);
|
|
27824
|
+
let result = maybeClip(finalCopper, clipGeom);
|
|
27825
|
+
return (0, import_colors2.colorize)(colors.copper, result);
|
|
27695
27826
|
} else {
|
|
27696
27827
|
throw new Error(`Unsupported plated hole shape: ${plated_hole.shape}`);
|
|
27697
27828
|
}
|
|
@@ -28421,13 +28552,24 @@ var BoardGeomBuilder = class {
|
|
|
28421
28552
|
processPlatedHole(ph, opts = {}) {
|
|
28422
28553
|
if (!this.boardGeom) return;
|
|
28423
28554
|
if (ph.shape === "circle" || ph.shape === "circular_hole_with_rect_pad") {
|
|
28424
|
-
|
|
28425
|
-
|
|
28426
|
-
|
|
28427
|
-
|
|
28428
|
-
|
|
28429
|
-
|
|
28430
|
-
|
|
28555
|
+
let cyGeom = null;
|
|
28556
|
+
if (ph.shape === "circular_hole_with_rect_pad") {
|
|
28557
|
+
cyGeom = (0, import_primitives6.cylinder)({
|
|
28558
|
+
center: [ph.x + ph.hole_offset_x, ph.y + ph.hole_offset_y, 0],
|
|
28559
|
+
radius: ph.hole_diameter / 2 + M,
|
|
28560
|
+
// Add margin for subtraction
|
|
28561
|
+
height: this.ctx.pcbThickness * 1.5
|
|
28562
|
+
// Ensure it cuts through
|
|
28563
|
+
});
|
|
28564
|
+
} else {
|
|
28565
|
+
cyGeom = (0, import_primitives6.cylinder)({
|
|
28566
|
+
center: [ph.x, ph.y, 0],
|
|
28567
|
+
radius: ph.hole_diameter / 2 + M,
|
|
28568
|
+
// Add margin for subtraction
|
|
28569
|
+
height: this.ctx.pcbThickness * 1.5
|
|
28570
|
+
// Ensure it cuts through
|
|
28571
|
+
});
|
|
28572
|
+
}
|
|
28431
28573
|
if (!opts.dontCutBoard) {
|
|
28432
28574
|
this.boardGeom = (0, import_booleans3.subtract)(this.boardGeom, cyGeom);
|
|
28433
28575
|
}
|
|
@@ -28444,22 +28586,58 @@ var BoardGeomBuilder = class {
|
|
|
28444
28586
|
const holeHeight = shouldRotate ? ph.hole_width : ph.hole_height;
|
|
28445
28587
|
const holeRadius = holeHeight / 2;
|
|
28446
28588
|
const rectLength = Math.abs(holeWidth - holeHeight);
|
|
28447
|
-
|
|
28448
|
-
|
|
28449
|
-
|
|
28450
|
-
|
|
28451
|
-
|
|
28452
|
-
|
|
28453
|
-
|
|
28454
|
-
|
|
28455
|
-
|
|
28456
|
-
|
|
28457
|
-
|
|
28458
|
-
|
|
28459
|
-
|
|
28460
|
-
|
|
28461
|
-
|
|
28462
|
-
|
|
28589
|
+
let pillHole;
|
|
28590
|
+
if (ph.shape === "pill_hole_with_rect_pad") {
|
|
28591
|
+
pillHole = (0, import_booleans3.union)(
|
|
28592
|
+
(0, import_primitives6.cuboid)({
|
|
28593
|
+
center: [ph.x + ph.hole_offset_x, ph.y + ph.hole_offset_y, 0],
|
|
28594
|
+
size: shouldRotate ? [holeHeight, rectLength, this.ctx.pcbThickness * 1.5] : [rectLength, holeHeight, this.ctx.pcbThickness * 1.5]
|
|
28595
|
+
}),
|
|
28596
|
+
(0, import_primitives6.cylinder)({
|
|
28597
|
+
center: shouldRotate ? [
|
|
28598
|
+
ph.x + ph.hole_offset_x,
|
|
28599
|
+
ph.y + ph.hole_offset_y - rectLength / 2,
|
|
28600
|
+
0
|
|
28601
|
+
] : [
|
|
28602
|
+
ph.x + ph.hole_offset_x - rectLength / 2,
|
|
28603
|
+
ph.y + ph.hole_offset_y,
|
|
28604
|
+
0
|
|
28605
|
+
],
|
|
28606
|
+
radius: holeRadius,
|
|
28607
|
+
height: this.ctx.pcbThickness * 1.5
|
|
28608
|
+
}),
|
|
28609
|
+
(0, import_primitives6.cylinder)({
|
|
28610
|
+
center: shouldRotate ? [
|
|
28611
|
+
ph.x + ph.hole_offset_x,
|
|
28612
|
+
ph.y + ph.hole_offset_y + rectLength / 2,
|
|
28613
|
+
0
|
|
28614
|
+
] : [
|
|
28615
|
+
ph.x + ph.hole_offset_x + rectLength / 2,
|
|
28616
|
+
ph.y + ph.hole_offset_y,
|
|
28617
|
+
0
|
|
28618
|
+
],
|
|
28619
|
+
radius: holeRadius,
|
|
28620
|
+
height: this.ctx.pcbThickness * 1.5
|
|
28621
|
+
})
|
|
28622
|
+
);
|
|
28623
|
+
} else {
|
|
28624
|
+
pillHole = (0, import_booleans3.union)(
|
|
28625
|
+
(0, import_primitives6.cuboid)({
|
|
28626
|
+
center: [ph.x, ph.y, 0],
|
|
28627
|
+
size: shouldRotate ? [holeHeight, rectLength, this.ctx.pcbThickness * 1.5] : [rectLength, holeHeight, this.ctx.pcbThickness * 1.5]
|
|
28628
|
+
}),
|
|
28629
|
+
(0, import_primitives6.cylinder)({
|
|
28630
|
+
center: shouldRotate ? [ph.x, ph.y - rectLength / 2, 0] : [ph.x - rectLength / 2, ph.y, 0],
|
|
28631
|
+
radius: holeRadius,
|
|
28632
|
+
height: this.ctx.pcbThickness * 1.5
|
|
28633
|
+
}),
|
|
28634
|
+
(0, import_primitives6.cylinder)({
|
|
28635
|
+
center: shouldRotate ? [ph.x, ph.y + rectLength / 2, 0] : [ph.x + rectLength / 2, ph.y, 0],
|
|
28636
|
+
radius: holeRadius,
|
|
28637
|
+
height: this.ctx.pcbThickness * 1.5
|
|
28638
|
+
})
|
|
28639
|
+
);
|
|
28640
|
+
}
|
|
28463
28641
|
if (!opts.dontCutBoard) {
|
|
28464
28642
|
this.boardGeom = (0, import_booleans3.subtract)(this.boardGeom, pillHole);
|
|
28465
28643
|
}
|
|
@@ -28486,6 +28664,99 @@ var BoardGeomBuilder = class {
|
|
|
28486
28664
|
this.padGeoms = this.padGeoms.map(
|
|
28487
28665
|
(pg) => (0, import_colors4.colorize)(colors.copper, (0, import_booleans3.subtract)(pg, cyGeom))
|
|
28488
28666
|
);
|
|
28667
|
+
} else if (hole.hole_shape === "pill") {
|
|
28668
|
+
const holeWidth = hole.hole_width;
|
|
28669
|
+
const holeHeight = hole.hole_height;
|
|
28670
|
+
const holeRadius = Math.min(holeWidth, holeHeight) / 2;
|
|
28671
|
+
const rectLength = Math.abs(holeWidth - holeHeight);
|
|
28672
|
+
let pillHole;
|
|
28673
|
+
if (holeWidth > holeHeight) {
|
|
28674
|
+
pillHole = (0, import_booleans3.union)(
|
|
28675
|
+
(0, import_primitives6.cuboid)({
|
|
28676
|
+
center: [hole.x, hole.y, 0],
|
|
28677
|
+
size: [rectLength, holeHeight, this.ctx.pcbThickness * 1.5]
|
|
28678
|
+
}),
|
|
28679
|
+
(0, import_primitives6.cylinder)({
|
|
28680
|
+
center: [hole.x - rectLength / 2, hole.y, 0],
|
|
28681
|
+
radius: holeRadius,
|
|
28682
|
+
height: this.ctx.pcbThickness * 1.5
|
|
28683
|
+
}),
|
|
28684
|
+
(0, import_primitives6.cylinder)({
|
|
28685
|
+
center: [hole.x + rectLength / 2, hole.y, 0],
|
|
28686
|
+
radius: holeRadius,
|
|
28687
|
+
height: this.ctx.pcbThickness * 1.5
|
|
28688
|
+
})
|
|
28689
|
+
);
|
|
28690
|
+
} else {
|
|
28691
|
+
pillHole = (0, import_booleans3.union)(
|
|
28692
|
+
(0, import_primitives6.cuboid)({
|
|
28693
|
+
center: [hole.x, hole.y, 0],
|
|
28694
|
+
size: [holeWidth, rectLength, this.ctx.pcbThickness * 1.5]
|
|
28695
|
+
}),
|
|
28696
|
+
(0, import_primitives6.cylinder)({
|
|
28697
|
+
center: [hole.x, hole.y - rectLength / 2, 0],
|
|
28698
|
+
radius: holeRadius,
|
|
28699
|
+
height: this.ctx.pcbThickness * 1.5
|
|
28700
|
+
}),
|
|
28701
|
+
(0, import_primitives6.cylinder)({
|
|
28702
|
+
center: [hole.x, hole.y + rectLength / 2, 0],
|
|
28703
|
+
radius: holeRadius,
|
|
28704
|
+
height: this.ctx.pcbThickness * 1.5
|
|
28705
|
+
})
|
|
28706
|
+
);
|
|
28707
|
+
}
|
|
28708
|
+
this.boardGeom = (0, import_booleans3.subtract)(this.boardGeom, pillHole);
|
|
28709
|
+
this.padGeoms = this.padGeoms.map(
|
|
28710
|
+
(pg) => (0, import_colors4.colorize)(colors.copper, (0, import_booleans3.subtract)(pg, pillHole))
|
|
28711
|
+
);
|
|
28712
|
+
} else if (hole.hole_shape === "rotated_pill") {
|
|
28713
|
+
const holeWidth = hole.hole_width;
|
|
28714
|
+
const holeHeight = hole.hole_height;
|
|
28715
|
+
const holeRadius = Math.min(holeWidth, holeHeight) / 2;
|
|
28716
|
+
const rectLength = Math.abs(holeWidth - holeHeight);
|
|
28717
|
+
let pillHole;
|
|
28718
|
+
if (holeWidth > holeHeight) {
|
|
28719
|
+
pillHole = (0, import_booleans3.union)(
|
|
28720
|
+
(0, import_primitives6.cuboid)({
|
|
28721
|
+
center: [0, 0, 0],
|
|
28722
|
+
size: [rectLength, holeHeight, this.ctx.pcbThickness * 1.5]
|
|
28723
|
+
}),
|
|
28724
|
+
(0, import_primitives6.cylinder)({
|
|
28725
|
+
center: [-rectLength / 2, 0, 0],
|
|
28726
|
+
radius: holeRadius,
|
|
28727
|
+
height: this.ctx.pcbThickness * 1.5
|
|
28728
|
+
}),
|
|
28729
|
+
(0, import_primitives6.cylinder)({
|
|
28730
|
+
center: [rectLength / 2, 0, 0],
|
|
28731
|
+
radius: holeRadius,
|
|
28732
|
+
height: this.ctx.pcbThickness * 1.5
|
|
28733
|
+
})
|
|
28734
|
+
);
|
|
28735
|
+
} else {
|
|
28736
|
+
pillHole = (0, import_booleans3.union)(
|
|
28737
|
+
(0, import_primitives6.cuboid)({
|
|
28738
|
+
center: [0, 0, 0],
|
|
28739
|
+
size: [holeWidth, rectLength, this.ctx.pcbThickness * 1.5]
|
|
28740
|
+
}),
|
|
28741
|
+
(0, import_primitives6.cylinder)({
|
|
28742
|
+
center: [0, -rectLength / 2, 0],
|
|
28743
|
+
radius: holeRadius,
|
|
28744
|
+
height: this.ctx.pcbThickness * 1.5
|
|
28745
|
+
}),
|
|
28746
|
+
(0, import_primitives6.cylinder)({
|
|
28747
|
+
center: [0, rectLength / 2, 0],
|
|
28748
|
+
radius: holeRadius,
|
|
28749
|
+
height: this.ctx.pcbThickness * 1.5
|
|
28750
|
+
})
|
|
28751
|
+
);
|
|
28752
|
+
}
|
|
28753
|
+
const rotationRadians = hole.ccw_rotation * Math.PI / 180;
|
|
28754
|
+
pillHole = (0, import_transforms4.rotateZ)(rotationRadians, pillHole);
|
|
28755
|
+
pillHole = (0, import_transforms4.translate)([hole.x, hole.y, 0], pillHole);
|
|
28756
|
+
this.boardGeom = (0, import_booleans3.subtract)(this.boardGeom, pillHole);
|
|
28757
|
+
this.padGeoms = this.padGeoms.map(
|
|
28758
|
+
(pg) => (0, import_colors4.colorize)(colors.copper, (0, import_booleans3.subtract)(pg, pillHole))
|
|
28759
|
+
);
|
|
28489
28760
|
}
|
|
28490
28761
|
}
|
|
28491
28762
|
processPad(pad2) {
|
|
@@ -29348,34 +29619,6 @@ function createPlatedHoleDrill({
|
|
|
29348
29619
|
return drill.translate([x, y, 0]);
|
|
29349
29620
|
}
|
|
29350
29621
|
|
|
29351
|
-
// src/utils/manifold/process-non-plated-holes.ts
|
|
29352
|
-
function isCircleHole(hole) {
|
|
29353
|
-
return (hole.shape === "circle" || hole.hole_shape === "circle") && typeof hole.hole_diameter === "number";
|
|
29354
|
-
}
|
|
29355
|
-
function processNonPlatedHolesForManifold(Manifold, circuitJson, pcbThickness, manifoldInstancesForCleanup) {
|
|
29356
|
-
const nonPlatedHoleBoardDrills = [];
|
|
29357
|
-
const pcbHoles = su7(circuitJson).pcb_hole.list();
|
|
29358
|
-
pcbHoles.forEach((hole) => {
|
|
29359
|
-
if (isCircleHole(hole)) {
|
|
29360
|
-
const translatedDrill = createCircleHoleDrill({
|
|
29361
|
-
Manifold,
|
|
29362
|
-
x: hole.x,
|
|
29363
|
-
y: hole.y,
|
|
29364
|
-
diameter: hole.hole_diameter,
|
|
29365
|
-
thickness: pcbThickness,
|
|
29366
|
-
segments: SMOOTH_CIRCLE_SEGMENTS
|
|
29367
|
-
});
|
|
29368
|
-
manifoldInstancesForCleanup.push(translatedDrill);
|
|
29369
|
-
nonPlatedHoleBoardDrills.push(translatedDrill);
|
|
29370
|
-
}
|
|
29371
|
-
});
|
|
29372
|
-
return { nonPlatedHoleBoardDrills };
|
|
29373
|
-
}
|
|
29374
|
-
|
|
29375
|
-
// src/utils/manifold/process-plated-holes.ts
|
|
29376
|
-
import { su as su8 } from "@tscircuit/circuit-json-util";
|
|
29377
|
-
import * as THREE19 from "three";
|
|
29378
|
-
|
|
29379
29622
|
// src/utils/pad-geoms.ts
|
|
29380
29623
|
var RECT_PAD_SEGMENTS2 = 64;
|
|
29381
29624
|
function createRoundedRectPrism({
|
|
@@ -29451,7 +29694,69 @@ function createPadManifoldOp({
|
|
|
29451
29694
|
return null;
|
|
29452
29695
|
}
|
|
29453
29696
|
|
|
29697
|
+
// src/utils/manifold/process-non-plated-holes.ts
|
|
29698
|
+
function isCircleHole(hole) {
|
|
29699
|
+
return (hole.shape === "circle" || hole.hole_shape === "circle") && typeof hole.hole_diameter === "number";
|
|
29700
|
+
}
|
|
29701
|
+
function isPillHole(hole) {
|
|
29702
|
+
return (hole.shape === "pill" || hole.hole_shape === "pill") && typeof hole.hole_width === "number" && typeof hole.hole_height === "number";
|
|
29703
|
+
}
|
|
29704
|
+
function isRotatedPillHole(hole) {
|
|
29705
|
+
return (hole.shape === "rotated_pill" || hole.hole_shape === "rotated_pill") && typeof hole.hole_width === "number" && typeof hole.hole_height === "number" && typeof hole.ccw_rotation === "number";
|
|
29706
|
+
}
|
|
29707
|
+
function processNonPlatedHolesForManifold(Manifold, circuitJson, pcbThickness, manifoldInstancesForCleanup) {
|
|
29708
|
+
const nonPlatedHoleBoardDrills = [];
|
|
29709
|
+
const pcbHoles = su7(circuitJson).pcb_hole.list();
|
|
29710
|
+
const createPillOp = (width10, height10, depth) => {
|
|
29711
|
+
const pillOp = createRoundedRectPrism({
|
|
29712
|
+
Manifold,
|
|
29713
|
+
width: width10,
|
|
29714
|
+
height: height10,
|
|
29715
|
+
thickness: depth,
|
|
29716
|
+
borderRadius: Math.min(width10, height10) / 2
|
|
29717
|
+
});
|
|
29718
|
+
manifoldInstancesForCleanup.push(pillOp);
|
|
29719
|
+
return pillOp;
|
|
29720
|
+
};
|
|
29721
|
+
pcbHoles.forEach((hole) => {
|
|
29722
|
+
if (isCircleHole(hole)) {
|
|
29723
|
+
const translatedDrill = createCircleHoleDrill({
|
|
29724
|
+
Manifold,
|
|
29725
|
+
x: hole.x,
|
|
29726
|
+
y: hole.y,
|
|
29727
|
+
diameter: hole.hole_diameter,
|
|
29728
|
+
thickness: pcbThickness,
|
|
29729
|
+
segments: SMOOTH_CIRCLE_SEGMENTS
|
|
29730
|
+
});
|
|
29731
|
+
manifoldInstancesForCleanup.push(translatedDrill);
|
|
29732
|
+
nonPlatedHoleBoardDrills.push(translatedDrill);
|
|
29733
|
+
} else if (isPillHole(hole)) {
|
|
29734
|
+
const holeW = hole.hole_width;
|
|
29735
|
+
const holeH = hole.hole_height;
|
|
29736
|
+
const drillDepth = pcbThickness * 1.2;
|
|
29737
|
+
const pillDrillOp = createPillOp(holeW, holeH, drillDepth);
|
|
29738
|
+
const translatedPillDrill = pillDrillOp.translate([hole.x, hole.y, 0]);
|
|
29739
|
+
manifoldInstancesForCleanup.push(translatedPillDrill);
|
|
29740
|
+
nonPlatedHoleBoardDrills.push(translatedPillDrill);
|
|
29741
|
+
} else if (isRotatedPillHole(hole)) {
|
|
29742
|
+
const holeW = hole.hole_width;
|
|
29743
|
+
const holeH = hole.hole_height;
|
|
29744
|
+
const drillDepth = pcbThickness * 1.2;
|
|
29745
|
+
let pillDrillOp = createPillOp(holeW, holeH, drillDepth);
|
|
29746
|
+
const rotatedOp = pillDrillOp.rotate([0, 0, hole.ccw_rotation]);
|
|
29747
|
+
manifoldInstancesForCleanup.push(rotatedOp);
|
|
29748
|
+
pillDrillOp = rotatedOp;
|
|
29749
|
+
const translatedPillDrill = pillDrillOp.translate([hole.x, hole.y, 0]);
|
|
29750
|
+
manifoldInstancesForCleanup.push(translatedPillDrill);
|
|
29751
|
+
nonPlatedHoleBoardDrills.push(translatedPillDrill);
|
|
29752
|
+
}
|
|
29753
|
+
});
|
|
29754
|
+
return { nonPlatedHoleBoardDrills };
|
|
29755
|
+
}
|
|
29756
|
+
|
|
29454
29757
|
// src/utils/manifold/process-plated-holes.ts
|
|
29758
|
+
import { su as su8 } from "@tscircuit/circuit-json-util";
|
|
29759
|
+
import * as THREE19 from "three";
|
|
29455
29760
|
var COPPER_COLOR = new THREE19.Color(...colors.copper);
|
|
29456
29761
|
var PLATED_HOLE_LIP_HEIGHT = 0.05;
|
|
29457
29762
|
function processPlatedHolesForManifold(Manifold, circuitJson, pcbThickness, manifoldInstancesForCleanup, boardClipVolume) {
|
|
@@ -29576,6 +29881,8 @@ function processPlatedHolesForManifold(Manifold, circuitJson, pcbThickness, mani
|
|
|
29576
29881
|
} else if (ph.shape === "pill_hole_with_rect_pad") {
|
|
29577
29882
|
const holeW = ph.hole_width;
|
|
29578
29883
|
const holeH = ph.hole_height;
|
|
29884
|
+
const holeOffsetX = ph.hole_offset_x || 0;
|
|
29885
|
+
const holeOffsetY = ph.hole_offset_y || 0;
|
|
29579
29886
|
const padWidth = ph.rect_pad_width;
|
|
29580
29887
|
const padHeight = ph.rect_pad_height;
|
|
29581
29888
|
const rectBorderRadius = extractRectBorderRadius(ph);
|
|
@@ -29583,7 +29890,9 @@ function processPlatedHolesForManifold(Manifold, circuitJson, pcbThickness, mani
|
|
|
29583
29890
|
const drillW = holeW + 2 * MANIFOLD_Z_OFFSET;
|
|
29584
29891
|
const drillH = holeH + 2 * MANIFOLD_Z_OFFSET;
|
|
29585
29892
|
const drillDepth = pcbThickness * 1.2;
|
|
29586
|
-
let boardPillDrillOp = createPillOp(drillW, drillH, drillDepth)
|
|
29893
|
+
let boardPillDrillOp = createPillOp(drillW, drillH, drillDepth).translate(
|
|
29894
|
+
[holeOffsetX, holeOffsetY, 0]
|
|
29895
|
+
);
|
|
29587
29896
|
const translatedBoardPillDrill = boardPillDrillOp.translate([
|
|
29588
29897
|
ph.x,
|
|
29589
29898
|
ph.y,
|
|
@@ -29591,51 +29900,59 @@ function processPlatedHolesForManifold(Manifold, circuitJson, pcbThickness, mani
|
|
|
29591
29900
|
]);
|
|
29592
29901
|
manifoldInstancesForCleanup.push(translatedBoardPillDrill);
|
|
29593
29902
|
platedHoleBoardDrills.push(translatedBoardPillDrill);
|
|
29594
|
-
|
|
29595
|
-
holeW,
|
|
29596
|
-
holeH,
|
|
29597
|
-
pcbThickness + 2 * MANIFOLD_Z_OFFSET
|
|
29598
|
-
);
|
|
29599
|
-
let topPadOp = createRoundedRectPrism({
|
|
29903
|
+
const mainFill = createRoundedRectPrism({
|
|
29600
29904
|
Manifold,
|
|
29601
29905
|
width: padWidth,
|
|
29602
29906
|
height: padHeight,
|
|
29603
|
-
thickness: padThickness,
|
|
29907
|
+
thickness: pcbThickness - 2 * padThickness + 0.1,
|
|
29908
|
+
// Fill between pads
|
|
29604
29909
|
borderRadius: rectBorderRadius
|
|
29605
29910
|
});
|
|
29606
|
-
manifoldInstancesForCleanup.push(
|
|
29607
|
-
|
|
29911
|
+
manifoldInstancesForCleanup.push(mainFill);
|
|
29912
|
+
const topPad = createRoundedRectPrism({
|
|
29608
29913
|
Manifold,
|
|
29609
29914
|
width: padWidth,
|
|
29610
29915
|
height: padHeight,
|
|
29611
|
-
thickness: padThickness,
|
|
29916
|
+
thickness: padThickness + 0.1,
|
|
29612
29917
|
borderRadius: rectBorderRadius
|
|
29613
|
-
});
|
|
29614
|
-
|
|
29615
|
-
|
|
29616
|
-
|
|
29617
|
-
|
|
29618
|
-
|
|
29619
|
-
|
|
29620
|
-
|
|
29621
|
-
|
|
29622
|
-
|
|
29623
|
-
|
|
29624
|
-
|
|
29918
|
+
}).translate([0, 0, pcbThickness / 2 - padThickness / 2 + 0.05]);
|
|
29919
|
+
const bottomPad = createRoundedRectPrism({
|
|
29920
|
+
Manifold,
|
|
29921
|
+
width: padWidth,
|
|
29922
|
+
height: padHeight,
|
|
29923
|
+
thickness: padThickness + 0.1,
|
|
29924
|
+
borderRadius: rectBorderRadius
|
|
29925
|
+
}).translate([0, 0, -pcbThickness / 2 + padThickness / 2 - 0.05]);
|
|
29926
|
+
manifoldInstancesForCleanup.push(topPad, bottomPad);
|
|
29927
|
+
const barrelPill = createPillOp(
|
|
29928
|
+
holeW,
|
|
29929
|
+
holeH,
|
|
29930
|
+
pcbThickness * 1.02
|
|
29931
|
+
// Slightly taller than board
|
|
29932
|
+
).translate([holeOffsetX, holeOffsetY, 0]);
|
|
29933
|
+
manifoldInstancesForCleanup.push(barrelPill);
|
|
29934
|
+
const copperUnion = Manifold.union([
|
|
29935
|
+
mainFill,
|
|
29936
|
+
topPad,
|
|
29937
|
+
bottomPad,
|
|
29938
|
+
barrelPill
|
|
29625
29939
|
]);
|
|
29626
|
-
manifoldInstancesForCleanup.push(
|
|
29627
|
-
const
|
|
29628
|
-
|
|
29629
|
-
|
|
29630
|
-
|
|
29631
|
-
|
|
29632
|
-
|
|
29633
|
-
|
|
29634
|
-
|
|
29635
|
-
|
|
29940
|
+
manifoldInstancesForCleanup.push(copperUnion);
|
|
29941
|
+
const holeCutOp = createPillOp(
|
|
29942
|
+
Math.max(holeW - 2 * PLATED_HOLE_LIP_HEIGHT, 0.01),
|
|
29943
|
+
Math.max(holeH - 2 * PLATED_HOLE_LIP_HEIGHT, 0.01),
|
|
29944
|
+
pcbThickness * 1.2
|
|
29945
|
+
// Ensure it cuts through
|
|
29946
|
+
).translate([holeOffsetX, holeOffsetY, 0]);
|
|
29947
|
+
manifoldInstancesForCleanup.push(holeCutOp);
|
|
29948
|
+
const finalCopper = copperUnion.subtract(holeCutOp);
|
|
29949
|
+
manifoldInstancesForCleanup.push(finalCopper);
|
|
29950
|
+
const translatedCopper = finalCopper.translate([ph.x, ph.y, 0]);
|
|
29951
|
+
manifoldInstancesForCleanup.push(translatedCopper);
|
|
29952
|
+
let finalCopperOp = translatedCopper;
|
|
29636
29953
|
if (boardClipVolume) {
|
|
29637
29954
|
const clipped = Manifold.intersection([
|
|
29638
|
-
|
|
29955
|
+
translatedCopper,
|
|
29639
29956
|
boardClipVolume
|
|
29640
29957
|
]);
|
|
29641
29958
|
manifoldInstancesForCleanup.push(clipped);
|
|
@@ -29648,71 +29965,77 @@ function processPlatedHolesForManifold(Manifold, circuitJson, pcbThickness, mani
|
|
|
29648
29965
|
color: COPPER_COLOR
|
|
29649
29966
|
});
|
|
29650
29967
|
} else if (ph.shape === "circular_hole_with_rect_pad") {
|
|
29968
|
+
const holeOffsetX = ph.hole_offset_x || 0;
|
|
29969
|
+
const holeOffsetY = ph.hole_offset_y || 0;
|
|
29651
29970
|
const translatedDrill = createCircleHoleDrill({
|
|
29652
29971
|
Manifold,
|
|
29653
|
-
x: ph.x,
|
|
29654
|
-
|
|
29972
|
+
x: ph.x + holeOffsetX,
|
|
29973
|
+
// Apply hole offset
|
|
29974
|
+
y: ph.y + holeOffsetY,
|
|
29975
|
+
// Apply hole offset
|
|
29655
29976
|
diameter: ph.hole_diameter,
|
|
29656
29977
|
thickness: pcbThickness,
|
|
29657
29978
|
segments: SMOOTH_CIRCLE_SEGMENTS
|
|
29658
29979
|
});
|
|
29659
29980
|
manifoldInstancesForCleanup.push(translatedDrill);
|
|
29660
29981
|
platedHoleBoardDrills.push(translatedDrill);
|
|
29661
|
-
const copperPartThickness = pcbThickness + 2 * MANIFOLD_Z_OFFSET;
|
|
29662
|
-
const holeRadius = ph.hole_diameter / 2;
|
|
29663
|
-
const barrelCylinder = Manifold.cylinder(
|
|
29664
|
-
copperPartThickness,
|
|
29665
|
-
holeRadius,
|
|
29666
|
-
holeRadius,
|
|
29667
|
-
SMOOTH_CIRCLE_SEGMENTS,
|
|
29668
|
-
true
|
|
29669
|
-
);
|
|
29670
|
-
manifoldInstancesForCleanup.push(barrelCylinder);
|
|
29671
29982
|
const padWidth = ph.rect_pad_width ?? ph.hole_diameter;
|
|
29672
29983
|
const padHeight = ph.rect_pad_height ?? ph.hole_diameter;
|
|
29673
29984
|
const rectBorderRadius = extractRectBorderRadius(ph);
|
|
29674
29985
|
const padThickness = DEFAULT_SMT_PAD_THICKNESS;
|
|
29986
|
+
const holeRadius = ph.hole_diameter / 2;
|
|
29987
|
+
const mainFill = createRoundedRectPrism({
|
|
29988
|
+
Manifold,
|
|
29989
|
+
width: padWidth,
|
|
29990
|
+
height: padHeight,
|
|
29991
|
+
thickness: pcbThickness - 2 * padThickness + 0.1,
|
|
29992
|
+
// Fill between pads
|
|
29993
|
+
borderRadius: rectBorderRadius
|
|
29994
|
+
});
|
|
29995
|
+
manifoldInstancesForCleanup.push(mainFill);
|
|
29675
29996
|
const topPad = createRoundedRectPrism({
|
|
29676
29997
|
Manifold,
|
|
29677
29998
|
width: padWidth,
|
|
29678
29999
|
height: padHeight,
|
|
29679
|
-
thickness: padThickness,
|
|
30000
|
+
thickness: padThickness + 0.1,
|
|
29680
30001
|
borderRadius: rectBorderRadius
|
|
29681
|
-
}).translate([
|
|
29682
|
-
0,
|
|
29683
|
-
0,
|
|
29684
|
-
pcbThickness / 2 + padThickness / 2 + MANIFOLD_Z_OFFSET
|
|
29685
|
-
]);
|
|
30002
|
+
}).translate([0, 0, pcbThickness / 2 - padThickness / 2 + 0.05]);
|
|
29686
30003
|
const bottomPad = createRoundedRectPrism({
|
|
29687
30004
|
Manifold,
|
|
29688
30005
|
width: padWidth,
|
|
29689
30006
|
height: padHeight,
|
|
29690
|
-
thickness: padThickness,
|
|
30007
|
+
thickness: padThickness + 0.1,
|
|
29691
30008
|
borderRadius: rectBorderRadius
|
|
29692
|
-
}).translate([
|
|
29693
|
-
0,
|
|
29694
|
-
0,
|
|
29695
|
-
-pcbThickness / 2 - padThickness / 2 - MANIFOLD_Z_OFFSET
|
|
29696
|
-
]);
|
|
30009
|
+
}).translate([0, 0, -pcbThickness / 2 + padThickness / 2 - 0.05]);
|
|
29697
30010
|
manifoldInstancesForCleanup.push(topPad, bottomPad);
|
|
29698
|
-
const
|
|
29699
|
-
|
|
30011
|
+
const barrelCylinder = Manifold.cylinder(
|
|
30012
|
+
pcbThickness * 1.02,
|
|
30013
|
+
// Slightly taller than board
|
|
30014
|
+
holeRadius,
|
|
30015
|
+
holeRadius,
|
|
30016
|
+
SMOOTH_CIRCLE_SEGMENTS,
|
|
30017
|
+
true
|
|
30018
|
+
).translate([holeOffsetX, holeOffsetY, 0]);
|
|
30019
|
+
manifoldInstancesForCleanup.push(barrelCylinder);
|
|
30020
|
+
const copperUnion = Manifold.union([
|
|
30021
|
+
mainFill,
|
|
29700
30022
|
topPad,
|
|
29701
|
-
bottomPad
|
|
30023
|
+
bottomPad,
|
|
30024
|
+
barrelCylinder
|
|
29702
30025
|
]);
|
|
29703
|
-
manifoldInstancesForCleanup.push(
|
|
29704
|
-
const
|
|
29705
|
-
|
|
29706
|
-
|
|
29707
|
-
|
|
29708
|
-
|
|
30026
|
+
manifoldInstancesForCleanup.push(copperUnion);
|
|
30027
|
+
const holeDrill = Manifold.cylinder(
|
|
30028
|
+
pcbThickness * 1.2,
|
|
30029
|
+
// Ensure it cuts through
|
|
30030
|
+
Math.max(holeRadius - M, 0.01),
|
|
30031
|
+
Math.max(holeRadius - M, 0.01),
|
|
29709
30032
|
SMOOTH_CIRCLE_SEGMENTS,
|
|
29710
30033
|
true
|
|
29711
|
-
);
|
|
29712
|
-
manifoldInstancesForCleanup.push(
|
|
29713
|
-
const
|
|
29714
|
-
manifoldInstancesForCleanup.push(
|
|
29715
|
-
const translatedCopper =
|
|
30034
|
+
).translate([holeOffsetX, holeOffsetY, 0]);
|
|
30035
|
+
manifoldInstancesForCleanup.push(holeDrill);
|
|
30036
|
+
const finalCopper = copperUnion.subtract(holeDrill);
|
|
30037
|
+
manifoldInstancesForCleanup.push(finalCopper);
|
|
30038
|
+
const translatedCopper = finalCopper.translate([ph.x, ph.y, 0]);
|
|
29716
30039
|
manifoldInstancesForCleanup.push(translatedCopper);
|
|
29717
30040
|
let finalCopperOp = translatedCopper;
|
|
29718
30041
|
if (boardClipVolume) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tscircuit/3d-viewer",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.413",
|
|
4
4
|
"main": "./dist/index.js",
|
|
5
5
|
"module": "./dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -47,8 +47,8 @@
|
|
|
47
47
|
"@storybook/blocks": "9.0.0-alpha.17",
|
|
48
48
|
"@storybook/react-vite": "^9.1.5",
|
|
49
49
|
"@tscircuit/circuit-json-util": "^0.0.72",
|
|
50
|
-
"@tscircuit/core": "^0.0.
|
|
51
|
-
"@tscircuit/props": "^0.0.
|
|
50
|
+
"@tscircuit/core": "^0.0.787",
|
|
51
|
+
"@tscircuit/props": "^0.0.364",
|
|
52
52
|
"@tscircuit/checks": "^0.0.85",
|
|
53
53
|
"@tscircuit/math-utils": "^0.0.27",
|
|
54
54
|
"@tscircuit/capacity-autorouter": "^0.0.131",
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
"@vitejs/plugin-react": "^4.3.4",
|
|
61
61
|
"bun-match-svg": "^0.0.9",
|
|
62
62
|
"bun-types": "1.2.1",
|
|
63
|
-
"circuit-json": "0.0.
|
|
63
|
+
"circuit-json": "0.0.279",
|
|
64
64
|
"circuit-to-svg": "^0.0.179",
|
|
65
65
|
"debug": "^4.4.0",
|
|
66
66
|
"jscad-electronics": "^0.0.48",
|