@tscircuit/schematic-trace-solver 0.0.131 → 0.0.133

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
@@ -7964,6 +7964,42 @@ var getMaxSearchDistance = (inputProblem) => {
7964
7964
  return maxChipWidth * 3;
7965
7965
  };
7966
7966
 
7967
+ // lib/solvers/AvailableNetOrientationSolver/orderRoutedLabelsBeforeOverlappingPortLabels.ts
7968
+ var isPortOnlyLabel = (label) => label.mspConnectionPairIds.length === 0;
7969
+ var orderRoutedLabelsBeforeOverlappingPortLabels = ({
7970
+ labelIndices,
7971
+ netLabelPlacements
7972
+ }) => {
7973
+ const orderedLabelIndices = [...labelIndices];
7974
+ for (const routedLabelIndex of labelIndices) {
7975
+ const routedLabel = netLabelPlacements[routedLabelIndex];
7976
+ if (isPortOnlyLabel(routedLabel)) continue;
7977
+ const routedBounds = getRectBounds(
7978
+ routedLabel.center,
7979
+ routedLabel.width,
7980
+ routedLabel.height
7981
+ );
7982
+ const blockingPosition = orderedLabelIndices.findIndex((labelIndex) => {
7983
+ const portOnlyLabel = netLabelPlacements[labelIndex];
7984
+ if (!isPortOnlyLabel(portOnlyLabel)) return false;
7985
+ if (portOnlyLabel.globalConnNetId === routedLabel.globalConnNetId) {
7986
+ return false;
7987
+ }
7988
+ const portOnlyBounds = getRectBounds(
7989
+ portOnlyLabel.center,
7990
+ portOnlyLabel.width,
7991
+ portOnlyLabel.height
7992
+ );
7993
+ return rectsOverlap2(routedBounds, portOnlyBounds);
7994
+ });
7995
+ const routedPosition = orderedLabelIndices.indexOf(routedLabelIndex);
7996
+ if (blockingPosition === -1 || blockingPosition > routedPosition) continue;
7997
+ orderedLabelIndices.splice(routedPosition, 1);
7998
+ orderedLabelIndices.splice(blockingPosition, 0, routedLabelIndex);
7999
+ }
8000
+ return orderedLabelIndices;
8001
+ };
8002
+
7967
8003
  // lib/solvers/AvailableNetOrientationSolver/visualize.ts
7968
8004
  var visualizeAvailableNetOrientationSolver = (params) => {
7969
8005
  const graphics = visualizeInputProblem(params.inputProblem);
@@ -8114,12 +8150,16 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
8114
8150
  }
8115
8151
  }
8116
8152
  this.sortCrowdedTopBankByPin(indices);
