@tscircuit/checks 0.0.118 → 0.0.120
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 +19 -14
- package/dist/index.js +106 -25
- package/dist/index.js.map +1 -1
- package/package.json +8 -7
package/README.md
CHANGED
|
@@ -19,6 +19,7 @@ and output an array of arrays for any issues found.
|
|
|
19
19
|
| [`checkPcbComponentOverlap`](./lib/check-pcb-components-overlap/checkPcbComponentOverlap.ts) | Returns `pcb_footprint_overlap_error` when footprint elements from different components overlap in disallowed ways. |
|
|
20
20
|
| [`checkPcbComponentsOutOfBoard`](./lib/check-pcb-components-out-of-board/checkPcbComponentsOutOfBoard.ts) | Returns `pcb_placement_error` when PCB components do not fit inside the board area. |
|
|
21
21
|
| [`checkPcbTracesOutOfBoard`](./lib/check-trace-out-of-board/checkTraceOutOfBoard.ts) | Returns `pcb_trace_error` when any trace segment or via extends beyond the board boundary. |
|
|
22
|
+
| [`checkViaTraceClearance`](./lib/check-via-trace-clearance.ts) | Returns `pcb_via_trace_clearance_error` when a via and unrelated trace segment violate minimum clearance. |
|
|
22
23
|
| [`checkPinMustBeConnected`](./lib/check-pin-must-be-connected.ts) | Returns `pcb_trace_error` when required source pins are not connected. |
|
|
23
24
|
| [`checkSameNetViaSpacing`](./lib/check-same-net-via-spacing.ts) | Returns `pcb_via_clearance_error` if vias on the same net are closer than the allowed margin. |
|
|
24
25
|
| [`checkSourceTracesHavePcbTraces`](./lib/check-source-traces-have-pcb-traces.ts) | Returns `pcb_trace_error` when source traces are missing corresponding `pcb_trace` routes. |
|
|
@@ -32,7 +33,7 @@ and output an array of arrays for any issues found.
|
|
|
32
33
|
| [`runAllPlacementChecks`](./lib/run-all-checks.ts) | Runs all placement checks (`checkViasOffBoard`, `checkPcbComponentsOutOfBoard`, `checkPcbComponentOverlap`, and `checkConnectorAccessibleOrientation`). |
|
|
33
34
|
| [`runAllNetlistChecks`](./lib/run-all-checks.ts) | Runs netlist connectivity checks (currently `checkPinMustBeConnected`). |
|
|
34
35
|
| [`runAllPinSpecificationChecks`](./lib/run-all-checks.ts) | Runs pin specification checks (e.g. `checkAllPinsInComponentAreUnderspecified`, `checkNoPowerPinDefined`, and `checkNoGroundPinDefined`). |
|
|
35
|
-
| [`runAllRoutingChecks`](./lib/run-all-checks.ts) | Runs all routing checks currently enabled (`checkEachPcbPortConnectedToPcbTraces`, `checkSourceTracesHavePcbTraces`, `checkEachPcbTraceNonOverlapping`, same/different net via spacing, and `checkPcbTracesOutOfBoard`). |
|
|
36
|
+
| [`runAllRoutingChecks`](./lib/run-all-checks.ts) | Runs all routing checks currently enabled (`checkEachPcbPortConnectedToPcbTraces`, `checkSourceTracesHavePcbTraces`, `checkEachPcbTraceNonOverlapping`, `checkViaTraceClearance`, same/different net via spacing, and `checkPcbTracesOutOfBoard`). |
|
|
36
37
|
| [`runAllChecks`](./lib/run-all-checks.ts) | Runs placement, netlist, pin specification, and routing checks and returns a combined list of issues. |
|
|
37
38
|
|
|
38
39
|
## Implementation Details
|
package/dist/index.d.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import * as circuit_json from 'circuit-json';
|
|
2
|
-
import { AnyCircuitElement, PcbPortNotConnectedError, PcbTraceError, PcbPlacementError, PcbComponentOutsideBoardError, PcbViaClearanceError, PcbTraceWarning, PcbTraceMissingError, PcbFootprintOverlapError, PcbPadPadClearanceError, PcbPadTraceClearanceError, SourceComponentPinsUnderspecifiedWarning, SourceNoPowerPinDefinedWarning, SourceNoGroundPinDefinedWarning, PcbConnectorNotInAccessibleOrientationWarning } from 'circuit-json';
|
|
2
|
+
import { AnyCircuitElement, PcbPortNotConnectedError, PcbTraceError, PcbPlacementError, PcbComponentOutsideBoardError, PcbViaClearanceError, PcbTraceWarning, PcbTraceMissingError, PcbFootprintOverlapError, PcbPadPadClearanceError, PcbPadTraceClearanceError, PcbViaTraceClearanceError, SourceComponentPinsUnderspecifiedWarning, SourceNoPowerPinDefinedWarning, SourceNoGroundPinDefinedWarning, PcbConnectorNotInAccessibleOrientationWarning } from 'circuit-json';
|
|
3
3
|
import { ConnectivityMap } from 'circuit-json-to-connectivity-map';
|
|
4
4
|
|
|
5
5
|
declare function checkEachPcbPortConnectedToPcbTraces(circuitJson: AnyCircuitElement[]): PcbPortNotConnectedError[];
|
|
6
6
|
|
|
7
|
-
declare function checkEachPcbTraceNonOverlapping(circuitJson: AnyCircuitElement[], { connMap,
|
|
7
|
+
declare function checkEachPcbTraceNonOverlapping(circuitJson: AnyCircuitElement[], { connMap, minClearance, }?: {
|
|
8
8
|
connMap?: ConnectivityMap;
|
|
9
|
-
|
|
9
|
+
minClearance?: number;
|
|
10
10
|
}): PcbTraceError[];
|
|
11
11
|
|
|
12
12
|
declare class NetManager {
|
|
@@ -23,14 +23,14 @@ declare function checkViasOffBoard(circuitJson: AnyCircuitElement[]): PcbPlaceme
|
|
|
23
23
|
*/
|
|
24
24
|
declare function checkPcbComponentsOutOfBoard(circuitJson: AnyCircuitElement[]): PcbComponentOutsideBoardError[];
|
|
25
25
|
|
|
26
|
-
declare function checkSameNetViaSpacing(circuitJson: AnyCircuitElement[], { connMap,
|
|
26
|
+
declare function checkSameNetViaSpacing(circuitJson: AnyCircuitElement[], { connMap, minClearance, }?: {
|
|
27
27
|
connMap?: ConnectivityMap;
|
|
28
|
-
|
|
28
|
+
minClearance?: number;
|
|
29
29
|
}): PcbViaClearanceError[];
|
|
30
30
|
|
|
31
|
-
declare function checkDifferentNetViaSpacing(circuitJson: AnyCircuitElement[], { connMap,
|
|
31
|
+
declare function checkDifferentNetViaSpacing(circuitJson: AnyCircuitElement[], { connMap, minClearance, }?: {
|
|
32
32
|
connMap?: ConnectivityMap;
|
|
33
|
-
|
|
33
|
+
minClearance?: number;
|
|
34
34
|
}): PcbViaClearanceError[];
|
|
35
35
|
|
|
36
36
|
declare function checkSourceTracesMatchPcbTraceThickness(circuitJson: AnyCircuitElement[]): PcbTraceWarning[];
|
|
@@ -61,16 +61,21 @@ declare function checkPcbTracesOutOfBoard(circuitJson: AnyCircuitElement[], conf
|
|
|
61
61
|
*/
|
|
62
62
|
declare function checkPcbComponentOverlap(circuitJson: AnyCircuitElement[]): PcbFootprintOverlapError[];
|
|
63
63
|
|
|
64
|
-
declare function checkPadPadClearance(circuitJson: AnyCircuitElement[], { connMap,
|
|
64
|
+
declare function checkPadPadClearance(circuitJson: AnyCircuitElement[], { connMap, minClearance, }?: {
|
|
65
65
|
connMap?: ConnectivityMap;
|
|
66
|
-
|
|
66
|
+
minClearance?: number;
|
|
67
67
|
}): PcbPadPadClearanceError[];
|
|
68
68
|
|
|
69
|
-
declare function checkPadTraceClearance(circuitJson: AnyCircuitElement[], { connMap,
|
|
69
|
+
declare function checkPadTraceClearance(circuitJson: AnyCircuitElement[], { connMap, minClearance, }?: {
|
|
70
70
|
connMap?: ConnectivityMap;
|
|
71
|
-
|
|
71
|
+
minClearance?: number;
|
|
72
72
|
}): PcbPadTraceClearanceError[];
|
|
73
73
|
|
|
74
|
+
declare function checkViaTraceClearance(circuitJson: AnyCircuitElement[], { connMap, minClearance, }?: {
|
|
75
|
+
connMap?: ConnectivityMap;
|
|
76
|
+
minClearance?: number;
|
|
77
|
+
}): PcbViaTraceClearanceError[];
|
|
78
|
+
|
|
74
79
|
type SourcePinMustBeConnectedError = {
|
|
75
80
|
type: "source_pin_must_be_connected_error";
|
|
76
81
|
source_pin_must_be_connected_error_id: string;
|
|
@@ -117,8 +122,8 @@ declare function runAllNetlistChecks(circuitJson: AnyCircuitElement[]): Promise<
|
|
|
117
122
|
subcircuit_id?: string;
|
|
118
123
|
}[]>;
|
|
119
124
|
declare function runAllPinSpecificationChecks(circuitJson: AnyCircuitElement[]): Promise<(circuit_json.SourceComponentPinsUnderspecifiedWarning | circuit_json.SourceNoPowerPinDefinedWarning | circuit_json.SourceNoGroundPinDefinedWarning)[]>;
|
|
120
|
-
declare function runAllRoutingChecks(circuitJson: AnyCircuitElement[]): Promise<(circuit_json.PcbPortNotConnectedError | circuit_json.PcbTraceError | circuit_json.PcbViaClearanceError | circuit_json.PcbTraceMissingError)[]>;
|
|
121
|
-
declare function runAllChecks(circuitJson: AnyCircuitElement[]): Promise<(circuit_json.PcbPortNotConnectedError | circuit_json.PcbTraceError | circuit_json.PcbPlacementError | circuit_json.PcbComponentOutsideBoardError | circuit_json.PcbViaClearanceError | circuit_json.PcbTraceMissingError | circuit_json.PcbFootprintOverlapError | circuit_json.PcbPadPadClearanceError | circuit_json.PcbPadTraceClearanceError | {
|
|
125
|
+
declare function runAllRoutingChecks(circuitJson: AnyCircuitElement[]): Promise<(circuit_json.PcbPortNotConnectedError | circuit_json.PcbTraceError | circuit_json.PcbViaClearanceError | circuit_json.PcbTraceMissingError | circuit_json.PcbViaTraceClearanceError)[]>;
|
|
126
|
+
declare function runAllChecks(circuitJson: AnyCircuitElement[]): Promise<(circuit_json.PcbPortNotConnectedError | circuit_json.PcbTraceError | circuit_json.PcbPlacementError | circuit_json.PcbComponentOutsideBoardError | circuit_json.PcbViaClearanceError | circuit_json.PcbTraceMissingError | circuit_json.PcbFootprintOverlapError | circuit_json.PcbPadPadClearanceError | circuit_json.PcbPadTraceClearanceError | circuit_json.PcbViaTraceClearanceError | {
|
|
122
127
|
type: "source_pin_must_be_connected_error";
|
|
123
128
|
source_pin_must_be_connected_error_id: string;
|
|
124
129
|
error_type: "source_pin_must_be_connected_error";
|
|
@@ -130,4 +135,4 @@ declare function runAllChecks(circuitJson: AnyCircuitElement[]): Promise<(circui
|
|
|
130
135
|
|
|
131
136
|
declare function checkConnectorAccessibleOrientation(circuitJson: AnyCircuitElement[]): PcbConnectorNotInAccessibleOrientationWarning[];
|
|
132
137
|
|
|
133
|
-
export { NetManager, checkAllPinsInComponentAreUnderspecified, checkConnectorAccessibleOrientation, checkDifferentNetViaSpacing, checkEachPcbPortConnectedToPcbTraces, checkEachPcbTraceNonOverlapping, checkNoGroundPinDefined, checkNoPowerPinDefined, checkPadPadClearance, checkPadTraceClearance, checkPcbComponentOverlap, checkPcbComponentsOutOfBoard, checkPcbTracesOutOfBoard, checkPinMustBeConnected, checkSameNetViaSpacing, checkSourceTracesHavePcbTraces, checkSourceTracesMatchPcbTraceThickness, checkViasOffBoard, runAllChecks, runAllNetlistChecks, runAllPinSpecificationChecks, runAllPlacementChecks, runAllRoutingChecks };
|
|
138
|
+
export { NetManager, checkAllPinsInComponentAreUnderspecified, checkConnectorAccessibleOrientation, checkDifferentNetViaSpacing, checkEachPcbPortConnectedToPcbTraces, checkEachPcbTraceNonOverlapping, checkNoGroundPinDefined, checkNoPowerPinDefined, checkPadPadClearance, checkPadTraceClearance, checkPcbComponentOverlap, checkPcbComponentsOutOfBoard, checkPcbTracesOutOfBoard, checkPinMustBeConnected, checkSameNetViaSpacing, checkSourceTracesHavePcbTraces, checkSourceTracesMatchPcbTraceThickness, checkViaTraceClearance, checkViasOffBoard, runAllChecks, runAllNetlistChecks, runAllPinSpecificationChecks, runAllPlacementChecks, runAllRoutingChecks };
|
package/dist/index.js
CHANGED
|
@@ -364,13 +364,15 @@ import {
|
|
|
364
364
|
} from "@tscircuit/math-utils";
|
|
365
365
|
|
|
366
366
|
// lib/drc-defaults.ts
|
|
367
|
+
import { jlcMinTolerances } from "@tscircuit/jlcpcb-manufacturing-specs";
|
|
367
368
|
var DEFAULT_TRACE_MARGIN = 0.1;
|
|
368
|
-
var DEFAULT_TRACE_THICKNESS =
|
|
369
|
+
var DEFAULT_TRACE_THICKNESS = jlcMinTolerances.min_trace_width;
|
|
370
|
+
var DEFAULT_VIA_DIAMETER = jlcMinTolerances.min_via_pad_diameter;
|
|
369
371
|
var DEFAULT_VIA_BOARD_MARGIN = 0.3;
|
|
370
|
-
var DEFAULT_SAME_NET_VIA_MARGIN =
|
|
371
|
-
var DEFAULT_DIFFERENT_NET_VIA_MARGIN =
|
|
372
|
-
var DEFAULT_PAD_PAD_CLEARANCE =
|
|
373
|
-
var DEFAULT_PAD_TRACE_CLEARANCE =
|
|
372
|
+
var DEFAULT_SAME_NET_VIA_MARGIN = jlcMinTolerances.min_via_to_via_clearance;
|
|
373
|
+
var DEFAULT_DIFFERENT_NET_VIA_MARGIN = jlcMinTolerances.min_via_to_via_clearance;
|
|
374
|
+
var DEFAULT_PAD_PAD_CLEARANCE = jlcMinTolerances.min_pad_to_pad_clearance;
|
|
375
|
+
var DEFAULT_PAD_TRACE_CLEARANCE = jlcMinTolerances.min_trace_to_pad_clearance;
|
|
374
376
|
var EPSILON = 5e-3;
|
|
375
377
|
|
|
376
378
|
// lib/check-each-pcb-trace-non-overlapping/getPcbPortIdsConnectedToTraces.ts
|
|
@@ -684,7 +686,7 @@ function getLayersOfPcbElement(obj) {
|
|
|
684
686
|
// lib/check-each-pcb-trace-non-overlapping/check-each-pcb-trace-non-overlapping.ts
|
|
685
687
|
function checkEachPcbTraceNonOverlapping(circuitJson, {
|
|
686
688
|
connMap,
|
|
687
|
-
|
|
689
|
+
minClearance = DEFAULT_TRACE_MARGIN
|
|
688
690
|
} = {}) {
|
|
689
691
|
const errors = [];
|
|
690
692
|
addStartAndEndPortIdsIfMissing(circuitJson);
|
|
@@ -732,7 +734,7 @@ function checkEachPcbTraceNonOverlapping(circuitJson, {
|
|
|
732
734
|
const getReadableName = (id) => getReadableNameForElement2(circuitJson, id);
|
|
733
735
|
const errorIds = /* @__PURE__ */ new Set();
|
|
734
736
|
for (const segmentA of pcbTraceSegments) {
|
|
735
|
-
const requiredMargin =
|
|
737
|
+
const requiredMargin = minClearance;
|
|
736
738
|
const bounds = getCollidableBounds(segmentA);
|
|
737
739
|
const nearbyObjects = spatialIndex.getObjectsInBounds(
|
|
738
740
|
bounds,
|
|
@@ -754,7 +756,7 @@ function checkEachPcbTraceNonOverlapping(circuitJson, {
|
|
|
754
756
|
{ x: segmentB.x1, y: segmentB.y1 },
|
|
755
757
|
{ x: segmentB.x2, y: segmentB.y2 }
|
|
756
758
|
) - segmentA.thickness / 2 - segmentB.thickness / 2;
|
|
757
|
-
if (gap2 >
|
|
759
|
+
if (gap2 > minClearance - EPSILON) continue;
|
|
758
760
|
const pcb_trace_error_id = `overlap_${segmentA.pcb_trace_id}_${segmentB.pcb_trace_id}`;
|
|
759
761
|
const pcb_trace_error_id_reverse = `overlap_${segmentB.pcb_trace_id}_${segmentA.pcb_trace_id}`;
|
|
760
762
|
if (errorIds.has(pcb_trace_error_id)) continue;
|
|
@@ -791,7 +793,7 @@ function checkEachPcbTraceNonOverlapping(circuitJson, {
|
|
|
791
793
|
{ x: obj.x, y: obj.y, radius }
|
|
792
794
|
);
|
|
793
795
|
const gap2 = distance3 - segmentA.thickness / 2;
|
|
794
|
-
if (gap2 >
|
|
796
|
+
if (gap2 > minClearance - EPSILON) continue;
|
|
795
797
|
const pcb_trace_error_id = `overlap_${segmentA.pcb_trace_id}_${primaryObjId}`;
|
|
796
798
|
if (errorIds.has(pcb_trace_error_id)) continue;
|
|
797
799
|
errorIds.add(pcb_trace_error_id);
|
|
@@ -1174,7 +1176,7 @@ function viasAreAtSameLocation(a, b) {
|
|
|
1174
1176
|
// lib/check-same-net-via-spacing.ts
|
|
1175
1177
|
function checkSameNetViaSpacing(circuitJson, {
|
|
1176
1178
|
connMap,
|
|
1177
|
-
|
|
1179
|
+
minClearance = DEFAULT_SAME_NET_VIA_MARGIN
|
|
1178
1180
|
} = {}) {
|
|
1179
1181
|
const vias = circuitJson.filter((el) => el.type === "pcb_via");
|
|
1180
1182
|
if (vias.length < 2) return [];
|
|
@@ -1188,7 +1190,7 @@ function checkSameNetViaSpacing(circuitJson, {
|
|
|
1188
1190
|
if (viasAreAtSameLocation(viaA, viaB)) continue;
|
|
1189
1191
|
if (!connMap.areIdsConnected(viaA.pcb_via_id, viaB.pcb_via_id)) continue;
|
|
1190
1192
|
const gap = distance2(viaA, viaB) - viaA.outer_diameter / 2 - viaB.outer_diameter / 2;
|
|
1191
|
-
if (gap + EPSILON >=
|
|
1193
|
+
if (gap + EPSILON >= minClearance) continue;
|
|
1192
1194
|
const pairId = [viaA.pcb_via_id, viaB.pcb_via_id].sort().join("_");
|
|
1193
1195
|
if (reported.has(pairId)) continue;
|
|
1194
1196
|
reported.add(pairId);
|
|
@@ -1204,7 +1206,7 @@ function checkSameNetViaSpacing(circuitJson, {
|
|
|
1204
1206
|
)} are too close together (gap: ${gap.toFixed(3)}mm)`,
|
|
1205
1207
|
error_type: "pcb_via_clearance_error",
|
|
1206
1208
|
pcb_via_ids: [viaA.pcb_via_id, viaB.pcb_via_id],
|
|
1207
|
-
minimum_clearance:
|
|
1209
|
+
minimum_clearance: minClearance,
|
|
1208
1210
|
actual_clearance: gap,
|
|
1209
1211
|
pcb_center: {
|
|
1210
1212
|
x: (viaA.x + viaB.x) / 2,
|
|
@@ -1223,7 +1225,7 @@ import {
|
|
|
1223
1225
|
} from "circuit-json-to-connectivity-map";
|
|
1224
1226
|
function checkDifferentNetViaSpacing(circuitJson, {
|
|
1225
1227
|
connMap,
|
|
1226
|
-
|
|
1228
|
+
minClearance = DEFAULT_DIFFERENT_NET_VIA_MARGIN
|
|
1227
1229
|
} = {}) {
|
|
1228
1230
|
const vias = circuitJson.filter((el) => el.type === "pcb_via");
|
|
1229
1231
|
if (vias.length < 2) return [];
|
|
@@ -1237,7 +1239,7 @@ function checkDifferentNetViaSpacing(circuitJson, {
|
|
|
1237
1239
|
if (viasAreAtSameLocation(viaA, viaB)) continue;
|
|
1238
1240
|
if (connMap.areIdsConnected(viaA.pcb_via_id, viaB.pcb_via_id)) continue;
|
|
1239
1241
|
const gap = distance2(viaA, viaB) - viaA.outer_diameter / 2 - viaB.outer_diameter / 2;
|
|
1240
|
-
if (gap + EPSILON >=
|
|
1242
|
+
if (gap + EPSILON >= minClearance) continue;
|
|
1241
1243
|
const pairId = [viaA.pcb_via_id, viaB.pcb_via_id].sort().join("_");
|
|
1242
1244
|
if (reported.has(pairId)) continue;
|
|
1243
1245
|
reported.add(pairId);
|
|
@@ -1255,7 +1257,7 @@ function checkDifferentNetViaSpacing(circuitJson, {
|
|
|
1255
1257
|
)}mm)`,
|
|
1256
1258
|
error_type: "pcb_via_clearance_error",
|
|
1257
1259
|
pcb_via_ids: [viaA.pcb_via_id, viaB.pcb_via_id],
|
|
1258
|
-
minimum_clearance:
|
|
1260
|
+
minimum_clearance: minClearance,
|
|
1259
1261
|
actual_clearance: gap,
|
|
1260
1262
|
pcb_center: {
|
|
1261
1263
|
x: (viaA.x + viaB.x) / 2,
|
|
@@ -1716,7 +1718,7 @@ var getTraceSegments = (circuitJson) => {
|
|
|
1716
1718
|
// lib/check-pad-pad-clearance.ts
|
|
1717
1719
|
function checkPadPadClearance(circuitJson, {
|
|
1718
1720
|
connMap,
|
|
1719
|
-
|
|
1721
|
+
minClearance = DEFAULT_PAD_PAD_CLEARANCE
|
|
1720
1722
|
} = {}) {
|
|
1721
1723
|
const pads = getPads(circuitJson);
|
|
1722
1724
|
if (pads.length < 2) return [];
|
|
@@ -1731,7 +1733,7 @@ function checkPadPadClearance(circuitJson, {
|
|
|
1731
1733
|
const padAId = getPrimaryId3(padA);
|
|
1732
1734
|
const nearbyPads = spatialIndex.getObjectsInBounds(
|
|
1733
1735
|
getPadBounds(padA),
|
|
1734
|
-
|
|
1736
|
+
minClearance
|
|
1735
1737
|
);
|
|
1736
1738
|
for (const padB of nearbyPads) {
|
|
1737
1739
|
const padBId = getPrimaryId3(padB);
|
|
@@ -1744,16 +1746,16 @@ function checkPadPadClearance(circuitJson, {
|
|
|
1744
1746
|
if (connMap.areIdsConnected(padAId, padBId)) continue;
|
|
1745
1747
|
const pairId = [padAId, padBId].sort().join("_");
|
|
1746
1748
|
const gap = getPadToPadGap(padA, padB);
|
|
1747
|
-
if (gap + EPSILON >=
|
|
1749
|
+
if (gap + EPSILON >= minClearance) continue;
|
|
1748
1750
|
const centerA = getPadCenter(padA);
|
|
1749
1751
|
const centerB = getPadCenter(padB);
|
|
1750
1752
|
const nextError = {
|
|
1751
1753
|
type: "pcb_pad_pad_clearance_error",
|
|
1752
1754
|
pcb_pad_pad_clearance_error_id: `pad_pad_clearance_${pairId}`,
|
|
1753
1755
|
error_type: "pcb_pad_pad_clearance_error",
|
|
1754
|
-
message: `Pads ${getReadableNameForElement6(circuitJson, padAId)} and ${getReadableNameForElement6(circuitJson, padBId)} are too close (clearance: ${formatMm(gap)}, minimum: ${formatMm(
|
|
1756
|
+
message: `Pads ${getReadableNameForElement6(circuitJson, padAId)} and ${getReadableNameForElement6(circuitJson, padBId)} are too close (clearance: ${formatMm(gap)}, minimum: ${formatMm(minClearance)})`,
|
|
1755
1757
|
pcb_pad_ids: [padAId, padBId],
|
|
1756
|
-
minimum_clearance:
|
|
1758
|
+
minimum_clearance: minClearance,
|
|
1757
1759
|
actual_clearance: gap,
|
|
1758
1760
|
center: {
|
|
1759
1761
|
x: (centerA.x + centerB.x) / 2,
|
|
@@ -1782,7 +1784,7 @@ import {
|
|
|
1782
1784
|
} from "circuit-json-to-connectivity-map";
|
|
1783
1785
|
function checkPadTraceClearance(circuitJson, {
|
|
1784
1786
|
connMap,
|
|
1785
|
-
|
|
1787
|
+
minClearance = DEFAULT_PAD_TRACE_CLEARANCE
|
|
1786
1788
|
} = {}) {
|
|
1787
1789
|
const pads = getPads(circuitJson);
|
|
1788
1790
|
const segments = getTraceSegments(circuitJson);
|
|
@@ -1797,7 +1799,7 @@ function checkPadTraceClearance(circuitJson, {
|
|
|
1797
1799
|
for (const segment of segments) {
|
|
1798
1800
|
const nearbyPads = spatialIndex.getObjectsInBounds(
|
|
1799
1801
|
getCollidableBounds(segment),
|
|
1800
|
-
|
|
1802
|
+
minClearance + segment.thickness / 2
|
|
1801
1803
|
);
|
|
1802
1804
|
for (const pad of nearbyPads) {
|
|
1803
1805
|
const padId = getPrimaryId4(pad);
|
|
@@ -1813,16 +1815,16 @@ function checkPadTraceClearance(circuitJson, {
|
|
|
1813
1815
|
{ x: segment.x2, y: segment.y2 },
|
|
1814
1816
|
getPadBounds(pad)
|
|
1815
1817
|
) - segment.thickness / 2;
|
|
1816
|
-
if (gap + EPSILON >=
|
|
1818
|
+
if (gap + EPSILON >= minClearance) continue;
|
|
1817
1819
|
const pairId = `${padId}_${segment.pcb_trace_id}`;
|
|
1818
1820
|
const nextError = {
|
|
1819
1821
|
type: "pcb_pad_trace_clearance_error",
|
|
1820
1822
|
pcb_pad_trace_clearance_error_id: `pad_trace_clearance_${pairId}`,
|
|
1821
1823
|
error_type: "pcb_pad_trace_clearance_error",
|
|
1822
|
-
message: `Pad ${getReadableNameForElement7(circuitJson, padId)} and trace ${getReadableNameForElement7(circuitJson, segment.pcb_trace_id)} are too close (clearance: ${formatMm(gap)}, minimum: ${formatMm(
|
|
1824
|
+
message: `Pad ${getReadableNameForElement7(circuitJson, padId)} and trace ${getReadableNameForElement7(circuitJson, segment.pcb_trace_id)} are too close (clearance: ${formatMm(gap)}, minimum: ${formatMm(minClearance)})`,
|
|
1823
1825
|
pcb_pad_id: padId,
|
|
1824
1826
|
pcb_trace_id: segment.pcb_trace_id,
|
|
1825
|
-
minimum_clearance:
|
|
1827
|
+
minimum_clearance: minClearance,
|
|
1826
1828
|
actual_clearance: gap,
|
|
1827
1829
|
center: {
|
|
1828
1830
|
x: (center.x + (segment.x1 + segment.x2) / 2) / 2,
|
|
@@ -1838,6 +1840,83 @@ function checkPadTraceClearance(circuitJson, {
|
|
|
1838
1840
|
return Array.from(errors.values()).map(({ error }) => error);
|
|
1839
1841
|
}
|
|
1840
1842
|
|
|
1843
|
+
// lib/check-via-trace-clearance.ts
|
|
1844
|
+
import { getReadableNameForElement as getReadableNameForElement8 } from "@tscircuit/circuit-json-util";
|
|
1845
|
+
import { segmentToCircleMinDistance as segmentToCircleMinDistance3 } from "@tscircuit/math-utils";
|
|
1846
|
+
import {
|
|
1847
|
+
getFullConnectivityMapFromCircuitJson as getFullConnectivityMapFromCircuitJson9
|
|
1848
|
+
} from "circuit-json-to-connectivity-map";
|
|
1849
|
+
var getClosestPointOnSegment = (point, segmentStart, segmentEnd) => {
|
|
1850
|
+
const dx = segmentEnd.x - segmentStart.x;
|
|
1851
|
+
const dy = segmentEnd.y - segmentStart.y;
|
|
1852
|
+
const lengthSquared = dx * dx + dy * dy;
|
|
1853
|
+
if (lengthSquared === 0) return segmentStart;
|
|
1854
|
+
const t = Math.max(
|
|
1855
|
+
0,
|
|
1856
|
+
Math.min(
|
|
1857
|
+
1,
|
|
1858
|
+
((point.x - segmentStart.x) * dx + (point.y - segmentStart.y) * dy) / lengthSquared
|
|
1859
|
+
)
|
|
1860
|
+
);
|
|
1861
|
+
return {
|
|
1862
|
+
x: segmentStart.x + t * dx,
|
|
1863
|
+
y: segmentStart.y + t * dy
|
|
1864
|
+
};
|
|
1865
|
+
};
|
|
1866
|
+
function checkViaTraceClearance(circuitJson, {
|
|
1867
|
+
connMap,
|
|
1868
|
+
minClearance = DEFAULT_PAD_TRACE_CLEARANCE
|
|
1869
|
+
} = {}) {
|
|
1870
|
+
const vias = circuitJson.filter((el) => el.type === "pcb_via");
|
|
1871
|
+
const segments = getTraceSegments(circuitJson);
|
|
1872
|
+
if (vias.length === 0 || segments.length === 0) return [];
|
|
1873
|
+
connMap ??= getFullConnectivityMapFromCircuitJson9(circuitJson);
|
|
1874
|
+
const errors = /* @__PURE__ */ new Map();
|
|
1875
|
+
for (const via of vias) {
|
|
1876
|
+
const viaRadius = via.outer_diameter / 2;
|
|
1877
|
+
for (const segment of segments) {
|
|
1878
|
+
if (!getLayersOfPcbElement(via).includes(segment.layer)) continue;
|
|
1879
|
+
if (connMap.areIdsConnected(segment.pcb_trace_id, via.pcb_via_id))
|
|
1880
|
+
continue;
|
|
1881
|
+
const gap = segmentToCircleMinDistance3(
|
|
1882
|
+
{ x: segment.x1, y: segment.y1 },
|
|
1883
|
+
{ x: segment.x2, y: segment.y2 },
|
|
1884
|
+
{
|
|
1885
|
+
x: via.x,
|
|
1886
|
+
y: via.y,
|
|
1887
|
+
radius: viaRadius
|
|
1888
|
+
}
|
|
1889
|
+
) - segment.thickness / 2;
|
|
1890
|
+
if (gap + EPSILON >= minClearance) continue;
|
|
1891
|
+
const closestPoint = getClosestPointOnSegment(
|
|
1892
|
+
{ x: via.x, y: via.y },
|
|
1893
|
+
{ x: segment.x1, y: segment.y1 },
|
|
1894
|
+
{ x: segment.x2, y: segment.y2 }
|
|
1895
|
+
);
|
|
1896
|
+
const pairId = `${via.pcb_via_id}_${segment.pcb_trace_id}`;
|
|
1897
|
+
const nextError = {
|
|
1898
|
+
type: "pcb_via_trace_clearance_error",
|
|
1899
|
+
pcb_via_trace_clearance_error_id: `via_trace_clearance_${pairId}`,
|
|
1900
|
+
error_type: "pcb_via_trace_clearance_error",
|
|
1901
|
+
message: `Via ${getReadableNameForElement8(circuitJson, via.pcb_via_id)} and trace ${getReadableNameForElement8(circuitJson, segment.pcb_trace_id)} are too close (clearance: ${formatMm(gap)}, minimum: ${formatMm(minClearance)})`,
|
|
1902
|
+
pcb_via_id: via.pcb_via_id,
|
|
1903
|
+
pcb_trace_id: segment.pcb_trace_id,
|
|
1904
|
+
minimum_clearance: minClearance,
|
|
1905
|
+
actual_clearance: gap,
|
|
1906
|
+
center: {
|
|
1907
|
+
x: (via.x + closestPoint.x) / 2,
|
|
1908
|
+
y: (via.y + closestPoint.y) / 2
|
|
1909
|
+
}
|
|
1910
|
+
};
|
|
1911
|
+
const current = errors.get(pairId);
|
|
1912
|
+
if (!current || gap < current.gap) {
|
|
1913
|
+
errors.set(pairId, { error: nextError, gap });
|
|
1914
|
+
}
|
|
1915
|
+
}
|
|
1916
|
+
}
|
|
1917
|
+
return Array.from(errors.values()).map(({ error }) => error);
|
|
1918
|
+
}
|
|
1919
|
+
|
|
1841
1920
|
// lib/check-pin-must-be-connected.ts
|
|
1842
1921
|
function checkPinMustBeConnected(circuitJson) {
|
|
1843
1922
|
const errors = [];
|
|
@@ -2248,6 +2327,7 @@ async function runAllRoutingChecks(circuitJson) {
|
|
|
2248
2327
|
...checkEachPcbPortConnectedToPcbTraces(circuitJson),
|
|
2249
2328
|
...checkSourceTracesHavePcbTraces(circuitJson),
|
|
2250
2329
|
...checkEachPcbTraceNonOverlapping(circuitJson),
|
|
2330
|
+
...checkViaTraceClearance(circuitJson),
|
|
2251
2331
|
...checkSameNetViaSpacing(circuitJson),
|
|
2252
2332
|
...checkDifferentNetViaSpacing(circuitJson),
|
|
2253
2333
|
// ...checkTracesAreContiguous(circuitJson),
|
|
@@ -2280,6 +2360,7 @@ export {
|
|
|
2280
2360
|
checkSameNetViaSpacing,
|
|
2281
2361
|
checkSourceTracesHavePcbTraces,
|
|
2282
2362
|
checkSourceTracesMatchPcbTraceThickness,
|
|
2363
|
+
checkViaTraceClearance,
|
|
2283
2364
|
checkViasOffBoard,
|
|
2284
2365
|
runAllChecks,
|
|
2285
2366
|
runAllNetlistChecks,
|