@tscircuit/schematic-trace-solver 0.0.152 → 0.0.154
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 +5 -5
- package/dist/index.js +84 -27
- package/lib/solvers/AvailableNetOrientationSolver/AvailableNetOrientationSolver.ts +7 -0
- package/lib/solvers/NetLabelPlacementSolver/NetLabelPlacementSolver.ts +1 -0
- package/lib/solvers/SameNetJunctionAlignmentSolver/alignSameNetJunctions.ts +81 -8
- package/lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/SchematicTraceSingleLineSolver2.ts +1 -1
- package/lib/solvers/TraceAnchoredNetLabelOverlapSolver/candidates.ts +1 -0
- package/lib/types/InputProblem.ts +5 -5
- package/lib/utils/getNetLabelWidthForConnection.ts +9 -10
- package/package.json +1 -1
- package/site/bug-reports/bug-report-20260825T103621Z.page.tsx +4 -0
- package/tests/assets/example51.json +159 -32
- package/tests/bug-reports/bug-report-20260825T103621Z/__snapshots__/bug-report-20260825T103621Z.snap.svg +452 -0
- package/tests/bug-reports/bug-report-20260825T103621Z/bug-report-20260825T103621Z.json +1696 -0
- package/tests/bug-reports/bug-report-20260825T103621Z/bug-report-20260825T103621Z.test.ts +12 -0
- package/tests/examples/__snapshots__/example51.snap.svg +485 -473
- package/tests/examples/example51.test.ts +3 -1
- package/tests/repros/__snapshots__/repro-core-tb67s579ftg-inline-label-routing.snap.svg +8 -8
- package/tests/repros/__snapshots__/repro-pga300-c6-trace-alignment.snap.svg +88 -0
- package/tests/repros/assets/repro-core-tb67s579ftg-inline-label-routing.input.json +33 -33
- package/tests/repros/assets/repro-pga300-c6-trace-alignment.input.json +97 -0
- package/tests/repros/repro-core-tb67s579ftg-inline-label-routing.test.ts +3 -2
- package/tests/repros/repro-pga300-c6-trace-alignment.test.ts +36 -0
- package/tests/solvers/InlineNetLabelSolver/{fallback-net-label-width.test.ts → anchored-net-label-width.test.ts} +34 -11
- /package/tests/solvers/InlineNetLabelSolver/__snapshots__/{fallback-net-label-width.snap.svg → anchored-net-label-width.snap.svg} +0 -0
package/dist/index.d.ts
CHANGED
|
@@ -108,11 +108,11 @@ interface InputDirectConnection {
|
|
|
108
108
|
netLabelText?: string;
|
|
109
109
|
netLabelWidth?: number;
|
|
110
110
|
/**
|
|
111
|
-
* Width of the conventional anchored
|
|
112
|
-
*
|
|
113
|
-
*
|
|
111
|
+
* Width of the conventional label anchored to a trace endpoint. Unlike
|
|
112
|
+
* `netLabelWidth`, this does not affect whether or how the point-to-point
|
|
113
|
+
* connection is routed.
|
|
114
114
|
*/
|
|
115
|
-
|
|
115
|
+
anchoredNetLabelWidth?: number;
|
|
116
116
|
/**
|
|
117
117
|
* When true, this point-to-point connection may be labeled with an "inline
|
|
118
118
|
* net label": the net name is drawn parallel to (and offset from) the routed
|
|
@@ -149,7 +149,7 @@ interface InputNetConnection {
|
|
|
149
149
|
*/
|
|
150
150
|
netLabelText?: string;
|
|
151
151
|
netLabelWidth?: number;
|
|
152
|
-
|
|
152
|
+
anchoredNetLabelWidth?: number;
|
|
153
153
|
netLabelHeight?: number;
|
|
154
154
|
/**
|
|
155
155
|
* When true, a named one- or two-pin net may use inline labels. A single-pin
|
package/dist/index.js
CHANGED
|
@@ -679,21 +679,20 @@ import "graphics-debug";
|
|
|
679
679
|
import { calculateElbow as calculateElbow2 } from "calculate-elbow";
|
|
680
680
|
|
|
681
681
|
// lib/utils/getNetLabelWidthForConnection.ts
|
|
682
|
-
var getConfiguredWidth = (connections,
|
|
683
|
-
const
|
|
682
|
+
var getConfiguredWidth = (connections, isPortOnlyLabel2) => {
|
|
683
|
+
const width = connections.find(
|
|
684
684
|
(connection) => connection?.netLabelWidth !== void 0
|
|
685
685
|
)?.netLabelWidth;
|
|
686
|
-
if (
|
|
687
|
-
if (!includeFallbackNetLabelWidth) return void 0;
|
|
686
|
+
if (width !== void 0 || !isPortOnlyLabel2) return width;
|
|
688
687
|
return connections.find(
|
|
689
|
-
(connection) => connection?.
|
|
690
|
-
)?.
|
|
688
|
+
(connection) => connection?.anchoredNetLabelWidth !== void 0
|
|
689
|
+
)?.anchoredNetLabelWidth;
|
|
691
690
|
};
|
|
692
691
|
var getNetLabelWidthForConnection = ({
|
|
693
692
|
inputProblem,
|
|
694
693
|
netId,
|
|
695
694
|
pinIds,
|
|
696
|
-
|
|
695
|
+
isPortOnlyLabel: isPortOnlyLabel2
|
|
697
696
|
}) => {
|
|
698
697
|
if (netId) {
|
|
699
698
|
const widthByNetId = getConfiguredWidth(
|
|
@@ -705,7 +704,7 @@ var getNetLabelWidthForConnection = ({
|
|
|
705
704
|
(connection) => connection.netId === netId
|
|
706
705
|
)
|
|
707
706
|
],
|
|
708
|
-
|
|
707
|
+
isPortOnlyLabel2
|
|
709
708
|
);
|
|
710
709
|
if (widthByNetId !== void 0) return widthByNetId;
|
|
711
710
|
}
|
|
@@ -718,7 +717,7 @@ var getNetLabelWidthForConnection = ({
|
|
|
718
717
|
(connection) => connection.pinIds.some((pinId) => pinIds.includes(pinId))
|
|
719
718
|
)
|
|
720
719
|
],
|
|
721
|
-
|
|
720
|
+
isPortOnlyLabel2
|
|
722
721
|
);
|
|
723
722
|
};
|
|
724
723
|
|
|
@@ -1329,7 +1328,7 @@ var SchematicTraceSingleLineSolver2 = class extends BaseSolver {
|
|
|
1329
1328
|
inputProblem: this.inputProblem,
|
|
1330
1329
|
netId,
|
|
1331
1330
|
pinIds: this.pins.map((pin) => pin.pinId),
|
|
1332
|
-
|
|
1331
|
+
isPortOnlyLabel: false
|
|
1333
1332
|
});
|
|
1334
1333
|
const netLabelHeight = this.getNetLabelHeightForConnectionPair(netId);
|
|
1335
1334
|
const padding = {
|
|
@@ -3270,7 +3269,8 @@ var NetLabelPlacementSolver = class extends BaseSolver {
|
|
|
3270
3269
|
return getNetLabelWidthForConnection({
|
|
3271
3270
|
inputProblem: this.inputProblem,
|
|
3272
3271
|
netId: group.netId,
|
|
3273
|
-
pinIds
|
|
3272
|
+
pinIds,
|
|
3273
|
+
isPortOnlyLabel: group.portOnlyPinId !== void 0
|
|
3274
3274
|
});
|
|
3275
3275
|
}
|
|
3276
3276
|
getNetLabelHeightForGroup(group) {
|
|
@@ -8620,7 +8620,8 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
8620
8620
|
const blockedLabelWidth = getNetLabelWidthForConnection({
|
|
8621
8621
|
inputProblem: this.inputProblem,
|
|
8622
8622
|
netId: blockedLabel.netId,
|
|
8623
|
-
pinIds: blockedLabel.pinIds
|
|
8623
|
+
pinIds: blockedLabel.pinIds,
|
|
8624
|
+
isPortOnlyLabel: this.isPortOnlyLabel(blockedLabel)
|
|
8624
8625
|
});
|
|
8625
8626
|
let columnLabelIndex;
|
|
8626
8627
|
if (blockedLabelWidth !== void 0) {
|
|
@@ -8630,7 +8631,8 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
8630
8631
|
return getNetLabelWidthForConnection({
|
|
8631
8632
|
inputProblem: this.inputProblem,
|
|
8632
8633
|
netId: label.netId,
|
|
8633
|
-
pinIds: label.pinIds
|
|
8634
|
+
pinIds: label.pinIds,
|
|
8635
|
+
isPortOnlyLabel: this.isPortOnlyLabel(label)
|
|
8634
8636
|
}) === blockedLabelWidth;
|
|
8635
8637
|
});
|
|
8636
8638
|
}
|
|
@@ -8855,7 +8857,8 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
8855
8857
|
netLabelWidth: getNetLabelWidthForConnection({
|
|
8856
8858
|
inputProblem: this.inputProblem,
|
|
8857
8859
|
netId: label.netId,
|
|
8858
|
-
pinIds: label.pinIds
|
|
8860
|
+
pinIds: label.pinIds,
|
|
8861
|
+
isPortOnlyLabel: this.isPortOnlyLabel(label)
|
|
8859
8862
|
}),
|
|
8860
8863
|
netLabelHeight: this.getNetLabelHeight(label)
|
|
8861
8864
|
});
|
|
@@ -9293,7 +9296,8 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
9293
9296
|
netLabelWidth: getNetLabelWidthForConnection({
|
|
9294
9297
|
inputProblem: this.inputProblem,
|
|
9295
9298
|
netId: label.netId,
|
|
9296
|
-
pinIds: label.pinIds
|
|
9299
|
+
pinIds: label.pinIds,
|
|
9300
|
+
isPortOnlyLabel: this.isPortOnlyLabel(label)
|
|
9297
9301
|
}),
|
|
9298
9302
|
netLabelHeight: this.getNetLabelHeight(label)
|
|
9299
9303
|
});
|
|
@@ -9315,7 +9319,8 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
9315
9319
|
netLabelWidth: getNetLabelWidthForConnection({
|
|
9316
9320
|
inputProblem: this.inputProblem,
|
|
9317
9321
|
netId: label.netId,
|
|
9318
|
-
pinIds: label.pinIds
|
|
9322
|
+
pinIds: label.pinIds,
|
|
9323
|
+
isPortOnlyLabel: this.isPortOnlyLabel(label)
|
|
9319
9324
|
}),
|
|
9320
9325
|
netLabelHeight: this.getNetLabelHeight(label)
|
|
9321
9326
|
});
|
|
@@ -9374,7 +9379,8 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
9374
9379
|
netLabelWidth: getNetLabelWidthForConnection({
|
|
9375
9380
|
inputProblem: this.inputProblem,
|
|
9376
9381
|
netId: label.netId,
|
|
9377
|
-
pinIds: label.pinIds
|
|
9382
|
+
pinIds: label.pinIds,
|
|
9383
|
+
isPortOnlyLabel: this.isPortOnlyLabel(label)
|
|
9378
9384
|
}),
|
|
9379
9385
|
netLabelHeight: this.getNetLabelHeight(label)
|
|
9380
9386
|
});
|
|
@@ -9429,7 +9435,8 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
9429
9435
|
netLabelWidth: getNetLabelWidthForConnection({
|
|
9430
9436
|
inputProblem: this.inputProblem,
|
|
9431
9437
|
netId: label.netId,
|
|
9432
|
-
pinIds: label.pinIds
|
|
9438
|
+
pinIds: label.pinIds,
|
|
9439
|
+
isPortOnlyLabel: this.isPortOnlyLabel(label)
|
|
9433
9440
|
}),
|
|
9434
9441
|
netLabelHeight: this.getNetLabelHeight(label)
|
|
9435
9442
|
});
|
|
@@ -10643,7 +10650,8 @@ var getNetLabelWidth = (inputProblem, label) => {
|
|
|
10643
10650
|
const configuredWidth = getNetLabelWidthForConnection({
|
|
10644
10651
|
inputProblem,
|
|
10645
10652
|
netId: label.netId,
|
|
10646
|
-
pinIds: label.pinIds
|
|
10653
|
+
pinIds: label.pinIds,
|
|
10654
|
+
isPortOnlyLabel: label.mspConnectionPairIds.length === 0
|
|
10647
10655
|
});
|
|
10648
10656
|
if (configuredWidth !== void 0) return configuredWidth;
|
|
10649
10657
|
if (label.orientation === "y+" || label.orientation === "y-") {
|
|
@@ -12131,6 +12139,7 @@ var pathEntersAnyNetLabel = ({
|
|
|
12131
12139
|
// lib/solvers/SameNetJunctionAlignmentSolver/alignSameNetJunctions.ts
|
|
12132
12140
|
var MAX_ALIGNED_LOAD_PIN_OFFSET = 0.2;
|
|
12133
12141
|
var MAX_SAME_NET_LABEL_BOUNDARY_RAIL_OFFSET = 0.2;
|
|
12142
|
+
var MAX_SHARED_PIN_RAIL_OFFSET = 0.05;
|
|
12134
12143
|
var getSharedPin = ({
|
|
12135
12144
|
donorTrace,
|
|
12136
12145
|
branchTrace
|
|
@@ -12170,6 +12179,28 @@ var railIsOnFacingSide = ({
|
|
|
12170
12179
|
if (pin._facingDirection === "y+") return railY > pin.y;
|
|
12171
12180
|
return false;
|
|
12172
12181
|
};
|
|
12182
|
+
var railIsOnSharedPinFacingSide = ({
|
|
12183
|
+
railY,
|
|
12184
|
+
pin
|
|
12185
|
+
}) => {
|
|
12186
|
+
if (pin._facingDirection === "y+") return railY > pin.y;
|
|
12187
|
+
if (pin._facingDirection === "y-") return railY < pin.y;
|
|
12188
|
+
return false;
|
|
12189
|
+
};
|
|
12190
|
+
var getHorizontalPinApproachPoint = ({
|
|
12191
|
+
branchTrace,
|
|
12192
|
+
sharedPin,
|
|
12193
|
+
otherPin
|
|
12194
|
+
}) => {
|
|
12195
|
+
if (otherPin._facingDirection !== "x-" && otherPin._facingDirection !== "x+") {
|
|
12196
|
+
return null;
|
|
12197
|
+
}
|
|
12198
|
+
const sharedToOtherPath = branchTrace.pins[0].pinId === sharedPin.pinId ? branchTrace.tracePath : [...branchTrace.tracePath].reverse();
|
|
12199
|
+
const approachPoint = sharedToOtherPath.at(-2);
|
|
12200
|
+
if (!approachPoint || !nearlyEqual(approachPoint.y, otherPin.y)) return null;
|
|
12201
|
+
const approachesFromFacingSide = otherPin._facingDirection === "x-" ? approachPoint.x < otherPin.x : approachPoint.x > otherPin.x;
|
|
12202
|
+
return approachesFromFacingSide ? approachPoint : null;
|
|
12203
|
+
};
|
|
12173
12204
|
var getAttachedLabelIndexes = (trace, netLabelPlacements) => netLabelPlacements.flatMap((label, index) => {
|
|
12174
12205
|
const labelOwnsTrace = label.mspConnectionPairIds.includes(trace.mspPairId) || label.mspConnectionPairIds.length === 0 && label.globalConnNetId === trace.globalConnNetId;
|
|
12175
12206
|
return labelOwnsTrace && tracePathContainsPoint(trace.tracePath, label.anchorPoint) ? [index] : [];
|
|
@@ -12218,19 +12249,45 @@ var getAlignedBranchPath = ({
|
|
|
12218
12249
|
if (branchRail && nearlyEqual(branchRail.start.y, donorRail.start.y)) {
|
|
12219
12250
|
return null;
|
|
12220
12251
|
}
|
|
12221
|
-
|
|
12252
|
+
const railFacesOtherPin = railIsOnFacingSide({
|
|
12253
|
+
railY: donorRail.start.y,
|
|
12254
|
+
pin: otherPin
|
|
12255
|
+
});
|
|
12256
|
+
const railFacesSharedPin = railIsOnSharedPinFacingSide({
|
|
12257
|
+
railY: donorRail.start.y,
|
|
12258
|
+
pin: sharedPin
|
|
12259
|
+
}) && Math.abs(donorRail.start.y - sharedPin.y) <= MAX_SHARED_PIN_RAIL_OFFSET;
|
|
12260
|
+
if (!railFacesOtherPin && !railFacesSharedPin) {
|
|
12222
12261
|
return null;
|
|
12223
12262
|
}
|
|
12224
12263
|
const junction = getJunctionPoint({ segment: donorRail, sharedPin });
|
|
12225
12264
|
const extendsDonorRail = donorOtherPin.x < junction.x && otherPin.x > junction.x || donorOtherPin.x > junction.x && otherPin.x < junction.x;
|
|
12226
12265
|
if (!extendsDonorRail) return null;
|
|
12227
|
-
|
|
12228
|
-
|
|
12229
|
-
|
|
12230
|
-
|
|
12231
|
-
|
|
12232
|
-
|
|
12233
|
-
|
|
12266
|
+
let sharedToOther;
|
|
12267
|
+
if (!railFacesOtherPin && railFacesSharedPin) {
|
|
12268
|
+
const approachPoint = getHorizontalPinApproachPoint({
|
|
12269
|
+
branchTrace,
|
|
12270
|
+
sharedPin,
|
|
12271
|
+
otherPin
|
|
12272
|
+
});
|
|
12273
|
+
if (!approachPoint) return null;
|
|
12274
|
+
sharedToOther = simplifyPath([
|
|
12275
|
+
{ x: sharedPin.x, y: sharedPin.y },
|
|
12276
|
+
{ x: junction.x, y: sharedPin.y },
|
|
12277
|
+
{ x: junction.x, y: junction.y },
|
|
12278
|
+
{ x: approachPoint.x, y: junction.y },
|
|
12279
|
+
{ x: approachPoint.x, y: otherPin.y },
|
|
12280
|
+
{ x: otherPin.x, y: otherPin.y }
|
|
12281
|
+
]);
|
|
12282
|
+
} else {
|
|
12283
|
+
sharedToOther = simplifyPath([
|
|
12284
|
+
{ x: sharedPin.x, y: sharedPin.y },
|
|
12285
|
+
{ x: junction.x, y: sharedPin.y },
|
|
12286
|
+
{ x: junction.x, y: junction.y },
|
|
12287
|
+
{ x: otherPin.x, y: junction.y },
|
|
12288
|
+
{ x: otherPin.x, y: otherPin.y }
|
|
12289
|
+
]);
|
|
12290
|
+
}
|
|
12234
12291
|
if (branchTrace.pins[0].pinId === sharedPin.pinId) return sharedToOther;
|
|
12235
12292
|
return [...sharedToOther].reverse();
|
|
12236
12293
|
};
|
|
@@ -185,6 +185,7 @@ export class AvailableNetOrientationSolver extends BaseSolver {
|
|
|
185
185
|
inputProblem: this.inputProblem,
|
|
186
186
|
netId: blockedLabel.netId,
|
|
187
187
|
pinIds: blockedLabel.pinIds,
|
|
188
|
+
isPortOnlyLabel: this.isPortOnlyLabel(blockedLabel),
|
|
188
189
|
})
|
|
189
190
|
let columnLabelIndex: number | undefined
|
|
190
191
|
if (blockedLabelWidth !== undefined) {
|
|
@@ -196,6 +197,7 @@ export class AvailableNetOrientationSolver extends BaseSolver {
|
|
|
196
197
|
inputProblem: this.inputProblem,
|
|
197
198
|
netId: label.netId,
|
|
198
199
|
pinIds: label.pinIds,
|
|
200
|
+
isPortOnlyLabel: this.isPortOnlyLabel(label),
|
|
199
201
|
}) === blockedLabelWidth
|
|
200
202
|
)
|
|
201
203
|
})
|
|
@@ -496,6 +498,7 @@ export class AvailableNetOrientationSolver extends BaseSolver {
|
|
|
496
498
|
inputProblem: this.inputProblem,
|
|
497
499
|
netId: label.netId,
|
|
498
500
|
pinIds: label.pinIds,
|
|
501
|
+
isPortOnlyLabel: this.isPortOnlyLabel(label),
|
|
499
502
|
}),
|
|
500
503
|
netLabelHeight: this.getNetLabelHeight(label),
|
|
501
504
|
})
|
|
@@ -1113,6 +1116,7 @@ export class AvailableNetOrientationSolver extends BaseSolver {
|
|
|
1113
1116
|
inputProblem: this.inputProblem,
|
|
1114
1117
|
netId: label.netId,
|
|
1115
1118
|
pinIds: label.pinIds,
|
|
1119
|
+
isPortOnlyLabel: this.isPortOnlyLabel(label),
|
|
1116
1120
|
}),
|
|
1117
1121
|
netLabelHeight: this.getNetLabelHeight(label),
|
|
1118
1122
|
})
|
|
@@ -1141,6 +1145,7 @@ export class AvailableNetOrientationSolver extends BaseSolver {
|
|
|
1141
1145
|
inputProblem: this.inputProblem,
|
|
1142
1146
|
netId: label.netId,
|
|
1143
1147
|
pinIds: label.pinIds,
|
|
1148
|
+
isPortOnlyLabel: this.isPortOnlyLabel(label),
|
|
1144
1149
|
}),
|
|
1145
1150
|
netLabelHeight: this.getNetLabelHeight(label),
|
|
1146
1151
|
})
|
|
@@ -1224,6 +1229,7 @@ export class AvailableNetOrientationSolver extends BaseSolver {
|
|
|
1224
1229
|
inputProblem: this.inputProblem,
|
|
1225
1230
|
netId: label.netId,
|
|
1226
1231
|
pinIds: label.pinIds,
|
|
1232
|
+
isPortOnlyLabel: this.isPortOnlyLabel(label),
|
|
1227
1233
|
}),
|
|
1228
1234
|
netLabelHeight: this.getNetLabelHeight(label),
|
|
1229
1235
|
})
|
|
@@ -1309,6 +1315,7 @@ export class AvailableNetOrientationSolver extends BaseSolver {
|
|
|
1309
1315
|
inputProblem: this.inputProblem,
|
|
1310
1316
|
netId: label.netId,
|
|
1311
1317
|
pinIds: label.pinIds,
|
|
1318
|
+
isPortOnlyLabel: this.isPortOnlyLabel(label),
|
|
1312
1319
|
}),
|
|
1313
1320
|
netLabelHeight: this.getNetLabelHeight(label),
|
|
1314
1321
|
})
|
|
@@ -34,6 +34,9 @@ interface HorizontalSegment {
|
|
|
34
34
|
const MAX_ALIGNED_LOAD_PIN_OFFSET = 0.2
|
|
35
35
|
// Limit label-boundary alignment to small corrections that cannot create spikes.
|
|
36
36
|
const MAX_SAME_NET_LABEL_BOUNDARY_RAIL_OFFSET = 0.2
|
|
37
|
+
// A shared vertical pin can anchor an existing rail when the rail is only a
|
|
38
|
+
// symbol-stem correction away from the pin itself.
|
|
39
|
+
const MAX_SHARED_PIN_RAIL_OFFSET = 0.05
|
|
37
40
|
|
|
38
41
|
const getSharedPin = ({
|
|
39
42
|
donorTrace,
|
|
@@ -96,6 +99,48 @@ const railIsOnFacingSide = ({
|
|
|
96
99
|
return false
|
|
97
100
|
}
|
|
98
101
|
|
|
102
|
+
const railIsOnSharedPinFacingSide = ({
|
|
103
|
+
railY,
|
|
104
|
+
pin,
|
|
105
|
+
}: {
|
|
106
|
+
railY: number
|
|
107
|
+
pin: InputPin
|
|
108
|
+
}) => {
|
|
109
|
+
if (pin._facingDirection === "y+") return railY > pin.y
|
|
110
|
+
if (pin._facingDirection === "y-") return railY < pin.y
|
|
111
|
+
return false
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const getHorizontalPinApproachPoint = ({
|
|
115
|
+
branchTrace,
|
|
116
|
+
sharedPin,
|
|
117
|
+
otherPin,
|
|
118
|
+
}: {
|
|
119
|
+
branchTrace: SolvedTracePath
|
|
120
|
+
sharedPin: InputPin
|
|
121
|
+
otherPin: InputPin
|
|
122
|
+
}): Point | null => {
|
|
123
|
+
if (
|
|
124
|
+
otherPin._facingDirection !== "x-" &&
|
|
125
|
+
otherPin._facingDirection !== "x+"
|
|
126
|
+
) {
|
|
127
|
+
return null
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const sharedToOtherPath =
|
|
131
|
+
branchTrace.pins[0].pinId === sharedPin.pinId
|
|
132
|
+
? branchTrace.tracePath
|
|
133
|
+
: [...branchTrace.tracePath].reverse()
|
|
134
|
+
const approachPoint = sharedToOtherPath.at(-2)
|
|
135
|
+
if (!approachPoint || !nearlyEqual(approachPoint.y, otherPin.y)) return null
|
|
136
|
+
|
|
137
|
+
const approachesFromFacingSide =
|
|
138
|
+
otherPin._facingDirection === "x-"
|
|
139
|
+
? approachPoint.x < otherPin.x
|
|
140
|
+
: approachPoint.x > otherPin.x
|
|
141
|
+
return approachesFromFacingSide ? approachPoint : null
|
|
142
|
+
}
|
|
143
|
+
|
|
99
144
|
const getAttachedLabelIndexes = (
|
|
100
145
|
trace: SolvedTracePath,
|
|
101
146
|
netLabelPlacements: NetLabelPlacement[],
|
|
@@ -165,7 +210,17 @@ const getAlignedBranchPath = ({
|
|
|
165
210
|
if (branchRail && nearlyEqual(branchRail.start.y, donorRail.start.y)) {
|
|
166
211
|
return null
|
|
167
212
|
}
|
|
168
|
-
|
|
213
|
+
const railFacesOtherPin = railIsOnFacingSide({
|
|
214
|
+
railY: donorRail.start.y,
|
|
215
|
+
pin: otherPin,
|
|
216
|
+
})
|
|
217
|
+
const railFacesSharedPin =
|
|
218
|
+
railIsOnSharedPinFacingSide({
|
|
219
|
+
railY: donorRail.start.y,
|
|
220
|
+
pin: sharedPin,
|
|
221
|
+
}) &&
|
|
222
|
+
Math.abs(donorRail.start.y - sharedPin.y) <= MAX_SHARED_PIN_RAIL_OFFSET
|
|
223
|
+
if (!railFacesOtherPin && !railFacesSharedPin) {
|
|
169
224
|
return null
|
|
170
225
|
}
|
|
171
226
|
|
|
@@ -175,13 +230,31 @@ const getAlignedBranchPath = ({
|
|
|
175
230
|
(donorOtherPin.x > junction.x && otherPin.x < junction.x)
|
|
176
231
|
if (!extendsDonorRail) return null
|
|
177
232
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
233
|
+
let sharedToOther: Point[]
|
|
234
|
+
if (!railFacesOtherPin && railFacesSharedPin) {
|
|
235
|
+
const approachPoint = getHorizontalPinApproachPoint({
|
|
236
|
+
branchTrace,
|
|
237
|
+
sharedPin,
|
|
238
|
+
otherPin,
|
|
239
|
+
})
|
|
240
|
+
if (!approachPoint) return null
|
|
241
|
+
sharedToOther = simplifyPath([
|
|
242
|
+
{ x: sharedPin.x, y: sharedPin.y },
|
|
243
|
+
{ x: junction.x, y: sharedPin.y },
|
|
244
|
+
{ x: junction.x, y: junction.y },
|
|
245
|
+
{ x: approachPoint.x, y: junction.y },
|
|
246
|
+
{ x: approachPoint.x, y: otherPin.y },
|
|
247
|
+
{ x: otherPin.x, y: otherPin.y },
|
|
248
|
+
])
|
|
249
|
+
} else {
|
|
250
|
+
sharedToOther = simplifyPath([
|
|
251
|
+
{ x: sharedPin.x, y: sharedPin.y },
|
|
252
|
+
{ x: junction.x, y: sharedPin.y },
|
|
253
|
+
{ x: junction.x, y: junction.y },
|
|
254
|
+
{ x: otherPin.x, y: junction.y },
|
|
255
|
+
{ x: otherPin.x, y: otherPin.y },
|
|
256
|
+
])
|
|
257
|
+
}
|
|
185
258
|
|
|
186
259
|
if (branchTrace.pins[0].pinId === sharedPin.pinId) return sharedToOther
|
|
187
260
|
return [...sharedToOther].reverse()
|
|
@@ -206,7 +206,7 @@ export class SchematicTraceSingleLineSolver2 extends BaseSolver {
|
|
|
206
206
|
inputProblem: this.inputProblem,
|
|
207
207
|
netId,
|
|
208
208
|
pinIds: this.pins.map((pin) => pin.pinId),
|
|
209
|
-
|
|
209
|
+
isPortOnlyLabel: false,
|
|
210
210
|
})
|
|
211
211
|
const netLabelHeight = this.getNetLabelHeightForConnectionPair(netId)
|
|
212
212
|
const padding: Required<RectPadding> = {
|
|
@@ -60,11 +60,11 @@ export interface InputDirectConnection {
|
|
|
60
60
|
netLabelWidth?: number
|
|
61
61
|
|
|
62
62
|
/**
|
|
63
|
-
* Width of the conventional anchored
|
|
64
|
-
*
|
|
65
|
-
*
|
|
63
|
+
* Width of the conventional label anchored to a trace endpoint. Unlike
|
|
64
|
+
* `netLabelWidth`, this does not affect whether or how the point-to-point
|
|
65
|
+
* connection is routed.
|
|
66
66
|
*/
|
|
67
|
-
|
|
67
|
+
anchoredNetLabelWidth?: number
|
|
68
68
|
|
|
69
69
|
/**
|
|
70
70
|
* When true, this point-to-point connection may be labeled with an "inline
|
|
@@ -106,7 +106,7 @@ export interface InputNetConnection {
|
|
|
106
106
|
*/
|
|
107
107
|
netLabelText?: string
|
|
108
108
|
netLabelWidth?: number
|
|
109
|
-
|
|
109
|
+
anchoredNetLabelWidth?: number
|
|
110
110
|
netLabelHeight?: number
|
|
111
111
|
|
|
112
112
|
/**
|
|
@@ -10,29 +10,28 @@ type ConnectionWithLabelWidth = InputDirectConnection | InputNetConnection
|
|
|
10
10
|
|
|
11
11
|
const getConfiguredWidth = (
|
|
12
12
|
connections: Array<ConnectionWithLabelWidth | undefined>,
|
|
13
|
-
|
|
13
|
+
isPortOnlyLabel: boolean,
|
|
14
14
|
) => {
|
|
15
|
-
const
|
|
15
|
+
const width = connections.find(
|
|
16
16
|
(connection) => connection?.netLabelWidth !== undefined,
|
|
17
17
|
)?.netLabelWidth
|
|
18
|
-
if (
|
|
19
|
-
if (!includeFallbackNetLabelWidth) return undefined
|
|
18
|
+
if (width !== undefined || !isPortOnlyLabel) return width
|
|
20
19
|
|
|
21
20
|
return connections.find(
|
|
22
|
-
(connection) => connection?.
|
|
23
|
-
)?.
|
|
21
|
+
(connection) => connection?.anchoredNetLabelWidth !== undefined,
|
|
22
|
+
)?.anchoredNetLabelWidth
|
|
24
23
|
}
|
|
25
24
|
|
|
26
25
|
export const getNetLabelWidthForConnection = ({
|
|
27
26
|
inputProblem,
|
|
28
27
|
netId,
|
|
29
28
|
pinIds,
|
|
30
|
-
|
|
29
|
+
isPortOnlyLabel,
|
|
31
30
|
}: {
|
|
32
31
|
inputProblem: InputProblem
|
|
33
32
|
netId?: NetId
|
|
34
33
|
pinIds: readonly PinId[]
|
|
35
|
-
|
|
34
|
+
isPortOnlyLabel: boolean
|
|
36
35
|
}): number | undefined => {
|
|
37
36
|
if (netId) {
|
|
38
37
|
const widthByNetId = getConfiguredWidth(
|
|
@@ -44,7 +43,7 @@ export const getNetLabelWidthForConnection = ({
|
|
|
44
43
|
(connection) => connection.netId === netId,
|
|
45
44
|
),
|
|
46
45
|
],
|
|
47
|
-
|
|
46
|
+
isPortOnlyLabel,
|
|
48
47
|
)
|
|
49
48
|
if (widthByNetId !== undefined) return widthByNetId
|
|
50
49
|
}
|
|
@@ -58,6 +57,6 @@ export const getNetLabelWidthForConnection = ({
|
|
|
58
57
|
connection.pinIds.some((pinId) => pinIds.includes(pinId)),
|
|
59
58
|
),
|
|
60
59
|
],
|
|
61
|
-
|
|
60
|
+
isPortOnlyLabel,
|
|
62
61
|
)
|
|
63
62
|
}
|
package/package.json
CHANGED