8117
- const blockedStandaloneLabelIndex = indices.find((index) => {
8153
+ const orderedIndices = orderRoutedLabelsBeforeOverlappingPortLabels({
8154
+ labelIndices: indices,
8155
+ netLabelPlacements: this.outputNetLabelPlacements
8156
+ });
8157
+ const blockedStandaloneLabelIndex = orderedIndices.find((index) => {
8118
8158
  const label = this.outputNetLabelPlacements[index];
8119
8159
  const orientations = this.getAvailableOrientations(label);
8120
8160
  return this.isPortOnlyLabel(label) && this.isStandaloneSinglePinNetLabel(label) && orientations.length === 1 && isYOrientation(orientations[0]) && this.labelIntersectsDifferentNetTrace(label);
8121
8161
  });
8122
- if (blockedStandaloneLabelIndex === void 0) return indices;
8162
+ if (blockedStandaloneLabelIndex === void 0) return orderedIndices;
8123
8163
  this.blockedStandaloneLabelIndex = blockedStandaloneLabelIndex;
8124
8164
  this.blockedStandaloneLabelTargetAnchorX = null;
8125
8165
  const blockedLabel = this.outputNetLabelPlacements[blockedStandaloneLabelIndex];
@@ -8127,8 +8167,8 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
8127
8167
  const chipSide = this.getChipSideForPoint(blockedLabel.anchorPoint);
8128
8168
  const affectedSlots = [];
8129
8169
  const labelsToOrder = [];
8130
- for (let slot = 0; slot < indices.length; slot++) {
8131
- const index = indices[slot];
8170
+ for (let slot = 0; slot < orderedIndices.length; slot++) {
8171
+ const index = orderedIndices[slot];
8132
8172
  const label = this.outputNetLabelPlacements[index];
8133
8173
  const orientations = this.getAvailableOrientations(label);
8134
8174
  if (this.getChipSideForPoint(label.anchorPoint) === chipSide && orientations.length === 1 && orientations[0] === requiredOrientation) {
@@ -8158,9 +8198,9 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
8158
8198
  ).x;
8159
8199
  }
8160
8200
  for (let i = 0; i < affectedSlots.length; i++) {
8161
- indices[affectedSlots[i]] = labelsToOrder[i];
8201
+ orderedIndices[affectedSlots[i]] = labelsToOrder[i];
8162
8202
  }
8163
- return indices;
8203
+ return orderedIndices;
8164
8204
  }
8165
8205
  sortCrowdedTopBankByPin(indices) {
8166
8206
  const slotsByChip = /* @__PURE__ */ new Map();
@@ -11664,6 +11704,13 @@ var candidateIsClear = ({
11664
11704
  if (doesPathCoincideWithTraces(candidateTrace.tracePath, otherNetTraces)) {
11665
11705
  return false;
11666
11706
  }
11707
+ const candidateTraces = traces.map((trace) => {
11708
+ if (trace.mspPairId === originalTrace.mspPairId) return candidateTrace;
11709
+ return trace;
11710
+ });
11711
+ if (!preservesLabelAnchors(netLabelPlacements, traces, candidateTraces)) {
11712
+ return false;
11713
+ }
11667
11714
  const otherNetLabelPlacements = netLabelPlacements.filter(
11668
11715
  (label) => label.globalConnNetId !== candidateTrace.globalConnNetId
11669
11716
  );
@@ -31,6 +31,7 @@ import {
31
31
  tracePathCrossesAnyBounds,
32
32
  tracePathIntersectsBounds,
33
33
  } from "./geometry"
34
+ import { orderRoutedLabelsBeforeOverlappingPortLabels } from "./orderRoutedLabelsBeforeOverlappingPortLabels"
34
35
  import { getPinMap, getTracePins, toNetLabelPlacementPatch } from "./traces"
35
36
  import type {
36
37
  AvailableNetOrientationSolverParams,
@@ -120,7 +121,12 @@ export class AvailableNetOrientationSolver extends BaseSolver {
120
121
  }
121
122
  this.sortCrowdedTopBankByPin(indices)
122
123
 
123
- const blockedStandaloneLabelIndex = indices.find((index) => {
124
+ const orderedIndices = orderRoutedLabelsBeforeOverlappingPortLabels({
125
+ labelIndices: indices,
126
+ netLabelPlacements: this.outputNetLabelPlacements,
127
+ })
128
+
129
+ const blockedStandaloneLabelIndex = orderedIndices.find((index) => {
124
130
  const label = this.outputNetLabelPlacements[index]!
125
131
  const orientations = this.getAvailableOrientations(label)
126
132
  return (
@@ -131,7 +137,7 @@ export class AvailableNetOrientationSolver extends BaseSolver {
131
137
  this.labelIntersectsDifferentNetTrace(label)
132
138
  )
133
139
  })
134
- if (blockedStandaloneLabelIndex === undefined) return indices
140
+ if (blockedStandaloneLabelIndex === undefined) return orderedIndices
135
141
  this.blockedStandaloneLabelIndex = blockedStandaloneLabelIndex
136
142
  this.blockedStandaloneLabelTargetAnchorX = null
137
143
 
@@ -142,8 +148,8 @@ export class AvailableNetOrientationSolver extends BaseSolver {
142
148
  const affectedSlots: number[] = []
143
149
  const labelsToOrder: number[] = []
144
150
 
145
- for (let slot = 0; slot < indices.length; slot++) {
146
- const index = indices[slot]!
151
+ for (let slot = 0; slot < orderedIndices.length; slot++) {
152
+ const index = orderedIndices[slot]!
147
153
  const label = this.outputNetLabelPlacements[index]!
148
154
  const orientations = this.getAvailableOrientations(label)
149
155
  if (
@@ -182,10 +188,10 @@ export class AvailableNetOrientationSolver extends BaseSolver {
182
188
  ).x
183
189
  }
184
190
  for (let i = 0; i < affectedSlots.length; i++) {
185
- indices[affectedSlots[i]!] = labelsToOrder[i]!
191
+ orderedIndices[affectedSlots[i]!] = labelsToOrder[i]!
186
192
  }
187
193
 
188
- return indices
194
+ return orderedIndices
189
195
  }
190
196
 
191
197
  private sortCrowdedTopBankByPin(indices: number[]) {
@@ -0,0 +1,47 @@
1
+ import type { NetLabelPlacement } from "lib/solvers/NetLabelPlacementSolver/NetLabelPlacementSolver"
2
+ import { getRectBounds } from "lib/solvers/NetLabelPlacementSolver/SingleNetLabelPlacementSolver/geometry"
3
+ import { rectsOverlap } from "./geometry"
4
+
5
+ const isPortOnlyLabel = (label: NetLabelPlacement) =>
6
+ label.mspConnectionPairIds.length === 0
7
+
8
+ export const orderRoutedLabelsBeforeOverlappingPortLabels = ({
9
+ labelIndices,
10
+ netLabelPlacements,
11
+ }: {
12
+ labelIndices: number[]
13
+ netLabelPlacements: NetLabelPlacement[]
14
+ }) => {
15
+ const orderedLabelIndices = [...labelIndices]
16
+
17
+ for (const routedLabelIndex of labelIndices) {
18
+ const routedLabel = netLabelPlacements[routedLabelIndex]!
19
+ if (isPortOnlyLabel(routedLabel)) continue
20
+
21
+ const routedBounds = getRectBounds(
22
+ routedLabel.center,
23
+ routedLabel.width,
24
+ routedLabel.height,
25
+ )
26
+ const blockingPosition = orderedLabelIndices.findIndex((labelIndex) => {
27
+ const portOnlyLabel = netLabelPlacements[labelIndex]!
28
+ if (!isPortOnlyLabel(portOnlyLabel)) return false
29
+ if (portOnlyLabel.globalConnNetId === routedLabel.globalConnNetId) {
30
+ return false
31
+ }
32
+ const portOnlyBounds = getRectBounds(
33
+ portOnlyLabel.center,
34
+ portOnlyLabel.width,
35
+ portOnlyLabel.height,
36
+ )
37
+ return rectsOverlap(routedBounds, portOnlyBounds)
38
+ })
39
+ const routedPosition = orderedLabelIndices.indexOf(routedLabelIndex)
40
+ if (blockingPosition === -1 || blockingPosition > routedPosition) continue
41
+
42
+ orderedLabelIndices.splice(routedPosition, 1)
43
+ orderedLabelIndices.splice(blockingPosition, 0, routedLabelIndex)
44
+ }
45
+
46
+ return orderedLabelIndices
47
+ }
@@ -4,6 +4,7 @@ import type { SolvedTracePath } from "lib/solvers/SchematicTraceLinesSolver/Sche
4
4
  import { isPathCollidingWithObstacles } from "lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/collisions"
5
5
  import { getObstacleRects } from "lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/rect"
6
6
  import { simplifyPath } from "lib/solvers/TraceCleanupSolver/simplifyPath"
7
+ import { preservesLabelAnchors } from "lib/solvers/TraceCleanupSolver/sameNetRailAlignment/preservesLabelAnchors"
7
8
  import {
8
9
  getVisibleTraceLength,
9
10
  getVisibleTraceSegmentCount,
@@ -164,6 +165,14 @@ const candidateIsClear = ({
164
165
  return false
165
166
  }
166
167
 
168
+ const candidateTraces = traces.map((trace) => {
169
+ if (trace.mspPairId === originalTrace.mspPairId) return candidateTrace
170
+ return trace
171
+ })
172
+ if (!preservesLabelAnchors(netLabelPlacements, traces, candidateTraces)) {
173
+ return false
174
+ }
175
+
167
176
  const otherNetLabelPlacements = netLabelPlacements.filter(
168
177
  (label) => label.globalConnNetId !== candidateTrace.globalConnNetId,
169
178
  )
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tscircuit/schematic-trace-solver",
3
3
  "main": "dist/index.js",
4
- "version": "0.0.131",
4
+ "version": "0.0.133",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "start": "cosmos",