circuit-json-to-lbrn 0.0.17 → 0.0.19
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 +246 -22
- package/lib/element-handlers/addPcbCutout/addCirclePcbCutout.ts +52 -0
- package/lib/element-handlers/addPcbCutout/addPathPcbCutout.ts +73 -0
- package/lib/element-handlers/addPcbCutout/addPolygonPcbCutout.ts +68 -0
- package/lib/element-handlers/addPcbCutout/addRectPcbCutout.ts +71 -0
- package/lib/element-handlers/addPcbCutout/index.ts +31 -0
- package/lib/element-handlers/addPcbHole/addCirclePcbHole.ts +2 -1
- package/lib/element-handlers/addPcbHole/addOvalPcbHole.ts +2 -1
- package/lib/element-handlers/addPcbHole/addPillPcbHole.ts +2 -1
- package/lib/element-handlers/addPcbHole/addRectPcbHole.ts +2 -1
- package/lib/element-handlers/addPcbHole/addRotatedPillPcbHole.ts +2 -1
- package/lib/element-handlers/addPcbVia/index.ts +1 -1
- package/lib/element-handlers/addPlatedHole/addCirclePlatedHole.ts +1 -2
- package/lib/element-handlers/addPlatedHole/addCircularHoleWithRectPad.ts +1 -1
- package/lib/element-handlers/addPlatedHole/addHoleWithPolygonPad.ts +11 -3
- package/lib/element-handlers/addPlatedHole/addOvalPlatedHole.ts +6 -2
- package/lib/element-handlers/addPlatedHole/addPillHoleWithRectPad.ts +1 -1
- package/lib/element-handlers/addPlatedHole/addPillPlatedHole.ts +5 -1
- package/lib/element-handlers/addPlatedHole/addRotatedPillHoleWithRectPad.ts +1 -1
- package/lib/index.ts +5 -0
- package/package.json +1 -1
- package/tests/examples/addPcbCutout/__snapshots__/pcb-cutout-circle.snap.svg +8 -0
- package/tests/examples/addPcbCutout/__snapshots__/pcb-cutout-path.snap.svg +8 -0
- package/tests/examples/addPcbCutout/__snapshots__/pcb-cutout-polygon.snap.svg +8 -0
- package/tests/examples/addPcbCutout/__snapshots__/pcb-cutout-rect.snap.svg +8 -0
- package/tests/examples/addPcbCutout/pcb-cutout-circle.test.ts +49 -0
- package/tests/examples/addPcbCutout/pcb-cutout-path.test.ts +44 -0
- package/tests/examples/addPcbCutout/pcb-cutout-polygon.test.ts +54 -0
- package/tests/examples/addPcbCutout/pcb-cutout-rect.test.ts +48 -0
- package/tests/examples/addPcbVia/__snapshots__/pcb-via-with-soldermask.snap.svg +1 -1
- package/tests/examples/soldermask/__snapshots__/soldermask-only.snap.svg +3 -3
- package/tests/examples/soldermask/soldermask-only.test.ts +10 -0
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// lib/index.ts
|
|
2
|
-
import { LightBurnProject, CutSetting, ShapePath as
|
|
2
|
+
import { LightBurnProject, CutSetting, ShapePath as ShapePath25 } from "lbrnts";
|
|
3
3
|
import { cju as cju2 } from "@tscircuit/circuit-json-util";
|
|
4
4
|
|
|
5
5
|
// lib/element-handlers/addPlatedHole/addCirclePlatedHole.ts
|
|
@@ -88,7 +88,7 @@ var addCirclePlatedHole = (platedHole, ctx) => {
|
|
|
88
88
|
})
|
|
89
89
|
);
|
|
90
90
|
}
|
|
91
|
-
if (platedHole.hole_diameter > 0) {
|
|
91
|
+
if (platedHole.hole_diameter > 0 && includeCopper) {
|
|
92
92
|
const innerRadius = platedHole.hole_diameter / 2;
|
|
93
93
|
const inner = createCirclePath(centerX, centerY, innerRadius);
|
|
94
94
|
project.children.push(
|
|
@@ -180,7 +180,7 @@ var addOvalPlatedHole = (platedHole, ctx) => {
|
|
|
180
180
|
})
|
|
181
181
|
);
|
|
182
182
|
}
|
|
183
|
-
if (platedHole.hole_width > 0 && platedHole.hole_height > 0) {
|
|
183
|
+
if (platedHole.hole_width > 0 && platedHole.hole_height > 0 && includeCopper) {
|
|
184
184
|
const inner = createOvalPath(
|
|
185
185
|
centerX,
|
|
186
186
|
centerY,
|
|
@@ -337,7 +337,7 @@ var addCircularHoleWithRectPad = (platedHole, ctx) => {
|
|
|
337
337
|
})
|
|
338
338
|
);
|
|
339
339
|
}
|
|
340
|
-
if (holeRadius > 0) {
|
|
340
|
+
if (holeRadius > 0 && includeCopper) {
|
|
341
341
|
const holeCenterX = centerX + platedHole.hole_offset_x;
|
|
342
342
|
const holeCenterY = centerY + platedHole.hole_offset_y;
|
|
343
343
|
const holePath = createCirclePath(holeCenterX, holeCenterY, holeRadius, 32);
|
|
@@ -491,7 +491,7 @@ var addPillHoleWithRectPad = (platedHole, ctx) => {
|
|
|
491
491
|
}
|
|
492
492
|
const holeWidth = platedHole.hole_width;
|
|
493
493
|
const holeHeight = platedHole.hole_height;
|
|
494
|
-
if (holeWidth > 0 && holeHeight > 0) {
|
|
494
|
+
if (holeWidth > 0 && holeHeight > 0 && includeCopper) {
|
|
495
495
|
const holeCenterX = centerX + platedHole.hole_offset_x;
|
|
496
496
|
const holeCenterY = centerY + platedHole.hole_offset_y;
|
|
497
497
|
const holePath = createPillPath(
|
|
@@ -575,7 +575,7 @@ var addRotatedPillHoleWithRectPad = (platedHole, ctx) => {
|
|
|
575
575
|
const holeWidth = platedHole.hole_width;
|
|
576
576
|
const holeHeight = platedHole.hole_height;
|
|
577
577
|
const holeRotation = (platedHole.hole_ccw_rotation ?? 0) * (Math.PI / 180);
|
|
578
|
-
if (holeWidth > 0 && holeHeight > 0) {
|
|
578
|
+
if (holeWidth > 0 && holeHeight > 0 && includeCopper) {
|
|
579
579
|
const holeCenterX = centerX + platedHole.hole_offset_x;
|
|
580
580
|
const holeCenterY = centerY + platedHole.hole_offset_y;
|
|
581
581
|
const holePath = createPillPath(
|
|
@@ -628,7 +628,7 @@ var addHoleWithPolygonPad = (platedHole, ctx) => {
|
|
|
628
628
|
includeSoldermask,
|
|
629
629
|
soldermaskMargin
|
|
630
630
|
} = ctx;
|
|
631
|
-
if (platedHole.pad_outline.length >= 3) {
|
|
631
|
+
if (platedHole.pad_outline.length >= 3 && includeCopper) {
|
|
632
632
|
const pad = createPolygonPathFromOutline(
|
|
633
633
|
platedHole.pad_outline,
|
|
634
634
|
platedHole.x + origin.x,
|
|
@@ -655,7 +655,7 @@ var addHoleWithPolygonPad = (platedHole, ctx) => {
|
|
|
655
655
|
);
|
|
656
656
|
}
|
|
657
657
|
}
|
|
658
|
-
if (platedHole.hole_shape === "circle" && platedHole.hole_diameter) {
|
|
658
|
+
if (platedHole.hole_shape === "circle" && platedHole.hole_diameter && includeCopper) {
|
|
659
659
|
const centerX = platedHole.x + platedHole.hole_offset_x + origin.x;
|
|
660
660
|
const centerY = platedHole.y + platedHole.hole_offset_y + origin.y;
|
|
661
661
|
const radius = platedHole.hole_diameter / 2;
|
|
@@ -669,7 +669,7 @@ var addHoleWithPolygonPad = (platedHole, ctx) => {
|
|
|
669
669
|
})
|
|
670
670
|
);
|
|
671
671
|
}
|
|
672
|
-
if (platedHole.hole_shape === "pill" && platedHole.hole_diameter) {
|
|
672
|
+
if (platedHole.hole_shape === "pill" && platedHole.hole_diameter && includeCopper) {
|
|
673
673
|
const centerX = platedHole.x + platedHole.hole_offset_x + origin.x;
|
|
674
674
|
const centerY = platedHole.y + platedHole.hole_offset_y + origin.y;
|
|
675
675
|
const radius = platedHole.hole_diameter / 2;
|
|
@@ -731,7 +731,7 @@ var addPcbPlatedHolePill = (platedHole, ctx) => {
|
|
|
731
731
|
})
|
|
732
732
|
);
|
|
733
733
|
}
|
|
734
|
-
if (platedHole.hole_width > 0 && platedHole.hole_height > 0) {
|
|
734
|
+
if (platedHole.hole_width > 0 && platedHole.hole_height > 0 && includeCopper) {
|
|
735
735
|
const inner = createPillPath(
|
|
736
736
|
centerX,
|
|
737
737
|
centerY,
|
|
@@ -1422,7 +1422,7 @@ var addPcbVia = (via, ctx) => {
|
|
|
1422
1422
|
})
|
|
1423
1423
|
);
|
|
1424
1424
|
}
|
|
1425
|
-
if (via.hole_diameter > 0) {
|
|
1425
|
+
if (via.hole_diameter > 0 && includeCopper) {
|
|
1426
1426
|
const innerRadius = via.hole_diameter / 2;
|
|
1427
1427
|
const inner = createCirclePath(centerX, centerY, innerRadius);
|
|
1428
1428
|
project.children.push(
|
|
@@ -1445,7 +1445,8 @@ var addCirclePcbHole = (hole, ctx) => {
|
|
|
1445
1445
|
soldermaskCutSetting,
|
|
1446
1446
|
origin,
|
|
1447
1447
|
includeSoldermask,
|
|
1448
|
-
soldermaskMargin
|
|
1448
|
+
soldermaskMargin,
|
|
1449
|
+
includeCopper
|
|
1449
1450
|
} = ctx;
|
|
1450
1451
|
const centerX = hole.x + origin.x;
|
|
1451
1452
|
const centerY = hole.y + origin.y;
|
|
@@ -1461,7 +1462,7 @@ var addCirclePcbHole = (hole, ctx) => {
|
|
|
1461
1462
|
})
|
|
1462
1463
|
);
|
|
1463
1464
|
}
|
|
1464
|
-
if (hole.hole_diameter > 0) {
|
|
1465
|
+
if (hole.hole_diameter > 0 && includeCopper) {
|
|
1465
1466
|
const radius = hole.hole_diameter / 2;
|
|
1466
1467
|
const circlePath = createCirclePath(centerX, centerY, radius);
|
|
1467
1468
|
project.children.push(
|
|
@@ -1484,7 +1485,8 @@ var addRectPcbHole = (hole, ctx) => {
|
|
|
1484
1485
|
soldermaskCutSetting,
|
|
1485
1486
|
origin,
|
|
1486
1487
|
includeSoldermask,
|
|
1487
|
-
soldermaskMargin
|
|
1488
|
+
soldermaskMargin,
|
|
1489
|
+
includeCopper
|
|
1488
1490
|
} = ctx;
|
|
1489
1491
|
const centerX = hole.x + origin.x;
|
|
1490
1492
|
const centerY = hole.y + origin.y;
|
|
@@ -1506,7 +1508,7 @@ var addRectPcbHole = (hole, ctx) => {
|
|
|
1506
1508
|
})
|
|
1507
1509
|
);
|
|
1508
1510
|
}
|
|
1509
|
-
if (hole.hole_width > 0 && hole.hole_height > 0) {
|
|
1511
|
+
if (hole.hole_width > 0 && hole.hole_height > 0 && includeCopper) {
|
|
1510
1512
|
const rectPath = createRoundedRectPath(
|
|
1511
1513
|
centerX,
|
|
1512
1514
|
centerY,
|
|
@@ -1535,7 +1537,8 @@ var addOvalPcbHole = (hole, ctx) => {
|
|
|
1535
1537
|
soldermaskCutSetting,
|
|
1536
1538
|
origin,
|
|
1537
1539
|
includeSoldermask,
|
|
1538
|
-
soldermaskMargin
|
|
1540
|
+
soldermaskMargin,
|
|
1541
|
+
includeCopper
|
|
1539
1542
|
} = ctx;
|
|
1540
1543
|
const centerX = hole.x + origin.x;
|
|
1541
1544
|
const centerY = hole.y + origin.y;
|
|
@@ -1555,7 +1558,7 @@ var addOvalPcbHole = (hole, ctx) => {
|
|
|
1555
1558
|
})
|
|
1556
1559
|
);
|
|
1557
1560
|
}
|
|
1558
|
-
if (hole.hole_width > 0 && hole.hole_height > 0) {
|
|
1561
|
+
if (hole.hole_width > 0 && hole.hole_height > 0 && includeCopper) {
|
|
1559
1562
|
const ovalPath = createOvalPath(
|
|
1560
1563
|
centerX,
|
|
1561
1564
|
centerY,
|
|
@@ -1582,7 +1585,8 @@ var addPillPcbHole = (hole, ctx) => {
|
|
|
1582
1585
|
soldermaskCutSetting,
|
|
1583
1586
|
origin,
|
|
1584
1587
|
includeSoldermask,
|
|
1585
|
-
soldermaskMargin
|
|
1588
|
+
soldermaskMargin,
|
|
1589
|
+
includeCopper
|
|
1586
1590
|
} = ctx;
|
|
1587
1591
|
const centerX = hole.x + origin.x;
|
|
1588
1592
|
const centerY = hole.y + origin.y;
|
|
@@ -1602,7 +1606,7 @@ var addPillPcbHole = (hole, ctx) => {
|
|
|
1602
1606
|
})
|
|
1603
1607
|
);
|
|
1604
1608
|
}
|
|
1605
|
-
if (hole.hole_width > 0 && hole.hole_height > 0) {
|
|
1609
|
+
if (hole.hole_width > 0 && hole.hole_height > 0 && includeCopper) {
|
|
1606
1610
|
const pillPath = createPillPath(
|
|
1607
1611
|
centerX,
|
|
1608
1612
|
centerY,
|
|
@@ -1629,7 +1633,8 @@ var addRotatedPillPcbHole = (hole, ctx) => {
|
|
|
1629
1633
|
soldermaskCutSetting,
|
|
1630
1634
|
origin,
|
|
1631
1635
|
includeSoldermask,
|
|
1632
|
-
soldermaskMargin
|
|
1636
|
+
soldermaskMargin,
|
|
1637
|
+
includeCopper
|
|
1633
1638
|
} = ctx;
|
|
1634
1639
|
const centerX = hole.x + origin.x;
|
|
1635
1640
|
const centerY = hole.y + origin.y;
|
|
@@ -1651,7 +1656,7 @@ var addRotatedPillPcbHole = (hole, ctx) => {
|
|
|
1651
1656
|
})
|
|
1652
1657
|
);
|
|
1653
1658
|
}
|
|
1654
|
-
if (hole.hole_width > 0 && hole.hole_height > 0) {
|
|
1659
|
+
if (hole.hole_width > 0 && hole.hole_height > 0 && includeCopper) {
|
|
1655
1660
|
const pillPath = createPillPath(
|
|
1656
1661
|
centerX,
|
|
1657
1662
|
centerY,
|
|
@@ -1690,6 +1695,222 @@ var addPcbHole = (hole, ctx) => {
|
|
|
1690
1695
|
}
|
|
1691
1696
|
};
|
|
1692
1697
|
|
|
1698
|
+
// lib/element-handlers/addPcbCutout/addCirclePcbCutout.ts
|
|
1699
|
+
import { ShapePath as ShapePath21 } from "lbrnts";
|
|
1700
|
+
var addCirclePcbCutout = (cutout, ctx) => {
|
|
1701
|
+
const {
|
|
1702
|
+
project,
|
|
1703
|
+
throughBoardCutSetting,
|
|
1704
|
+
origin,
|
|
1705
|
+
includeCopper,
|
|
1706
|
+
includeSoldermask,
|
|
1707
|
+
soldermaskMargin,
|
|
1708
|
+
soldermaskCutSetting
|
|
1709
|
+
} = ctx;
|
|
1710
|
+
const centerX = cutout.center.x + origin.x;
|
|
1711
|
+
const centerY = cutout.center.y + origin.y;
|
|
1712
|
+
if (cutout.radius > 0 && includeCopper) {
|
|
1713
|
+
const circlePath = createCirclePath(centerX, centerY, cutout.radius);
|
|
1714
|
+
project.children.push(
|
|
1715
|
+
new ShapePath21({
|
|
1716
|
+
cutIndex: throughBoardCutSetting.index,
|
|
1717
|
+
verts: circlePath.verts,
|
|
1718
|
+
prims: circlePath.prims,
|
|
1719
|
+
isClosed: true
|
|
1720
|
+
})
|
|
1721
|
+
);
|
|
1722
|
+
}
|
|
1723
|
+
if (cutout.radius > 0 && includeSoldermask) {
|
|
1724
|
+
const smRadius = cutout.radius + soldermaskMargin;
|
|
1725
|
+
const outer = createCirclePath(centerX, centerY, smRadius);
|
|
1726
|
+
project.children.push(
|
|
1727
|
+
new ShapePath21({
|
|
1728
|
+
cutIndex: soldermaskCutSetting.index,
|
|
1729
|
+
verts: outer.verts,
|
|
1730
|
+
prims: outer.prims,
|
|
1731
|
+
isClosed: true
|
|
1732
|
+
})
|
|
1733
|
+
);
|
|
1734
|
+
}
|
|
1735
|
+
};
|
|
1736
|
+
|
|
1737
|
+
// lib/element-handlers/addPcbCutout/addRectPcbCutout.ts
|
|
1738
|
+
import { ShapePath as ShapePath22 } from "lbrnts";
|
|
1739
|
+
var addRectPcbCutout = (cutout, ctx) => {
|
|
1740
|
+
const {
|
|
1741
|
+
project,
|
|
1742
|
+
throughBoardCutSetting,
|
|
1743
|
+
origin,
|
|
1744
|
+
includeCopper,
|
|
1745
|
+
includeSoldermask,
|
|
1746
|
+
soldermaskMargin,
|
|
1747
|
+
soldermaskCutSetting
|
|
1748
|
+
} = ctx;
|
|
1749
|
+
const centerX = cutout.center.x + origin.x;
|
|
1750
|
+
const centerY = cutout.center.y + origin.y;
|
|
1751
|
+
if (cutout.width > 0 && cutout.height > 0 && includeCopper) {
|
|
1752
|
+
const rotation = (cutout.rotation ?? 0) * (Math.PI / 180);
|
|
1753
|
+
const rectPath = createRoundedRectPath(
|
|
1754
|
+
centerX,
|
|
1755
|
+
centerY,
|
|
1756
|
+
cutout.width,
|
|
1757
|
+
cutout.height,
|
|
1758
|
+
0,
|
|
1759
|
+
// no border radius for cutouts
|
|
1760
|
+
4,
|
|
1761
|
+
// segments
|
|
1762
|
+
rotation
|
|
1763
|
+
);
|
|
1764
|
+
project.children.push(
|
|
1765
|
+
new ShapePath22({
|
|
1766
|
+
cutIndex: throughBoardCutSetting.index,
|
|
1767
|
+
verts: rectPath.verts,
|
|
1768
|
+
prims: rectPath.prims,
|
|
1769
|
+
isClosed: true
|
|
1770
|
+
})
|
|
1771
|
+
);
|
|
1772
|
+
}
|
|
1773
|
+
if (cutout.width > 0 && cutout.height > 0 && includeSoldermask) {
|
|
1774
|
+
const rotation = (cutout.rotation ?? 0) * (Math.PI / 180);
|
|
1775
|
+
const smWidth = cutout.width + 2 * soldermaskMargin;
|
|
1776
|
+
const smHeight = cutout.height + 2 * soldermaskMargin;
|
|
1777
|
+
const rectPath = createRoundedRectPath(
|
|
1778
|
+
centerX,
|
|
1779
|
+
centerY,
|
|
1780
|
+
smWidth,
|
|
1781
|
+
smHeight,
|
|
1782
|
+
0,
|
|
1783
|
+
// no border radius for cutouts
|
|
1784
|
+
4,
|
|
1785
|
+
// segments
|
|
1786
|
+
rotation
|
|
1787
|
+
);
|
|
1788
|
+
project.children.push(
|
|
1789
|
+
new ShapePath22({
|
|
1790
|
+
cutIndex: soldermaskCutSetting.index,
|
|
1791
|
+
verts: rectPath.verts,
|
|
1792
|
+
prims: rectPath.prims,
|
|
1793
|
+
isClosed: true
|
|
1794
|
+
})
|
|
1795
|
+
);
|
|
1796
|
+
}
|
|
1797
|
+
};
|
|
1798
|
+
|
|
1799
|
+
// lib/element-handlers/addPcbCutout/addPolygonPcbCutout.ts
|
|
1800
|
+
import { ShapePath as ShapePath23 } from "lbrnts";
|
|
1801
|
+
var addPolygonPcbCutout = (cutout, ctx) => {
|
|
1802
|
+
const {
|
|
1803
|
+
project,
|
|
1804
|
+
throughBoardCutSetting,
|
|
1805
|
+
origin,
|
|
1806
|
+
includeCopper,
|
|
1807
|
+
includeSoldermask,
|
|
1808
|
+
soldermaskCutSetting,
|
|
1809
|
+
soldermaskMargin
|
|
1810
|
+
} = ctx;
|
|
1811
|
+
if (cutout.points.length >= 3 && includeCopper) {
|
|
1812
|
+
const polygonPath = createPolygonPathFromOutline(
|
|
1813
|
+
cutout.points,
|
|
1814
|
+
origin.x,
|
|
1815
|
+
origin.y
|
|
1816
|
+
);
|
|
1817
|
+
project.children.push(
|
|
1818
|
+
new ShapePath23({
|
|
1819
|
+
cutIndex: throughBoardCutSetting.index,
|
|
1820
|
+
verts: polygonPath.verts,
|
|
1821
|
+
prims: polygonPath.prims,
|
|
1822
|
+
isClosed: true
|
|
1823
|
+
})
|
|
1824
|
+
);
|
|
1825
|
+
}
|
|
1826
|
+
if (cutout.points.length >= 3 && includeSoldermask) {
|
|
1827
|
+
const points = soldermaskMargin && soldermaskMargin > 0 ? cutout.points.map((p) => ({
|
|
1828
|
+
x: (p.x ?? 0) + (p.x ?? 0) > 0 ? soldermaskMargin : -soldermaskMargin,
|
|
1829
|
+
y: (p.y ?? 0) + (p.y ?? 0) > 0 ? soldermaskMargin : -soldermaskMargin
|
|
1830
|
+
})) : cutout.points;
|
|
1831
|
+
const polygonPath = createPolygonPathFromOutline(points, origin.x, origin.y);
|
|
1832
|
+
project.children.push(
|
|
1833
|
+
new ShapePath23({
|
|
1834
|
+
cutIndex: soldermaskCutSetting.index,
|
|
1835
|
+
verts: polygonPath.verts,
|
|
1836
|
+
prims: polygonPath.prims,
|
|
1837
|
+
isClosed: true
|
|
1838
|
+
})
|
|
1839
|
+
);
|
|
1840
|
+
}
|
|
1841
|
+
};
|
|
1842
|
+
|
|
1843
|
+
// lib/element-handlers/addPcbCutout/addPathPcbCutout.ts
|
|
1844
|
+
import { ShapePath as ShapePath24 } from "lbrnts";
|
|
1845
|
+
var addPathPcbCutout = (cutout, ctx) => {
|
|
1846
|
+
const {
|
|
1847
|
+
project,
|
|
1848
|
+
throughBoardCutSetting,
|
|
1849
|
+
origin,
|
|
1850
|
+
includeCopper,
|
|
1851
|
+
includeSoldermask,
|
|
1852
|
+
soldermaskMargin,
|
|
1853
|
+
soldermaskCutSetting
|
|
1854
|
+
} = ctx;
|
|
1855
|
+
if (cutout.route.length >= 2 && includeCopper) {
|
|
1856
|
+
const verts = [];
|
|
1857
|
+
const prims = [];
|
|
1858
|
+
for (const point6 of cutout.route) {
|
|
1859
|
+
verts.push({
|
|
1860
|
+
x: point6.x + origin.x,
|
|
1861
|
+
y: point6.y + origin.y
|
|
1862
|
+
});
|
|
1863
|
+
prims.push({ type: 0 });
|
|
1864
|
+
}
|
|
1865
|
+
project.children.push(
|
|
1866
|
+
new ShapePath24({
|
|
1867
|
+
cutIndex: throughBoardCutSetting.index,
|
|
1868
|
+
verts,
|
|
1869
|
+
prims,
|
|
1870
|
+
isClosed: false
|
|
1871
|
+
// Paths are typically not closed
|
|
1872
|
+
})
|
|
1873
|
+
);
|
|
1874
|
+
}
|
|
1875
|
+
if (cutout.route.length >= 2 && includeSoldermask) {
|
|
1876
|
+
const verts = [];
|
|
1877
|
+
const prims = [];
|
|
1878
|
+
for (const point6 of cutout.route) {
|
|
1879
|
+
verts.push({
|
|
1880
|
+
x: point6.x + origin.x,
|
|
1881
|
+
y: point6.y + origin.y
|
|
1882
|
+
});
|
|
1883
|
+
prims.push({ type: 0 });
|
|
1884
|
+
}
|
|
1885
|
+
project.children.push(
|
|
1886
|
+
new ShapePath24({
|
|
1887
|
+
cutIndex: soldermaskCutSetting.index,
|
|
1888
|
+
verts,
|
|
1889
|
+
prims,
|
|
1890
|
+
isClosed: false
|
|
1891
|
+
// Match the same path as the copper cutout
|
|
1892
|
+
})
|
|
1893
|
+
);
|
|
1894
|
+
}
|
|
1895
|
+
};
|
|
1896
|
+
|
|
1897
|
+
// lib/element-handlers/addPcbCutout/index.ts
|
|
1898
|
+
var addPcbCutout = (cutout, ctx) => {
|
|
1899
|
+
switch (cutout.shape) {
|
|
1900
|
+
case "circle":
|
|
1901
|
+
return addCirclePcbCutout(cutout, ctx);
|
|
1902
|
+
case "rect":
|
|
1903
|
+
return addRectPcbCutout(cutout, ctx);
|
|
1904
|
+
case "polygon":
|
|
1905
|
+
return addPolygonPcbCutout(cutout, ctx);
|
|
1906
|
+
case "path":
|
|
1907
|
+
return addPathPcbCutout(cutout, ctx);
|
|
1908
|
+
default:
|
|
1909
|
+
const _exhaustive = cutout;
|
|
1910
|
+
console.warn(`Unknown cutout shape: ${cutout.shape}`);
|
|
1911
|
+
}
|
|
1912
|
+
};
|
|
1913
|
+
|
|
1693
1914
|
// lib/index.ts
|
|
1694
1915
|
var convertCircuitJsonToLbrn = (circuitJson, options = {}) => {
|
|
1695
1916
|
const db = cju2(circuitJson);
|
|
@@ -1767,6 +1988,9 @@ var convertCircuitJsonToLbrn = (circuitJson, options = {}) => {
|
|
|
1767
1988
|
for (const hole of db.pcb_hole.list()) {
|
|
1768
1989
|
addPcbHole(hole, ctx);
|
|
1769
1990
|
}
|
|
1991
|
+
for (const cutout of db.pcb_cutout.list()) {
|
|
1992
|
+
addPcbCutout(cutout, ctx);
|
|
1993
|
+
}
|
|
1770
1994
|
if (ctx.includeCopper) {
|
|
1771
1995
|
for (const net of Object.keys(connMap.netMap)) {
|
|
1772
1996
|
const netGeoms = ctx.netGeoms.get(net);
|
|
@@ -1787,7 +2011,7 @@ var convertCircuitJsonToLbrn = (circuitJson, options = {}) => {
|
|
|
1787
2011
|
for (const island of union.splitToIslands()) {
|
|
1788
2012
|
const { verts, prims } = polygonToShapePathData(island);
|
|
1789
2013
|
project.children.push(
|
|
1790
|
-
new
|
|
2014
|
+
new ShapePath25({
|
|
1791
2015
|
cutIndex: copperCutSetting.index,
|
|
1792
2016
|
verts,
|
|
1793
2017
|
prims,
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { PcbCutoutCircle } from "circuit-json"
|
|
2
|
+
import type { ConvertContext } from "../../ConvertContext"
|
|
3
|
+
import { ShapePath } from "lbrnts"
|
|
4
|
+
import { createCirclePath } from "../../helpers/circleShape"
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Adds a circular PCB cutout to the project
|
|
8
|
+
* Cutouts are regions removed from the board entirely
|
|
9
|
+
*/
|
|
10
|
+
export const addCirclePcbCutout = (
|
|
11
|
+
cutout: PcbCutoutCircle,
|
|
12
|
+
ctx: ConvertContext,
|
|
13
|
+
): void => {
|
|
14
|
+
const {
|
|
15
|
+
project,
|
|
16
|
+
throughBoardCutSetting,
|
|
17
|
+
origin,
|
|
18
|
+
includeCopper,
|
|
19
|
+
includeSoldermask,
|
|
20
|
+
soldermaskMargin,
|
|
21
|
+
soldermaskCutSetting,
|
|
22
|
+
} = ctx
|
|
23
|
+
const centerX = cutout.center.x + origin.x
|
|
24
|
+
const centerY = cutout.center.y + origin.y
|
|
25
|
+
|
|
26
|
+
// Add the cutout - cut through the board
|
|
27
|
+
if (cutout.radius > 0 && includeCopper) {
|
|
28
|
+
const circlePath = createCirclePath(centerX, centerY, cutout.radius)
|
|
29
|
+
project.children.push(
|
|
30
|
+
new ShapePath({
|
|
31
|
+
cutIndex: throughBoardCutSetting.index,
|
|
32
|
+
verts: circlePath.verts,
|
|
33
|
+
prims: circlePath.prims,
|
|
34
|
+
isClosed: true,
|
|
35
|
+
}),
|
|
36
|
+
)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Add soldermask opening if drawing soldermask
|
|
40
|
+
if (cutout.radius > 0 && includeSoldermask) {
|
|
41
|
+
const smRadius = cutout.radius + soldermaskMargin
|
|
42
|
+
const outer = createCirclePath(centerX, centerY, smRadius)
|
|
43
|
+
project.children.push(
|
|
44
|
+
new ShapePath({
|
|
45
|
+
cutIndex: soldermaskCutSetting.index,
|
|
46
|
+
verts: outer.verts,
|
|
47
|
+
prims: outer.prims,
|
|
48
|
+
isClosed: true,
|
|
49
|
+
}),
|
|
50
|
+
)
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { PcbCutoutPath } from "circuit-json"
|
|
2
|
+
import type { ConvertContext } from "../../ConvertContext"
|
|
3
|
+
import { ShapePath } from "lbrnts"
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Adds a path-based PCB cutout to the project
|
|
7
|
+
* Path cutouts create slots along a route (e.g., for routed slots or complex cutout paths)
|
|
8
|
+
*/
|
|
9
|
+
export const addPathPcbCutout = (
|
|
10
|
+
cutout: PcbCutoutPath,
|
|
11
|
+
ctx: ConvertContext,
|
|
12
|
+
): void => {
|
|
13
|
+
const {
|
|
14
|
+
project,
|
|
15
|
+
throughBoardCutSetting,
|
|
16
|
+
origin,
|
|
17
|
+
includeCopper,
|
|
18
|
+
includeSoldermask,
|
|
19
|
+
soldermaskMargin,
|
|
20
|
+
soldermaskCutSetting,
|
|
21
|
+
} = ctx
|
|
22
|
+
|
|
23
|
+
// For path cutouts, we need to create a stroke along the route with the given width
|
|
24
|
+
// For simplicity, we'll convert the path to a polyline
|
|
25
|
+
if (cutout.route.length >= 2 && includeCopper) {
|
|
26
|
+
const verts: { x: number; y: number }[] = []
|
|
27
|
+
const prims: { type: number }[] = []
|
|
28
|
+
|
|
29
|
+
for (const point of cutout.route) {
|
|
30
|
+
verts.push({
|
|
31
|
+
x: point.x + origin.x,
|
|
32
|
+
y: point.y + origin.y,
|
|
33
|
+
})
|
|
34
|
+
prims.push({ type: 0 })
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Note: slot_width, slot_length, space_between_slots, and slot_corner_radius
|
|
38
|
+
// would require more complex path offsetting and aren't currently implemented
|
|
39
|
+
// For now, we just create a simple path along the route
|
|
40
|
+
project.children.push(
|
|
41
|
+
new ShapePath({
|
|
42
|
+
cutIndex: throughBoardCutSetting.index,
|
|
43
|
+
verts,
|
|
44
|
+
prims,
|
|
45
|
+
isClosed: false, // Paths are typically not closed
|
|
46
|
+
}),
|
|
47
|
+
)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Add soldermask opening if drawing soldermask
|
|
51
|
+
if (cutout.route.length >= 2 && includeSoldermask) {
|
|
52
|
+
const verts: { x: number; y: number }[] = []
|
|
53
|
+
const prims: { type: number }[] = []
|
|
54
|
+
|
|
55
|
+
// Create path with soldermask margin
|
|
56
|
+
for (const point of cutout.route) {
|
|
57
|
+
verts.push({
|
|
58
|
+
x: point.x + origin.x,
|
|
59
|
+
y: point.y + origin.y,
|
|
60
|
+
})
|
|
61
|
+
prims.push({ type: 0 })
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
project.children.push(
|
|
65
|
+
new ShapePath({
|
|
66
|
+
cutIndex: soldermaskCutSetting.index,
|
|
67
|
+
verts,
|
|
68
|
+
prims,
|
|
69
|
+
isClosed: false, // Match the same path as the copper cutout
|
|
70
|
+
}),
|
|
71
|
+
)
|
|
72
|
+
}
|
|
73
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { PcbCutoutPolygon } from "circuit-json"
|
|
2
|
+
import type { ConvertContext } from "../../ConvertContext"
|
|
3
|
+
import { ShapePath } from "lbrnts"
|
|
4
|
+
import { createPolygonPathFromOutline } from "../../helpers/polygonShape"
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Adds a polygon PCB cutout to the project
|
|
8
|
+
* Cutouts are regions removed from the board entirely
|
|
9
|
+
*/
|
|
10
|
+
export const addPolygonPcbCutout = (
|
|
11
|
+
cutout: PcbCutoutPolygon,
|
|
12
|
+
ctx: ConvertContext,
|
|
13
|
+
): void => {
|
|
14
|
+
const {
|
|
15
|
+
project,
|
|
16
|
+
throughBoardCutSetting,
|
|
17
|
+
origin,
|
|
18
|
+
includeCopper,
|
|
19
|
+
includeSoldermask,
|
|
20
|
+
soldermaskCutSetting,
|
|
21
|
+
soldermaskMargin,
|
|
22
|
+
} = ctx
|
|
23
|
+
|
|
24
|
+
// Add the cutout - cut through the board
|
|
25
|
+
if (cutout.points.length >= 3 && includeCopper) {
|
|
26
|
+
const polygonPath = createPolygonPathFromOutline(
|
|
27
|
+
cutout.points,
|
|
28
|
+
origin.x,
|
|
29
|
+
origin.y,
|
|
30
|
+
)
|
|
31
|
+
project.children.push(
|
|
32
|
+
new ShapePath({
|
|
33
|
+
cutIndex: throughBoardCutSetting.index,
|
|
34
|
+
verts: polygonPath.verts,
|
|
35
|
+
prims: polygonPath.prims,
|
|
36
|
+
isClosed: true,
|
|
37
|
+
}),
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Add soldermask opening if drawing soldermask
|
|
42
|
+
if (cutout.points.length >= 3 && includeSoldermask) {
|
|
43
|
+
// Apply soldermask margin to the points if margin is specified
|
|
44
|
+
const points =
|
|
45
|
+
soldermaskMargin && soldermaskMargin > 0
|
|
46
|
+
? cutout.points.map((p) => ({
|
|
47
|
+
x:
|
|
48
|
+
(p.x ?? 0) + (p.x ?? 0) > 0
|
|
49
|
+
? soldermaskMargin
|
|
50
|
+
: -soldermaskMargin,
|
|
51
|
+
y:
|
|
52
|
+
(p.y ?? 0) + (p.y ?? 0) > 0
|
|
53
|
+
? soldermaskMargin
|
|
54
|
+
: -soldermaskMargin,
|
|
55
|
+
}))
|
|
56
|
+
: cutout.points
|
|
57
|
+
|
|
58
|
+
const polygonPath = createPolygonPathFromOutline(points, origin.x, origin.y)
|
|
59
|
+
project.children.push(
|
|
60
|
+
new ShapePath({
|
|
61
|
+
cutIndex: soldermaskCutSetting.index,
|
|
62
|
+
verts: polygonPath.verts,
|
|
63
|
+
prims: polygonPath.prims,
|
|
64
|
+
isClosed: true,
|
|
65
|
+
}),
|
|
66
|
+
)
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { PcbCutoutRect } from "circuit-json"
|
|
2
|
+
import type { ConvertContext } from "../../ConvertContext"
|
|
3
|
+
import { ShapePath } from "lbrnts"
|
|
4
|
+
import { createRoundedRectPath } from "../../helpers/roundedRectShape"
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Adds a rectangular PCB cutout to the project
|
|
8
|
+
* Cutouts are regions removed from the board entirely
|
|
9
|
+
*/
|
|
10
|
+
export const addRectPcbCutout = (
|
|
11
|
+
cutout: PcbCutoutRect,
|
|
12
|
+
ctx: ConvertContext,
|
|
13
|
+
): void => {
|
|
14
|
+
const {
|
|
15
|
+
project,
|
|
16
|
+
throughBoardCutSetting,
|
|
17
|
+
origin,
|
|
18
|
+
includeCopper,
|
|
19
|
+
includeSoldermask,
|
|
20
|
+
soldermaskMargin,
|
|
21
|
+
soldermaskCutSetting,
|
|
22
|
+
} = ctx
|
|
23
|
+
const centerX = cutout.center.x + origin.x
|
|
24
|
+
const centerY = cutout.center.y + origin.y
|
|
25
|
+
|
|
26
|
+
// Add the cutout - cut through the board
|
|
27
|
+
if (cutout.width > 0 && cutout.height > 0 && includeCopper) {
|
|
28
|
+
const rotation = (cutout.rotation ?? 0) * (Math.PI / 180) // Convert degrees to radians
|
|
29
|
+
const rectPath = createRoundedRectPath(
|
|
30
|
+
centerX,
|
|
31
|
+
centerY,
|
|
32
|
+
cutout.width,
|
|
33
|
+
cutout.height,
|
|
34
|
+
0, // no border radius for cutouts
|
|
35
|
+
4, // segments
|
|
36
|
+
rotation,
|
|
37
|
+
)
|
|
38
|
+
project.children.push(
|
|
39
|
+
new ShapePath({
|
|
40
|
+
cutIndex: throughBoardCutSetting.index,
|
|
41
|
+
verts: rectPath.verts,
|
|
42
|
+
prims: rectPath.prims,
|
|
43
|
+
isClosed: true,
|
|
44
|
+
}),
|
|
45
|
+
)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Add soldermask opening if drawing soldermask
|
|
49
|
+
if (cutout.width > 0 && cutout.height > 0 && includeSoldermask) {
|
|
50
|
+
const rotation = (cutout.rotation ?? 0) * (Math.PI / 180) // Convert degrees to radians
|
|
51
|
+
const smWidth = cutout.width + 2 * soldermaskMargin
|
|
52
|
+
const smHeight = cutout.height + 2 * soldermaskMargin
|
|
53
|
+
const rectPath = createRoundedRectPath(
|
|
54
|
+
centerX,
|
|
55
|
+
centerY,
|
|
56
|
+
smWidth,
|
|
57
|
+
smHeight,
|
|
58
|
+
0, // no border radius for cutouts
|
|
59
|
+
4, // segments
|
|
60
|
+
rotation,
|
|
61
|
+
)
|
|
62
|
+
project.children.push(
|
|
63
|
+
new ShapePath({
|
|
64
|
+
cutIndex: soldermaskCutSetting.index,
|
|
65
|
+
verts: rectPath.verts,
|
|
66
|
+
prims: rectPath.prims,
|
|
67
|
+
isClosed: true,
|
|
68
|
+
}),
|
|
69
|
+
)
|
|
70
|
+
}
|
|
71
|
+
}
|