circuit-json-to-lbrn 0.0.16 → 0.0.18
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 +478 -2
- 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 +51 -0
- package/lib/element-handlers/addPcbHole/addOvalPcbHole.ts +59 -0
- package/lib/element-handlers/addPcbHole/addPillPcbHole.ts +59 -0
- package/lib/element-handlers/addPcbHole/addRectPcbHole.ts +61 -0
- package/lib/element-handlers/addPcbHole/addRotatedPillPcbHole.ts +62 -0
- package/lib/element-handlers/addPcbHole/index.ts +36 -0
- package/lib/index.ts +10 -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/addPcbHole/__snapshots__/pcb-hole-circle.snap.svg +8 -0
- package/tests/examples/addPcbHole/__snapshots__/pcb-hole-oval.snap.svg +8 -0
- package/tests/examples/addPcbHole/__snapshots__/pcb-hole-pill.snap.svg +8 -0
- package/tests/examples/addPcbHole/__snapshots__/pcb-hole-rect.snap.svg +8 -0
- package/tests/examples/addPcbHole/__snapshots__/pcb-hole-rotated-pill.snap.svg +8 -0
- package/tests/examples/addPcbHole/__snapshots__/pcb-hole-with-soldermask.snap.svg +8 -0
- package/tests/examples/addPcbHole/pcb-hole-circle.test.ts +47 -0
- package/tests/examples/addPcbHole/pcb-hole-oval.test.ts +49 -0
- package/tests/examples/addPcbHole/pcb-hole-pill.test.ts +49 -0
- package/tests/examples/addPcbHole/pcb-hole-rect.test.ts +49 -0
- package/tests/examples/addPcbHole/pcb-hole-rotated-pill.test.ts +61 -0
- package/tests/examples/addPcbHole/pcb-hole-with-soldermask.test.ts +60 -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
|
|
@@ -1436,6 +1436,476 @@ var addPcbVia = (via, ctx) => {
|
|
|
1436
1436
|
}
|
|
1437
1437
|
};
|
|
1438
1438
|
|
|
1439
|
+
// lib/element-handlers/addPcbHole/addCirclePcbHole.ts
|
|
1440
|
+
import { ShapePath as ShapePath16 } from "lbrnts";
|
|
1441
|
+
var addCirclePcbHole = (hole, ctx) => {
|
|
1442
|
+
const {
|
|
1443
|
+
project,
|
|
1444
|
+
throughBoardCutSetting,
|
|
1445
|
+
soldermaskCutSetting,
|
|
1446
|
+
origin,
|
|
1447
|
+
includeSoldermask,
|
|
1448
|
+
soldermaskMargin
|
|
1449
|
+
} = ctx;
|
|
1450
|
+
const centerX = hole.x + origin.x;
|
|
1451
|
+
const centerY = hole.y + origin.y;
|
|
1452
|
+
if (hole.hole_diameter > 0 && includeSoldermask) {
|
|
1453
|
+
const smRadius = hole.hole_diameter / 2 + soldermaskMargin;
|
|
1454
|
+
const soldermaskPath = createCirclePath(centerX, centerY, smRadius);
|
|
1455
|
+
project.children.push(
|
|
1456
|
+
new ShapePath16({
|
|
1457
|
+
cutIndex: soldermaskCutSetting.index,
|
|
1458
|
+
verts: soldermaskPath.verts,
|
|
1459
|
+
prims: soldermaskPath.prims,
|
|
1460
|
+
isClosed: true
|
|
1461
|
+
})
|
|
1462
|
+
);
|
|
1463
|
+
}
|
|
1464
|
+
if (hole.hole_diameter > 0) {
|
|
1465
|
+
const radius = hole.hole_diameter / 2;
|
|
1466
|
+
const circlePath = createCirclePath(centerX, centerY, radius);
|
|
1467
|
+
project.children.push(
|
|
1468
|
+
new ShapePath16({
|
|
1469
|
+
cutIndex: throughBoardCutSetting.index,
|
|
1470
|
+
verts: circlePath.verts,
|
|
1471
|
+
prims: circlePath.prims,
|
|
1472
|
+
isClosed: true
|
|
1473
|
+
})
|
|
1474
|
+
);
|
|
1475
|
+
}
|
|
1476
|
+
};
|
|
1477
|
+
|
|
1478
|
+
// lib/element-handlers/addPcbHole/addRectPcbHole.ts
|
|
1479
|
+
import { ShapePath as ShapePath17 } from "lbrnts";
|
|
1480
|
+
var addRectPcbHole = (hole, ctx) => {
|
|
1481
|
+
const {
|
|
1482
|
+
project,
|
|
1483
|
+
throughBoardCutSetting,
|
|
1484
|
+
soldermaskCutSetting,
|
|
1485
|
+
origin,
|
|
1486
|
+
includeSoldermask,
|
|
1487
|
+
soldermaskMargin
|
|
1488
|
+
} = ctx;
|
|
1489
|
+
const centerX = hole.x + origin.x;
|
|
1490
|
+
const centerY = hole.y + origin.y;
|
|
1491
|
+
if (hole.hole_width > 0 && hole.hole_height > 0 && includeSoldermask) {
|
|
1492
|
+
const soldermaskPath = createRoundedRectPath(
|
|
1493
|
+
centerX,
|
|
1494
|
+
centerY,
|
|
1495
|
+
hole.hole_width + soldermaskMargin * 2,
|
|
1496
|
+
hole.hole_height + soldermaskMargin * 2,
|
|
1497
|
+
0
|
|
1498
|
+
// no border radius for rect holes
|
|
1499
|
+
);
|
|
1500
|
+
project.children.push(
|
|
1501
|
+
new ShapePath17({
|
|
1502
|
+
cutIndex: soldermaskCutSetting.index,
|
|
1503
|
+
verts: soldermaskPath.verts,
|
|
1504
|
+
prims: soldermaskPath.prims,
|
|
1505
|
+
isClosed: true
|
|
1506
|
+
})
|
|
1507
|
+
);
|
|
1508
|
+
}
|
|
1509
|
+
if (hole.hole_width > 0 && hole.hole_height > 0) {
|
|
1510
|
+
const rectPath = createRoundedRectPath(
|
|
1511
|
+
centerX,
|
|
1512
|
+
centerY,
|
|
1513
|
+
hole.hole_width,
|
|
1514
|
+
hole.hole_height,
|
|
1515
|
+
0
|
|
1516
|
+
// no border radius for rect holes
|
|
1517
|
+
);
|
|
1518
|
+
project.children.push(
|
|
1519
|
+
new ShapePath17({
|
|
1520
|
+
cutIndex: throughBoardCutSetting.index,
|
|
1521
|
+
verts: rectPath.verts,
|
|
1522
|
+
prims: rectPath.prims,
|
|
1523
|
+
isClosed: true
|
|
1524
|
+
})
|
|
1525
|
+
);
|
|
1526
|
+
}
|
|
1527
|
+
};
|
|
1528
|
+
|
|
1529
|
+
// lib/element-handlers/addPcbHole/addOvalPcbHole.ts
|
|
1530
|
+
import { ShapePath as ShapePath18 } from "lbrnts";
|
|
1531
|
+
var addOvalPcbHole = (hole, ctx) => {
|
|
1532
|
+
const {
|
|
1533
|
+
project,
|
|
1534
|
+
throughBoardCutSetting,
|
|
1535
|
+
soldermaskCutSetting,
|
|
1536
|
+
origin,
|
|
1537
|
+
includeSoldermask,
|
|
1538
|
+
soldermaskMargin
|
|
1539
|
+
} = ctx;
|
|
1540
|
+
const centerX = hole.x + origin.x;
|
|
1541
|
+
const centerY = hole.y + origin.y;
|
|
1542
|
+
if (hole.hole_width > 0 && hole.hole_height > 0 && includeSoldermask) {
|
|
1543
|
+
const soldermaskPath = createOvalPath(
|
|
1544
|
+
centerX,
|
|
1545
|
+
centerY,
|
|
1546
|
+
hole.hole_width + soldermaskMargin * 2,
|
|
1547
|
+
hole.hole_height + soldermaskMargin * 2
|
|
1548
|
+
);
|
|
1549
|
+
project.children.push(
|
|
1550
|
+
new ShapePath18({
|
|
1551
|
+
cutIndex: soldermaskCutSetting.index,
|
|
1552
|
+
verts: soldermaskPath.verts,
|
|
1553
|
+
prims: soldermaskPath.prims,
|
|
1554
|
+
isClosed: true
|
|
1555
|
+
})
|
|
1556
|
+
);
|
|
1557
|
+
}
|
|
1558
|
+
if (hole.hole_width > 0 && hole.hole_height > 0) {
|
|
1559
|
+
const ovalPath = createOvalPath(
|
|
1560
|
+
centerX,
|
|
1561
|
+
centerY,
|
|
1562
|
+
hole.hole_width,
|
|
1563
|
+
hole.hole_height
|
|
1564
|
+
);
|
|
1565
|
+
project.children.push(
|
|
1566
|
+
new ShapePath18({
|
|
1567
|
+
cutIndex: throughBoardCutSetting.index,
|
|
1568
|
+
verts: ovalPath.verts,
|
|
1569
|
+
prims: ovalPath.prims,
|
|
1570
|
+
isClosed: true
|
|
1571
|
+
})
|
|
1572
|
+
);
|
|
1573
|
+
}
|
|
1574
|
+
};
|
|
1575
|
+
|
|
1576
|
+
// lib/element-handlers/addPcbHole/addPillPcbHole.ts
|
|
1577
|
+
import { ShapePath as ShapePath19 } from "lbrnts";
|
|
1578
|
+
var addPillPcbHole = (hole, ctx) => {
|
|
1579
|
+
const {
|
|
1580
|
+
project,
|
|
1581
|
+
throughBoardCutSetting,
|
|
1582
|
+
soldermaskCutSetting,
|
|
1583
|
+
origin,
|
|
1584
|
+
includeSoldermask,
|
|
1585
|
+
soldermaskMargin
|
|
1586
|
+
} = ctx;
|
|
1587
|
+
const centerX = hole.x + origin.x;
|
|
1588
|
+
const centerY = hole.y + origin.y;
|
|
1589
|
+
if (hole.hole_width > 0 && hole.hole_height > 0 && includeSoldermask) {
|
|
1590
|
+
const soldermaskPath = createPillPath(
|
|
1591
|
+
centerX,
|
|
1592
|
+
centerY,
|
|
1593
|
+
hole.hole_width + soldermaskMargin * 2,
|
|
1594
|
+
hole.hole_height + soldermaskMargin * 2
|
|
1595
|
+
);
|
|
1596
|
+
project.children.push(
|
|
1597
|
+
new ShapePath19({
|
|
1598
|
+
cutIndex: soldermaskCutSetting.index,
|
|
1599
|
+
verts: soldermaskPath.verts,
|
|
1600
|
+
prims: soldermaskPath.prims,
|
|
1601
|
+
isClosed: true
|
|
1602
|
+
})
|
|
1603
|
+
);
|
|
1604
|
+
}
|
|
1605
|
+
if (hole.hole_width > 0 && hole.hole_height > 0) {
|
|
1606
|
+
const pillPath = createPillPath(
|
|
1607
|
+
centerX,
|
|
1608
|
+
centerY,
|
|
1609
|
+
hole.hole_width,
|
|
1610
|
+
hole.hole_height
|
|
1611
|
+
);
|
|
1612
|
+
project.children.push(
|
|
1613
|
+
new ShapePath19({
|
|
1614
|
+
cutIndex: throughBoardCutSetting.index,
|
|
1615
|
+
verts: pillPath.verts,
|
|
1616
|
+
prims: pillPath.prims,
|
|
1617
|
+
isClosed: true
|
|
1618
|
+
})
|
|
1619
|
+
);
|
|
1620
|
+
}
|
|
1621
|
+
};
|
|
1622
|
+
|
|
1623
|
+
// lib/element-handlers/addPcbHole/addRotatedPillPcbHole.ts
|
|
1624
|
+
import { ShapePath as ShapePath20 } from "lbrnts";
|
|
1625
|
+
var addRotatedPillPcbHole = (hole, ctx) => {
|
|
1626
|
+
const {
|
|
1627
|
+
project,
|
|
1628
|
+
throughBoardCutSetting,
|
|
1629
|
+
soldermaskCutSetting,
|
|
1630
|
+
origin,
|
|
1631
|
+
includeSoldermask,
|
|
1632
|
+
soldermaskMargin
|
|
1633
|
+
} = ctx;
|
|
1634
|
+
const centerX = hole.x + origin.x;
|
|
1635
|
+
const centerY = hole.y + origin.y;
|
|
1636
|
+
const rotation = (hole.ccw_rotation || 0) * (Math.PI / 180);
|
|
1637
|
+
if (hole.hole_width > 0 && hole.hole_height > 0 && includeSoldermask) {
|
|
1638
|
+
const soldermaskPath = createPillPath(
|
|
1639
|
+
centerX,
|
|
1640
|
+
centerY,
|
|
1641
|
+
hole.hole_width + soldermaskMargin * 2,
|
|
1642
|
+
hole.hole_height + soldermaskMargin * 2,
|
|
1643
|
+
rotation
|
|
1644
|
+
);
|
|
1645
|
+
project.children.push(
|
|
1646
|
+
new ShapePath20({
|
|
1647
|
+
cutIndex: soldermaskCutSetting.index,
|
|
1648
|
+
verts: soldermaskPath.verts,
|
|
1649
|
+
prims: soldermaskPath.prims,
|
|
1650
|
+
isClosed: true
|
|
1651
|
+
})
|
|
1652
|
+
);
|
|
1653
|
+
}
|
|
1654
|
+
if (hole.hole_width > 0 && hole.hole_height > 0) {
|
|
1655
|
+
const pillPath = createPillPath(
|
|
1656
|
+
centerX,
|
|
1657
|
+
centerY,
|
|
1658
|
+
hole.hole_width,
|
|
1659
|
+
hole.hole_height,
|
|
1660
|
+
rotation
|
|
1661
|
+
);
|
|
1662
|
+
project.children.push(
|
|
1663
|
+
new ShapePath20({
|
|
1664
|
+
cutIndex: throughBoardCutSetting.index,
|
|
1665
|
+
verts: pillPath.verts,
|
|
1666
|
+
prims: pillPath.prims,
|
|
1667
|
+
isClosed: true
|
|
1668
|
+
})
|
|
1669
|
+
);
|
|
1670
|
+
}
|
|
1671
|
+
};
|
|
1672
|
+
|
|
1673
|
+
// lib/element-handlers/addPcbHole/index.ts
|
|
1674
|
+
var addPcbHole = (hole, ctx) => {
|
|
1675
|
+
switch (hole.hole_shape) {
|
|
1676
|
+
case "circle":
|
|
1677
|
+
case "square":
|
|
1678
|
+
return addCirclePcbHole(hole, ctx);
|
|
1679
|
+
case "rect":
|
|
1680
|
+
return addRectPcbHole(hole, ctx);
|
|
1681
|
+
case "oval":
|
|
1682
|
+
return addOvalPcbHole(hole, ctx);
|
|
1683
|
+
case "pill":
|
|
1684
|
+
return addPillPcbHole(hole, ctx);
|
|
1685
|
+
case "rotated_pill":
|
|
1686
|
+
return addRotatedPillPcbHole(hole, ctx);
|
|
1687
|
+
default:
|
|
1688
|
+
const _exhaustive = hole;
|
|
1689
|
+
console.warn(`Unknown hole shape: ${hole.hole_shape}`);
|
|
1690
|
+
}
|
|
1691
|
+
};
|
|
1692
|
+
|
|
1693
|
+
// lib/element-handlers/addPcbCutout/addCirclePcbCutout.ts
|
|
1694
|
+
import { ShapePath as ShapePath21 } from "lbrnts";
|
|
1695
|
+
var addCirclePcbCutout = (cutout, ctx) => {
|
|
1696
|
+
const {
|
|
1697
|
+
project,
|
|
1698
|
+
throughBoardCutSetting,
|
|
1699
|
+
origin,
|
|
1700
|
+
includeCopper,
|
|
1701
|
+
includeSoldermask,
|
|
1702
|
+
soldermaskMargin,
|
|
1703
|
+
soldermaskCutSetting
|
|
1704
|
+
} = ctx;
|
|
1705
|
+
const centerX = cutout.center.x + origin.x;
|
|
1706
|
+
const centerY = cutout.center.y + origin.y;
|
|
1707
|
+
if (cutout.radius > 0 && includeCopper) {
|
|
1708
|
+
const circlePath = createCirclePath(centerX, centerY, cutout.radius);
|
|
1709
|
+
project.children.push(
|
|
1710
|
+
new ShapePath21({
|
|
1711
|
+
cutIndex: throughBoardCutSetting.index,
|
|
1712
|
+
verts: circlePath.verts,
|
|
1713
|
+
prims: circlePath.prims,
|
|
1714
|
+
isClosed: true
|
|
1715
|
+
})
|
|
1716
|
+
);
|
|
1717
|
+
}
|
|
1718
|
+
if (cutout.radius > 0 && includeSoldermask) {
|
|
1719
|
+
const smRadius = cutout.radius + soldermaskMargin;
|
|
1720
|
+
const outer = createCirclePath(centerX, centerY, smRadius);
|
|
1721
|
+
project.children.push(
|
|
1722
|
+
new ShapePath21({
|
|
1723
|
+
cutIndex: soldermaskCutSetting.index,
|
|
1724
|
+
verts: outer.verts,
|
|
1725
|
+
prims: outer.prims,
|
|
1726
|
+
isClosed: true
|
|
1727
|
+
})
|
|
1728
|
+
);
|
|
1729
|
+
}
|
|
1730
|
+
};
|
|
1731
|
+
|
|
1732
|
+
// lib/element-handlers/addPcbCutout/addRectPcbCutout.ts
|
|
1733
|
+
import { ShapePath as ShapePath22 } from "lbrnts";
|
|
1734
|
+
var addRectPcbCutout = (cutout, ctx) => {
|
|
1735
|
+
const {
|
|
1736
|
+
project,
|
|
1737
|
+
throughBoardCutSetting,
|
|
1738
|
+
origin,
|
|
1739
|
+
includeCopper,
|
|
1740
|
+
includeSoldermask,
|
|
1741
|
+
soldermaskMargin,
|
|
1742
|
+
soldermaskCutSetting
|
|
1743
|
+
} = ctx;
|
|
1744
|
+
const centerX = cutout.center.x + origin.x;
|
|
1745
|
+
const centerY = cutout.center.y + origin.y;
|
|
1746
|
+
if (cutout.width > 0 && cutout.height > 0 && includeCopper) {
|
|
1747
|
+
const rotation = (cutout.rotation ?? 0) * (Math.PI / 180);
|
|
1748
|
+
const rectPath = createRoundedRectPath(
|
|
1749
|
+
centerX,
|
|
1750
|
+
centerY,
|
|
1751
|
+
cutout.width,
|
|
1752
|
+
cutout.height,
|
|
1753
|
+
0,
|
|
1754
|
+
// no border radius for cutouts
|
|
1755
|
+
4,
|
|
1756
|
+
// segments
|
|
1757
|
+
rotation
|
|
1758
|
+
);
|
|
1759
|
+
project.children.push(
|
|
1760
|
+
new ShapePath22({
|
|
1761
|
+
cutIndex: throughBoardCutSetting.index,
|
|
1762
|
+
verts: rectPath.verts,
|
|
1763
|
+
prims: rectPath.prims,
|
|
1764
|
+
isClosed: true
|
|
1765
|
+
})
|
|
1766
|
+
);
|
|
1767
|
+
}
|
|
1768
|
+
if (cutout.width > 0 && cutout.height > 0 && includeSoldermask) {
|
|
1769
|
+
const rotation = (cutout.rotation ?? 0) * (Math.PI / 180);
|
|
1770
|
+
const smWidth = cutout.width + 2 * soldermaskMargin;
|
|
1771
|
+
const smHeight = cutout.height + 2 * soldermaskMargin;
|
|
1772
|
+
const rectPath = createRoundedRectPath(
|
|
1773
|
+
centerX,
|
|
1774
|
+
centerY,
|
|
1775
|
+
smWidth,
|
|
1776
|
+
smHeight,
|
|
1777
|
+
0,
|
|
1778
|
+
// no border radius for cutouts
|
|
1779
|
+
4,
|
|
1780
|
+
// segments
|
|
1781
|
+
rotation
|
|
1782
|
+
);
|
|
1783
|
+
project.children.push(
|
|
1784
|
+
new ShapePath22({
|
|
1785
|
+
cutIndex: soldermaskCutSetting.index,
|
|
1786
|
+
verts: rectPath.verts,
|
|
1787
|
+
prims: rectPath.prims,
|
|
1788
|
+
isClosed: true
|
|
1789
|
+
})
|
|
1790
|
+
);
|
|
1791
|
+
}
|
|
1792
|
+
};
|
|
1793
|
+
|
|
1794
|
+
// lib/element-handlers/addPcbCutout/addPolygonPcbCutout.ts
|
|
1795
|
+
import { ShapePath as ShapePath23 } from "lbrnts";
|
|
1796
|
+
var addPolygonPcbCutout = (cutout, ctx) => {
|
|
1797
|
+
const {
|
|
1798
|
+
project,
|
|
1799
|
+
throughBoardCutSetting,
|
|
1800
|
+
origin,
|
|
1801
|
+
includeCopper,
|
|
1802
|
+
includeSoldermask,
|
|
1803
|
+
soldermaskCutSetting,
|
|
1804
|
+
soldermaskMargin
|
|
1805
|
+
} = ctx;
|
|
1806
|
+
if (cutout.points.length >= 3 && includeCopper) {
|
|
1807
|
+
const polygonPath = createPolygonPathFromOutline(
|
|
1808
|
+
cutout.points,
|
|
1809
|
+
origin.x,
|
|
1810
|
+
origin.y
|
|
1811
|
+
);
|
|
1812
|
+
project.children.push(
|
|
1813
|
+
new ShapePath23({
|
|
1814
|
+
cutIndex: throughBoardCutSetting.index,
|
|
1815
|
+
verts: polygonPath.verts,
|
|
1816
|
+
prims: polygonPath.prims,
|
|
1817
|
+
isClosed: true
|
|
1818
|
+
})
|
|
1819
|
+
);
|
|
1820
|
+
}
|
|
1821
|
+
if (cutout.points.length >= 3 && includeSoldermask) {
|
|
1822
|
+
const points = soldermaskMargin && soldermaskMargin > 0 ? cutout.points.map((p) => ({
|
|
1823
|
+
x: (p.x ?? 0) + (p.x ?? 0) > 0 ? soldermaskMargin : -soldermaskMargin,
|
|
1824
|
+
y: (p.y ?? 0) + (p.y ?? 0) > 0 ? soldermaskMargin : -soldermaskMargin
|
|
1825
|
+
})) : cutout.points;
|
|
1826
|
+
const polygonPath = createPolygonPathFromOutline(points, origin.x, origin.y);
|
|
1827
|
+
project.children.push(
|
|
1828
|
+
new ShapePath23({
|
|
1829
|
+
cutIndex: soldermaskCutSetting.index,
|
|
1830
|
+
verts: polygonPath.verts,
|
|
1831
|
+
prims: polygonPath.prims,
|
|
1832
|
+
isClosed: true
|
|
1833
|
+
})
|
|
1834
|
+
);
|
|
1835
|
+
}
|
|
1836
|
+
};
|
|
1837
|
+
|
|
1838
|
+
// lib/element-handlers/addPcbCutout/addPathPcbCutout.ts
|
|
1839
|
+
import { ShapePath as ShapePath24 } from "lbrnts";
|
|
1840
|
+
var addPathPcbCutout = (cutout, ctx) => {
|
|
1841
|
+
const {
|
|
1842
|
+
project,
|
|
1843
|
+
throughBoardCutSetting,
|
|
1844
|
+
origin,
|
|
1845
|
+
includeCopper,
|
|
1846
|
+
includeSoldermask,
|
|
1847
|
+
soldermaskMargin,
|
|
1848
|
+
soldermaskCutSetting
|
|
1849
|
+
} = ctx;
|
|
1850
|
+
if (cutout.route.length >= 2 && includeCopper) {
|
|
1851
|
+
const verts = [];
|
|
1852
|
+
const prims = [];
|
|
1853
|
+
for (const point6 of cutout.route) {
|
|
1854
|
+
verts.push({
|
|
1855
|
+
x: point6.x + origin.x,
|
|
1856
|
+
y: point6.y + origin.y
|
|
1857
|
+
});
|
|
1858
|
+
prims.push({ type: 0 });
|
|
1859
|
+
}
|
|
1860
|
+
project.children.push(
|
|
1861
|
+
new ShapePath24({
|
|
1862
|
+
cutIndex: throughBoardCutSetting.index,
|
|
1863
|
+
verts,
|
|
1864
|
+
prims,
|
|
1865
|
+
isClosed: false
|
|
1866
|
+
// Paths are typically not closed
|
|
1867
|
+
})
|
|
1868
|
+
);
|
|
1869
|
+
}
|
|
1870
|
+
if (cutout.route.length >= 2 && includeSoldermask) {
|
|
1871
|
+
const verts = [];
|
|
1872
|
+
const prims = [];
|
|
1873
|
+
for (const point6 of cutout.route) {
|
|
1874
|
+
verts.push({
|
|
1875
|
+
x: point6.x + origin.x,
|
|
1876
|
+
y: point6.y + origin.y
|
|
1877
|
+
});
|
|
1878
|
+
prims.push({ type: 0 });
|
|
1879
|
+
}
|
|
1880
|
+
project.children.push(
|
|
1881
|
+
new ShapePath24({
|
|
1882
|
+
cutIndex: soldermaskCutSetting.index,
|
|
1883
|
+
verts,
|
|
1884
|
+
prims,
|
|
1885
|
+
isClosed: false
|
|
1886
|
+
// Match the same path as the copper cutout
|
|
1887
|
+
})
|
|
1888
|
+
);
|
|
1889
|
+
}
|
|
1890
|
+
};
|
|
1891
|
+
|
|
1892
|
+
// lib/element-handlers/addPcbCutout/index.ts
|
|
1893
|
+
var addPcbCutout = (cutout, ctx) => {
|
|
1894
|
+
switch (cutout.shape) {
|
|
1895
|
+
case "circle":
|
|
1896
|
+
return addCirclePcbCutout(cutout, ctx);
|
|
1897
|
+
case "rect":
|
|
1898
|
+
return addRectPcbCutout(cutout, ctx);
|
|
1899
|
+
case "polygon":
|
|
1900
|
+
return addPolygonPcbCutout(cutout, ctx);
|
|
1901
|
+
case "path":
|
|
1902
|
+
return addPathPcbCutout(cutout, ctx);
|
|
1903
|
+
default:
|
|
1904
|
+
const _exhaustive = cutout;
|
|
1905
|
+
console.warn(`Unknown cutout shape: ${cutout.shape}`);
|
|
1906
|
+
}
|
|
1907
|
+
};
|
|
1908
|
+
|
|
1439
1909
|
// lib/index.ts
|
|
1440
1910
|
var convertCircuitJsonToLbrn = (circuitJson, options = {}) => {
|
|
1441
1911
|
const db = cju2(circuitJson);
|
|
@@ -1510,6 +1980,12 @@ var convertCircuitJsonToLbrn = (circuitJson, options = {}) => {
|
|
|
1510
1980
|
for (const via of db.pcb_via.list()) {
|
|
1511
1981
|
addPcbVia(via, ctx);
|
|
1512
1982
|
}
|
|
1983
|
+
for (const hole of db.pcb_hole.list()) {
|
|
1984
|
+
addPcbHole(hole, ctx);
|
|
1985
|
+
}
|
|
1986
|
+
for (const cutout of db.pcb_cutout.list()) {
|
|
1987
|
+
addPcbCutout(cutout, ctx);
|
|
1988
|
+
}
|
|
1513
1989
|
if (ctx.includeCopper) {
|
|
1514
1990
|
for (const net of Object.keys(connMap.netMap)) {
|
|
1515
1991
|
const netGeoms = ctx.netGeoms.get(net);
|
|
@@ -1530,7 +2006,7 @@ var convertCircuitJsonToLbrn = (circuitJson, options = {}) => {
|
|
|
1530
2006
|
for (const island of union.splitToIslands()) {
|
|
1531
2007
|
const { verts, prims } = polygonToShapePathData(island);
|
|
1532
2008
|
project.children.push(
|
|
1533
|
-
new
|
|
2009
|
+
new ShapePath25({
|
|
1534
2010
|
cutIndex: copperCutSetting.index,
|
|
1535
2011
|
verts,
|
|
1536
2012
|
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
|
+
}
|