@tscircuit/checks 0.0.205 → 0.0.206

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.d.ts CHANGED
@@ -1,11 +1,16 @@
1
1
  import * as circuit_json from 'circuit-json';
2
2
  import { AnyCircuitElement, PcbPlacementError, PcbPortNotConnectedError, PcbTraceError, PcbKeepoutOverlapWarning, PcbComponentOutsideBoardError, PcbViaClearanceError, PcbTraceWarning, PcbTraceMissingError, PcbFootprintOverlapError, PcbPadPadClearanceError, PcbCourtyardOverlapError, PcbComponentMissingCourtyardWarning, PcbTraceTooLongError, PcbPadTraceClearanceError, PcbViaTraceClearanceError, SourceComponentMisconfiguredError, SourceComponentPinsUnderspecifiedWarning, SourceNoPowerPinDefinedWarning, SourceNoGroundPinDefinedWarning, SchematicComponentStylingWarning, PcbConnectorNotInAccessibleOrientationWarning, SourceConfusingNetNameWarning, PcbBusLengthSkewError } from 'circuit-json';
3
- import { ConnectivityMap } from 'circuit-json-to-connectivity-map';
3
+ import { ConnectivityMap, PcbConnectivityMap } from 'circuit-json-to-connectivity-map';
4
4
 
5
5
  /** Detect accidental copper contact, rather than enforcing a clearance margin. */
6
- declare function checkCopperPourShorts(circuitJson: AnyCircuitElement[]): PcbPlacementError[];
6
+ declare function checkCopperPourShorts(circuitJson: AnyCircuitElement[], { connMap }?: {
7
+ connMap?: ConnectivityMap;
8
+ }): PcbPlacementError[];
7
9
 
8
- declare function checkEachPcbPortConnectedToPcbTraces(circuitJson: AnyCircuitElement[]): PcbPortNotConnectedError[];
10
+ declare function checkEachPcbPortConnectedToPcbTraces(circuitJson: AnyCircuitElement[], { connMap, pcbConnectivityMap, }?: {
11
+ connMap?: ConnectivityMap;
12
+ pcbConnectivityMap?: PcbConnectivityMap;
13
+ }): PcbPortNotConnectedError[];
9
14
 
