@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 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(compareDetours);
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; prefer the candidate that keeps its new internal rails out
427
- // of the pin band, then use length to choose between equivalent routes.
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(compareDetours)
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
@@ -5,7 +5,7 @@
5
5
  "url": "https://github.com/tscircuit/schematic-trace-solver.git"
6
6
  },
7
7
  "main": "dist/index.js",
8
- "version": "0.0.155",
8
+ "version": "0.0.156",
9
9
  "type": "module",
10
10
  "scripts": {
11
11
  "start": "cosmos",
@@ -0,0 +1,4 @@
1
+ import { PipelineDebugger } from "site/components/PipelineDebugger"
2
+ import inputProblem from "../../tests/bug-reports/bug-report-20260825T045913Z/bug-report-20260825T045913Z.json"
3
+
4
+ export default () => <PipelineDebugger inputProblem={inputProblem as any} />