@tscircuit/checks 0.0.170 → 0.0.172
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 +2 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +146 -44
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -20,6 +20,7 @@ and output an array of arrays for any issues found.
|
|
|
20
20
|
| [`checkEachPcbTraceNonOverlapping`](./lib/check-each-pcb-trace-non-overlapping/check-each-pcb-trace-non-overlapping.ts) | Returns `pcb_trace_error` when `pcb_trace` segments physically overlap incompatible geometry on the same layer. Pad/via near-misses are reported by the typed clearance checks instead. |
|
|
21
21
|
| [`checkPcbComponentOverlap`](./lib/check-pcb-components-overlap/checkPcbComponentOverlap.ts) | Returns `pcb_footprint_overlap_error` when footprint elements from different components overlap in disallowed ways. |
|
|
22
22
|
| [`checkPcbComponentsOutOfBoard`](./lib/check-pcb-components-out-of-board/checkPcbComponentsOutOfBoard.ts) | Returns `pcb_placement_error` when PCB components do not fit inside the board area. |
|
|
23
|
+
| [`checkPcbCopperOverKeepout`](./lib/check-pcb-copper-over-keepout.ts) | Returns one `pcb_placement_error` per non-excluded component or via whose copper overlaps a keepout on a shared layer. |
|
|
23
24
|
| [`checkPcbTracesOutOfBoard`](./lib/check-trace-out-of-board/checkTraceOutOfBoard.ts) | Returns `pcb_trace_error` when any trace segment or via extends beyond the board boundary. |
|
|
24
25
|
| [`checkPadTraceClearance`](./lib/check-pad-trace-clearance.ts) | Returns `pcb_pad_trace_clearance_error` when a pad and unrelated trace have a positive gap below the minimum clearance. Physical overlaps are reported by `checkEachPcbTraceNonOverlapping`. |
|
|
25
26
|
| [`checkViaTraceClearance`](./lib/check-via-trace-clearance.ts) | Returns `pcb_via_trace_clearance_error` when a via and unrelated trace have a positive gap below the minimum clearance. Physical overlaps are reported by `checkEachPcbTraceNonOverlapping`. |
|
|
@@ -34,7 +35,7 @@ and output an array of arrays for any issues found.
|
|
|
34
35
|
|
|
35
36
|
| Function | Description |
|
|
36
37
|
| --- | --- |
|
|
37
|
-
| [`runAllPlacementChecks`](./lib/run-all-checks.ts) | Runs placement checks (`checkCopperToBoardEdgeClearance`, `checkPcbComponentsOutOfBoard`, `checkPcbComponentOverlap`, `checkPadPadClearance`, `checkCourtyardOverlap`, `checkConnectorAccessibleOrientation`, and `checkTestPointAccessibility`). |
|
|
38
|
+
| [`runAllPlacementChecks`](./lib/run-all-checks.ts) | Runs placement checks (`checkCopperToBoardEdgeClearance`, `checkPcbComponentsOutOfBoard`, `checkPcbCopperOverKeepout`, `checkPcbComponentOverlap`, `checkPadPadClearance`, `checkCourtyardOverlap`, `checkConnectorAccessibleOrientation`, and `checkTestPointAccessibility`). |
|
|
38
39
|
| [`runAllNetlistChecks`](./lib/run-all-checks.ts) | Runs netlist connectivity checks (currently `checkPinMustBeConnected`). |
|
|
39
40
|
| [`runAllPinSpecificationChecks`](./lib/run-all-checks.ts) | Runs pin specification checks (e.g. `checkAllPinsInComponentAreUnderspecified`, `checkNoPowerPinDefined`, and `checkNoGroundPinDefined`). |
|
|
40
41
|
| [`runAllSchematicChecks`](./lib/run-all-checks.ts) | Runs schematic-layout checks (currently `checkSchematicComponentExcessiveVerticalPadding`). |
|
package/dist/index.d.ts
CHANGED
|
@@ -41,6 +41,8 @@ declare function checkPcbComponentsOutOfBoard(circuitJson: AnyCircuitElement[]):
|
|
|
41
41
|
*/
|
|
42
42
|
declare function checkPcbComponentOverCutout(circuitJson: AnyCircuitElement[]): PcbPlacementError[];
|
|
43
43
|
|
|
44
|
+
declare function checkPcbCopperOverKeepout(circuitJson: AnyCircuitElement[]): PcbPlacementError[];
|
|
45
|
+
|
|
44
46
|
declare function checkSameNetViaSpacing(circuitJson: AnyCircuitElement[], { connMap, minClearance, }?: {
|
|
45
47
|
connMap?: ConnectivityMap;
|
|
46
48
|
minClearance?: number;
|
|
@@ -198,4 +200,4 @@ declare function checkConnectorAccessibleOrientation(circuitJson: AnyCircuitElem
|
|
|
198
200
|
*/
|
|
199
201
|
declare function checkTestPointAccessibility(circuitJson: AnyCircuitElement[]): PcbPlacementError[];
|
|
200
202
|
|
|
201
|
-
export { NetManager, checkAllPinsInComponentAreUnderspecified, checkConnectorAccessibleOrientation, checkCopperToBoardEdgeClearance, checkDifferentNetViaSpacing, checkEachPcbPortConnectedToPcbTraces, checkEachPcbTraceNonOverlapping, checkNoGroundPinDefined, checkNoPowerPinDefined, checkPadPadClearance, checkPadTraceClearance, checkPcbComponentOverCutout, checkPcbComponentOverlap, checkPcbComponentsMissingCourtyard, checkPcbComponentsOutOfBoard, checkPcbTraceLengths, checkPcbTraceViaCounts, checkPcbTracesOutOfBoard, checkPinMustBeConnected, checkSameNetViaSpacing, checkSchematicComponentExcessiveVerticalPadding, checkSourceTracesHavePcbTraces, checkSourceTracesMatchPcbTraceThickness, checkTestPointAccessibility, checkTracesAreContiguous, checkViaPadClearance, checkViaTraceClearance, checkViasInPads, checkViasOffBoard, dedupePcbDrcErrors, runAllChecks, runAllNetlistChecks, runAllPinSpecificationChecks, runAllPlacementChecks, runAllRoutingChecks, runAllSchematicChecks };
|
|
203
|
+
export { NetManager, checkAllPinsInComponentAreUnderspecified, checkConnectorAccessibleOrientation, checkCopperToBoardEdgeClearance, checkDifferentNetViaSpacing, checkEachPcbPortConnectedToPcbTraces, checkEachPcbTraceNonOverlapping, checkNoGroundPinDefined, checkNoPowerPinDefined, checkPadPadClearance, checkPadTraceClearance, checkPcbComponentOverCutout, checkPcbComponentOverlap, checkPcbComponentsMissingCourtyard, checkPcbComponentsOutOfBoard, checkPcbCopperOverKeepout, checkPcbTraceLengths, checkPcbTraceViaCounts, checkPcbTracesOutOfBoard, checkPinMustBeConnected, checkSameNetViaSpacing, checkSchematicComponentExcessiveVerticalPadding, checkSourceTracesHavePcbTraces, checkSourceTracesMatchPcbTraceThickness, checkTestPointAccessibility, checkTracesAreContiguous, checkViaPadClearance, checkViaTraceClearance, checkViasInPads, checkViasOffBoard, dedupePcbDrcErrors, runAllChecks, runAllNetlistChecks, runAllPinSpecificationChecks, runAllPlacementChecks, runAllRoutingChecks, runAllSchematicChecks };
|
package/dist/index.js
CHANGED
|
@@ -605,8 +605,27 @@ var getPcbBoard = (circuitJson) => circuitJson.find((el) => el.type === "pcb_boa
|
|
|
605
605
|
var getBoardDrcValue = (board, key) => board?.[key];
|
|
606
606
|
|
|
607
607
|
// lib/check-pad-clearance/common.ts
|
|
608
|
-
var getPadBounds = (pad) =>
|
|
608
|
+
var getPadBounds = (pad) => {
|
|
609
|
+
if (pad.type === "pcb_keepout") {
|
|
610
|
+
if (pad.shape === "circle") {
|
|
611
|
+
return {
|
|
612
|
+
minX: pad.center.x - pad.radius,
|
|
613
|
+
minY: pad.center.y - pad.radius,
|
|
614
|
+
maxX: pad.center.x + pad.radius,
|
|
615
|
+
maxY: pad.center.y + pad.radius
|
|
616
|
+
};
|
|
617
|
+
}
|
|
618
|
+
return {
|
|
619
|
+
minX: pad.center.x - pad.width / 2,
|
|
620
|
+
minY: pad.center.y - pad.height / 2,
|
|
621
|
+
maxX: pad.center.x + pad.width / 2,
|
|
622
|
+
maxY: pad.center.y + pad.height / 2
|
|
623
|
+
};
|
|
624
|
+
}
|
|
625
|
+
return getBoundsOfPcbElements2([pad]);
|
|
626
|
+
};
|
|
609
627
|
var getPadCenter = (pad) => {
|
|
628
|
+
if (pad.type === "pcb_keepout") return pad.center;
|
|
610
629
|
const bounds = getPadBounds(pad);
|
|
611
630
|
return midpoint(
|
|
612
631
|
{ x: bounds.minX, y: bounds.minY },
|
|
@@ -614,6 +633,7 @@ var getPadCenter = (pad) => {
|
|
|
614
633
|
);
|
|
615
634
|
};
|
|
616
635
|
var getPadRadius = (pad) => {
|
|
636
|
+
if (pad.type === "pcb_keepout" && pad.shape === "circle") return pad.radius;
|
|
617
637
|
const bounds = getPadBounds(pad);
|
|
618
638
|
return Math.min(bounds.maxX - bounds.minX, bounds.maxY - bounds.minY) / 2;
|
|
619
639
|
};
|
|
@@ -629,6 +649,32 @@ var getCircleShape = (pad) => {
|
|
|
629
649
|
};
|
|
630
650
|
};
|
|
631
651
|
var getPolygonShape = (pad) => {
|
|
652
|
+
if (pad.type === "pcb_keepout") {
|
|
653
|
+
if (pad.shape !== "rect") {
|
|
654
|
+
throw new Error(`Expected rectangular keepout, got ${pad.shape}`);
|
|
655
|
+
}
|
|
656
|
+
return {
|
|
657
|
+
kind: "polygon",
|
|
658
|
+
points: [
|
|
659
|
+
{
|
|
660
|
+
x: pad.center.x - pad.width / 2,
|
|
661
|
+
y: pad.center.y - pad.height / 2
|
|
662
|
+
},
|
|
663
|
+
{
|
|
664
|
+
x: pad.center.x + pad.width / 2,
|
|
665
|
+
y: pad.center.y - pad.height / 2
|
|
666
|
+
},
|
|
667
|
+
{
|
|
668
|
+
x: pad.center.x + pad.width / 2,
|
|
669
|
+
y: pad.center.y + pad.height / 2
|
|
670
|
+
},
|
|
671
|
+
{
|
|
672
|
+
x: pad.center.x - pad.width / 2,
|
|
673
|
+
y: pad.center.y + pad.height / 2
|
|
674
|
+
}
|
|
675
|
+
]
|
|
676
|
+
};
|
|
677
|
+
}
|
|
632
678
|
if (pad.type === "pcb_smtpad" && (pad.shape === "polygon" || pad.shape === "rotated_rect")) {
|
|
633
679
|
return {
|
|
634
680
|
kind: "polygon",
|
|
@@ -2340,6 +2386,62 @@ function checkPcbComponentOverCutout(circuitJson) {
|
|
|
2340
2386
|
return errors;
|
|
2341
2387
|
}
|
|
2342
2388
|
|
|
2389
|
+
// lib/check-pcb-copper-over-keepout.ts
|
|
2390
|
+
import { cju as cju3, getPrimaryId as getPrimaryId2 } from "@tscircuit/circuit-json-util";
|
|
2391
|
+
var getErrorOwnerId = (copper) => "pcb_component_id" in copper && copper.pcb_component_id ? copper.pcb_component_id : getPrimaryId2(copper);
|
|
2392
|
+
var getReadableCopperName = (circuitJson, copper) => {
|
|
2393
|
+
if ("pcb_component_id" in copper && copper.pcb_component_id) {
|
|
2394
|
+
const pcbComponent = circuitJson.find(
|
|
2395
|
+
(element) => element.type === "pcb_component" && element.pcb_component_id === copper.pcb_component_id
|
|
2396
|
+
);
|
|
2397
|
+
const sourceComponent = pcbComponent?.type === "pcb_component" ? circuitJson.find(
|
|
2398
|
+
(element) => element.type === "source_component" && element.source_component_id === pcbComponent.source_component_id
|
|
2399
|
+
) : void 0;
|
|
2400
|
+
const componentName = sourceComponent?.type === "source_component" && sourceComponent.name ? sourceComponent.name : getReadableNameForComponent(circuitJson, copper.pcb_component_id);
|
|
2401
|
+
return `component ${componentName}`;
|
|
2402
|
+
}
|
|
2403
|
+
return copper.type === "pcb_via" ? `via ${copper.pcb_via_id}` : `${copper.type} ${getPrimaryId2(copper)}`;
|
|
2404
|
+
};
|
|
2405
|
+
function checkPcbCopperOverKeepout(circuitJson) {
|
|
2406
|
+
const keepouts = cju3(circuitJson).pcb_keepout.list();
|
|
2407
|
+
if (keepouts.length === 0) return [];
|
|
2408
|
+
const copper = [
|
|
2409
|
+
...getPads(circuitJson),
|
|
2410
|
+
...cju3(circuitJson).pcb_via.list()
|
|
2411
|
+
];
|
|
2412
|
+
const errors = /* @__PURE__ */ new Map();
|
|
2413
|
+
for (const keepout of keepouts) {
|
|
2414
|
+
const excludedComponentIds = new Set(
|
|
2415
|
+
keepout.excluded_pcb_component_ids ?? []
|
|
2416
|
+
);
|
|
2417
|
+
for (const copperElement of copper) {
|
|
2418
|
+
const copperComponentId = "pcb_component_id" in copperElement ? copperElement.pcb_component_id : void 0;
|
|
2419
|
+
if (copperComponentId && excludedComponentIds.has(copperComponentId)) {
|
|
2420
|
+
continue;
|
|
2421
|
+
}
|
|
2422
|
+
const copperLayers = getLayersOfPcbElement(copperElement);
|
|
2423
|
+
if (!copperLayers.some((layer) => keepout.layers.includes(layer))) {
|
|
2424
|
+
continue;
|
|
2425
|
+
}
|
|
2426
|
+
if (getPadToPadGap(copperElement, keepout) > EPSILON) continue;
|
|
2427
|
+
const ownerId = getErrorOwnerId(copperElement);
|
|
2428
|
+
const errorId = `copper_over_keepout_${ownerId}_${keepout.pcb_keepout_id}`;
|
|
2429
|
+
if (errors.has(errorId)) continue;
|
|
2430
|
+
errors.set(errorId, {
|
|
2431
|
+
type: "pcb_placement_error",
|
|
2432
|
+
pcb_placement_error_id: errorId,
|
|
2433
|
+
error_type: "pcb_placement_error",
|
|
2434
|
+
message: `Copper for ${getReadableCopperName(
|
|
2435
|
+
circuitJson,
|
|
2436
|
+
copperElement
|
|
2437
|
+
)} overlaps ${keepout.description ? `PCB keepout "${keepout.description}"` : "a PCB keepout"}`,
|
|
2438
|
+
subcircuit_id: copperElement.subcircuit_id ?? keepout.subcircuit_id
|
|
2439
|
+
});
|
|
2440
|
+
}
|
|
2441
|
+
}
|
|
2442
|
+
return [...errors.values()];
|
|
2443
|
+
}
|
|
2444
|
+
|
|
2343
2445
|
// lib/check-same-net-via-spacing.ts
|
|
2344
2446
|
import { getReadableNameForElement as getReadableNameForElement4 } from "@tscircuit/circuit-json-util";
|
|
2345
2447
|
import {
|
|
@@ -2457,11 +2559,11 @@ function checkDifferentNetViaSpacing(circuitJson, {
|
|
|
2457
2559
|
}
|
|
2458
2560
|
|
|
2459
2561
|
// lib/check-source-traces-match-pcb-trace-thickness.ts
|
|
2460
|
-
import { cju as
|
|
2562
|
+
import { cju as cju4 } from "@tscircuit/circuit-json-util";
|
|
2461
2563
|
import { getFullConnectivityMapFromCircuitJson as getFullConnectivityMapFromCircuitJson5 } from "circuit-json-to-connectivity-map";
|
|
2462
2564
|
function checkSourceTracesMatchPcbTraceThickness(circuitJson) {
|
|
2463
2565
|
const warnings = [];
|
|
2464
|
-
const db =
|
|
2566
|
+
const db = cju4(circuitJson);
|
|
2465
2567
|
const sourceTraces = db.source_trace.list();
|
|
2466
2568
|
const pcbTraces = db.pcb_trace.list();
|
|
2467
2569
|
const pcbPorts = db.pcb_port.list();
|
|
@@ -2877,7 +2979,7 @@ function checkTracesAreContiguous(circuitJson) {
|
|
|
2877
2979
|
}
|
|
2878
2980
|
|
|
2879
2981
|
// lib/check-trace-out-of-board/checkTraceOutOfBoard.ts
|
|
2880
|
-
import { cju as
|
|
2982
|
+
import { cju as cju5 } from "@tscircuit/circuit-json-util";
|
|
2881
2983
|
import { segmentToSegmentMinDistance as segmentToSegmentMinDistance4 } from "@tscircuit/math-utils";
|
|
2882
2984
|
function getBoardPolygonPoints(board) {
|
|
2883
2985
|
if (board.outline && board.outline.length > 0) {
|
|
@@ -2908,7 +3010,7 @@ function checkPcbTracesOutOfBoard(circuitJson, config = {}) {
|
|
|
2908
3010
|
const margin = config.margin ?? getBoardDrcValue(board, "min_board_edge_clearance") ?? jlcMinTolerances.min_board_edge_clearance;
|
|
2909
3011
|
const boardPoints = getBoardPolygonPoints(board);
|
|
2910
3012
|
if (!boardPoints) return errors;
|
|
2911
|
-
const pcbTraces =
|
|
3013
|
+
const pcbTraces = cju5(circuitJson).pcb_trace.list();
|
|
2912
3014
|
for (const trace of pcbTraces) {
|
|
2913
3015
|
if (trace.route.length < 2) continue;
|
|
2914
3016
|
for (let i = 0; i < trace.route.length - 1; i++) {
|
|
@@ -2957,9 +3059,9 @@ function checkPcbTracesOutOfBoard(circuitJson, config = {}) {
|
|
|
2957
3059
|
|
|
2958
3060
|
// lib/check-pcb-components-overlap/checkPcbComponentOverlap.ts
|
|
2959
3061
|
import {
|
|
2960
|
-
cju as
|
|
3062
|
+
cju as cju6,
|
|
2961
3063
|
getBoundsOfPcbElements as getBoundsOfPcbElements5,
|
|
2962
|
-
getPrimaryId as
|
|
3064
|
+
getPrimaryId as getPrimaryId3
|
|
2963
3065
|
} from "@tscircuit/circuit-json-util";
|
|
2964
3066
|
import { doBoundsOverlap as doBoundsOverlap3 } from "@tscircuit/math-utils";
|
|
2965
3067
|
import { getFullConnectivityMapFromCircuitJson as getFullConnectivityMapFromCircuitJson7 } from "circuit-json-to-connectivity-map";
|
|
@@ -2995,20 +3097,20 @@ var formatOverlapElementDescription = (circuitJson, element) => {
|
|
|
2995
3097
|
if ("pcb_port_id" in element && element.pcb_port_id) {
|
|
2996
3098
|
return getReadableNameForPort(circuitJson, element.pcb_port_id);
|
|
2997
3099
|
}
|
|
2998
|
-
const id =
|
|
3100
|
+
const id = getPrimaryId3(element);
|
|
2999
3101
|
const readableName = getReadableNameForElementId(circuitJson, id);
|
|
3000
3102
|
return readableName === "element" ? `[${id}]` : readableName;
|
|
3001
3103
|
};
|
|
3002
3104
|
function checkPcbComponentOverlap(circuitJson) {
|
|
3003
3105
|
const errors = [];
|
|
3004
3106
|
const connMap = getFullConnectivityMapFromCircuitJson7(circuitJson);
|
|
3005
|
-
const smtPads =
|
|
3006
|
-
const platedHoles =
|
|
3007
|
-
const holes =
|
|
3107
|
+
const smtPads = cju6(circuitJson).pcb_smtpad.list();
|
|
3108
|
+
const platedHoles = cju6(circuitJson).pcb_plated_hole.list();
|
|
3109
|
+
const holes = cju6(circuitJson).pcb_hole.list();
|
|
3008
3110
|
const courtyards = circuitJson.filter(isCourtyardElement);
|
|
3009
3111
|
const componentMap = /* @__PURE__ */ new Map();
|
|
3010
3112
|
for (const pad of smtPads) {
|
|
3011
|
-
const componentId = pad.pcb_component_id || `standalone_pad_${
|
|
3113
|
+
const componentId = pad.pcb_component_id || `standalone_pad_${getPrimaryId3(pad)}`;
|
|
3012
3114
|
if (!componentMap.has(componentId)) {
|
|
3013
3115
|
componentMap.set(componentId, {
|
|
3014
3116
|
component_id: componentId,
|
|
@@ -3018,7 +3120,7 @@ function checkPcbComponentOverlap(circuitJson) {
|
|
|
3018
3120
|
componentMap.get(componentId).elements.push(pad);
|
|
3019
3121
|
}
|
|
3020
3122
|
for (const hole of platedHoles) {
|
|
3021
|
-
const componentId = hole.pcb_component_id || `standalone_plated_hole_${
|
|
3123
|
+
const componentId = hole.pcb_component_id || `standalone_plated_hole_${getPrimaryId3(hole)}`;
|
|
3022
3124
|
if (!componentMap.has(componentId)) {
|
|
3023
3125
|
componentMap.set(componentId, {
|
|
3024
3126
|
component_id: componentId,
|
|
@@ -3028,7 +3130,7 @@ function checkPcbComponentOverlap(circuitJson) {
|
|
|
3028
3130
|
componentMap.get(componentId).elements.push(hole);
|
|
3029
3131
|
}
|
|
3030
3132
|
for (const hole of holes) {
|
|
3031
|
-
const componentId = hole.pcb_component_id || `standalone_hole_${
|
|
3133
|
+
const componentId = hole.pcb_component_id || `standalone_hole_${getPrimaryId3(hole)}`;
|
|
3032
3134
|
if (!componentMap.has(componentId)) {
|
|
3033
3135
|
componentMap.set(componentId, {
|
|
3034
3136
|
component_id: componentId,
|
|
@@ -3064,8 +3166,8 @@ function checkPcbComponentOverlap(circuitJson) {
|
|
|
3064
3166
|
}
|
|
3065
3167
|
for (const elem1 of comp1.elements) {
|
|
3066
3168
|
for (const elem2 of comp2.elements) {
|
|
3067
|
-
const id1 =
|
|
3068
|
-
const id2 =
|
|
3169
|
+
const id1 = getPrimaryId3(elem1);
|
|
3170
|
+
const id2 = getPrimaryId3(elem2);
|
|
3069
3171
|
if ((isCourtyardElement(elem1) || isCourtyardElement(elem2)) && elem1.type !== "pcb_hole" && elem2.type !== "pcb_hole") {
|
|
3070
3172
|
continue;
|
|
3071
3173
|
}
|
|
@@ -3260,7 +3362,7 @@ var checkPcbTraceViaCounts = (circuitJson) => {
|
|
|
3260
3362
|
|
|
3261
3363
|
// lib/check-pad-pad-clearance.ts
|
|
3262
3364
|
import {
|
|
3263
|
-
getPrimaryId as
|
|
3365
|
+
getPrimaryId as getPrimaryId4,
|
|
3264
3366
|
getReadableNameForElement as getReadableNameForElement6
|
|
3265
3367
|
} from "@tscircuit/circuit-json-util";
|
|
3266
3368
|
import { formatMm } from "format-si-unit";
|
|
@@ -3279,17 +3381,17 @@ function checkPadPadClearance(circuitJson, {
|
|
|
3279
3381
|
const spatialIndex = new SpatialObjectIndex({
|
|
3280
3382
|
objects: pads,
|
|
3281
3383
|
getBounds: getPadBounds,
|
|
3282
|
-
getId: (pad) =>
|
|
3384
|
+
getId: (pad) => getPrimaryId4(pad)
|
|
3283
3385
|
});
|
|
3284
3386
|
const errors = /* @__PURE__ */ new Map();
|
|
3285
3387
|
for (const padA of pads) {
|
|
3286
|
-
const padAId =
|
|
3388
|
+
const padAId = getPrimaryId4(padA);
|
|
3287
3389
|
const nearbyPads = spatialIndex.getObjectsInBounds(
|
|
3288
3390
|
getPadBounds(padA),
|
|
3289
3391
|
minClearance
|
|
3290
3392
|
);
|
|
3291
3393
|
for (const padB of nearbyPads) {
|
|
3292
|
-
const padBId =
|
|
3394
|
+
const padBId = getPrimaryId4(padB);
|
|
3293
3395
|
if (padAId === padBId) continue;
|
|
3294
3396
|
if (!getLayersOfPcbElement(padA).some(
|
|
3295
3397
|
(layer) => getLayersOfPcbElement(padB).includes(layer)
|
|
@@ -3325,7 +3427,7 @@ function checkPadPadClearance(circuitJson, {
|
|
|
3325
3427
|
|
|
3326
3428
|
// lib/check-pad-trace-clearance.ts
|
|
3327
3429
|
import {
|
|
3328
|
-
getPrimaryId as
|
|
3430
|
+
getPrimaryId as getPrimaryId5,
|
|
3329
3431
|
getReadableNameForElement as getReadableNameForElement7
|
|
3330
3432
|
} from "@tscircuit/circuit-json-util";
|
|
3331
3433
|
import { formatMm as formatMm2 } from "format-si-unit";
|
|
@@ -3345,7 +3447,7 @@ function checkPadTraceClearance(circuitJson, {
|
|
|
3345
3447
|
const spatialIndex = new SpatialObjectIndex({
|
|
3346
3448
|
objects: pads,
|
|
3347
3449
|
getBounds: getPadBounds,
|
|
3348
|
-
getId: (pad) =>
|
|
3450
|
+
getId: (pad) => getPrimaryId5(pad)
|
|
3349
3451
|
});
|
|
3350
3452
|
const errors = /* @__PURE__ */ new Map();
|
|
3351
3453
|
const overlappingPairIds = /* @__PURE__ */ new Set();
|
|
@@ -3355,7 +3457,7 @@ function checkPadTraceClearance(circuitJson, {
|
|
|
3355
3457
|
minClearance + segment.thickness / 2
|
|
3356
3458
|
);
|
|
3357
3459
|
for (const pad of nearbyPads) {
|
|
3358
|
-
const padId =
|
|
3460
|
+
const padId = getPrimaryId5(pad);
|
|
3359
3461
|
if (!getLayersOfPcbElement(pad).includes(segment.layer)) continue;
|
|
3360
3462
|
if (connMap.areIdsConnected(segment.pcb_trace_id, padId)) continue;
|
|
3361
3463
|
const pairId = `${padId}_${segment.pcb_trace_id}`;
|
|
@@ -3441,7 +3543,7 @@ function checkViaTraceClearance(circuitJson, {
|
|
|
3441
3543
|
|
|
3442
3544
|
// lib/check-via-pad-clearance.ts
|
|
3443
3545
|
import {
|
|
3444
|
-
getPrimaryId as
|
|
3546
|
+
getPrimaryId as getPrimaryId6,
|
|
3445
3547
|
getReadableNameForElement as getReadableNameForElement9
|
|
3446
3548
|
} from "@tscircuit/circuit-json-util";
|
|
3447
3549
|
import { formatMm as formatMm4 } from "format-si-unit";
|
|
@@ -3463,7 +3565,7 @@ function checkViaPadClearance(circuitJson, {
|
|
|
3463
3565
|
const padIndex = new SpatialObjectIndex({
|
|
3464
3566
|
objects: pads,
|
|
3465
3567
|
getBounds: getPadBounds,
|
|
3466
|
-
getId:
|
|
3568
|
+
getId: getPrimaryId6
|
|
3467
3569
|
});
|
|
3468
3570
|
const errors = [];
|
|
3469
3571
|
for (const via of vias) {
|
|
@@ -3472,7 +3574,7 @@ function checkViaPadClearance(circuitJson, {
|
|
|
3472
3574
|
requiredClearance
|
|
3473
3575
|
);
|
|
3474
3576
|
for (const pad of nearbyPads) {
|
|
3475
|
-
const padId =
|
|
3577
|
+
const padId = getPrimaryId6(pad);
|
|
3476
3578
|
if (!getLayersOfPcbElement(via).some(
|
|
3477
3579
|
(layer) => getLayersOfPcbElement(pad).includes(layer)
|
|
3478
3580
|
)) {
|
|
@@ -3502,7 +3604,8 @@ function checkViaPadClearance(circuitJson, {
|
|
|
3502
3604
|
}
|
|
3503
3605
|
|
|
3504
3606
|
// lib/check-vias-in-pads.ts
|
|
3505
|
-
import { getPrimaryId as
|
|
3607
|
+
import { getPrimaryId as getPrimaryId7 } from "@tscircuit/circuit-json-util";
|
|
3608
|
+
import { getFullConnectivityMapFromCircuitJson as getFullConnectivityMapFromCircuitJson12 } from "circuit-json-to-connectivity-map";
|
|
3506
3609
|
function checkViasInPads(circuitJson) {
|
|
3507
3610
|
const board = getPcbBoard(circuitJson);
|
|
3508
3611
|
if (board && "is_via_in_pad_allowed" in board && board.is_via_in_pad_allowed === true) {
|
|
@@ -3513,28 +3616,25 @@ function checkViasInPads(circuitJson) {
|
|
|
3513
3616
|
);
|
|
3514
3617
|
const pads = getPads(circuitJson);
|
|
3515
3618
|
if (vias.length === 0 || pads.length === 0) return [];
|
|
3619
|
+
const connMap = getFullConnectivityMapFromCircuitJson12(circuitJson);
|
|
3516
3620
|
const padOrdinals = new Map(
|
|
3517
|
-
pads.map((pad, index) => [
|
|
3621
|
+
pads.map((pad, index) => [getPrimaryId7(pad), index])
|
|
3518
3622
|
);
|
|
3519
3623
|
const padIndex = new SpatialObjectIndex({
|
|
3520
3624
|
objects: pads,
|
|
3521
3625
|
getBounds: getPadBounds,
|
|
3522
|
-
getId:
|
|
3626
|
+
getId: getPrimaryId7
|
|
3523
3627
|
});
|
|
3524
3628
|
const errors = [];
|
|
3525
3629
|
for (const via of vias) {
|
|
3526
|
-
const nearbyPads = padIndex.getObjectsInBounds(
|
|
3527
|
-
minX: via.x,
|
|
3528
|
-
minY: via.y,
|
|
3529
|
-
maxX: via.x,
|
|
3530
|
-
maxY: via.y
|
|
3531
|
-
});
|
|
3630
|
+
const nearbyPads = padIndex.getObjectsInBounds(getPadBounds(via));
|
|
3532
3631
|
for (const pad of nearbyPads) {
|
|
3632
|
+
const padId = getPrimaryId7(pad);
|
|
3533
3633
|
const viaLayers = getLayersOfPcbElement(via);
|
|
3534
3634
|
const padLayers = getLayersOfPcbElement(pad);
|
|
3535
3635
|
if (!viaLayers.some((layer) => padLayers.includes(layer))) continue;
|
|
3536
|
-
if (
|
|
3537
|
-
|
|
3636
|
+
if (connMap.areIdsConnected(via.pcb_via_id, padId)) continue;
|
|
3637
|
+
if (getPadToPadGap(via, pad) > 0) continue;
|
|
3538
3638
|
const padOrdinal = padOrdinals.get(padId) ?? 0;
|
|
3539
3639
|
const padName = getReadableNameForFootprintPad(
|
|
3540
3640
|
circuitJson,
|
|
@@ -3545,7 +3645,7 @@ function checkViasInPads(circuitJson) {
|
|
|
3545
3645
|
type: "pcb_placement_error",
|
|
3546
3646
|
pcb_placement_error_id: `via_in_pad_${via.pcb_via_id}_${padId}`,
|
|
3547
3647
|
error_type: "pcb_placement_error",
|
|
3548
|
-
message: `Via at (${via.x.toFixed(2)}mm, ${via.y.toFixed(2)}mm)
|
|
3648
|
+
message: `Via copper at (${via.x.toFixed(2)}mm, ${via.y.toFixed(2)}mm) overlaps ${padName}`,
|
|
3549
3649
|
subcircuit_id: via.subcircuit_id ?? pad.subcircuit_id
|
|
3550
3650
|
});
|
|
3551
3651
|
}
|
|
@@ -3633,7 +3733,7 @@ function checkPinMustBeConnected(circuitJson) {
|
|
|
3633
3733
|
}
|
|
3634
3734
|
|
|
3635
3735
|
// lib/check-all-pins-in-component-are-underspecified.ts
|
|
3636
|
-
import { cju as
|
|
3736
|
+
import { cju as cju7 } from "@tscircuit/circuit-json-util";
|
|
3637
3737
|
var PIN_ATTRIBUTE_KEYS = [
|
|
3638
3738
|
"must_be_connected",
|
|
3639
3739
|
"provides_power",
|
|
@@ -3678,7 +3778,7 @@ function hasAnyPinAttribute(port) {
|
|
|
3678
3778
|
}
|
|
3679
3779
|
function checkAllPinsInComponentAreUnderspecified(circuitJson) {
|
|
3680
3780
|
const warnings = [];
|
|
3681
|
-
const db =
|
|
3781
|
+
const db = cju7(circuitJson);
|
|
3682
3782
|
const sourceComponents = db.source_component.list();
|
|
3683
3783
|
const sourcePorts = db.source_port.list();
|
|
3684
3784
|
const portsByComponent = /* @__PURE__ */ new Map();
|
|
@@ -3710,10 +3810,10 @@ function checkAllPinsInComponentAreUnderspecified(circuitJson) {
|
|
|
3710
3810
|
}
|
|
3711
3811
|
|
|
3712
3812
|
// lib/check-no-power-pin-defined.ts
|
|
3713
|
-
import { cju as
|
|
3813
|
+
import { cju as cju8 } from "@tscircuit/circuit-json-util";
|
|
3714
3814
|
function checkNoPowerPinDefined(circuitJson) {
|
|
3715
3815
|
const warnings = [];
|
|
3716
|
-
const db =
|
|
3816
|
+
const db = cju8(circuitJson);
|
|
3717
3817
|
const sourceComponents = db.source_component.list();
|
|
3718
3818
|
const sourcePorts = db.source_port.list();
|
|
3719
3819
|
const portsByComponent = /* @__PURE__ */ new Map();
|
|
@@ -3745,10 +3845,10 @@ function checkNoPowerPinDefined(circuitJson) {
|
|
|
3745
3845
|
}
|
|
3746
3846
|
|
|
3747
3847
|
// lib/check-no-ground-pin-defined.ts
|
|
3748
|
-
import { cju as
|
|
3848
|
+
import { cju as cju9 } from "@tscircuit/circuit-json-util";
|
|
3749
3849
|
function checkNoGroundPinDefined(circuitJson) {
|
|
3750
3850
|
const warnings = [];
|
|
3751
|
-
const db =
|
|
3851
|
+
const db = cju9(circuitJson);
|
|
3752
3852
|
const sourceComponents = db.source_component.list();
|
|
3753
3853
|
const sourcePorts = db.source_port.list();
|
|
3754
3854
|
const portsByComponent = /* @__PURE__ */ new Map();
|
|
@@ -4124,6 +4224,7 @@ async function runAllPlacementChecks(circuitJson) {
|
|
|
4124
4224
|
...checkViasInPads(circuitJson),
|
|
4125
4225
|
...checkPcbComponentsOutOfBoard(circuitJson),
|
|
4126
4226
|
...checkPcbComponentOverCutout(circuitJson),
|
|
4227
|
+
...checkPcbCopperOverKeepout(circuitJson),
|
|
4127
4228
|
...checkPcbComponentOverlap(circuitJson),
|
|
4128
4229
|
...checkPcbComponentsMissingCourtyard(circuitJson),
|
|
4129
4230
|
...checkPadPadClearance(circuitJson),
|
|
@@ -4186,6 +4287,7 @@ export {
|
|
|
4186
4287
|
checkPcbComponentOverlap,
|
|
4187
4288
|
checkPcbComponentsMissingCourtyard,
|
|
4188
4289
|
checkPcbComponentsOutOfBoard,
|
|
4290
|
+
checkPcbCopperOverKeepout,
|
|
4189
4291
|
checkPcbTraceLengths,
|
|
4190
4292
|
checkPcbTraceViaCounts,
|
|
4191
4293
|
checkPcbTracesOutOfBoard,
|