@tscircuit/checks 0.0.169 → 0.0.170

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -2583,6 +2583,9 @@ import {
2583
2583
  getReadableNameForPcbTrace
2584
2584
  } from "@tscircuit/circuit-json-util";
2585
2585
  import { PcbConnectivityMap as PcbConnectivityMap2 } from "circuit-json-to-connectivity-map";
2586
+ function routePointTouchesPad(point, pad) {
2587
+ return point.route_type === "wire" && getLayersOfPcbElement(pad).includes(point.layer) && isPointInPad(point, pad);
2588
+ }
2586
2589
  function getRoutePointCenter(point) {
2587
2590
  if (point.route_type === "through_pad") {
2588
2591
  return {
@@ -2593,15 +2596,12 @@ function getRoutePointCenter(point) {
2593
2596
  return { x: point.x, y: point.y };
2594
2597
  }
2595
2598
  function routePointConnectsToAnotherExpectedPort(point, expectedPorts, missingPcbPortId, padMap) {
2596
- if (point.route_type !== "wire") return false;
2597
2599
  return expectedPorts.some((expectedPort) => {
2598
2600
  if (!expectedPort.pcb_port_id || expectedPort.pcb_port_id === missingPcbPortId) {
2599
2601
  return false;
2600
2602
  }
2601
2603
  const expectedPads = padMap.get(expectedPort.pcb_port_id);
2602
- return expectedPads?.some(
2603
- (pad) => isPointInPad({ x: point.x, y: point.y }, pad)
2604
- ) ?? false;
2604
+ return expectedPads?.some((pad) => routePointTouchesPad(point, pad)) ?? false;
2605
2605
  });
2606
2606
  }
2607
2607
  function getMissingConnectionErrorCenter({
@@ -2685,6 +2685,65 @@ function checkTracesAreContiguous(circuitJson) {
2685
2685
  ]);
2686
2686
  }
2687
2687
  }
2688
+ const touchedPortIdsByTraceId = /* @__PURE__ */ new Map();
2689
+ const traceIdsByTouchedPortId = /* @__PURE__ */ new Map();
2690
+ for (const trace of pcbTraces) {
2691
+ const touchedPortIds = /* @__PURE__ */ new Set();
2692
+ const firstPoint = trace.route[0];
2693
+ const lastPoint = trace.route.at(-1);
2694
+ for (const point of [firstPoint, lastPoint]) {
2695
+ if (!point) continue;
2696
+ for (const [pcbPortId, pads] of padMap) {
2697
+ if (pads.some((pad) => routePointTouchesPad(point, pad))) {
2698
+ touchedPortIds.add(pcbPortId);
2699
+ }
2700
+ }
2701
+ }
2702
+ touchedPortIdsByTraceId.set(trace.pcb_trace_id, touchedPortIds);
2703
+ for (const pcbPortId of touchedPortIds) {
2704
+ const traceIds = traceIdsByTouchedPortId.get(pcbPortId) ?? /* @__PURE__ */ new Set();
2705
+ traceIds.add(trace.pcb_trace_id);
2706
+ traceIdsByTouchedPortId.set(pcbPortId, traceIds);
2707
+ }
2708
+ }
2709
+ const physicallyConnectedTracesByTraceId = /* @__PURE__ */ new Map();
2710
+ const getPhysicallyConnectedTraces = (startTrace) => {
2711
+ const cached = physicallyConnectedTracesByTraceId.get(
2712
+ startTrace.pcb_trace_id
2713
+ );
2714
+ if (cached) return cached;
2715
+ const connectedTraceIds = /* @__PURE__ */ new Set();
2716
+ const pendingTraceIds = [startTrace.pcb_trace_id];
2717
+ while (pendingTraceIds.length > 0) {
2718
+ const traceId = pendingTraceIds.pop();
2719
+ if (connectedTraceIds.has(traceId)) continue;
2720
+ connectedTraceIds.add(traceId);
2721
+ for (const connectedTrace of pcbConnectivityMap.getAllTracesConnectedToTrace(
2722
+ traceId
2723
+ )) {
2724
+ if (!connectedTraceIds.has(connectedTrace.pcb_trace_id)) {
2725
+ pendingTraceIds.push(connectedTrace.pcb_trace_id);
2726
+ }
2727
+ }
2728
+ for (const pcbPortId of touchedPortIdsByTraceId.get(traceId) ?? []) {
2729
+ for (const touchingTraceId of traceIdsByTouchedPortId.get(pcbPortId) ?? []) {
2730
+ if (!connectedTraceIds.has(touchingTraceId)) {
2731
+ pendingTraceIds.push(touchingTraceId);
2732
+ }
2733
+ }
2734
+ }
2735
+ }
2736
+ const connectedTraces = pcbTraces.filter(
2737
+ (trace) => connectedTraceIds.has(trace.pcb_trace_id)
2738
+ );
2739
+ for (const trace of connectedTraces) {
2740
+ physicallyConnectedTracesByTraceId.set(
2741
+ trace.pcb_trace_id,
2742
+ connectedTraces
2743
+ );
2744
+ }
2745
+ return connectedTraces;
2746
+ };
2688
2747
  for (const trace of pcbTraces) {
2689
2748
  if (trace.route.length === 0) continue;
2690
2749
  const firstPoint = trace.route[0];
@@ -2736,39 +2795,17 @@ function checkTracesAreContiguous(circuitJson) {
2736
2795
  if (!port.pcb_port_id) continue;
2737
2796
  const pads = padMap.get(port.pcb_port_id);
2738
2797
  if (!pads?.length) continue;
2739
- let isConnectedByRoutedSourceTrace = false;
2740
- const candidateTraces = [
2741
- ...pcbConnectivityMap.getAllTracesConnectedToTrace(trace.pcb_trace_id),
2742
- ...pcbTraces.filter(
2743
- (candidateTrace) => candidateTrace.source_trace_id === sourceTrace?.source_trace_id
2744
- )
2745
- ];
2746
- for (const candidateTrace of candidateTraces) {
2747
- if (candidateTrace.pcb_trace_id === trace.pcb_trace_id) continue;
2748
- if (!candidateTrace.source_trace_id) continue;
2749
- const candidateSourceTrace = sourceTraces.find(
2750
- (st) => st.source_trace_id === candidateTrace.source_trace_id
2751
- );
2752
- if (!sourceTrace || candidateTrace.source_trace_id !== sourceTrace.source_trace_id && !candidateSourceTrace?.connected_source_port_ids.includes(
2753
- port.source_port_id
2754
- )) {
2755
- continue;
2756
- }
2757
- const candidateFirstPoint = candidateTrace.route[0];
2758
- const candidateLastPoint = candidateTrace.route.at(-1);
2759
- if (getPcbPortIdsConnectedToTrace(candidateTrace).includes(
2760
- port.pcb_port_id
2761
- ) || candidateFirstPoint?.route_type === "wire" && pads.some((pad) => isPointInPad(candidateFirstPoint, pad)) || candidateLastPoint?.route_type === "wire" && pads.some((pad) => isPointInPad(candidateLastPoint, pad))) {
2762
- isConnectedByRoutedSourceTrace = true;
2763
- break;
2764
- }
2765
- }
2798
+ const isConnectedByRoutedSourceTrace = getPhysicallyConnectedTraces(
2799
+ trace
2800
+ ).some(
2801
+ (candidateTrace) => touchedPortIdsByTraceId.get(candidateTrace.pcb_trace_id)?.has(port.pcb_port_id)
2802
+ );
2766
2803
  if (isConnectedByRoutedSourceTrace) continue;
2767
- const isFirstPointConnected = firstPoint.route_type === "wire" && pads.some(
2768
- (pad) => isPointInPad({ x: firstPoint.x, y: firstPoint.y }, pad)
2804
+ const isFirstPointConnected = pads.some(
2805
+ (pad) => routePointTouchesPad(firstPoint, pad)
2769
2806
  );
2770
- const isLastPointConnected = lastPoint.route_type === "wire" && pads.some(
2771
- (pad) => isPointInPad({ x: lastPoint.x, y: lastPoint.y }, pad)
2807
+ const isLastPointConnected = pads.some(
2808
+ (pad) => routePointTouchesPad(lastPoint, pad)
2772
2809
  );
2773
2810
  if (!isFirstPointConnected && !isLastPointConnected) {
2774
2811
  const portName = getReadableNameForPcbPort2(
@@ -2801,14 +2838,10 @@ function checkTracesAreContiguous(circuitJson) {
2801
2838
  let lastConnectsToAnyPad = false;
2802
2839
  const endpointsAreSame = firstPoint.route_type === "wire" && lastPoint.route_type === "wire" && Math.abs(firstPoint.x - lastPoint.x) < 0.01 && Math.abs(firstPoint.y - lastPoint.y) < 0.01;
2803
2840
  for (const pads of padMap.values()) {
2804
- if (firstPoint.route_type === "wire" && pads.some(
2805
- (pad) => isPointInPad({ x: firstPoint.x, y: firstPoint.y }, pad)
2806
- )) {
2841
+ if (pads.some((pad) => routePointTouchesPad(firstPoint, pad))) {
2807
2842
  firstConnectsToAnyPad = true;
2808
2843
  }
2809
- if (lastPoint.route_type === "wire" && pads.some(
2810
- (pad) => isPointInPad({ x: lastPoint.x, y: lastPoint.y }, pad)
2811
- )) {
2844
+ if (pads.some((pad) => routePointTouchesPad(lastPoint, pad))) {
2812
2845
  lastConnectsToAnyPad = true;
2813
2846
  }
2814
2847
  }