@tscircuit/checks 0.0.161 → 0.0.162
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/README.md +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.js +83 -9
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -28,7 +28,7 @@ and output an array of arrays for any issues found.
|
|
|
28
28
|
| [`checkSourceTracesHavePcbTraces`](./lib/check-source-traces-have-pcb-traces.ts) | Returns `pcb_trace_error` when source traces are missing corresponding `pcb_trace` routes. |
|
|
29
29
|
| [`checkTracesAreContiguous`](./lib/check-traces-are-contiguous/check-traces-are-contiguous.ts) | Returns `pcb_trace_error` when trace endpoints are floating or do not connect as expected. |
|
|
30
30
|
| [`checkViasOffBoard`](./lib/check-pcb-components-out-of-board/checkViasOffBoard.ts) | Returns `pcb_placement_error` if any PCB via lies outside or crosses the board boundary. |
|
|
31
|
-
| [`checkCopperToBoardEdgeClearance`](./lib/check-copper-to-board-edge-clearance.ts) | Checks via, SMT-pad,
|
|
31
|
+
| [`checkCopperToBoardEdgeClearance`](./lib/check-copper-to-board-edge-clearance.ts) | Checks via, SMT-pad, plated-hole, and copper-pour geometry against the polygon board outline and required edge clearance. |
|
|
32
32
|
|
|
33
33
|
## Aggregate check runner functions
|
|
34
34
|
|
package/dist/index.d.ts
CHANGED
|
@@ -18,8 +18,9 @@ declare class NetManager {
|
|
|
18
18
|
declare function checkViasOffBoard(circuitJson: AnyCircuitElement[]): PcbPlacementError[];
|
|
19
19
|
|
|
20
20
|
/**
|
|
21
|
-
* Checks the finished copper geometry of every via, SMT pad,
|
|
22
|
-
* against the real board outline and its configured edge-clearance
|
|
21
|
+
* Checks the finished copper geometry of every via, SMT pad, plated hole, and
|
|
22
|
+
* copper pour against the real board outline and its configured edge-clearance
|
|
23
|
+
* rule.
|
|
23
24
|
*
|
|
24
25
|
* Component and footprint rotations are normally composed into Circuit JSON's
|
|
25
26
|
* absolute coordinates and `ccw_rotation` fields. Polygon-pad plated holes are
|
package/dist/index.js
CHANGED
|
@@ -1536,6 +1536,57 @@ var pointsToPolygon = (points) => {
|
|
|
1536
1536
|
if (points.length < 3) return null;
|
|
1537
1537
|
return new Flatten.Polygon(points.map(({ x, y }) => new Flatten.Point(x, y)));
|
|
1538
1538
|
};
|
|
1539
|
+
var brepRingToPolygon = (vertices) => {
|
|
1540
|
+
const ring = vertices.filter((vertex, index) => {
|
|
1541
|
+
const previous = vertices[index - 1];
|
|
1542
|
+
return !previous || Math.abs(previous.x - vertex.x) > GEOMETRY_EPSILON || Math.abs(previous.y - vertex.y) > GEOMETRY_EPSILON;
|
|
1543
|
+
});
|
|
1544
|
+
if (ring.length > 1 && Math.abs(ring[0].x - ring.at(-1).x) <= GEOMETRY_EPSILON && Math.abs(ring[0].y - ring.at(-1).y) <= GEOMETRY_EPSILON) {
|
|
1545
|
+
ring.pop();
|
|
1546
|
+
}
|
|
1547
|
+
if (ring.length < 3) return null;
|
|
1548
|
+
const edges = [];
|
|
1549
|
+
for (let index = 0; index < ring.length; index++) {
|
|
1550
|
+
const start = ring[index];
|
|
1551
|
+
const end = ring[(index + 1) % ring.length];
|
|
1552
|
+
const startPoint = new Flatten.Point(start.x, start.y);
|
|
1553
|
+
const endPoint = new Flatten.Point(end.x, end.y);
|
|
1554
|
+
const bulge = start.bulge ?? 0;
|
|
1555
|
+
if (Math.abs(bulge) <= GEOMETRY_EPSILON) {
|
|
1556
|
+
edges.push(new Flatten.Segment(startPoint, endPoint));
|
|
1557
|
+
continue;
|
|
1558
|
+
}
|
|
1559
|
+
const chordLength = startPoint.distanceTo(endPoint)[0];
|
|
1560
|
+
if (chordLength <= GEOMETRY_EPSILON) continue;
|
|
1561
|
+
const midpoint2 = {
|
|
1562
|
+
x: (start.x + end.x) / 2,
|
|
1563
|
+
y: (start.y + end.y) / 2
|
|
1564
|
+
};
|
|
1565
|
+
const leftNormal = {
|
|
1566
|
+
x: -(end.y - start.y) / chordLength,
|
|
1567
|
+
y: (end.x - start.x) / chordLength
|
|
1568
|
+
};
|
|
1569
|
+
const centerOffset = chordLength * (1 - bulge * bulge) / (4 * bulge);
|
|
1570
|
+
const center = new Flatten.Point(
|
|
1571
|
+
midpoint2.x + leftNormal.x * centerOffset,
|
|
1572
|
+
midpoint2.y + leftNormal.y * centerOffset
|
|
1573
|
+
);
|
|
1574
|
+
const radius = chordLength * (1 + bulge * bulge) / (4 * Math.abs(bulge));
|
|
1575
|
+
edges.push(
|
|
1576
|
+
new Flatten.Arc(
|
|
1577
|
+
center,
|
|
1578
|
+
radius,
|
|
1579
|
+
Math.atan2(start.y - center.y, start.x - center.x),
|
|
1580
|
+
Math.atan2(end.y - center.y, end.x - center.x),
|
|
1581
|
+
bulge > 0
|
|
1582
|
+
)
|
|
1583
|
+
);
|
|
1584
|
+
}
|
|
1585
|
+
if (edges.length < 3) return null;
|
|
1586
|
+
const polygon = new Flatten.Polygon();
|
|
1587
|
+
polygon.addFace(edges);
|
|
1588
|
+
return polygon;
|
|
1589
|
+
};
|
|
1539
1590
|
var boardToPolygon = (board) => {
|
|
1540
1591
|
if (board.outline && board.outline.length >= 3) {
|
|
1541
1592
|
return pointsToPolygon(board.outline);
|
|
@@ -1773,22 +1824,45 @@ var getCopperGeometry = (element, componentCcwRotationsById) => {
|
|
|
1773
1824
|
};
|
|
1774
1825
|
}
|
|
1775
1826
|
if (element.type === "pcb_smtpad") return getSmtPadGeometry(element);
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1827
|
+
if (element.type === "pcb_plated_hole") {
|
|
1828
|
+
return getPlatedHoleGeometry(
|
|
1829
|
+
element,
|
|
1830
|
+
element.pcb_component_id ? componentCcwRotationsById.get(
|
|
1831
|
+
toPcbComponentId(element.pcb_component_id)
|
|
1832
|
+
) ?? 0 : 0
|
|
1833
|
+
);
|
|
1834
|
+
}
|
|
1835
|
+
let polygon;
|
|
1836
|
+
switch (element.shape) {
|
|
1837
|
+
case "rect":
|
|
1838
|
+
polygon = getRectanglePolygon({
|
|
1839
|
+
x: element.center.x,
|
|
1840
|
+
y: element.center.y,
|
|
1841
|
+
width: element.width,
|
|
1842
|
+
height: element.height,
|
|
1843
|
+
ccwRotationDegrees: element.rotation ?? 0
|
|
1844
|
+
});
|
|
1845
|
+
break;
|
|
1846
|
+
case "polygon":
|
|
1847
|
+
polygon = pointsToPolygon(element.points);
|
|
1848
|
+
break;
|
|
1849
|
+
case "brep":
|
|
1850
|
+
polygon = brepRingToPolygon(element.brep_shape.outer_ring.vertices);
|
|
1851
|
+
break;
|
|
1852
|
+
}
|
|
1853
|
+
return polygon ? { kind: "shapes", shapes: [polygon] } : null;
|
|
1782
1854
|
};
|
|
1783
1855
|
var getCopperElementId = (element) => {
|
|
1784
1856
|
if (element.type === "pcb_via") return element.pcb_via_id;
|
|
1785
1857
|
if (element.type === "pcb_smtpad") return element.pcb_smtpad_id;
|
|
1786
|
-
return element.pcb_plated_hole_id;
|
|
1858
|
+
if (element.type === "pcb_plated_hole") return element.pcb_plated_hole_id;
|
|
1859
|
+
return element.pcb_copper_pour_id;
|
|
1787
1860
|
};
|
|
1788
1861
|
var getCopperElementLabel = (element) => {
|
|
1789
1862
|
if (element.type === "pcb_via") return "Via";
|
|
1790
1863
|
if (element.type === "pcb_smtpad") return "SMT pad";
|
|
1791
|
-
return "Plated hole";
|
|
1864
|
+
if (element.type === "pcb_plated_hole") return "Plated hole";
|
|
1865
|
+
return "Copper pour";
|
|
1792
1866
|
};
|
|
1793
1867
|
var measureClearance = (board, geometry) => {
|
|
1794
1868
|
if (geometry.kind === "shapes") {
|
|
@@ -1816,7 +1890,7 @@ function checkCopperToBoardEdgeClearance(circuitJson) {
|
|
|
1816
1890
|
const requiredClearance = getBoardDrcValue(board, "min_board_edge_clearance") ?? jlcMinTolerances.min_board_edge_clearance;
|
|
1817
1891
|
if (requiredClearance === void 0) return [];
|
|
1818
1892
|
const copperElements = circuitJson.filter(
|
|
1819
|
-
(element) => element.type === "pcb_via" || element.type === "pcb_smtpad" || element.type === "pcb_plated_hole"
|
|
1893
|
+
(element) => element.type === "pcb_via" || element.type === "pcb_smtpad" || element.type === "pcb_plated_hole" || element.type === "pcb_copper_pour"
|
|
1820
1894
|
);
|
|
1821
1895
|
const componentCcwRotationsById = new Map(
|
|
1822
1896
|
circuitJson.filter(
|