@tscircuit/schematic-trace-solver 0.0.132 → 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 +46 -6
- package/lib/solvers/AvailableNetOrientationSolver/AvailableNetOrientationSolver.ts +12 -6
- package/lib/solvers/AvailableNetOrientationSolver/orderRoutedLabelsBeforeOverlappingPortLabels.ts +47 -0
- package/package.json +1 -1
- package/tests/repros/__snapshots__/repro-usb-power-vbus-label-detour.snap.svg +3 -3
- package/tests/repros/repro-usb-power-vbus-label-detour.test.ts +20 -1
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
|
|
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
|
|
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 <
|
|
8131
|
-
const index =
|
|
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
|
-
|
|
8201
|
+
orderedIndices[affectedSlots[i]] = labelsToOrder[i];
|
|
8162
8202
|
}
|
|
8163
|
-
return
|
|
8203
|
+
return orderedIndices;
|
|
8164
8204
|
}
|
|
8165
8205
|
sortCrowdedTopBankByPin(indices) {
|
|
8166
8206
|
const slotsByChip = /* @__PURE__ */ new Map();
|
|
@@ -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
|
|
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
|
|
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 <
|
|
146
|
-
const index =
|
|
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
|
-
|
|
191
|
+
orderedIndices[affectedSlots[i]!] = labelsToOrder[i]!
|
|
186
192
|
}
|
|
187
193
|
|
|
188
|
-
return
|
|
194
|
+
return orderedIndices
|
|
189
195
|
}
|
|
190
196
|
|
|
191
197
|
private sortCrowdedTopBankByPin(indices: number[]) {
|
package/lib/solvers/AvailableNetOrientationSolver/orderRoutedLabelsBeforeOverlappingPortLabels.ts
ADDED
|
@@ -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
|
+
}
|