@tscircuit/checks 0.0.168 → 0.0.170
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 +107 -44
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -332,7 +332,10 @@ var addStartAndEndPortIdsIfMissing = (soup) => {
|
|
|
332
332
|
};
|
|
333
333
|
|
|
334
334
|
// lib/check-each-pcb-port-connected-to-pcb-trace.ts
|
|
335
|
-
import {
|
|
335
|
+
import {
|
|
336
|
+
getFullConnectivityMapFromCircuitJson,
|
|
337
|
+
PcbConnectivityMap
|
|
338
|
+
} from "circuit-json-to-connectivity-map";
|
|
336
339
|
|
|
337
340
|
// lib/util/get-readable-names.ts
|
|
338
341
|
import {
|
|
@@ -470,14 +473,41 @@ function checkEachPcbPortConnectedToPcbTraces(circuitJson) {
|
|
|
470
473
|
const pcbPorts = circuitJson.filter(
|
|
471
474
|
(item) => item.type === "pcb_port"
|
|
472
475
|
);
|
|
476
|
+
const sourceNets = circuitJson.filter(
|
|
477
|
+
(item) => item.type === "source_net"
|
|
478
|
+
);
|
|
473
479
|
const errors = [];
|
|
474
480
|
const connectivityMap = getFullConnectivityMapFromCircuitJson(circuitJson);
|
|
481
|
+
const pcbConnectivityMap = new PcbConnectivityMap(circuitJson);
|
|
475
482
|
const sourcePortToPcbPort = /* @__PURE__ */ new Map();
|
|
476
483
|
for (const pcbPort of pcbPorts) {
|
|
477
484
|
sourcePortToPcbPort.set(pcbPort.source_port_id, pcbPort);
|
|
478
485
|
}
|
|
486
|
+
const sourceNetNameById = new Map(
|
|
487
|
+
sourceNets.map((sourceNet) => [sourceNet.source_net_id, sourceNet.name])
|
|
488
|
+
);
|
|
479
489
|
for (const sourceTrace of sourceTraces) {
|
|
480
490
|
const connectedSourcePortIds = sourceTrace.connected_source_port_ids;
|
|
491
|
+
if (connectedSourcePortIds.length === 1 && sourceTrace.connected_source_net_ids.length > 0) {
|
|
492
|
+
const pcbPort = sourcePortToPcbPort.get(connectedSourcePortIds[0]);
|
|
493
|
+
if (!pcbPort) continue;
|
|
494
|
+
const connectedPcbTraces = pcbConnectivityMap.getAllTracesConnectedToPort(
|
|
495
|
+
pcbPort.pcb_port_id
|
|
496
|
+
);
|
|
497
|
+
if (connectedPcbTraces.length === 0) {
|
|
498
|
+
const connectedNetNames = sourceTrace.connected_source_net_ids.map((sourceNetId) => sourceNetNameById.get(sourceNetId)).filter((name) => Boolean(name));
|
|
499
|
+
const netDescription = connectedNetNames.length > 0 ? `net [${connectedNetNames.join(", ")}]` : "its connected net";
|
|
500
|
+
errors.push({
|
|
501
|
+
type: "pcb_port_not_connected_error",
|
|
502
|
+
message: `Port [${getReadableNameForPort(circuitJson, pcbPort.pcb_port_id)}] is not connected to ${netDescription} by a PCB trace.`,
|
|
503
|
+
error_type: "pcb_port_not_connected_error",
|
|
504
|
+
pcb_port_ids: [pcbPort.pcb_port_id],
|
|
505
|
+
pcb_component_ids: pcbPort.pcb_component_id ? [pcbPort.pcb_component_id] : [],
|
|
506
|
+
pcb_port_not_connected_error_id: `pcb_port_not_connected_error_trace_${sourceTrace.source_trace_id}`
|
|
507
|
+
});
|
|
508
|
+
}
|
|
509
|
+
continue;
|
|
510
|
+
}
|
|
481
511
|
if (connectedSourcePortIds.length < 2) {
|
|
482
512
|
continue;
|
|
483
513
|
}
|
|
@@ -2552,7 +2582,10 @@ import {
|
|
|
2552
2582
|
getReadableNameForPcbPort as getReadableNameForPcbPort2,
|
|
2553
2583
|
getReadableNameForPcbTrace
|
|
2554
2584
|
} from "@tscircuit/circuit-json-util";
|
|
2555
|
-
import { PcbConnectivityMap } from "circuit-json-to-connectivity-map";
|
|
2585
|
+
import { PcbConnectivityMap as PcbConnectivityMap2 } from "circuit-json-to-connectivity-map";
|
|
2586
|
+
function routePointTouchesPad(point, pad) {
|
|
2587
|
+
return point.route_type === "wire" && getLayersOfPcbElement(pad).includes(point.layer) && isPointInPad(point, pad);
|
|
2588
|
+
}
|
|
2556
2589
|
function getRoutePointCenter(point) {
|
|
2557
2590
|
if (point.route_type === "through_pad") {
|
|
2558
2591
|
return {
|
|
@@ -2563,15 +2596,12 @@ function getRoutePointCenter(point) {
|
|
|
2563
2596
|
return { x: point.x, y: point.y };
|
|
2564
2597
|
}
|
|
2565
2598
|
function routePointConnectsToAnotherExpectedPort(point, expectedPorts, missingPcbPortId, padMap) {
|
|
2566
|
-
if (point.route_type !== "wire") return false;
|
|
2567
2599
|
return expectedPorts.some((expectedPort) => {
|
|
2568
2600
|
if (!expectedPort.pcb_port_id || expectedPort.pcb_port_id === missingPcbPortId) {
|
|
2569
2601
|
return false;
|
|
2570
2602
|
}
|
|
2571
2603
|
const expectedPads = padMap.get(expectedPort.pcb_port_id);
|
|
2572
|
-
return expectedPads?.some(
|
|
2573
|
-
(pad) => isPointInPad({ x: point.x, y: point.y }, pad)
|
|
2574
|
-
) ?? false;
|
|
2604
|
+
return expectedPads?.some((pad) => routePointTouchesPad(point, pad)) ?? false;
|
|
2575
2605
|
});
|
|
2576
2606
|
}
|
|
2577
2607
|
function getMissingConnectionErrorCenter({
|
|
@@ -2640,7 +2670,7 @@ function checkTracesAreContiguous(circuitJson) {
|
|
|
2640
2670
|
(el) => el.type === "pcb_plated_hole"
|
|
2641
2671
|
);
|
|
2642
2672
|
const padMap = /* @__PURE__ */ new Map();
|
|
2643
|
-
const pcbConnectivityMap = new
|
|
2673
|
+
const pcbConnectivityMap = new PcbConnectivityMap2(circuitJson);
|
|
2644
2674
|
const checkedSourceTraceIds = /* @__PURE__ */ new Set();
|
|
2645
2675
|
for (const pad of pcbSmtPads) {
|
|
2646
2676
|
if (pad.pcb_port_id) {
|
|
@@ -2655,6 +2685,65 @@ function checkTracesAreContiguous(circuitJson) {
|
|
|
2655
2685
|
]);
|
|
2656
2686
|
}
|
|
2657
2687
|
}
|
|
2688
|
+
const touchedPortIdsByTraceId = /* @__PURE__ */ new Map();
|
|
2689
|
+
const traceIdsByTouchedPortId = /* @__PURE__ */ new Map();
|
|
2690
|
+
for (const trace of pcbTraces) {
|
|
2691
|
+
const touchedPortIds = /* @__PURE__ */ new Set();
|
|
2692
|
+
const firstPoint = trace.route[0];
|
|
2693
|
+
const lastPoint = trace.route.at(-1);
|
|
2694
|
+
for (const point of [firstPoint, lastPoint]) {
|
|
2695
|
+
if (!point) continue;
|
|
2696
|
+
for (const [pcbPortId, pads] of padMap) {
|
|
2697
|
+
if (pads.some((pad) => routePointTouchesPad(point, pad))) {
|
|
2698
|
+
touchedPortIds.add(pcbPortId);
|
|
2699
|
+
}
|
|
2700
|
+
}
|
|
2701
|
+
}
|
|
2702
|
+
touchedPortIdsByTraceId.set(trace.pcb_trace_id, touchedPortIds);
|
|
2703
|
+
for (const pcbPortId of touchedPortIds) {
|
|
2704
|
+
const traceIds = traceIdsByTouchedPortId.get(pcbPortId) ?? /* @__PURE__ */ new Set();
|
|
2705
|
+
traceIds.add(trace.pcb_trace_id);
|
|
2706
|
+
traceIdsByTouchedPortId.set(pcbPortId, traceIds);
|
|
2707
|
+
}
|
|
2708
|
+
}
|
|
2709
|
+
const physicallyConnectedTracesByTraceId = /* @__PURE__ */ new Map();
|
|
2710
|
+
const getPhysicallyConnectedTraces = (startTrace) => {
|
|
2711
|
+
const cached = physicallyConnectedTracesByTraceId.get(
|
|
2712
|
+
startTrace.pcb_trace_id
|
|
2713
|
+
);
|
|
2714
|
+
if (cached) return cached;
|
|
2715
|
+
const connectedTraceIds = /* @__PURE__ */ new Set();
|
|
2716
|
+
const pendingTraceIds = [startTrace.pcb_trace_id];
|
|
2717
|
+
while (pendingTraceIds.length > 0) {
|
|
2718
|
+
const traceId = pendingTraceIds.pop();
|
|
2719
|
+
if (connectedTraceIds.has(traceId)) continue;
|
|
2720
|
+
connectedTraceIds.add(traceId);
|
|
2721
|
+
for (const connectedTrace of pcbConnectivityMap.getAllTracesConnectedToTrace(
|
|
2722
|
+
traceId
|
|
2723
|
+
)) {
|
|
2724
|
+
if (!connectedTraceIds.has(connectedTrace.pcb_trace_id)) {
|
|
2725
|
+
pendingTraceIds.push(connectedTrace.pcb_trace_id);
|
|
2726
|
+
}
|
|
2727
|
+
}
|
|
2728
|
+
for (const pcbPortId of touchedPortIdsByTraceId.get(traceId) ?? []) {
|
|
2729
|
+
for (const touchingTraceId of traceIdsByTouchedPortId.get(pcbPortId) ?? []) {
|
|
2730
|
+
if (!connectedTraceIds.has(touchingTraceId)) {
|
|
2731
|
+
pendingTraceIds.push(touchingTraceId);
|
|
2732
|
+
}
|
|
2733
|
+
}
|
|
2734
|
+
}
|
|
2735
|
+
}
|
|
2736
|
+
const connectedTraces = pcbTraces.filter(
|
|
2737
|
+
(trace) => connectedTraceIds.has(trace.pcb_trace_id)
|
|
2738
|
+
);
|
|
2739
|
+
for (const trace of connectedTraces) {
|
|
2740
|
+
physicallyConnectedTracesByTraceId.set(
|
|
2741
|
+
trace.pcb_trace_id,
|
|
2742
|
+
connectedTraces
|
|
2743
|
+
);
|
|
2744
|
+
}
|
|
2745
|
+
return connectedTraces;
|
|
2746
|
+
};
|
|
2658
2747
|
for (const trace of pcbTraces) {
|
|
2659
2748
|
if (trace.route.length === 0) continue;
|
|
2660
2749
|
const firstPoint = trace.route[0];
|
|
@@ -2706,39 +2795,17 @@ function checkTracesAreContiguous(circuitJson) {
|
|
|
2706
2795
|
if (!port.pcb_port_id) continue;
|
|
2707
2796
|
const pads = padMap.get(port.pcb_port_id);
|
|
2708
2797
|
if (!pads?.length) continue;
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
)
|
|
2715
|
-
];
|
|
2716
|
-
for (const candidateTrace of candidateTraces) {
|
|
2717
|
-
if (candidateTrace.pcb_trace_id === trace.pcb_trace_id) continue;
|
|
2718
|
-
if (!candidateTrace.source_trace_id) continue;
|
|
2719
|
-
const candidateSourceTrace = sourceTraces.find(
|
|
2720
|
-
(st) => st.source_trace_id === candidateTrace.source_trace_id
|
|
2721
|
-
);
|
|
2722
|
-
if (!sourceTrace || candidateTrace.source_trace_id !== sourceTrace.source_trace_id && !candidateSourceTrace?.connected_source_port_ids.includes(
|
|
2723
|
-
port.source_port_id
|
|
2724
|
-
)) {
|
|
2725
|
-
continue;
|
|
2726
|
-
}
|
|
2727
|
-
const candidateFirstPoint = candidateTrace.route[0];
|
|
2728
|
-
const candidateLastPoint = candidateTrace.route.at(-1);
|
|
2729
|
-
if (getPcbPortIdsConnectedToTrace(candidateTrace).includes(
|
|
2730
|
-
port.pcb_port_id
|
|
2731
|
-
) || candidateFirstPoint?.route_type === "wire" && pads.some((pad) => isPointInPad(candidateFirstPoint, pad)) || candidateLastPoint?.route_type === "wire" && pads.some((pad) => isPointInPad(candidateLastPoint, pad))) {
|
|
2732
|
-
isConnectedByRoutedSourceTrace = true;
|
|
2733
|
-
break;
|
|
2734
|
-
}
|
|
2735
|
-
}
|
|
2798
|
+
const isConnectedByRoutedSourceTrace = getPhysicallyConnectedTraces(
|
|
2799
|
+
trace
|
|
2800
|
+
).some(
|
|
2801
|
+
(candidateTrace) => touchedPortIdsByTraceId.get(candidateTrace.pcb_trace_id)?.has(port.pcb_port_id)
|
|
2802
|
+
);
|
|
2736
2803
|
if (isConnectedByRoutedSourceTrace) continue;
|
|
2737
|
-
const isFirstPointConnected =
|
|
2738
|
-
(pad) =>
|
|
2804
|
+
const isFirstPointConnected = pads.some(
|
|
2805
|
+
(pad) => routePointTouchesPad(firstPoint, pad)
|
|
2739
2806
|
);
|
|
2740
|
-
const isLastPointConnected =
|
|
2741
|
-
(pad) =>
|
|
2807
|
+
const isLastPointConnected = pads.some(
|
|
2808
|
+
(pad) => routePointTouchesPad(lastPoint, pad)
|
|
2742
2809
|
);
|
|
2743
2810
|
if (!isFirstPointConnected && !isLastPointConnected) {
|
|
2744
2811
|
const portName = getReadableNameForPcbPort2(
|
|
@@ -2771,14 +2838,10 @@ function checkTracesAreContiguous(circuitJson) {
|
|
|
2771
2838
|
let lastConnectsToAnyPad = false;
|
|
2772
2839
|
const endpointsAreSame = firstPoint.route_type === "wire" && lastPoint.route_type === "wire" && Math.abs(firstPoint.x - lastPoint.x) < 0.01 && Math.abs(firstPoint.y - lastPoint.y) < 0.01;
|
|
2773
2840
|
for (const pads of padMap.values()) {
|
|
2774
|
-
if (
|
|
2775
|
-
(pad) => isPointInPad({ x: firstPoint.x, y: firstPoint.y }, pad)
|
|
2776
|
-
)) {
|
|
2841
|
+
if (pads.some((pad) => routePointTouchesPad(firstPoint, pad))) {
|
|
2777
2842
|
firstConnectsToAnyPad = true;
|
|
2778
2843
|
}
|
|
2779
|
-
if (
|
|
2780
|
-
(pad) => isPointInPad({ x: lastPoint.x, y: lastPoint.y }, pad)
|
|
2781
|
-
)) {
|
|
2844
|
+
if (pads.some((pad) => routePointTouchesPad(lastPoint, pad))) {
|
|
2782
2845
|
lastConnectsToAnyPad = true;
|
|
2783
2846
|
}
|
|
2784
2847
|
}
|