10
15
  declare function checkEachPcbTraceNonOverlapping(circuitJson: AnyCircuitElement[], { connMap, minClearance, }?: {
11
16
  connMap?: ConnectivityMap;
@@ -63,9 +68,14 @@ declare function checkSourceTracesMatchPcbTraceThickness(circuitJson: AnyCircuit
63
68
  * pcb_trace associated with it, or its ports physically joined through a
64
69
  * same-net copper pour. Otherwise return an error for that source_trace.
65
70
  */
66
- declare function checkSourceTracesHavePcbTraces(circuitJson: AnyCircuitElement[]): PcbTraceMissingError[];
71
+ declare function checkSourceTracesHavePcbTraces(circuitJson: AnyCircuitElement[], { connMap }?: {
72
+ connMap?: ConnectivityMap;
73
+ }): PcbTraceMissingError[];
67
74
 
68
- declare function checkTracesAreContiguous(circuitJson: AnyCircuitElement[]): PcbTraceError[];
75
+ declare function checkTracesAreContiguous(circuitJson: AnyCircuitElement[], { connMap, pcbConnectivityMap, }?: {
76
+ connMap?: ConnectivityMap;
77
+ pcbConnectivityMap?: PcbConnectivityMap;
78
+ }): PcbTraceError[];
69
79
 
70
80
  /**
71
81
  * Configuration for trace board boundary checking
package/dist/index.js CHANGED
@@ -635,14 +635,16 @@ function convertCircuitJsonToFlattenJs(json, options = {}) {
635
635
  }
636
636
 
637
637
  // lib/check-copper-pour-shorts.ts
638
- import { getFullConnectivityMapFromCircuitJson } from "circuit-json-to-connectivity-map";
638
+ import {
639
+ getFullConnectivityMapFromCircuitJson
640
+ } from "circuit-json-to-connectivity-map";
639
641
  function touchesPour(pour, geometry) {
640
642
  if (!pour.box.intersect(geometry.box)) return false;
641
643
  return pour.intersect(geometry).length > 0 || [...geometry.faces].some((face) => pour.contains(face.first.start)) || [...pour.faces].some((face) => geometry.contains(face.first.start));
642
644
  }
643
- function checkCopperPourShorts(circuitJson) {
645
+ function checkCopperPourShorts(circuitJson, { connMap } = {}) {
644
646
  if (!circuitJson.some((e) => e.type === "pcb_copper_pour")) return [];
645
- const connMap = getFullConnectivityMapFromCircuitJson(circuitJson);
647
+ connMap ??= getFullConnectivityMapFromCircuitJson(circuitJson);
646
648
  const { elements: copper } = convertCircuitJsonToFlattenJs(circuitJson, {
647
649
  elementTypes: [
648
650
  "pcb_smtpad",
@@ -706,6 +708,97 @@ function checkCopperPourShorts(circuitJson) {
706
708
  return [...errors.values()];
707
709
  }
708
710
 
711
+ // lib/util/create-indexed-pcb-connectivity-map.ts
712
+ import {
713
+ ConnectivityMap,
714
+ findConnectedNetworks,
715
+ PcbConnectivityMap
716
+ } from "circuit-json-to-connectivity-map";
717
+ import Flatbush2 from "flatbush";
718
+ function createIndexedPcbConnectivityMap(circuitJson) {
719
+ const map = new PcbConnectivityMap();
720
+ map.circuitJson = circuitJson;
721
+ for (const element of circuitJson) {
722
+ if (element.type === "pcb_trace") {
723
+ map.traceIdToElm.set(element.pcb_trace_id, element);
724
+ } else if (element.type === "pcb_port") {
725
+ map.portIdToElm.set(element.pcb_port_id, element);
726
+ }
727
+ }
728
+ const traces = [...map.traceIdToElm.values()];
729
+ const boundsByLayer = /* @__PURE__ */ new Map();
730
+ for (const [traceIndex, trace] of traces.entries()) {
731
+ const boundsForTrace = /* @__PURE__ */ new Map();
732
+ for (let i = 0; i < trace.route.length - 1; i++) {
733
+ const a = trace.route[i];
734
+ const b = trace.route[i + 1];
735
+ if (a.route_type !== "wire" || b.route_type !== "wire" || a.layer !== b.layer)
736
+ continue;
737
+ const bounds = boundsForTrace.get(a.layer) ?? {
738
+ traceIndex,
739
+ minX: Infinity,
740
+ minY: Infinity,
741
+ maxX: -Infinity,
742
+ maxY: -Infinity
743
+ };
744
+ const radius = a.width / 2 + 1e-9;
745
+ bounds.minX = Math.min(bounds.minX, a.x - radius, b.x - radius);
746
+ bounds.minY = Math.min(bounds.minY, a.y - radius, b.y - radius);
747
+ bounds.maxX = Math.max(bounds.maxX, a.x + radius, b.x + radius);
748
+ bounds.maxY = Math.max(bounds.maxY, a.y + radius, b.y + radius);
749
+ boundsForTrace.set(a.layer, bounds);
750
+ }
751
+ for (const [layer, bounds] of boundsForTrace) {
752
+ const entries = boundsByLayer.get(layer) ?? [];
753
+ entries.push(bounds);
754
+ boundsByLayer.set(layer, entries);
755
+ }
756
+ }
757
+ const candidates = traces.map(() => /* @__PURE__ */ new Set());
758
+ for (const bounds of boundsByLayer.values()) {
759
+ const index = new Flatbush2(bounds.length);
760
+ for (const box of bounds) index.add(box.minX, box.minY, box.maxX, box.maxY);
761
+ index.finish();
762
+ for (const box of bounds) {
763
+ for (const hit of index.search(box.minX, box.minY, box.maxX, box.maxY)) {
764
+ const other = bounds[hit].traceIndex;
765
+ if (other > box.traceIndex) candidates[box.traceIndex].add(other);
766
+ }
767
+ }
768
+ }
769
+ const connections = [];
770
+ for (const [i, neighbors] of candidates.entries()) {
771
+ for (const j of [...neighbors].sort((a, b) => a - b)) {
772
+ if (map._arePcbTracesConnected(traces[i], traces[j])) {
773
+ connections.push([traces[i].pcb_trace_id, traces[j].pcb_trace_id]);
774
+ }
775
+ }
776
+ }
777
+ const connectionsByPort = /* @__PURE__ */ new Map();
778
+ for (const trace of traces) {
779
+ for (const point2 of trace.route) {
780
+ if (point2.route_type !== "wire") continue;
781
+ for (const portId of /* @__PURE__ */ new Set([
782
+ point2.start_pcb_port_id,
783
+ point2.end_pcb_port_id
784
+ ])) {
785
+ if (!portId || !map.portIdToElm.has(portId)) continue;
786
+ const entries = connectionsByPort.get(portId) ?? [];
787
+ entries.push(
788
+ point2.start_pcb_port_id === portId ? [portId, trace.pcb_trace_id] : [trace.pcb_trace_id, portId]
789
+ );
790
+ connectionsByPort.set(portId, entries);
791
+ }
792
+ }
793
+ }
794
+ for (const portId of map.portIdToElm.keys()) {
795
+ for (const connection of connectionsByPort.get(portId) ?? [])
796
+ connections.push(connection);
797
+ }
798
+ map.connMap = new ConnectivityMap(findConnectedNetworks(connections));
799
+ return map;
800
+ }
801
+
709
802
  // lib/check-traces-are-contiguous/is-point-in-pad.ts
710
803
  import { pointToSegmentDistance } from "@tscircuit/math-utils";
711
804
 
@@ -1041,8 +1134,7 @@ var addStartAndEndPortIdsIfMissing = (soup) => {
1041
1134
 
1042
1135
  // lib/check-each-pcb-port-connected-to-pcb-trace.ts
1043
1136
  import {
1044
- getFullConnectivityMapFromCircuitJson as getFullConnectivityMapFromCircuitJson2,
1045
- PcbConnectivityMap
1137
+ getFullConnectivityMapFromCircuitJson as getFullConnectivityMapFromCircuitJson2
1046
1138
  } from "circuit-json-to-connectivity-map";
1047
1139
 
1048
1140
  // lib/util/get-readable-names.ts
@@ -1339,7 +1431,10 @@ function getCopperPourConnectivity(circuitJson, connectivity) {
1339
1431
  }
1340
1432
 
1341
1433
  // lib/check-each-pcb-port-connected-to-pcb-trace.ts
1342
- function checkEachPcbPortConnectedToPcbTraces(circuitJson) {
1434
+ function checkEachPcbPortConnectedToPcbTraces(circuitJson, {
1435
+ connMap,
1436
+ pcbConnectivityMap
1437
+ } = {}) {
1343
1438
  addStartAndEndPortIdsIfMissing(circuitJson);
1344
1439
  const sourceTraces = circuitJson.filter(
1345
1440
  (item) => item.type === "source_trace"
@@ -1351,8 +1446,8 @@ function checkEachPcbPortConnectedToPcbTraces(circuitJson) {
1351
1446
  (item) => item.type === "source_net"
1352
1447
  );
1353
1448
  const errors = [];
1354
- const connectivityMap = getFullConnectivityMapFromCircuitJson2(circuitJson);
1355
- const pcbConnectivityMap = new PcbConnectivityMap(circuitJson);
1449
+ const connectivityMap = connMap ?? getFullConnectivityMapFromCircuitJson2(circuitJson);
1450
+ pcbConnectivityMap ??= createIndexedPcbConnectivityMap(circuitJson);
1356
1451
  let pourConnectivity;
1357
1452
  const getPourConnectivity = () => pourConnectivity ??= getCopperPourConnectivity(
1358
1453
  circuitJson,
@@ -3279,8 +3374,10 @@ function checkSourceTracesMatchPcbTraceThickness(circuitJson) {
3279
3374
  }
3280
3375
 
3281
3376
  // lib/check-source-traces-have-pcb-traces.ts
3282
- import { getFullConnectivityMapFromCircuitJson as getFullConnectivityMapFromCircuitJson7 } from "circuit-json-to-connectivity-map";
3283
- function checkSourceTracesHavePcbTraces(circuitJson) {
3377
+ import {
3378
+ getFullConnectivityMapFromCircuitJson as getFullConnectivityMapFromCircuitJson7
3379
+ } from "circuit-json-to-connectivity-map";
3380
+ function checkSourceTracesHavePcbTraces(circuitJson, { connMap } = {}) {
3284
3381
  const errors = [];
3285
3382
  const sourceTraces = circuitJson.filter(
3286
3383
  (el) => el.type === "source_trace"
@@ -3294,7 +3391,7 @@ function checkSourceTracesHavePcbTraces(circuitJson) {
3294
3391
  const sourcePortToPcbPort = new Map(
3295
3392
  pcbPorts.map((pcbPort) => [pcbPort.source_port_id, pcbPort])
3296
3393
  );
3297
- const connectivityMap = getFullConnectivityMapFromCircuitJson7(circuitJson);
3394
+ const connectivityMap = connMap ?? getFullConnectivityMapFromCircuitJson7(circuitJson);
3298
3395
  let pourConnectivity;
3299
3396
  const getPourConnectivity = () => pourConnectivity ??= getCopperPourConnectivity(
3300
3397
  circuitJson,
@@ -3342,8 +3439,7 @@ import {
3342
3439
  getReadableNameForPcbTrace
3343
3440
  } from "@tscircuit/circuit-json-util";
3344
3441
  import {
3345
- getFullConnectivityMapFromCircuitJson as getFullConnectivityMapFromCircuitJson8,
3346
- PcbConnectivityMap as PcbConnectivityMap2
3442
+ getFullConnectivityMapFromCircuitJson as getFullConnectivityMapFromCircuitJson8
3347
3443
  } from "circuit-json-to-connectivity-map";
3348
3444
 
3349
3445
  // lib/check-traces-are-contiguous/via-contact-index.ts
@@ -3607,7 +3703,10 @@ function getMissingConnectionErrorCenter({
3607
3703
  y: (firstPointCenter.y + lastPointCenter.y) / 2
3608
3704
  };
3609
3705
  }
3610
- function checkTracesAreContiguous(circuitJson) {
3706
+ function checkTracesAreContiguous(circuitJson, {
3707
+ connMap,
3708
+ pcbConnectivityMap
3709
+ } = {}) {
3611
3710
  const errors = [];
3612
3711
  const pcbPorts = circuitJson.filter(
3613
3712
  (el) => el.type === "pcb_port"
@@ -3625,8 +3724,8 @@ function checkTracesAreContiguous(circuitJson) {
3625
3724
  (el) => el.type === "pcb_plated_hole"
3626
3725
  );
3627
3726
  const padMap = /* @__PURE__ */ new Map();
3628
- const pcbConnectivityMap = new PcbConnectivityMap2(circuitJson);
3629
- let fullConnectivityMap;
3727
+ pcbConnectivityMap ??= createIndexedPcbConnectivityMap(circuitJson);
3728
+ let fullConnectivityMap = connMap;
3630
3729
  let traceWireSegmentsByNetAndLayer;
3631
3730
  const getFullConnectivityMap = () => {
3632
3731
  fullConnectivityMap ??= getFullConnectivityMapFromCircuitJson8(circuitJson);
@@ -5206,6 +5305,9 @@ function checkSchematicComponentPortsOutsideBody(circuitJson) {
5206
5305
  return warnings;
5207
5306
  }
5208
5307
 
5308
+ // lib/run-all-checks.ts
5309
+ import { getFullConnectivityMapFromCircuitJson as getFullConnectivityMapFromCircuitJson15 } from "circuit-json-to-connectivity-map";
5310
+
5209
5311
  // lib/check-pcb-bus-length-skew.ts
5210
5312
  var checkPcbBusLengthSkew = (circuitJson) => {
5211
5313
  const buses = circuitJson.filter(
@@ -5731,20 +5833,25 @@ async function runAllPinSpecificationChecks(circuitJson) {
5731
5833
  ];
5732
5834
  }
5733
5835
  async function runAllRoutingChecks(circuitJson) {
5836
+ addStartAndEndPortIdsIfMissing(circuitJson);
5837
+ const connectivity = {
5838
+ connMap: getFullConnectivityMapFromCircuitJson15(circuitJson),
5839
+ pcbConnectivityMap: createIndexedPcbConnectivityMap(circuitJson)
5840
+ };
5734
5841
  return [
5735
- ...checkEachPcbPortConnectedToPcbTraces(circuitJson),
5736
- ...checkSourceTracesHavePcbTraces(circuitJson),
5842
+ ...checkEachPcbPortConnectedToPcbTraces(circuitJson, connectivity),
5843
+ ...checkSourceTracesHavePcbTraces(circuitJson, connectivity),
5737
5844
  ...checkPcbTraceLengths(circuitJson),
5738
5845
  ...checkPcbBusLengthSkew(circuitJson),
5739
5846
  ...checkPcbTraceViaCounts(circuitJson),
5740
- ...checkEachPcbTraceNonOverlapping(circuitJson),
5741
- ...checkCopperPourShorts(circuitJson),
5742
- ...checkPadTraceClearance(circuitJson),
5743
- ...checkViaTraceClearance(circuitJson),
5744
- ...checkViaPadClearance(circuitJson),
5745
- ...checkSameNetViaSpacing(circuitJson),
5746
- ...checkDifferentNetViaSpacing(circuitJson),
5747
- ...checkTracesAreContiguous(circuitJson),
5847
+ ...checkEachPcbTraceNonOverlapping(circuitJson, connectivity),
5848
+ ...checkCopperPourShorts(circuitJson, connectivity),
5849
+ ...checkPadTraceClearance(circuitJson, connectivity),
5850
+ ...checkViaTraceClearance(circuitJson, connectivity),
5851
+ ...checkViaPadClearance(circuitJson, connectivity),
5852
+ ...checkSameNetViaSpacing(circuitJson, connectivity),
5853
+ ...checkDifferentNetViaSpacing(circuitJson, connectivity),
5854
+ ...checkTracesAreContiguous(circuitJson, connectivity),
5748
5855
  ...checkPcbTracesOutOfBoard(circuitJson)
5749
5856
  ];
5750
5857
  }