circuit-json-to-lbrn 0.0.15 → 0.0.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. package/dist/index.js +337 -13
  2. package/lib/element-handlers/addPcbHole/addCirclePcbHole.ts +51 -0
  3. package/lib/element-handlers/addPcbHole/addOvalPcbHole.ts +59 -0
  4. package/lib/element-handlers/addPcbHole/addPillPcbHole.ts +59 -0
  5. package/lib/element-handlers/addPcbHole/addRectPcbHole.ts +61 -0
  6. package/lib/element-handlers/addPcbHole/addRotatedPillPcbHole.ts +62 -0
  7. package/lib/element-handlers/addPcbHole/index.ts +36 -0
  8. package/lib/element-handlers/addPcbVia/index.ts +84 -0
  9. package/lib/index.ts +10 -0
  10. package/package.json +1 -1
  11. package/tests/examples/addPcbHole/__snapshots__/pcb-hole-circle.snap.svg +8 -0
  12. package/tests/examples/addPcbHole/__snapshots__/pcb-hole-oval.snap.svg +8 -0
  13. package/tests/examples/addPcbHole/__snapshots__/pcb-hole-pill.snap.svg +8 -0
  14. package/tests/examples/addPcbHole/__snapshots__/pcb-hole-rect.snap.svg +8 -0
  15. package/tests/examples/addPcbHole/__snapshots__/pcb-hole-rotated-pill.snap.svg +8 -0
  16. package/tests/examples/addPcbHole/__snapshots__/pcb-hole-with-soldermask.snap.svg +8 -0
  17. package/tests/examples/addPcbHole/pcb-hole-circle.test.ts +47 -0
  18. package/tests/examples/addPcbHole/pcb-hole-oval.test.ts +49 -0
  19. package/tests/examples/addPcbHole/pcb-hole-pill.test.ts +49 -0
  20. package/tests/examples/addPcbHole/pcb-hole-rect.test.ts +49 -0
  21. package/tests/examples/addPcbHole/pcb-hole-rotated-pill.test.ts +61 -0
  22. package/tests/examples/addPcbHole/pcb-hole-with-soldermask.test.ts +60 -0
  23. package/tests/examples/addPcbVia/__snapshots__/pcb-via-basic.snap.svg +8 -0
  24. package/tests/examples/addPcbVia/__snapshots__/pcb-via-with-net.snap.svg +8 -0
  25. package/tests/examples/addPcbVia/__snapshots__/pcb-via-with-soldermask.snap.svg +8 -0
  26. package/tests/examples/addPcbVia/pcb-via-basic.test.ts +49 -0
  27. package/tests/examples/addPcbVia/pcb-via-with-net.test.ts +126 -0
  28. package/tests/examples/addPcbVia/pcb-via-with-soldermask.test.ts +53 -0
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // lib/index.ts
2
- import { LightBurnProject, CutSetting, ShapePath as ShapePath15 } from "lbrnts";
2
+ import { LightBurnProject, CutSetting, ShapePath as ShapePath21 } from "lbrnts";
3
3
  import { cju as cju2 } from "@tscircuit/circuit-json-util";
4
4
 
5
5
  // lib/element-handlers/addPlatedHole/addCirclePlatedHole.ts
@@ -602,9 +602,9 @@ import { ShapePath as ShapePath6 } from "lbrnts";
602
602
  // lib/helpers/polygonShape.ts
