@tscircuit/schematic-trace-solver 0.0.155 → 0.0.156
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 +2 -0
- package/dist/index.js +34 -4
- package/lib/solvers/SchematicTraceLinesSolver/SchematicTraceLinesSolver.ts +38 -0
- package/lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/SchematicTraceSingleLineSolver2.ts +19 -11
- package/package.json +1 -1
- package/site/bug-reports/bug-report-20260825T045913Z.page.tsx +4 -0
- package/tests/bug-reports/bug-report-20260825T045913Z/__snapshots__/bug-report-20260825T045913Z.snap.svg +271 -0
- package/tests/bug-reports/bug-report-20260825T045913Z/bug-report-20260825T045913Z.json +874 -0
- package/tests/bug-reports/bug-report-20260825T045913Z/bug-report-20260825T045913Z.test.ts +23 -0
package/dist/index.d.ts
CHANGED
|
@@ -244,6 +244,7 @@ declare class SchematicTraceSingleLineSolver2 extends BaseSolver {
|
|
|
244
244
|
maxY: number;
|
|
245
245
|
};
|
|
246
246
|
baseElbow: Point[];
|
|
247
|
+
preferExteriorDetours: boolean;
|
|
247
248
|
solvedTracePath: Point[] | null;
|
|
248
249
|
private queue;
|
|
249
250
|
private visited;
|
|
@@ -252,6 +253,7 @@ declare class SchematicTraceSingleLineSolver2 extends BaseSolver {
|
|
|
252
253
|
connectionPair?: MspConnectionPair;
|
|
253
254
|
inputProblem: InputProblem;
|
|
254
255
|
chipMap: Record<string, InputChip>;
|
|
256
|
+
preferExteriorDetours?: boolean;
|
|
255
257
|
});
|
|
256
258
|
getConstructorParams(): ConstructorParameters<typeof SchematicTraceSingleLineSolver2>[0];
|
|
257
259
|
private getTextBoxPaddingForConnectionPair;
|
package/dist/index.js
CHANGED
|
@@ -1255,6 +1255,7 @@ var SchematicTraceSingleLineSolver2 = class extends BaseSolver {
|
|
|
1255
1255
|
endpointTextObstacles;
|
|
1256
1256
|
aabb;
|
|
1257
1257
|
baseElbow;
|
|
1258
|
+
preferExteriorDetours;
|
|
1258
1259
|
solvedTracePath = null;
|
|
1259
1260
|
queue = [];
|
|
1260
1261
|
visited = /* @__PURE__ */ new Set();
|
|
@@ -1264,6 +1265,7 @@ var SchematicTraceSingleLineSolver2 = class extends BaseSolver {
|
|
|
1264
1265
|
this.connectionPair = params.connectionPair;
|
|
1265
1266
|
this.inputProblem = params.inputProblem;
|
|
1266
1267
|
this.chipMap = params.chipMap;
|
|
1268
|
+
this.preferExteriorDetours = params.preferExteriorDetours ?? true;
|
|
1267
1269
|
for (const pin of this.pins) {
|
|
1268
1270
|
if (!pin._facingDirection) {
|
|
1269
1271
|
const chip = this.chipMap[pin.chipId];
|
|
@@ -1316,7 +1318,8 @@ var SchematicTraceSingleLineSolver2 = class extends BaseSolver {
|
|
|
1316
1318
|
chipMap: this.chipMap,
|
|
1317
1319
|
pins: this.pins,
|
|
1318
1320
|
connectionPair: this.connectionPair,
|
|
1319
|
-
inputProblem: this.inputProblem
|
|
1321
|
+
inputProblem: this.inputProblem,
|
|
1322
|
+
preferExteriorDetours: this.preferExteriorDetours
|
|
1320
1323
|
};
|
|
1321
1324
|
}
|
|
1322
1325
|
getTextBoxPaddingForConnectionPair() {
|
|
@@ -1481,7 +1484,6 @@ var SchematicTraceSingleLineSolver2 = class extends BaseSolver {
|
|
|
1481
1484
|
const isEndpointChipObstacle = rect.kind === "chip" && this.pins.some((pin) => pin.chipId === rect.chipId);
|
|
1482
1485
|
const canGenerateEndpointDetour = path.length === 3 || path.length === 4 && this.connectionPair !== void 0 && !isEndpointChipObstacle;
|
|
1483
1486
|
if (canGenerateEndpointDetour && (isFirstSegment || isLastSegment)) {
|
|
1484
|
-
const compareDetours = path.length === 4 ? (a2, b2) => this.getPinBandPenalty(a2) - this.getPinBandPenalty(b2) || this.pathLength(a2) - this.pathLength(b2) : (a2, b2) => this.pathLength(a2) - this.pathLength(b2) || this.getPinBandPenalty(a2) - this.getPinBandPenalty(b2);
|
|
1485
1487
|
const detours = generateEndpointCollisionDetours({
|
|
1486
1488
|
path,
|
|
1487
1489
|
collidingSegmentIndex: segIndex,
|
|
@@ -1491,7 +1493,12 @@ var SchematicTraceSingleLineSolver2 = class extends BaseSolver {
|
|
|
1491
1493
|
if (this.visited.has(key)) return false;
|
|
1492
1494
|
this.visited.add(key);
|
|
1493
1495
|
return true;
|
|
1494
|
-
}).sort(
|
|
1496
|
+
}).sort((a2, b2) => {
|
|
1497
|
+
if (path.length === 4 && this.preferExteriorDetours) {
|
|
1498
|
+
return this.getPinBandPenalty(a2) - this.getPinBandPenalty(b2) || this.pathLength(a2) - this.pathLength(b2);
|
|
1499
|
+
}
|
|
1500
|
+
return this.pathLength(a2) - this.pathLength(b2) || this.getPinBandPenalty(a2) - this.getPinBandPenalty(b2);
|
|
1501
|
+
});
|
|
1495
1502
|
for (const detour of detours) {
|
|
1496
1503
|
const nextCollisionRects = new Set(collisionRects);
|
|
1497
1504
|
nextCollisionRects.add(rect);
|
|
@@ -1644,6 +1651,24 @@ var SchematicTraceSingleLineSolver2 = class extends BaseSolver {
|
|
|
1644
1651
|
import { getBounds } from "graphics-debug";
|
|
1645
1652
|
|
|
1646
1653
|
// lib/solvers/SchematicTraceLinesSolver/SchematicTraceLinesSolver.ts
|
|
1654
|
+
var shouldPreferExteriorDetours = ({
|
|
1655
|
+
connectionPair,
|
|
1656
|
+
allConnectionPairs,
|
|
1657
|
+
inputProblem
|
|
1658
|
+
}) => {
|
|
1659
|
+
const [firstPin, secondPin] = connectionPair.pins;
|
|
1660
|
+
const belongsToNetConnection = inputProblem.netConnections.some(
|
|
1661
|
+
(netConnection) => netConnection.pinIds.includes(firstPin.pinId) && netConnection.pinIds.includes(secondPin.pinId)
|
|
1662
|
+
);
|
|
1663
|
+
if (belongsToNetConnection) return true;
|
|
1664
|
+
return allConnectionPairs.some((otherPair) => {
|
|
1665
|
+
if (otherPair === connectionPair) return false;
|
|
1666
|
+
const [otherFirstPin, otherSecondPin] = otherPair.pins;
|
|
1667
|
+
const sameOrder = firstPin.chipId === otherFirstPin.chipId && secondPin.chipId === otherSecondPin.chipId;
|
|
1668
|
+
if (sameOrder) return true;
|
|
1669
|
+
return firstPin.chipId === otherSecondPin.chipId && secondPin.chipId === otherFirstPin.chipId;
|
|
1670
|
+
});
|
|
1671
|
+
};
|
|
1647
1672
|
var SchematicTraceLinesSolver = class extends BaseSolver {
|
|
1648
1673
|
inputProblem;
|
|
1649
1674
|
mspConnectionPairs;
|
|
@@ -1711,7 +1736,12 @@ var SchematicTraceLinesSolver = class extends BaseSolver {
|
|
|
1711
1736
|
inputProblem: this.inputProblem,
|
|
1712
1737
|
pins,
|
|
1713
1738
|
connectionPair,
|
|
1714
|
-
chipMap: this.chipMap
|
|
1739
|
+
chipMap: this.chipMap,
|
|
1740
|
+
preferExteriorDetours: shouldPreferExteriorDetours({
|
|
1741
|
+
connectionPair,
|
|
1742
|
+
allConnectionPairs: this.mspConnectionPairs,
|
|
1743
|
+
inputProblem: this.inputProblem
|
|
1744
|
+
})
|
|
1715
1745
|
});
|
|
1716
1746
|
}
|
|
1717
1747
|
visualize() {
|
|
@@ -12,6 +12,39 @@ import type { Guideline } from "../GuidelinesSolver/GuidelinesSolver"
|
|
|
12
12
|
import { visualizeGuidelines } from "../GuidelinesSolver/visualizeGuidelines"
|
|
13
13
|
import type { Point } from "@tscircuit/math-utils"
|
|
14
14
|
|
|
15
|
+
const shouldPreferExteriorDetours = ({
|
|
16
|
+
connectionPair,
|
|
17
|
+
allConnectionPairs,
|
|
18
|
+
inputProblem,
|
|
19
|
+
}: {
|
|
20
|
+
connectionPair: MspConnectionPair
|
|
21
|
+
allConnectionPairs: MspConnectionPair[]
|
|
22
|
+
inputProblem: InputProblem
|
|
23
|
+
}) => {
|
|
24
|
+
const [firstPin, secondPin] = connectionPair.pins
|
|
25
|
+
const belongsToNetConnection = inputProblem.netConnections.some(
|
|
26
|
+
(netConnection) =>
|
|
27
|
+
netConnection.pinIds.includes(firstPin.pinId) &&
|
|
28
|
+
netConnection.pinIds.includes(secondPin.pinId),
|
|
29
|
+
)
|
|
30
|
+
if (belongsToNetConnection) return true
|
|
31
|
+
|
|
32
|
+
return allConnectionPairs.some((otherPair) => {
|
|
33
|
+
if (otherPair === connectionPair) return false
|
|
34
|
+
|
|
35
|
+
const [otherFirstPin, otherSecondPin] = otherPair.pins
|
|
36
|
+
const sameOrder =
|
|
37
|
+
firstPin.chipId === otherFirstPin.chipId &&
|
|
38
|
+
secondPin.chipId === otherSecondPin.chipId
|
|
39
|
+
if (sameOrder) return true
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
firstPin.chipId === otherSecondPin.chipId &&
|
|
43
|
+
secondPin.chipId === otherFirstPin.chipId
|
|
44
|
+
)
|
|
45
|
+
})
|
|
46
|
+
}
|
|
47
|
+
|
|
15
48
|
export interface SolvedTracePath extends MspConnectionPair {
|
|
16
49
|
tracePath: Point[]
|
|
17
50
|
mspConnectionPairIds: MspConnectionPairId[]
|
|
@@ -112,6 +145,11 @@ export class SchematicTraceLinesSolver extends BaseSolver {
|
|
|
112
145
|
pins,
|
|
113
146
|
connectionPair,
|
|
114
147
|
chipMap: this.chipMap,
|
|
148
|
+
preferExteriorDetours: shouldPreferExteriorDetours({
|
|
149
|
+
connectionPair,
|
|
150
|
+
allConnectionPairs: this.mspConnectionPairs,
|
|
151
|
+
inputProblem: this.inputProblem,
|
|
152
|
+
}),
|
|
115
153
|
})
|
|
116
154
|
}
|
|
117
155
|
|
|
@@ -90,6 +90,7 @@ export class SchematicTraceSingleLineSolver2 extends BaseSolver {
|
|
|
90
90
|
aabb: { minX: number; maxX: number; minY: number; maxY: number }
|
|
91
91
|
|
|
92
92
|
baseElbow: Point[]
|
|
93
|
+
preferExteriorDetours: boolean
|
|
93
94
|
|
|
94
95
|
solvedTracePath: Point[] | null = null
|
|
95
96
|
|
|
@@ -102,12 +103,14 @@ export class SchematicTraceSingleLineSolver2 extends BaseSolver {
|
|
|
102
103
|
connectionPair?: MspConnectionPair
|
|
103
104
|
inputProblem: InputProblem
|
|
104
105
|
chipMap: Record<string, InputChip>
|
|
106
|
+
preferExteriorDetours?: boolean
|
|
105
107
|
}) {
|
|
106
108
|
super()
|
|
107
109
|
this.pins = params.pins
|
|
108
110
|
this.connectionPair = params.connectionPair
|
|
109
111
|
this.inputProblem = params.inputProblem
|
|
110
112
|
this.chipMap = params.chipMap
|
|
113
|
+
this.preferExteriorDetours = params.preferExteriorDetours ?? true
|
|
111
114
|
|
|
112
115
|
// Ensure facing directions are present
|
|
113
116
|
for (const pin of this.pins) {
|
|
@@ -190,6 +193,7 @@ export class SchematicTraceSingleLineSolver2 extends BaseSolver {
|
|
|
190
193
|
pins: this.pins,
|
|
191
194
|
connectionPair: this.connectionPair,
|
|
192
195
|
inputProblem: this.inputProblem,
|
|
196
|
+
preferExteriorDetours: this.preferExteriorDetours,
|
|
193
197
|
}
|
|
194
198
|
}
|
|
195
199
|
|
|
@@ -423,16 +427,8 @@ export class SchematicTraceSingleLineSolver2 extends BaseSolver {
|
|
|
423
427
|
if (canGenerateEndpointDetour && (isFirstSegment || isLastSegment)) {
|
|
424
428
|
// A three-point detour replaces an L elbow, so the shortest valid route
|
|
425
429
|
// remains the best choice. A four-point detour preserves the far side of
|
|
426
|
-
// a U elbow
|
|
427
|
-
//
|
|
428
|
-
const compareDetours =
|
|
429
|
-
path.length === 4
|
|
430
|
-
? (a: Point[], b: Point[]) =>
|
|
431
|
-
this.getPinBandPenalty(a) - this.getPinBandPenalty(b) ||
|
|
432
|
-
this.pathLength(a) - this.pathLength(b)
|
|
433
|
-
: (a: Point[], b: Point[]) =>
|
|
434
|
-
this.pathLength(a) - this.pathLength(b) ||
|
|
435
|
-
this.getPinBandPenalty(a) - this.getPinBandPenalty(b)
|
|
430
|
+
// a U elbow. Bundled or net-connected traces preserve the exterior route;
|
|
431
|
+
// isolated direct traces prefer the shorter route.
|
|
436
432
|
const detours = generateEndpointCollisionDetours({
|
|
437
433
|
path,
|
|
438
434
|
collidingSegmentIndex: segIndex,
|
|
@@ -444,7 +440,19 @@ export class SchematicTraceSingleLineSolver2 extends BaseSolver {
|
|
|
444
440
|
this.visited.add(key)
|
|
445
441
|
return true
|
|
446
442
|
})
|
|
447
|
-
.sort(
|
|
443
|
+
.sort((a, b) => {
|
|
444
|
+
if (path.length === 4 && this.preferExteriorDetours) {
|
|
445
|
+
return (
|
|
446
|
+
this.getPinBandPenalty(a) - this.getPinBandPenalty(b) ||
|
|
447
|
+
this.pathLength(a) - this.pathLength(b)
|
|
448
|
+
)
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
return (
|
|
452
|
+
this.pathLength(a) - this.pathLength(b) ||
|
|
453
|
+
this.getPinBandPenalty(a) - this.getPinBandPenalty(b)
|
|
454
|
+
)
|
|
455
|
+
})
|
|
448
456
|
|
|
449
457
|
for (const detour of detours) {
|
|
450
458
|
const nextCollisionRects = new Set(collisionRects)
|
package/package.json
CHANGED