@tscircuit/schematic-trace-solver 0.0.197 → 0.0.199
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 +4 -0
- package/dist/index.js +84 -5
- package/lib/solvers/AvailableNetOrientationSolver/AvailableNetOrientationSolver.ts +10 -1
- package/lib/solvers/RailNetLabelCornerPlacementSolver/RailNetLabelCornerPlacementSolver.ts +128 -2
- package/lib/solvers/RailNetLabelCornerPlacementSolver/types.ts +1 -0
- package/lib/solvers/SchematicTracePipelineSolver/SchematicTracePipelineSolver.ts +2 -0
- package/package.json +1 -1
- package/site/SchematicTracePipelineSolver/repro-am3352-sheet3-power-rails.page.tsx +7 -0
- package/site/bug-reports/bug-report-20260911T195723Z.page.tsx +4 -0
- package/site/bug-reports/bug-report-20260916T054012Z.page.tsx +4 -0
- package/tests/bug-reports/bug-report-20260911T195723Z/__snapshots__/bug-report-20260911T195723Z.snap.svg +559 -0
- package/tests/bug-reports/bug-report-20260911T195723Z/bug-report-20260911T195723Z.json +1792 -0
- package/tests/bug-reports/bug-report-20260911T195723Z/bug-report-20260911T195723Z.test.ts +35 -0
- package/tests/bug-reports/bug-report-20260916T054012Z/__snapshots__/bug-report-20260916T054012Z.snap.svg +504 -0
- package/tests/bug-reports/bug-report-20260916T054012Z/bug-report-20260916T054012Z.json +1847 -0
- package/tests/bug-reports/bug-report-20260916T054012Z/bug-report-20260916T054012Z.test.ts +28 -0
- package/tests/repros/__snapshots__/repro-am3352-sheet3-power-rails.snap.svg +187 -0
- package/tests/repros/__snapshots__/repro-normal-net-label-branch-from-junction.snap.svg +31 -31
- package/tests/repros/assets/repro-am3352-sheet3-power-rails.input.json +698 -0
- package/tests/repros/repro-am3352-sheet3-power-rails.md +66 -0
- package/tests/repros/repro-am3352-sheet3-power-rails.test.ts +39 -0
- package/tests/repros/repro-normal-net-label-branch-from-junction.test.ts +13 -0
package/dist/index.d.ts
CHANGED
|
@@ -963,6 +963,7 @@ interface RailNetLabelCornerPlacementSolverParams {
|
|
|
963
963
|
inputProblem: InputProblem;
|
|
964
964
|
traces: SolvedTracePath[];
|
|
965
965
|
netLabelPlacements: NetLabelPlacement[];
|
|
966
|
+
netLabelConnectorTraceIds?: ReadonlySet<string>;
|
|
966
967
|
}
|
|
967
968
|
type TraceCornerCandidate = {
|
|
968
969
|
anchorPoint: Point;
|
|
@@ -996,6 +997,7 @@ declare class RailNetLabelCornerPlacementSolver extends BaseSolver {
|
|
|
996
997
|
private queuedCornerCandidates;
|
|
997
998
|
private shouldAdvanceToNextLabel;
|
|
998
999
|
private traceMap;
|
|
1000
|
+
private netLabelConnectorTraceIds;
|
|
999
1001
|
constructor(params: RailNetLabelCornerPlacementSolverParams);
|
|
1000
1002
|
getConstructorParams(): ConstructorParameters<typeof RailNetLabelCornerPlacementSolver>[0];
|
|
1001
1003
|
_step(): void;
|
|
@@ -1015,6 +1017,8 @@ declare class RailNetLabelCornerPlacementSolver extends BaseSolver {
|
|
|
1015
1017
|
private intersectsAnyChip;
|
|
1016
1018
|
private intersectsAnyOtherNetLabel;
|
|
1017
1019
|
private getCornerCandidatesForLabel;
|
|
1020
|
+
private getStraightConnectorCandidates;
|
|
1021
|
+
private isComponentAdjacentCorner;
|
|
1018
1022
|
private isConfiguredRailLabel;
|
|
1019
1023
|
private isLabelCrossedByOtherNetTrace;
|
|
1020
1024
|
private pointsEqual;
|
package/dist/index.js
CHANGED
|
@@ -10274,7 +10274,8 @@ var AvailableNetOrientationSolver = class extends BaseSolver {
|
|
|
10274
10274
|
result.selected = true;
|
|
10275
10275
|
return result;
|
|
10276
10276
|
}
|
|
10277
|
-
if (stopOnTraceCollision && result.status === "trace-collision")
|
|
10277
|
+
if (stopOnTraceCollision && result.status === "trace-collision" && (!projectedConnectorSource || orientation !== "y-" || !this.isGroundLabel(label)))
|
|
10278
|
+
break;
|
|
10278
10279
|
}
|
|
10279
10280
|
return null;
|
|
10280
10281
|
}
|
|
@@ -11181,6 +11182,7 @@ var RailNetLabelCornerPlacementSolver = class extends BaseSolver {
|
|
|
11181
11182
|
queuedCornerCandidates = [];
|
|
11182
11183
|
shouldAdvanceToNextLabel = false;
|
|
11183
11184
|
traceMap;
|
|
11185
|
+
netLabelConnectorTraceIds;
|
|
11184
11186
|
constructor(params) {
|
|
11185
11187
|
super();
|
|
11186
11188
|
this.inputProblem = params.inputProblem;
|
|
@@ -11190,6 +11192,7 @@ var RailNetLabelCornerPlacementSolver = class extends BaseSolver {
|
|
|
11190
11192
|
this.traceMap = Object.fromEntries(
|
|
11191
11193
|
params.traces.map((trace) => [trace.mspPairId, trace])
|
|
11192
11194
|
);
|
|
11195
|
+
this.netLabelConnectorTraceIds = params.netLabelConnectorTraceIds ?? /* @__PURE__ */ new Set();
|
|
11193
11196
|
this.queuedLabelIndices = this.getProcessableLabelIndices();
|
|
11194
11197
|
this.prepareNextLabel();
|
|
11195
11198
|
}
|
|
@@ -11197,7 +11200,8 @@ var RailNetLabelCornerPlacementSolver = class extends BaseSolver {
|
|
|
11197
11200
|
return {
|
|
11198
11201
|
inputProblem: this.inputProblem,
|
|
11199
11202
|
traces: this.traces,
|
|
11200
|
-
netLabelPlacements: this.netLabelPlacements
|
|
11203
|
+
netLabelPlacements: this.netLabelPlacements,
|
|
11204
|
+
netLabelConnectorTraceIds: this.netLabelConnectorTraceIds
|
|
11201
11205
|
};
|
|
11202
11206
|
}
|
|
11203
11207
|
_step() {
|
|
@@ -11248,7 +11252,10 @@ var RailNetLabelCornerPlacementSolver = class extends BaseSolver {
|
|
|
11248
11252
|
this.currentLabelIndex = labelIndex;
|
|
11249
11253
|
this.currentLabel = label;
|
|
11250
11254
|
this.currentCandidateResults = [];
|
|
11251
|
-
this.queuedCornerCandidates =
|
|
11255
|
+
this.queuedCornerCandidates = [
|
|
11256
|
+
...this.getStraightConnectorCandidates(label),
|
|
11257
|
+
...this.getCornerCandidatesForLabel(label)
|
|
11258
|
+
];
|
|
11252
11259
|
return true;
|
|
11253
11260
|
}
|
|
11254
11261
|
advanceToNextLabel() {
|
|
@@ -11330,7 +11337,7 @@ var RailNetLabelCornerPlacementSolver = class extends BaseSolver {
|
|
|
11330
11337
|
}
|
|
11331
11338
|
shouldProcessLabel(label) {
|
|
11332
11339
|
const isVerticalRailLabel = label.orientation === "y+" || label.orientation === "y-";
|
|
11333
|
-
return isVerticalRailLabel && this.getCornerCandidatesForLabel(label).length > 0;
|
|
11340
|
+
return isVerticalRailLabel && (this.getStraightConnectorCandidates(label).length > 0 || this.getCornerCandidatesForLabel(label).length > 0);
|
|
11334
11341
|
}
|
|
11335
11342
|
intersectsAnyChip(bounds) {
|
|
11336
11343
|
return this.inputProblem.chips.some(
|
|
@@ -11387,6 +11394,77 @@ var RailNetLabelCornerPlacementSolver = class extends BaseSolver {
|
|
|
11387
11394
|
...railAlignedCandidates.sort((a, b) => a.distance - b.distance)
|
|
11388
11395
|
];
|
|
11389
11396
|
}
|
|
11397
|
+
getStraightConnectorCandidates(label) {
|
|
11398
|
+
if (label.pinIds.length !== 2 || !this.isConfiguredRailLabel(label)) {
|
|
11399
|
+
return [];
|
|
11400
|
+
}
|
|
11401
|
+
const pins = this.inputProblem.chips.flatMap((chip) => chip.pins).filter((pin) => label.pinIds.includes(pin.pinId));
|
|
11402
|
+
if (pins.length !== 2 || pins[0]._facingDirection !== pins[1]._facingDirection || pins[0]._facingDirection !== "x+" && pins[0]._facingDirection !== "x-" || Math.abs(pins[0].y - pins[1].y) > EPS8) {
|
|
11403
|
+
return [];
|
|
11404
|
+
}
|
|
11405
|
+
const configuredOrientations = this.inputProblem.availableNetLabelOrientations[label.netId];
|
|
11406
|
+
if (configuredOrientations?.length !== 1 || configuredOrientations[0] !== label.orientation) {
|
|
11407
|
+
return [];
|
|
11408
|
+
}
|
|
11409
|
+
const netConnection = this.inputProblem.netConnections.find(
|
|
11410
|
+
(connection) => connection.netId === label.netId
|
|
11411
|
+
);
|
|
11412
|
+
if (netConnection?.isGround) return [];
|
|
11413
|
+
const connector = this.traces.find(
|
|
11414
|
+
(trace) => this.netLabelConnectorTraceIds.has(trace.mspPairId) && trace.globalConnNetId === label.globalConnNetId && label.pinIds.every((pinId) => trace.pinIds.includes(pinId)) && trace.tracePath.length >= 2 && (this.pointsEqual(trace.tracePath[0], label.anchorPoint) || this.pointsEqual(trace.tracePath.at(-1), label.anchorPoint))
|
|
11415
|
+
);
|
|
11416
|
+
if (!connector) return [];
|
|
11417
|
+
const sourcePoint = this.pointsEqual(
|
|
11418
|
+
connector.tracePath[0],
|
|
11419
|
+
label.anchorPoint
|
|
11420
|
+
) ? connector.tracePath.at(-1) : connector.tracePath[0];
|
|
11421
|
+
if (!this.isComponentAdjacentCorner(label, sourcePoint)) return [];
|
|
11422
|
+
const direction = label.orientation === "y+" ? 1 : -1;
|
|
11423
|
+
const maxSearchDistance = Math.min(
|
|
11424
|
+
getMaxSearchDistance(this.inputProblem),
|
|
11425
|
+
label.height * 2
|
|
11426
|
+
);
|
|
11427
|
+
for (let distance7 = WICK_CLEARANCE + LABEL_SEARCH_STEP; distance7 <= maxSearchDistance + EPS8; distance7 += LABEL_SEARCH_STEP) {
|
|
11428
|
+
const anchorPoint = {
|
|
11429
|
+
x: sourcePoint.x,
|
|
11430
|
+
y: sourcePoint.y + direction * distance7
|
|
11431
|
+
};
|
|
11432
|
+
const center = getCenterFromAnchor(
|
|
11433
|
+
anchorPoint,
|
|
11434
|
+
label.orientation,
|
|
11435
|
+
label.width,
|
|
11436
|
+
label.height
|
|
11437
|
+
);
|
|
11438
|
+
if (this.intersectsAnyChip(getRectBounds(center, label.width, label.height))) {
|
|
11439
|
+
continue;
|
|
11440
|
+
}
|
|
11441
|
+
return [
|
|
11442
|
+
{
|
|
11443
|
+
anchorPoint,
|
|
11444
|
+
traceId: connector.mspPairId,
|
|
11445
|
+
distance: getDistance(anchorPoint, label.anchorPoint),
|
|
11446
|
+
pinAligned: true,
|
|
11447
|
+
reroutedTracePath: [sourcePoint, anchorPoint]
|
|
11448
|
+
}
|
|
11449
|
+
];
|
|
11450
|
+
}
|
|
11451
|
+
return [];
|
|
11452
|
+
}
|
|
11453
|
+
isComponentAdjacentCorner(label, corner) {
|
|
11454
|
+
return label.mspConnectionPairIds.some((traceId) => {
|
|
11455
|
+
const trace = this.traceMap[traceId];
|
|
11456
|
+
if (!trace || trace.tracePath.length < 2) return false;
|
|
11457
|
+
return [
|
|
11458
|
+
{ point: trace.tracePath[0], neighbor: trace.tracePath[1] },
|
|
11459
|
+
{
|
|
11460
|
+
point: trace.tracePath.at(-1),
|
|
11461
|
+
neighbor: trace.tracePath.at(-2)
|
|
11462
|
+
}
|
|
11463
|
+
].some(
|
|
11464
|
+
({ point, neighbor }) => this.pointsEqual(neighbor, corner) && trace.pins.some((pin) => this.pointsEqual(pin, point))
|
|
11465
|
+
);
|
|
11466
|
+
});
|
|
11467
|
+
}
|
|
11390
11468
|
isConfiguredRailLabel(label) {
|
|
11391
11469
|
if (!label.netId) return false;
|
|
11392
11470
|
return this.inputProblem.availableNetLabelOrientations[label.netId]?.some(
|
|
@@ -18710,7 +18788,8 @@ var SchematicTracePipelineSolver = class extends BaseSolver {
|
|
|
18710
18788
|
traces: Object.values(
|
|
18711
18789
|
instance.postLabelTraceOverlapShiftSolver.correctedTraceMap
|
|
18712
18790
|
),
|
|
18713
|
-
netLabelPlacements: instance.availableNetOrientationSolver.outputNetLabelPlacements
|
|
18791
|
+
netLabelPlacements: instance.availableNetOrientationSolver.outputNetLabelPlacements,
|
|
18792
|
+
netLabelConnectorTraceIds: instance.availableNetOrientationSolver.netLabelConnectorTraceIds
|
|
18714
18793
|
}
|
|
18715
18794
|
];
|
|
18716
18795
|
}
|
|
@@ -1172,7 +1172,16 @@ export class AvailableNetOrientationSolver extends BaseSolver {
|
|
|
1172
1172
|
result.selected = true
|
|
1173
1173
|
return result
|
|
1174
1174
|
}
|
|
1175
|
-
|
|
1175
|
+
// A downward ground branch projected onto its existing trace can reach a
|
|
1176
|
+
// clear position below a crossing trace.
|
|
1177
|
+
if (
|
|
1178
|
+
stopOnTraceCollision &&
|
|
1179
|
+
result.status === "trace-collision" &&
|
|
1180
|
+
(!projectedConnectorSource ||
|
|
1181
|
+
orientation !== "y-" ||
|
|
1182
|
+
!this.isGroundLabel(label))
|
|
1183
|
+
)
|
|
1184
|
+
break
|
|
1176
1185
|
}
|
|
1177
1186
|
|
|
1178
1187
|
return null
|
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import type { GraphicsObject } from "graphics-debug"
|
|
2
2
|
import type { Point } from "@tscircuit/math-utils"
|
|
3
3
|
import {
|
|
4
|
+
getMaxSearchDistance,
|
|
4
5
|
segmentCrossesBoundsInterior,
|
|
5
6
|
traceCrossesBoundsInterior,
|
|
6
7
|
} from "lib/solvers/AvailableNetOrientationSolver/geometry"
|
|
8
|
+
import {
|
|
9
|
+
LABEL_SEARCH_STEP,
|
|
10
|
+
WICK_CLEARANCE,
|
|
11
|
+
} from "lib/solvers/AvailableNetOrientationSolver/constants"
|
|
7
12
|
import { BaseSolver } from "lib/solvers/BaseSolver/BaseSolver"
|
|
8
13
|
import { moveAttachedLabelsToReroutedTrace } from "lib/solvers/Example28Solver/labelMovement"
|
|
9
14
|
import type { NetLabelPlacement } from "lib/solvers/NetLabelPlacementSolver/NetLabelPlacementSolver"
|
|
@@ -51,6 +56,7 @@ export class RailNetLabelCornerPlacementSolver extends BaseSolver {
|
|
|
51
56
|
private queuedCornerCandidates: TraceCornerCandidate[] = []
|
|
52
57
|
private shouldAdvanceToNextLabel = false
|
|
53
58
|
private traceMap: Record<string, SolvedTracePath>
|
|
59
|
+
private netLabelConnectorTraceIds: ReadonlySet<string>
|
|
54
60
|
|
|
55
61
|
constructor(params: RailNetLabelCornerPlacementSolverParams) {
|
|
56
62
|
super()
|
|
@@ -61,6 +67,8 @@ export class RailNetLabelCornerPlacementSolver extends BaseSolver {
|
|
|
61
67
|
this.traceMap = Object.fromEntries(
|
|
62
68
|
params.traces.map((trace) => [trace.mspPairId, trace]),
|
|
63
69
|
)
|
|
70
|
+
this.netLabelConnectorTraceIds =
|
|
71
|
+
params.netLabelConnectorTraceIds ?? new Set()
|
|
64
72
|
this.queuedLabelIndices = this.getProcessableLabelIndices()
|
|
65
73
|
this.prepareNextLabel()
|
|
66
74
|
}
|
|
@@ -72,6 +80,7 @@ export class RailNetLabelCornerPlacementSolver extends BaseSolver {
|
|
|
72
80
|
inputProblem: this.inputProblem,
|
|
73
81
|
traces: this.traces,
|
|
74
82
|
netLabelPlacements: this.netLabelPlacements,
|
|
83
|
+
netLabelConnectorTraceIds: this.netLabelConnectorTraceIds,
|
|
75
84
|
}
|
|
76
85
|
}
|
|
77
86
|
|
|
@@ -135,7 +144,10 @@ export class RailNetLabelCornerPlacementSolver extends BaseSolver {
|
|
|
135
144
|
this.currentLabelIndex = labelIndex
|
|
136
145
|
this.currentLabel = label
|
|
137
146
|
this.currentCandidateResults = []
|
|
138
|
-
this.queuedCornerCandidates =
|
|
147
|
+
this.queuedCornerCandidates = [
|
|
148
|
+
...this.getStraightConnectorCandidates(label),
|
|
149
|
+
...this.getCornerCandidatesForLabel(label),
|
|
150
|
+
]
|
|
139
151
|
|
|
140
152
|
return true
|
|
141
153
|
}
|
|
@@ -250,7 +262,9 @@ export class RailNetLabelCornerPlacementSolver extends BaseSolver {
|
|
|
250
262
|
const isVerticalRailLabel =
|
|
251
263
|
label.orientation === "y+" || label.orientation === "y-"
|
|
252
264
|
return (
|
|
253
|
-
isVerticalRailLabel &&
|
|
265
|
+
isVerticalRailLabel &&
|
|
266
|
+
(this.getStraightConnectorCandidates(label).length > 0 ||
|
|
267
|
+
this.getCornerCandidatesForLabel(label).length > 0)
|
|
254
268
|
)
|
|
255
269
|
}
|
|
256
270
|
|
|
@@ -323,6 +337,118 @@ export class RailNetLabelCornerPlacementSolver extends BaseSolver {
|
|
|
323
337
|
]
|
|
324
338
|
}
|
|
325
339
|
|
|
340
|
+
private getStraightConnectorCandidates(
|
|
341
|
+
label: NetLabelPlacement,
|
|
342
|
+
): TraceCornerCandidate[] {
|
|
343
|
+
if (label.pinIds.length !== 2 || !this.isConfiguredRailLabel(label)) {
|
|
344
|
+
return []
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
const pins = this.inputProblem.chips
|
|
348
|
+
.flatMap((chip) => chip.pins)
|
|
349
|
+
.filter((pin) => label.pinIds.includes(pin.pinId))
|
|
350
|
+
if (
|
|
351
|
+
pins.length !== 2 ||
|
|
352
|
+
pins[0]!._facingDirection !== pins[1]!._facingDirection ||
|
|
353
|
+
(pins[0]!._facingDirection !== "x+" &&
|
|
354
|
+
pins[0]!._facingDirection !== "x-") ||
|
|
355
|
+
Math.abs(pins[0]!.y - pins[1]!.y) > EPS
|
|
356
|
+
) {
|
|
357
|
+
return []
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
const configuredOrientations =
|
|
361
|
+
this.inputProblem.availableNetLabelOrientations[label.netId!]
|
|
362
|
+
if (
|
|
363
|
+
configuredOrientations?.length !== 1 ||
|
|
364
|
+
configuredOrientations[0] !== label.orientation
|
|
365
|
+
) {
|
|
366
|
+
return []
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
const netConnection = this.inputProblem.netConnections.find(
|
|
370
|
+
(connection) => connection.netId === label.netId,
|
|
371
|
+
)
|
|
372
|
+
if (netConnection?.isGround) return []
|
|
373
|
+
|
|
374
|
+
const connector = this.traces.find(
|
|
375
|
+
(trace) =>
|
|
376
|
+
this.netLabelConnectorTraceIds.has(trace.mspPairId) &&
|
|
377
|
+
trace.globalConnNetId === label.globalConnNetId &&
|
|
378
|
+
label.pinIds.every((pinId) => trace.pinIds.includes(pinId)) &&
|
|
379
|
+
trace.tracePath.length >= 2 &&
|
|
380
|
+
(this.pointsEqual(trace.tracePath[0]!, label.anchorPoint) ||
|
|
381
|
+
this.pointsEqual(trace.tracePath.at(-1)!, label.anchorPoint)),
|
|
382
|
+
)
|
|
383
|
+
if (!connector) return []
|
|
384
|
+
|
|
385
|
+
const sourcePoint = this.pointsEqual(
|
|
386
|
+
connector.tracePath[0]!,
|
|
387
|
+
label.anchorPoint,
|
|
388
|
+
)
|
|
389
|
+
? connector.tracePath.at(-1)!
|
|
390
|
+
: connector.tracePath[0]!
|
|
391
|
+
if (!this.isComponentAdjacentCorner(label, sourcePoint)) return []
|
|
392
|
+
|
|
393
|
+
const direction = label.orientation === "y+" ? 1 : -1
|
|
394
|
+
const maxSearchDistance = Math.min(
|
|
395
|
+
getMaxSearchDistance(this.inputProblem),
|
|
396
|
+
label.height * 2,
|
|
397
|
+
)
|
|
398
|
+
for (
|
|
399
|
+
let distance = WICK_CLEARANCE + LABEL_SEARCH_STEP;
|
|
400
|
+
distance <= maxSearchDistance + EPS;
|
|
401
|
+
distance += LABEL_SEARCH_STEP
|
|
402
|
+
) {
|
|
403
|
+
const anchorPoint = {
|
|
404
|
+
x: sourcePoint.x,
|
|
405
|
+
y: sourcePoint.y + direction * distance,
|
|
406
|
+
}
|
|
407
|
+
const center = getCenterFromAnchor(
|
|
408
|
+
anchorPoint,
|
|
409
|
+
label.orientation,
|
|
410
|
+
label.width,
|
|
411
|
+
label.height,
|
|
412
|
+
)
|
|
413
|
+
if (
|
|
414
|
+
this.intersectsAnyChip(getRectBounds(center, label.width, label.height))
|
|
415
|
+
) {
|
|
416
|
+
continue
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
return [
|
|
420
|
+
{
|
|
421
|
+
anchorPoint,
|
|
422
|
+
traceId: connector.mspPairId,
|
|
423
|
+
distance: getDistance(anchorPoint, label.anchorPoint),
|
|
424
|
+
pinAligned: true,
|
|
425
|
+
reroutedTracePath: [sourcePoint, anchorPoint],
|
|
426
|
+
},
|
|
427
|
+
]
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
return []
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
private isComponentAdjacentCorner(label: NetLabelPlacement, corner: Point) {
|
|
434
|
+
return label.mspConnectionPairIds.some((traceId) => {
|
|
435
|
+
const trace = this.traceMap[traceId]
|
|
436
|
+
if (!trace || trace.tracePath.length < 2) return false
|
|
437
|
+
|
|
438
|
+
return [
|
|
439
|
+
{ point: trace.tracePath[0]!, neighbor: trace.tracePath[1]! },
|
|
440
|
+
{
|
|
441
|
+
point: trace.tracePath.at(-1)!,
|
|
442
|
+
neighbor: trace.tracePath.at(-2)!,
|
|
443
|
+
},
|
|
444
|
+
].some(
|
|
445
|
+
({ point, neighbor }) =>
|
|
446
|
+
this.pointsEqual(neighbor, corner) &&
|
|
447
|
+
trace.pins.some((pin) => this.pointsEqual(pin, point)),
|
|
448
|
+
)
|
|
449
|
+
})
|
|
450
|
+
}
|
|
451
|
+
|
|
326
452
|
private isConfiguredRailLabel(label: NetLabelPlacement) {
|
|
327
453
|
if (!label.netId) return false
|
|
328
454
|
return this.inputProblem.availableNetLabelOrientations[label.netId]?.some(
|
|
@@ -402,6 +402,8 @@ export class SchematicTracePipelineSolver extends BaseSolver {
|
|
|
402
402
|
),
|
|
403
403
|
netLabelPlacements:
|
|
404
404
|
instance.availableNetOrientationSolver!.outputNetLabelPlacements,
|
|
405
|
+
netLabelConnectorTraceIds:
|
|
406
|
+
instance.availableNetOrientationSolver!.netLabelConnectorTraceIds,
|
|
405
407
|
},
|
|
406
408
|
]
|
|
407
409
|
},
|
package/package.json
CHANGED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { InputProblem } from "lib/types/InputProblem"
|
|
2
|
+
import { PipelineDebugger } from "site/components/PipelineDebugger"
|
|
3
|
+
import input from "../../tests/repros/assets/repro-am3352-sheet3-power-rails.input.json"
|
|
4
|
+
|
|
5
|
+
export default () => (
|
|
6
|
+
<PipelineDebugger inputProblem={structuredClone(input) as InputProblem} />
|
|
7
|
+
)
|