603
603
  var createPolygonPathFromOutline = (outline, offsetX, offsetY) => {
604
604
  const verts = [];
605
- for (const point5 of outline) {
606
- const x = (point5.x ?? 0) + offsetX;
607
- const y = (point5.y ?? 0) + offsetY;
605
+ for (const point6 of outline) {
606
+ const x = (point6.x ?? 0) + offsetX;
607
+ const y = (point6.y ?? 0) + offsetY;
608
608
  verts.push({ x, y });
609
609
  }
610
610
  if (verts.length === 0) {
@@ -1207,7 +1207,7 @@ var addPcbTrace = (trace, ctx) => {
1207
1207
  return;
1208
1208
  }
1209
1209
  const { route } = trace;
1210
- const traceWidth = route.find((point5) => point5.route_type === "wire")?.width ?? 0.15;
1210
+ const traceWidth = route.find((point6) => point6.route_type === "wire")?.width ?? 0.15;
1211
1211
  const polygons = [];
1212
1212
  for (const routePoint of route) {
1213
1213
  const circle = new Flatten2.Circle(
@@ -1341,14 +1341,14 @@ var calculateCircuitBounds = (circuitJson) => {
1341
1341
  }
1342
1342
  }
1343
1343
  for (const trace of db.pcb_trace.list()) {
1344
- const isWidthPoint = (point5) => "width" in point5 && typeof point5.width === "number";
1344
+ const isWidthPoint = (point6) => "width" in point6 && typeof point6.width === "number";
1345
1345
  const halfWidth = trace.route_thickness_mode === "interpolated" ? 0 : (trace.route.find(isWidthPoint)?.width ?? 0) / 2;
1346
- for (const point5 of trace.route) {
1347
- const pointWidth = trace.route_thickness_mode === "interpolated" ? isWidthPoint(point5) ? point5.width / 2 : 0 : halfWidth;
1348
- minX = Math.min(minX, point5.x - pointWidth);
1349
- minY = Math.min(minY, point5.y - pointWidth);
1350
- maxX = Math.max(maxX, point5.x + pointWidth);
1351
- maxY = Math.max(maxY, point5.y + pointWidth);
1346
+ for (const point6 of trace.route) {
1347
+ const pointWidth = trace.route_thickness_mode === "interpolated" ? isWidthPoint(point6) ? point6.width / 2 : 0 : halfWidth;
1348
+ minX = Math.min(minX, point6.x - pointWidth);
1349
+ minY = Math.min(minY, point6.y - pointWidth);
1350
+ maxX = Math.max(maxX, point6.x + pointWidth);
1351
+ maxY = Math.max(maxY, point6.y + pointWidth);
1352
1352
  }
1353
1353
  }
1354
1354
  for (const hole of db.pcb_plated_hole.list()) {
@@ -1372,6 +1372,324 @@ var calculateOriginFromBounds = (bounds, margin) => {
1372
1372
  return { x: originX, y: originY };
1373
1373
  };
1374
1374
 
1375
+ // lib/element-handlers/addPcbVia/index.ts
1376
+ import { ShapePath as ShapePath15 } from "lbrnts";
1377
+ import { Circle as Circle3, point as point5 } from "@flatten-js/core";
1378
+ var addPcbVia = (via, ctx) => {
1379
+ const {
1380
+ db,
1381
+ project,
1382
+ copperCutSetting,
1383
+ soldermaskCutSetting,
1384
+ throughBoardCutSetting,
1385
+ origin,
1386
+ includeCopper,
1387
+ includeSoldermask,
1388
+ connMap,
1389
+ soldermaskMargin
1390
+ } = ctx;
1391
+ const centerX = via.x + origin.x;
1392
+ const centerY = via.y + origin.y;
1393
+ if (via.outer_diameter > 0 && includeCopper) {
1394
+ const viaPort = db.pcb_port.list().find((port) => port.x === via.x && port.y === via.y);
1395
+ const netId = viaPort ? connMap.getNetConnectedToId(viaPort.pcb_port_id) : void 0;
1396
+ const outerRadius = via.outer_diameter / 2;
1397
+ const circle = new Circle3(point5(centerX, centerY), outerRadius);
1398
+ const polygon = circleToPolygon(circle);
1399
+ if (netId) {
1400
+ ctx.netGeoms.get(netId)?.push(polygon);
1401
+ } else {
1402
+ const outer = createCirclePath(centerX, centerY, outerRadius);
1403
+ project.children.push(
1404
+ new ShapePath15({
1405
+ cutIndex: copperCutSetting.index,
1406
+ verts: outer.verts,
1407
+ prims: outer.prims,
1408
+ isClosed: true
1409
+ })
1410
+ );
1411
+ }
1412
+ }
1413
+ if (via.outer_diameter > 0 && includeSoldermask) {
1414
+ const smRadius = via.outer_diameter / 2 + soldermaskMargin;
1415
+ const outer = createCirclePath(centerX, centerY, smRadius);
1416
+ project.children.push(
1417
+ new ShapePath15({
1418
+ cutIndex: soldermaskCutSetting.index,
1419
+ verts: outer.verts,
1420
+ prims: outer.prims,
1421
+ isClosed: true
1422
+ })
1423
+ );
1424
+ }
1425
+ if (via.hole_diameter > 0) {
1426
+ const innerRadius = via.hole_diameter / 2;
1427
+ const inner = createCirclePath(centerX, centerY, innerRadius);
1428
+ project.children.push(
1429
+ new ShapePath15({
1430
+ cutIndex: throughBoardCutSetting.index,
1431
+ verts: inner.verts,
1432
+ prims: inner.prims,
1433
+ isClosed: true
1434
+ })
1435
+ );
1436
+ }
1437
+ };
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
+
1375
1693
  // lib/index.ts
1376
1694
  var convertCircuitJsonToLbrn = (circuitJson, options = {}) => {
1377
1695
  const db = cju2(circuitJson);
@@ -1443,6 +1761,12 @@ var convertCircuitJsonToLbrn = (circuitJson, options = {}) => {
1443
1761
  for (const board of db.pcb_board.list()) {
1444
1762
  addPcbBoard(board, ctx);
1445
1763
  }
1764
+ for (const via of db.pcb_via.list()) {
1765
+ addPcbVia(via, ctx);
1766
+ }
1767
+ for (const hole of db.pcb_hole.list()) {
1768
+ addPcbHole(hole, ctx);
1769
+ }
1446
1770
  if (ctx.includeCopper) {
1447
1771
  for (const net of Object.keys(connMap.netMap)) {
1448
1772
  const netGeoms = ctx.netGeoms.get(net);
@@ -1463,7 +1787,7 @@ var convertCircuitJsonToLbrn = (circuitJson, options = {}) => {
1463
1787
  for (const island of union.splitToIslands()) {
1464
1788
  const { verts, prims } = polygonToShapePathData(island);
1465
1789
  project.children.push(
1466
- new ShapePath15({
1790
+ new ShapePath21({
1467
1791
  cutIndex: copperCutSetting.index,
1468
1792
  verts,
1469
1793
  prims,
@@ -0,0 +1,51 @@
1
+ import type { PcbHoleCircle, PcbHoleCircleOrSquare } 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 hole (non-plated) to the project
8
+ */
9
+ export const addCirclePcbHole = (
10
+ hole: PcbHoleCircle | PcbHoleCircleOrSquare,
11
+ ctx: ConvertContext,
12
+ ): void => {
13
+ const {
14
+ project,
15
+ throughBoardCutSetting,
16
+ soldermaskCutSetting,
17
+ origin,
18
+ includeSoldermask,
19
+ soldermaskMargin,
20
+ } = ctx
21
+ const centerX = hole.x + origin.x
22
+ const centerY = hole.y + origin.y
23
+
24
+ // Add soldermask opening if drawing soldermask
25
+ if (hole.hole_diameter > 0 && includeSoldermask) {
26
+ const smRadius = hole.hole_diameter / 2 + soldermaskMargin
27
+ const soldermaskPath = createCirclePath(centerX, centerY, smRadius)
28
+ project.children.push(
29
+ new ShapePath({
30
+ cutIndex: soldermaskCutSetting.index,
31
+ verts: soldermaskPath.verts,
32
+ prims: soldermaskPath.prims,
33
+ isClosed: true,
34
+ }),
35
+ )
36
+ }
37
+
38
+ // Add the hole - cut through the board
39
+ if (hole.hole_diameter > 0) {
40
+ const radius = hole.hole_diameter / 2
41
+ const circlePath = createCirclePath(centerX, centerY, radius)
42
+ project.children.push(
43
+ new ShapePath({
44
+ cutIndex: throughBoardCutSetting.index,
45
+ verts: circlePath.verts,
46
+ prims: circlePath.prims,
47
+ isClosed: true,
48
+ }),
49
+ )
50
+ }
51
+ }
@@ -0,0 +1,59 @@
1
+ import type { PcbHoleOval } from "circuit-json"
2
+ import type { ConvertContext } from "../../ConvertContext"
3
+ import { ShapePath } from "lbrnts"
4
+ import { createOvalPath } from "../../helpers/ovalShape"
5
+
6
+ /**
7
+ * Adds an oval PCB hole (non-plated) to the project
8
+ */
9
+ export const addOvalPcbHole = (
10
+ hole: PcbHoleOval,
11
+ ctx: ConvertContext,
12
+ ): void => {
13
+ const {
14
+ project,
15
+ throughBoardCutSetting,
16
+ soldermaskCutSetting,
17
+ origin,
18
+ includeSoldermask,
19
+ soldermaskMargin,
20
+ } = ctx
21
+ const centerX = hole.x + origin.x
22
+ const centerY = hole.y + origin.y
23
+
24
+ // Add soldermask opening if drawing soldermask
25
+ if (hole.hole_width > 0 && hole.hole_height > 0 && includeSoldermask) {
26
+ const soldermaskPath = createOvalPath(
27
+ centerX,
28
+ centerY,
29
+ hole.hole_width + soldermaskMargin * 2,
30
+ hole.hole_height + soldermaskMargin * 2,
31
+ )
32
+ project.children.push(
33
+ new ShapePath({
34
+ cutIndex: soldermaskCutSetting.index,
35
+ verts: soldermaskPath.verts,
36
+ prims: soldermaskPath.prims,
37
+ isClosed: true,
38
+ }),
39
+ )
40
+ }
41
+
42
+ // Add the hole - cut through the board
43
+ if (hole.hole_width > 0 && hole.hole_height > 0) {
44
+ const ovalPath = createOvalPath(
45
+ centerX,
46
+ centerY,
47
+ hole.hole_width,
48
+ hole.hole_height,
49
+ )
50
+ project.children.push(
51
+ new ShapePath({
52
+ cutIndex: throughBoardCutSetting.index,
53
+ verts: ovalPath.verts,
54
+ prims: ovalPath.prims,
55
+ isClosed: true,
56
+ }),
57
+ )
58
+ }
59
+ }
@@ -0,0 +1,59 @@
1
+ import type { PcbHolePill } from "circuit-json"
2
+ import type { ConvertContext } from "../../ConvertContext"
3
+ import { ShapePath } from "lbrnts"
4
+ import { createPillPath } from "../../helpers/pillShape"
5
+
6
+ /**
7
+ * Adds a pill-shaped PCB hole (non-plated) to the project
8
+ */
9
+ export const addPillPcbHole = (
10
+ hole: PcbHolePill,
11
+ ctx: ConvertContext,
12
+ ): void => {
13
+ const {
14
+ project,
15
+ throughBoardCutSetting,
16
+ soldermaskCutSetting,
17
+ origin,
18
+ includeSoldermask,
19
+ soldermaskMargin,
20
+ } = ctx
21
+ const centerX = hole.x + origin.x
22
+ const centerY = hole.y + origin.y
23
+
24
+ // Add soldermask opening if drawing soldermask
25
+ if (hole.hole_width > 0 && hole.hole_height > 0 && includeSoldermask) {
26
+ const soldermaskPath = createPillPath(
27
+ centerX,
28
+ centerY,
29
+ hole.hole_width + soldermaskMargin * 2,
30
+ hole.hole_height + soldermaskMargin * 2,
31
+ )
32
+ project.children.push(
33
+ new ShapePath({
34
+ cutIndex: soldermaskCutSetting.index,
35
+ verts: soldermaskPath.verts,
36
+ prims: soldermaskPath.prims,
37
+ isClosed: true,
38
+ }),
39
+ )
40
+ }
41
+
42
+ // Add the hole - cut through the board
43
+ if (hole.hole_width > 0 && hole.hole_height > 0) {
44
+ const pillPath = createPillPath(
45
+ centerX,
46
+ centerY,
47
+ hole.hole_width,
48
+ hole.hole_height,
49
+ )
50
+ project.children.push(
51
+ new ShapePath({
52
+ cutIndex: throughBoardCutSetting.index,
53
+ verts: pillPath.verts,
54
+ prims: pillPath.prims,
55
+ isClosed: true,
56
+ }),
57
+ )
58
+ }
59
+ }
@@ -0,0 +1,61 @@
1
+ import type { PcbHoleRect } 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 hole (non-plated) to the project
8
+ */
9
+ export const addRectPcbHole = (
10
+ hole: PcbHoleRect,
11
+ ctx: ConvertContext,
12
+ ): void => {
13
+ const {
14
+ project,
15
+ throughBoardCutSetting,
16
+ soldermaskCutSetting,
17
+ origin,
18
+ includeSoldermask,
19
+ soldermaskMargin,
20
+ } = ctx
21
+ const centerX = hole.x + origin.x
22
+ const centerY = hole.y + origin.y
23
+
24
+ // Add soldermask opening if drawing soldermask
25
+ if (hole.hole_width > 0 && hole.hole_height > 0 && includeSoldermask) {
26
+ const soldermaskPath = createRoundedRectPath(
27
+ centerX,
28
+ centerY,
29
+ hole.hole_width + soldermaskMargin * 2,
30
+ hole.hole_height + soldermaskMargin * 2,
31
+ 0, // no border radius for rect holes
32
+ )
33
+ project.children.push(
34
+ new ShapePath({
35
+ cutIndex: soldermaskCutSetting.index,
36
+ verts: soldermaskPath.verts,
37
+ prims: soldermaskPath.prims,
38
+ isClosed: true,
39
+ }),
40
+ )
41
+ }
42
+
43
+ // Add the hole - cut through the board
44
+ if (hole.hole_width > 0 && hole.hole_height > 0) {
45
+ const rectPath = createRoundedRectPath(
46
+ centerX,
47
+ centerY,
48
+ hole.hole_width,
49
+ hole.hole_height,
50
+ 0, // no border radius for rect holes
51
+ )
52
+ project.children.push(
53
+ new ShapePath({
54
+ cutIndex: throughBoardCutSetting.index,
55
+ verts: rectPath.verts,
56
+ prims: rectPath.prims,
57
+ isClosed: true,
58
+ }),
59
+ )
60
+ }
61
+ }
@@ -0,0 +1,62 @@
1
+ import type { PcbHoleRotatedPill } from "circuit-json"
2
+ import type { ConvertContext } from "../../ConvertContext"
3
+ import { ShapePath } from "lbrnts"
4
+ import { createPillPath } from "../../helpers/pillShape"
5
+
6
+ /**
7
+ * Adds a rotated pill-shaped PCB hole (non-plated) to the project
8
+ */
9
+ export const addRotatedPillPcbHole = (
10
+ hole: PcbHoleRotatedPill,
11
+ ctx: ConvertContext,
12
+ ): void => {
13
+ const {
14
+ project,
15
+ throughBoardCutSetting,
16
+ soldermaskCutSetting,
17
+ origin,
18
+ includeSoldermask,
19
+ soldermaskMargin,
20
+ } = ctx
21
+ const centerX = hole.x + origin.x
22
+ const centerY = hole.y + origin.y
23
+ const rotation = (hole.ccw_rotation || 0) * (Math.PI / 180) // Convert degrees to radians
24
+
25
+ // Add soldermask opening if drawing soldermask
26
+ if (hole.hole_width > 0 && hole.hole_height > 0 && includeSoldermask) {
27
+ const soldermaskPath = createPillPath(
28
+ centerX,
29
+ centerY,
30
+ hole.hole_width + soldermaskMargin * 2,
31
+ hole.hole_height + soldermaskMargin * 2,
32
+ rotation,
33
+ )
34
+ project.children.push(
35
+ new ShapePath({
36
+ cutIndex: soldermaskCutSetting.index,
37
+ verts: soldermaskPath.verts,
38
+ prims: soldermaskPath.prims,
39
+ isClosed: true,
40
+ }),
41
+ )
42
+ }
43
+
44
+ // Add the hole - cut through the board
45
+ if (hole.hole_width > 0 && hole.hole_height > 0) {
46
+ const pillPath = createPillPath(
47
+ centerX,
48
+ centerY,
49
+ hole.hole_width,
50
+ hole.hole_height,
51
+ rotation,
52
+ )
53
+ project.children.push(
54
+ new ShapePath({
55
+ cutIndex: throughBoardCutSetting.index,
56
+ verts: pillPath.verts,
57
+ prims: pillPath.prims,
58
+ isClosed: true,
59
+ }),
60
+ )
61
+ }
62
+ }