@tscircuit/checks 0.0.127 → 0.0.129
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 +97 -15
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -811,14 +811,17 @@ var getCollidableBounds = (collidable) => {
|
|
|
811
811
|
};
|
|
812
812
|
|
|
813
813
|
// lib/check-each-pcb-trace-non-overlapping/getPcbPortIdsConnectedToTraces.ts
|
|
814
|
+
function getPcbPortIdsConnectedToRoutePoint(routePoint) {
|
|
815
|
+
if (routePoint.route_type !== "wire") return [];
|
|
816
|
+
return [routePoint.start_pcb_port_id, routePoint.end_pcb_port_id].filter(
|
|
817
|
+
(portId) => Boolean(portId)
|
|
818
|
+
);
|
|
819
|
+
}
|
|
814
820
|
function getPcbPortIdsConnectedToTrace(trace) {
|
|
815
821
|
const connectedPcbPorts = /* @__PURE__ */ new Set();
|
|
816
822
|
for (const segment of trace.route) {
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
connectedPcbPorts.add(segment.start_pcb_port_id);
|
|
820
|
-
if (segment.end_pcb_port_id)
|
|
821
|
-
connectedPcbPorts.add(segment.end_pcb_port_id);
|
|
823
|
+
for (const portId of getPcbPortIdsConnectedToRoutePoint(segment)) {
|
|
824
|
+
connectedPcbPorts.add(portId);
|
|
822
825
|
}
|
|
823
826
|
}
|
|
824
827
|
return Array.from(connectedPcbPorts);
|
|
@@ -1706,6 +1709,9 @@ import { getFullConnectivityMapFromCircuitJson as getFullConnectivityMapFromCirc
|
|
|
1706
1709
|
import { getBoundsOfPcbElements as getBoundsOfPcbElements3 } from "@tscircuit/circuit-json-util";
|
|
1707
1710
|
import { doBoundsOverlap } from "@tscircuit/math-utils";
|
|
1708
1711
|
function getElementLayers(elem) {
|
|
1712
|
+
if (elem.type === "pcb_courtyard_circle" || elem.type === "pcb_courtyard_outline" || elem.type === "pcb_courtyard_polygon" || elem.type === "pcb_courtyard_rect") {
|
|
1713
|
+
return [elem.layer];
|
|
1714
|
+
}
|
|
1709
1715
|
return getLayersOfPcbElement(elem);
|
|
1710
1716
|
}
|
|
1711
1717
|
function doLayersOverlap(layers1, layers2) {
|
|
@@ -1722,6 +1728,7 @@ function doPcbElementsOverlap(elem1, elem2) {
|
|
|
1722
1728
|
}
|
|
1723
1729
|
|
|
1724
1730
|
// lib/check-pcb-components-overlap/checkPcbComponentOverlap.ts
|
|
1731
|
+
var isCourtyardElement = (element) => element.type === "pcb_courtyard_circle" || element.type === "pcb_courtyard_outline" || element.type === "pcb_courtyard_polygon" || element.type === "pcb_courtyard_rect";
|
|
1725
1732
|
var formatOverlapElementDescription = (circuitJson, element) => {
|
|
1726
1733
|
if ("pcb_port_id" in element && element.pcb_port_id) {
|
|
1727
1734
|
return getReadableNameForPort(circuitJson, element.pcb_port_id);
|
|
@@ -1736,14 +1743,14 @@ function checkPcbComponentOverlap(circuitJson) {
|
|
|
1736
1743
|
const smtPads = cju4(circuitJson).pcb_smtpad.list();
|
|
1737
1744
|
const platedHoles = cju4(circuitJson).pcb_plated_hole.list();
|
|
1738
1745
|
const holes = cju4(circuitJson).pcb_hole.list();
|
|
1746
|
+
const courtyards = circuitJson.filter(isCourtyardElement);
|
|
1739
1747
|
const componentMap = /* @__PURE__ */ new Map();
|
|
1740
1748
|
for (const pad of smtPads) {
|
|
1741
1749
|
const componentId = pad.pcb_component_id || `standalone_pad_${getPrimaryId2(pad)}`;
|
|
1742
1750
|
if (!componentMap.has(componentId)) {
|
|
1743
1751
|
componentMap.set(componentId, {
|
|
1744
1752
|
component_id: componentId,
|
|
1745
|
-
elements: []
|
|
1746
|
-
bounds: { minX: 0, minY: 0, maxX: 0, maxY: 0 }
|
|
1753
|
+
elements: []
|
|
1747
1754
|
});
|
|
1748
1755
|
}
|
|
1749
1756
|
componentMap.get(componentId).elements.push(pad);
|
|
@@ -1753,8 +1760,7 @@ function checkPcbComponentOverlap(circuitJson) {
|
|
|
1753
1760
|
if (!componentMap.has(componentId)) {
|
|
1754
1761
|
componentMap.set(componentId, {
|
|
1755
1762
|
component_id: componentId,
|
|
1756
|
-
elements: []
|
|
1757
|
-
bounds: { minX: 0, minY: 0, maxX: 0, maxY: 0 }
|
|
1763
|
+
elements: []
|
|
1758
1764
|
});
|
|
1759
1765
|
}
|
|
1760
1766
|
componentMap.get(componentId).elements.push(hole);
|
|
@@ -1763,10 +1769,19 @@ function checkPcbComponentOverlap(circuitJson) {
|
|
|
1763
1769
|
const componentId = `standalone_hole_${getPrimaryId2(hole)}`;
|
|
1764
1770
|
componentMap.set(componentId, {
|
|
1765
1771
|
component_id: componentId,
|
|
1766
|
-
elements: [hole]
|
|
1767
|
-
bounds: { minX: 0, minY: 0, maxX: 0, maxY: 0 }
|
|
1772
|
+
elements: [hole]
|
|
1768
1773
|
});
|
|
1769
1774
|
}
|
|
1775
|
+
for (const courtyard of courtyards) {
|
|
1776
|
+
const componentId = courtyard.pcb_component_id;
|
|
1777
|
+
if (!componentMap.has(componentId)) {
|
|
1778
|
+
componentMap.set(componentId, {
|
|
1779
|
+
component_id: componentId,
|
|
1780
|
+
elements: []
|
|
1781
|
+
});
|
|
1782
|
+
}
|
|
1783
|
+
componentMap.get(componentId).elements.push(courtyard);
|
|
1784
|
+
}
|
|
1770
1785
|
for (const [componentId, componentData] of componentMap) {
|
|
1771
1786
|
if (componentData.elements.length > 0) {
|
|
1772
1787
|
componentData.bounds = getBoundsOfPcbElements4(componentData.elements);
|
|
@@ -1777,6 +1792,9 @@ function checkPcbComponentOverlap(circuitJson) {
|
|
|
1777
1792
|
for (let j = i + 1; j < componentsWithElements.length; j++) {
|
|
1778
1793
|
const comp1 = componentsWithElements[i];
|
|
1779
1794
|
const comp2 = componentsWithElements[j];
|
|
1795
|
+
if (!comp1.bounds || !comp2.bounds) {
|
|
1796
|
+
continue;
|
|
1797
|
+
}
|
|
1780
1798
|
if (!doBoundsOverlap2(comp1.bounds, comp2.bounds)) {
|
|
1781
1799
|
continue;
|
|
1782
1800
|
}
|
|
@@ -1784,6 +1802,9 @@ function checkPcbComponentOverlap(circuitJson) {
|
|
|
1784
1802
|
for (const elem2 of comp2.elements) {
|
|
1785
1803
|
const id1 = getPrimaryId2(elem1);
|
|
1786
1804
|
const id2 = getPrimaryId2(elem2);
|
|
1805
|
+
if ((isCourtyardElement(elem1) || isCourtyardElement(elem2)) && elem1.type !== "pcb_hole" && elem2.type !== "pcb_hole") {
|
|
1806
|
+
continue;
|
|
1807
|
+
}
|
|
1787
1808
|
if (elem1.type === "pcb_smtpad" && elem2.type === "pcb_smtpad" && connMap.areIdsConnected(id1, id2)) {
|
|
1788
1809
|
continue;
|
|
1789
1810
|
}
|
|
@@ -2626,6 +2647,64 @@ import {
|
|
|
2626
2647
|
getReadableNameForPcbPort as getReadableNameForPcbPort2,
|
|
2627
2648
|
getReadableNameForPcbTrace
|
|
2628
2649
|
} from "@tscircuit/circuit-json-util";
|
|
2650
|
+
function routePointConnectsToAnotherExpectedPort(point, expectedPorts, missingPcbPortId, padMap) {
|
|
2651
|
+
if (point.route_type !== "wire") return false;
|
|
2652
|
+
return expectedPorts.some((expectedPort) => {
|
|
2653
|
+
if (!expectedPort.pcb_port_id || expectedPort.pcb_port_id === missingPcbPortId) {
|
|
2654
|
+
return false;
|
|
2655
|
+
}
|
|
2656
|
+
const expectedPads = padMap.get(expectedPort.pcb_port_id);
|
|
2657
|
+
return expectedPads?.some(
|
|
2658
|
+
(pad) => isPointInPad({ x: point.x, y: point.y }, pad)
|
|
2659
|
+
) ?? false;
|
|
2660
|
+
});
|
|
2661
|
+
}
|
|
2662
|
+
function getMissingConnectionErrorCenter({
|
|
2663
|
+
firstPoint,
|
|
2664
|
+
lastPoint,
|
|
2665
|
+
port,
|
|
2666
|
+
expectedPorts,
|
|
2667
|
+
padMap
|
|
2668
|
+
}) {
|
|
2669
|
+
let errorLocation;
|
|
2670
|
+
const firstWirePoint = firstPoint.route_type === "wire" ? firstPoint : void 0;
|
|
2671
|
+
const lastWirePoint = lastPoint.route_type === "wire" ? lastPoint : void 0;
|
|
2672
|
+
const firstWirePointReferencesPort = getPcbPortIdsConnectedToRoutePoint(
|
|
2673
|
+
firstPoint
|
|
2674
|
+
).includes(port.pcb_port_id);
|
|
2675
|
+
const lastWirePointReferencesPort = getPcbPortIdsConnectedToRoutePoint(
|
|
2676
|
+
lastPoint
|
|
2677
|
+
).includes(port.pcb_port_id);
|
|
2678
|
+
if (firstWirePointReferencesPort && firstWirePoint) {
|
|
2679
|
+
errorLocation = firstWirePoint;
|
|
2680
|
+
} else if (lastWirePointReferencesPort && lastWirePoint) {
|
|
2681
|
+
errorLocation = lastWirePoint;
|
|
2682
|
+
} else if (routePointConnectsToAnotherExpectedPort(
|
|
2683
|
+
firstPoint,
|
|
2684
|
+
expectedPorts,
|
|
2685
|
+
port.pcb_port_id,
|
|
2686
|
+
padMap
|
|
2687
|
+
) && lastWirePoint) {
|
|
2688
|
+
errorLocation = lastWirePoint;
|
|
2689
|
+
} else if (routePointConnectsToAnotherExpectedPort(
|
|
2690
|
+
lastPoint,
|
|
2691
|
+
expectedPorts,
|
|
2692
|
+
port.pcb_port_id,
|
|
2693
|
+
padMap
|
|
2694
|
+
) && firstWirePoint) {
|
|
2695
|
+
errorLocation = firstWirePoint;
|
|
2696
|
+
} else if (firstWirePoint && lastWirePoint) {
|
|
2697
|
+
errorLocation = distance2(firstWirePoint, port) <= distance2(lastWirePoint, port) ? firstWirePoint : lastWirePoint;
|
|
2698
|
+
} else if (firstWirePoint) {
|
|
2699
|
+
errorLocation = firstWirePoint;
|
|
2700
|
+
} else if (lastWirePoint) {
|
|
2701
|
+
errorLocation = lastWirePoint;
|
|
2702
|
+
}
|
|
2703
|
+
return errorLocation ? { x: errorLocation.x, y: errorLocation.y } : {
|
|
2704
|
+
x: (firstPoint.x + lastPoint.x) / 2,
|
|
2705
|
+
y: (firstPoint.y + lastPoint.y) / 2
|
|
2706
|
+
};
|
|
2707
|
+
}
|
|
2629
2708
|
function checkTracesAreContiguous(circuitJson) {
|
|
2630
2709
|
const errors = [];
|
|
2631
2710
|
const pcbPorts = circuitJson.filter(
|
|
@@ -2716,10 +2795,13 @@ function checkTracesAreContiguous(circuitJson) {
|
|
|
2716
2795
|
port.pcb_port_id
|
|
2717
2796
|
).replace("pcb_port", "");
|
|
2718
2797
|
const padType = pads[0].type.replace(/pcb_/, "");
|
|
2719
|
-
const errorCenter = {
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2798
|
+
const errorCenter = getMissingConnectionErrorCenter({
|
|
2799
|
+
firstPoint,
|
|
2800
|
+
lastPoint,
|
|
2801
|
+
port,
|
|
2802
|
+
expectedPorts,
|
|
2803
|
+
padMap
|
|
2804
|
+
});
|
|
2723
2805
|
errors.push({
|
|
2724
2806
|
type: "pcb_trace_error",
|
|
2725
2807
|
message: `Trace [${traceName}] is missing a connection to ${padType}${portName}`,
|