@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 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, minSpacing, }?: {
7
+ declare function checkEachPcbTraceNonOverlapping(circuitJson: AnyCircuitElement[], { connMap, minClearance, }?: {
8
8
  connMap?: ConnectivityMap;
9
- minSpacing?: number;
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, minSpacing, }?: {
26
+ declare function checkSameNetViaSpacing(circuitJson: AnyCircuitElement[], { connMap, minClearance, }?: {
27
27
  connMap?: ConnectivityMap;
28
- minSpacing?: number;
28
+ minClearance?: number;
29
29
  }): PcbViaClearanceError[];
30
30
 
31
- declare function checkDifferentNetViaSpacing(circuitJson: AnyCircuitElement[], { connMap, minSpacing, }?: {
31
+ declare function checkDifferentNetViaSpacing(circuitJson: AnyCircuitElement[], { connMap, minClearance, }?: {
32
32
  connMap?: ConnectivityMap;
33
- minSpacing?: number;
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, minSpacing, }?: {
64
+ declare function checkPadPadClearance(circuitJson: AnyCircuitElement[], { connMap, minClearance, }?: {
65
65
  connMap?: ConnectivityMap;
66
- minSpacing?: number;
66
+ minClearance?: number;
67
67
  }): PcbPadPadClearanceError[];
68
68
 
69
- declare function checkPadTraceClearance(circuitJson: AnyCircuitElement[], { connMap, minSpacing, }?: {
69
+ declare function checkPadTraceClearance(circuitJson: AnyCircuitElement[], { connMap, minClearance, }?: {
70
70
  connMap?: ConnectivityMap;
71
- minSpacing?: number;
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 = 0.15;
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 = 0.2;
371
- var DEFAULT_DIFFERENT_NET_VIA_MARGIN = 0.3;
372
- var DEFAULT_PAD_PAD_CLEARANCE = 0.1;
373
- var DEFAULT_PAD_TRACE_CLEARANCE = 0.1;
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
- minSpacing = DEFAULT_TRACE_MARGIN
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 = minSpacing;
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 > minSpacing - EPSILON) continue;
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 > minSpacing - EPSILON) continue;
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
- minSpacing = DEFAULT_SAME_NET_VIA_MARGIN
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 >= minSpacing) continue;
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: minSpacing,
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
- minSpacing = DEFAULT_DIFFERENT_NET_VIA_MARGIN
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 >= minSpacing) continue;
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: minSpacing,
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
- minSpacing = DEFAULT_PAD_PAD_CLEARANCE
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
- minSpacing
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 >= minSpacing) continue;
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(minSpacing)})`,
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: minSpacing,
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
- minSpacing = DEFAULT_PAD_TRACE_CLEARANCE
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
- minSpacing + segment.thickness / 2
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 >= minSpacing) continue;
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(minSpacing)})`,
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: minSpacing,
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,