@tscircuit/schematic-trace-solver 0.0.142 → 0.0.143

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
@@ -825,6 +825,7 @@ declare class AvailableNetOrientationSolver extends BaseSolver {
825
825
  private findValidTraceAnchorCandidate;
826
826
  private findValidOutwardTraceAnchorCandidate;
827
827
  private getTraceAnchorCandidatePoints;
828
+ private sharesVerticalRailWithAny;
828
829
  private getAvailableOrientations;
829
830
  private findValidShiftedCandidate;
830
831
  /**
package/dist/index.js CHANGED
@@ -8842,13 +8842,14 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
8842
8842
  }
8843
8843
  findValidTraceAnchorCandidate(label, orientation, labelIndex) {
8844
8844
  const direction = dir(orientation);
8845
- const candidatePoints = this.getTraceAnchorCandidatePoints(label).sort(
8846
- (a, b) => {
8847
- const aAlongDirection = a.x * direction.x + a.y * direction.y;
8848
- const bAlongDirection = b.x * direction.x + b.y * direction.y;
8849
- return bAlongDirection - aAlongDirection;
8850
- }
8851
- );
8845
+ const candidatePoints = this.getTraceAnchorCandidatePoints(
8846
+ label,
8847
+ orientation
8848
+ ).sort((a, b) => {
8849
+ const aAlongDirection = a.x * direction.x + a.y * direction.y;
8850
+ const bAlongDirection = b.x * direction.x + b.y * direction.y;
8851
+ return bAlongDirection - aAlongDirection;
8852
+ });
8852
8853
  for (const anchorPoint of candidatePoints) {
8853
8854
  const candidate = this.createCandidate(label, anchorPoint, orientation);
8854
8855
  const result = this.evaluateCandidate(
@@ -8867,13 +8868,14 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
8867
8868
  }
8868
8869
  findValidOutwardTraceAnchorCandidate(label, orientation, labelIndex) {
8869
8870
  const direction = dir(orientation);
8870
- const candidatePoints = this.getTraceAnchorCandidatePoints(label).sort(
8871
- (a, b) => {
8872
- const aAlongDirection = a.x * direction.x + a.y * direction.y;
8873
- const bAlongDirection = b.x * direction.x + b.y * direction.y;
8874
- return bAlongDirection - aAlongDirection;
8875
- }
8876
- );
8871
+ const candidatePoints = this.getTraceAnchorCandidatePoints(
8872
+ label,
8873
+ orientation
8874
+ ).sort((a, b) => {
8875
+ const aAlongDirection = a.x * direction.x + a.y * direction.y;
8876
+ const bAlongDirection = b.x * direction.x + b.y * direction.y;
8877
+ return bAlongDirection - aAlongDirection;
8878
+ });
8877
8879
  for (const connectorSource of candidatePoints) {
8878
8880
  const preservedColumnAnchor = this.getSearchStartAnchor(
8879
8881
  label,
@@ -8931,10 +8933,40 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
8931
8933
  }
8932
8934
  return null;
8933
8935
  }
8934
- getTraceAnchorCandidatePoints(label) {
8936
+ getTraceAnchorCandidatePoints(label, orientation) {
8935
8937
  const seen = /* @__PURE__ */ new Set();
8936
8938
  const points = [];
8937
- for (const traceId of label.mspConnectionPairIds ?? []) {
8939
+ const connectedTraceIds = new Set(label.mspConnectionPairIds ?? []);
8940
+ if (isYOrientation(orientation)) {
8941
+ const connectedPinIds = /* @__PURE__ */ new Set();
8942
+ for (const traceId of connectedTraceIds) {
8943
+ for (const pinId of this.traceMap[traceId]?.pinIds ?? []) {
8944
+ connectedPinIds.add(pinId);
8945
+ }
8946
+ }
8947
+ let foundConnectedTrace = true;
8948
+ while (foundConnectedTrace) {
8949
+ foundConnectedTrace = false;
8950
+ for (const trace of Object.values(this.traceMap)) {
8951
+ if (connectedTraceIds.has(trace.mspPairId)) continue;
8952
+ if (trace.mspPairId.startsWith("available-net-orientation-")) continue;
8953
+ if (trace.globalConnNetId !== label.globalConnNetId) continue;
8954
+ if (!trace.pinIds.some((pinId) => connectedPinIds.has(pinId)))
8955
+ continue;
8956
+ const connectedTraces = [...connectedTraceIds].flatMap((traceId) => {
8957
+ const connectedTrace = this.traceMap[traceId];
8958
+ return connectedTrace ? [connectedTrace] : [];
8959
+ });
8960
+ if (!this.sharesVerticalRailWithAny(trace, connectedTraces)) {
8961
+ continue;
8962
+ }
8963
+ connectedTraceIds.add(trace.mspPairId);
8964
+ for (const pinId of trace.pinIds) connectedPinIds.add(pinId);
8965
+ foundConnectedTrace = true;
8966
+ }
8967
+ }
8968
+ }
8969
+ for (const traceId of connectedTraceIds) {
8938
8970
  const trace = this.traceMap[traceId];
8939
8971
  if (!trace) continue;
8940
8972
  for (const point of trace.tracePath) {
@@ -8946,6 +8978,26 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
8946
8978
  }
8947
8979
  return points;
8948
8980
  }
8981
+ sharesVerticalRailWithAny(trace, otherTraces) {
8982
+ const verticalRailXs = /* @__PURE__ */ new Set();
8983
+ for (const otherTrace of otherTraces) {
8984
+ for (let i = 0; i < otherTrace.tracePath.length - 1; i++) {
8985
+ const start = otherTrace.tracePath[i];
8986
+ const end = otherTrace.tracePath[i + 1];
8987
+ if (Math.abs(start.x - end.x) <= EPS12 && Math.abs(start.y - end.y) > EPS12) {
8988
+ verticalRailXs.add(start.x);
8989
+ }
8990
+ }
8991
+ }
8992
+ for (let i = 0; i < trace.tracePath.length - 1; i++) {
8993
+ const start = trace.tracePath[i];
8994
+ const end = trace.tracePath[i + 1];
8995
+ if (Math.abs(start.x - end.x) <= EPS12 && Math.abs(start.y - end.y) > EPS12 && [...verticalRailXs].some((x) => Math.abs(x - start.x) <= EPS12)) {
8996
+ return true;
8997
+ }
8998
+ }
8999
+ return false;
9000
+ }
8949
9001
  getAvailableOrientations(label) {
8950
9002
  const effectiveNetId = label.netId ?? label.globalConnNetId;
8951
9003
  return this.inputProblem.availableNetLabelOrientations[effectiveNetId] ?? [];
@@ -635,13 +635,14 @@ export class AvailableNetOrientationSolver extends BaseSolver {
635
635
  labelIndex: number,
636
636
  ) {
637
637
  const direction = dir(orientation)
638
- const candidatePoints = this.getTraceAnchorCandidatePoints(label).sort(
639
- (a, b) => {
640
- const aAlongDirection = a.x * direction.x + a.y * direction.y
641
- const bAlongDirection = b.x * direction.x + b.y * direction.y
642
- return bAlongDirection - aAlongDirection
643
- },
644
- )
638
+ const candidatePoints = this.getTraceAnchorCandidatePoints(
639
+ label,
640
+ orientation,
641
+ ).sort((a, b) => {
642
+ const aAlongDirection = a.x * direction.x + a.y * direction.y
643
+ const bAlongDirection = b.x * direction.x + b.y * direction.y
644
+ return bAlongDirection - aAlongDirection
645
+ })
645
646
 
646
647
  for (const anchorPoint of candidatePoints) {
647
648
  const candidate = this.createCandidate(label, anchorPoint, orientation)
@@ -668,13 +669,14 @@ export class AvailableNetOrientationSolver extends BaseSolver {
668
669
  labelIndex: number,
669
670
  ) {
670
671
  const direction = dir(orientation)
671
- const candidatePoints = this.getTraceAnchorCandidatePoints(label).sort(
672
- (a, b) => {
673
- const aAlongDirection = a.x * direction.x + a.y * direction.y
674
- const bAlongDirection = b.x * direction.x + b.y * direction.y
675
- return bAlongDirection - aAlongDirection
676
- },
677
- )
672
+ const candidatePoints = this.getTraceAnchorCandidatePoints(
673
+ label,
674
+ orientation,
675
+ ).sort((a, b) => {
676
+ const aAlongDirection = a.x * direction.x + a.y * direction.y
677
+ const bAlongDirection = b.x * direction.x + b.y * direction.y
678
+ return bAlongDirection - aAlongDirection
679
+ })
678
680
 
679
681
  for (const connectorSource of candidatePoints) {
680
682
  const preservedColumnAnchor = this.getSearchStartAnchor(
@@ -742,11 +744,52 @@ export class AvailableNetOrientationSolver extends BaseSolver {
742
744
  return null
743
745
  }
744
746
 
745
- private getTraceAnchorCandidatePoints(label: NetLabelPlacement) {
747
+ private getTraceAnchorCandidatePoints(
748
+ label: NetLabelPlacement,
749
+ orientation: FacingDirection,
750
+ ) {
746
751
  const seen = new Set<string>()
747
752
  const points: Point[] = []
753
+ const connectedTraceIds = new Set(label.mspConnectionPairIds ?? [])
754
+
755
+ if (isYOrientation(orientation)) {
756
+ const connectedPinIds = new Set<string>()
757
+ for (const traceId of connectedTraceIds) {
758
+ for (const pinId of this.traceMap[traceId]?.pinIds ?? []) {
759
+ connectedPinIds.add(pinId)
760
+ }
761
+ }
762
+
763
+ // Multi-pin rails are routed as a chain of pairwise traces. Follow the
764
+ // pairs only when they share both a pin and an aligned vertical rail,
765
+ // which identifies one continuous rail. A shared pin alone can join
766
+ // unrelated branches whose rail offsets are far apart; walking those
767
+ // branches would extend the label connector across the schematic.
768
+ let foundConnectedTrace = true
769
+ while (foundConnectedTrace) {
770
+ foundConnectedTrace = false
771
+ for (const trace of Object.values(this.traceMap)) {
772
+ if (connectedTraceIds.has(trace.mspPairId)) continue
773
+ if (trace.mspPairId.startsWith("available-net-orientation-")) continue
774
+ if (trace.globalConnNetId !== label.globalConnNetId) continue
775
+ if (!trace.pinIds.some((pinId) => connectedPinIds.has(pinId)))
776
+ continue
777
+ const connectedTraces = [...connectedTraceIds].flatMap((traceId) => {
778
+ const connectedTrace = this.traceMap[traceId]
779
+ return connectedTrace ? [connectedTrace] : []
780
+ })
781
+ if (!this.sharesVerticalRailWithAny(trace, connectedTraces)) {
782
+ continue
783
+ }
784
+
785
+ connectedTraceIds.add(trace.mspPairId)
786
+ for (const pinId of trace.pinIds) connectedPinIds.add(pinId)
787
+ foundConnectedTrace = true
788
+ }
789
+ }
790
+ }
748
791
 
749
- for (const traceId of label.mspConnectionPairIds ?? []) {
792
+ for (const traceId of connectedTraceIds) {
750
793
  const trace = this.traceMap[traceId]
751
794
  if (!trace) continue
752
795
  for (const point of trace.tracePath) {
@@ -760,6 +803,39 @@ export class AvailableNetOrientationSolver extends BaseSolver {
760
803
  return points
761
804
  }
762
805
 
806
+ private sharesVerticalRailWithAny(
807
+ trace: SolvedTracePath,
808
+ otherTraces: SolvedTracePath[],
809
+ ) {
810
+ const verticalRailXs = new Set<number>()
811
+ for (const otherTrace of otherTraces) {
812
+ for (let i = 0; i < otherTrace.tracePath.length - 1; i++) {
813
+ const start = otherTrace.tracePath[i]!
814
+ const end = otherTrace.tracePath[i + 1]!
815
+ if (
816
+ Math.abs(start.x - end.x) <= EPS &&
817
+ Math.abs(start.y - end.y) > EPS
818
+ ) {
819
+ verticalRailXs.add(start.x)
820
+ }
821
+ }
822
+ }
823
+
824
+ for (let i = 0; i < trace.tracePath.length - 1; i++) {
825
+ const start = trace.tracePath[i]!
826
+ const end = trace.tracePath[i + 1]!
827
+ if (
828
+ Math.abs(start.x - end.x) <= EPS &&
829
+ Math.abs(start.y - end.y) > EPS &&
830
+ [...verticalRailXs].some((x) => Math.abs(x - start.x) <= EPS)
831
+ ) {
832
+ return true
833
+ }
834
+ }
835
+
836
+ return false
837
+ }
838
+
763
839
  private getAvailableOrientations(label: NetLabelPlacement) {
764
840
  const effectiveNetId = label.netId ?? label.globalConnNetId
765
841
  return this.inputProblem.availableNetLabelOrientations[effectiveNetId] ?? []
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "url": "https://github.com/tscircuit/schematic-trace-solver.git"
6
6
  },
7
7
  "main": "dist/index.js",
8
- "version": "0.0.142",
8
+ "version": "0.0.143",
9
9
  "type": "module",
10
10
  "scripts": {
11
11
  "start": "cosmos",