@tscircuit/schematic-trace-solver 0.0.183 → 0.0.185
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 +242 -24
- package/lib/solvers/SameNetJunctionAlignmentSolver/alignSameNetJunctions.ts +30 -12
- package/lib/solvers/SameNetJunctionAlignmentSolver/collapseRedundantSharedEndpointStubs.ts +267 -0
- package/lib/solvers/SameNetJunctionAlignmentSolver/collapseSameNetCycles.ts +1 -1
- package/lib/solvers/SameNetJunctionAlignmentSolver/getSharedPin.ts +13 -0
- package/lib/solvers/UnroutedTraceRecoverySolver/UnroutedTraceRecoverySolver.ts +12 -4
- package/package.json +1 -1
- package/site/bug-reports/bug-report-20260905T041712Z.page.tsx +4 -0
- package/tests/bug-reports/bug-report-20260706T213649Z/__snapshots__/bug-report-20260706T213649Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260706T220324Z/__snapshots__/bug-report-20260706T220324Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260707T020342Z/__snapshots__/bug-report-20260707T020342Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260707T020342Z/bug-report-20260707T020342Z.test.ts +10 -0
- package/tests/bug-reports/bug-report-20260707T092615Z/__snapshots__/bug-report-20260707T092615Z.snap.svg +524 -533
- package/tests/bug-reports/bug-report-20260707T134549Z/__snapshots__/bug-report-20260707T134549Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260707T140410Z/__snapshots__/bug-report-20260707T140410Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260707T141025Z/__snapshots__/bug-report-20260707T141025Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260707T141421Z/__snapshots__/bug-report-20260707T141421Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260707T230831Z/__snapshots__/bug-report-20260707T230831Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260708T095725Z/__snapshots__/bug-report-20260708T095725Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260716T144856Z/__snapshots__/bug-report-20260716T144856Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260717T022934Z/__snapshots__/bug-report-20260717T022934Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260717T042845Z/__snapshots__/bug-report-20260717T042845Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260721T221026Z/__snapshots__/bug-report-20260721T221026Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260724T175257Z/__snapshots__/bug-report-20260724T175257Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260728T144234Z/__snapshots__/bug-report-20260728T144234Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260728T144234Z/bug-report-20260728T144234Z.test.ts +2 -0
- package/tests/bug-reports/bug-report-20260730T061837Z/__snapshots__/bug-report-20260730T061837Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260730T061837Z/bug-report-20260730T061837Z.test.ts +1 -1
- package/tests/bug-reports/bug-report-20260731T052229Z/__snapshots__/bug-report-20260731T052229Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260804T171919Z/__snapshots__/bug-report-20260804T171919Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260804T225912Z/__snapshots__/bug-report-20260804T225912Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260805T061316Z/__snapshots__/bug-report-20260805T061316Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260806T061548Z/__snapshots__/bug-report-20260806T061548Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260815T073240Z/__snapshots__/bug-report-20260815T073240Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260819T091818Z/__snapshots__/bug-report-20260819T091818Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260825T045913Z/__snapshots__/bug-report-20260825T045913Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260825T103621Z/__snapshots__/bug-report-20260825T103621Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260826T072956Z/__snapshots__/bug-report-20260826T072956Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260901T055358Z/__snapshots__/bug-report-20260901T055358Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260901T064117Z/__snapshots__/bug-report-20260901T064117Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260901T134241Z/__snapshots__/bug-report-20260901T134241Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260902T092425Z/__snapshots__/bug-report-20260902T092425Z.snap.svg +2 -2
- package/tests/bug-reports/bug-report-20260905T041712Z/__snapshots__/bug-report-20260905T041712Z.snap.svg +546 -0
- package/tests/bug-reports/bug-report-20260905T041712Z/bug-report-20260905T041712Z.json +2023 -0
- package/tests/bug-reports/bug-report-20260905T041712Z/bug-report-20260905T041712Z.test.ts +33 -0
- package/tests/examples/__snapshots__/example02.snap.svg +2 -2
- package/tests/examples/__snapshots__/example13.snap.svg +2 -2
- package/tests/examples/__snapshots__/example14.snap.svg +2 -2
- package/tests/examples/__snapshots__/example15.snap.svg +2 -2
- package/tests/examples/__snapshots__/example18.snap.svg +2 -2
- package/tests/examples/__snapshots__/example19.snap.svg +2 -2
- package/tests/examples/__snapshots__/example21.snap.svg +2 -2
- package/tests/examples/__snapshots__/example27.snap.svg +2 -2
- package/tests/examples/__snapshots__/example29.snap.svg +2 -2
- package/tests/examples/__snapshots__/example42.snap.svg +2 -2
- package/tests/examples/__snapshots__/example45.snap.svg +2 -2
- package/tests/examples/__snapshots__/example46.snap.svg +2 -2
- package/tests/examples/__snapshots__/example47.snap.svg +2 -2
- package/tests/examples/__snapshots__/example51.snap.svg +2 -2
- package/tests/repros/__snapshots__/board-1273-trace-overlap-cycle.snap.svg +2 -2
- package/tests/repros/__snapshots__/board-15984-same-net-junction.snap.svg +2 -2
- package/tests/repros/__snapshots__/board1096-usb-label-overlap-iteration.snap.svg +2 -2
- package/tests/repros/__snapshots__/bugreport-001-gnd-overlap.snap.svg +2 -2
- package/tests/repros/__snapshots__/netlabel-connector-through-rail-label.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-battery-management-bq24073.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-bc107a-common-emitter-routing.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-bluetooth-controller-ground-decoupling-groups.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-board-589-regulator-section.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-board-648-esp12f-section.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-board-8090-power-section.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-bq24074-battery-charger.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-bq25895-cross-net-trace-overlap.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-bq40z60-current-sense.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-cc2340r5.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-core-ground-inline-label-fallback.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-esp12f-section.snap.svg +508 -0
- package/tests/repros/__snapshots__/repro-example35-minimize-trace-crossing.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-hdc2080-ground-label-alignment.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-hdc3020-ground-label-alignment.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-hub-usb-sheet.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-ina237-current-monitor.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-isolated-rs485-isow7841.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-mspm0l1306-capacitor-symmetry.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-pga300-c6-trace-alignment.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-pga300-redundant-ground-traces.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-pmp11282-isolated-dcdc.snap.svg +18 -18
- package/tests/repros/__snapshots__/repro-power-group-rail-labels.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-powerbank-3v-system-power.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-rectifier-trace-overlap.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-rp2040-gamepad-trace-alignment.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-rp2040-usb-cc2-ground-overlap.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-smartwatch-power-sheet.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-ti-power-output-section.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-tida-01389-hbridge.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-tida00553-j4-cell-divider.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-tida010076-j4-ground-bus.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-tida010076-page02.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-tmp1075-ground-label-overlap.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-tps61222-trace-intersection.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-trellis-core-gnd-net-label-overlap.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-type-c-vbus-led-ground-label.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro-usb-power-vbus-label-detour.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro130-bq27441-fuel-gauge-trace-through-c1.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro161-power-section-autolayout.snap.svg +2 -2
- package/tests/repros/__snapshots__/repro48-555-timer-vcc-rail-label.snap.svg +2 -2
- package/tests/repros/assets/repro-esp12f-status-section.input.json +1394 -0
- package/tests/repros/repro-esp12f-section.test.ts +12 -0
- package/tests/solvers/SameNetJunctionAlignmentSolver/collapse-redundant-shared-endpoint-stubs.test.ts +101 -0
- package/tests/solvers/UnroutedTraceRecoverySolver/local-elbow-obstacles.test.ts +74 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { expect, test } from "bun:test"
|
|
2
|
+
import { SchematicTracePipelineSolver } from "lib/solvers/SchematicTracePipelineSolver/SchematicTracePipelineSolver"
|
|
3
|
+
import inputProblem from "./assets/repro-esp12f-status-section.input.json"
|
|
4
|
+
import "tests/fixtures/matcher"
|
|
5
|
+
|
|
6
|
+
test("reproduces ESP-12F schematic section routing", () => {
|
|
7
|
+
const solver = new SchematicTracePipelineSolver(inputProblem as any)
|
|
8
|
+
|
|
9
|
+
solver.solve()
|
|
10
|
+
|
|
11
|
+
expect(solver).toMatchSolverSnapshot(import.meta.path)
|
|
12
|
+
})
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { expect, test } from "bun:test"
|
|
2
|
+
import type { Point } from "@tscircuit/math-utils"
|
|
3
|
+
import type { MspConnectionPairId } from "lib/solvers/MspConnectionPairSolver/MspConnectionPairSolver"
|
|
4
|
+
import { collapseRedundantSharedEndpointStubs } from "lib/solvers/SameNetJunctionAlignmentSolver/collapseRedundantSharedEndpointStubs"
|
|
5
|
+
import type { SolvedTracePath } from "lib/solvers/SchematicTraceLinesSolver/SchematicTraceLinesSolver"
|
|
6
|
+
import type { PinId } from "lib/types/InputProblem"
|
|
7
|
+
|
|
8
|
+
const createTrace = ({
|
|
9
|
+
mspPairId,
|
|
10
|
+
pinIds,
|
|
11
|
+
tracePath,
|
|
12
|
+
}: {
|
|
13
|
+
mspPairId: MspConnectionPairId
|
|
14
|
+
pinIds: [PinId, PinId]
|
|
15
|
+
tracePath: Point[]
|
|
16
|
+
}): SolvedTracePath => ({
|
|
17
|
+
mspPairId,
|
|
18
|
+
dcConnNetId: "gnd",
|
|
19
|
+
globalConnNetId: "gnd",
|
|
20
|
+
pins: [
|
|
21
|
+
{ pinId: pinIds[0], chipId: "first-chip", ...tracePath[0]! },
|
|
22
|
+
{ pinId: pinIds[1], chipId: "second-chip", ...tracePath.at(-1)! },
|
|
23
|
+
],
|
|
24
|
+
tracePath,
|
|
25
|
+
mspConnectionPairIds: [mspPairId],
|
|
26
|
+
pinIds,
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
test("collapses one duplicate stub at a shared same-net endpoint", () => {
|
|
30
|
+
const traces = [
|
|
31
|
+
createTrace({
|
|
32
|
+
mspPairId: "upper-shared",
|
|
33
|
+
pinIds: ["upper", "shared"],
|
|
34
|
+
tracePath: [
|
|
35
|
+
{ x: 0, y: 0 },
|
|
36
|
+
{ x: 2, y: 0 },
|
|
37
|
+
{ x: 2, y: 2 },
|
|
38
|
+
{ x: 1, y: 2 },
|
|
39
|
+
],
|
|
40
|
+
}),
|
|
41
|
+
createTrace({
|
|
42
|
+
mspPairId: "lower-shared",
|
|
43
|
+
pinIds: ["lower", "shared"],
|
|
44
|
+
tracePath: [
|
|
45
|
+
{ x: 0, y: 5 },
|
|
46
|
+
{ x: 0, y: 4 },
|
|
47
|
+
{ x: 2, y: 4 },
|
|
48
|
+
{ x: 2, y: 2 },
|
|
49
|
+
{ x: 1, y: 2 },
|
|
50
|
+
],
|
|
51
|
+
}),
|
|
52
|
+
]
|
|
53
|
+
|
|
54
|
+
const result = collapseRedundantSharedEndpointStubs({
|
|
55
|
+
traces,
|
|
56
|
+
netLabelPlacements: [],
|
|
57
|
+
netLabelConnectorTraceIds: new Set<MspConnectionPairId>(),
|
|
58
|
+
multiPinNetPinIds: new Set(["shared"]),
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
expect(result.map((trace) => trace.tracePath.length)).toEqual([4, 4])
|
|
62
|
+
expect(result[1]?.tracePath.at(-1)).toEqual({ x: 2, y: 2 })
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
test("collapses a shared stub and partial rail overlap", () => {
|
|
66
|
+
const traces = [
|
|
67
|
+
createTrace({
|
|
68
|
+
mspPairId: "shared-trunk",
|
|
69
|
+
pinIds: ["shared", "trunk"],
|
|
70
|
+
tracePath: [
|
|
71
|
+
{ x: 0, y: 0 },
|
|
72
|
+
{ x: 0, y: -1 },
|
|
73
|
+
{ x: -4, y: -1 },
|
|
74
|
+
{ x: -4, y: 0 },
|
|
75
|
+
],
|
|
76
|
+
}),
|
|
77
|
+
createTrace({
|
|
78
|
+
mspPairId: "feed-shared",
|
|
79
|
+
pinIds: ["feed", "shared"],
|
|
80
|
+
tracePath: [
|
|
81
|
+
{ x: -1, y: 3 },
|
|
82
|
+
{ x: -1, y: -1 },
|
|
83
|
+
{ x: 0, y: -1 },
|
|
84
|
+
{ x: 0, y: 0 },
|
|
85
|
+
],
|
|
86
|
+
}),
|
|
87
|
+
]
|
|
88
|
+
|
|
89
|
+
const result = collapseRedundantSharedEndpointStubs({
|
|
90
|
+
traces,
|
|
91
|
+
netLabelPlacements: [],
|
|
92
|
+
netLabelConnectorTraceIds: new Set<MspConnectionPairId>(),
|
|
93
|
+
multiPinNetPinIds: new Set(["shared"]),
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
expect(result[0]?.tracePath).toEqual(traces[0]?.tracePath)
|
|
97
|
+
expect(result[1]?.tracePath).toEqual([
|
|
98
|
+
{ x: -1, y: 3 },
|
|
99
|
+
{ x: -1, y: -1 },
|
|
100
|
+
])
|
|
101
|
+
})
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { expect, test } from "bun:test"
|
|
2
|
+
import {
|
|
3
|
+
countPathIntersections,
|
|
4
|
+
getPathLength,
|
|
5
|
+
} from "lib/solvers/Example28Solver/geometry"
|
|
6
|
+
import { SchematicTracePipelineSolver } from "lib/solvers/SchematicTracePipelineSolver/SchematicTracePipelineSolver"
|
|
7
|
+
import { findFirstCollision } from "lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/collisions"
|
|
8
|
+
import { UnroutedTraceRecoverySolver } from "lib/solvers/UnroutedTraceRecoverySolver/UnroutedTraceRecoverySolver"
|
|
9
|
+
import type { InputProblem } from "lib/types/InputProblem"
|
|
10
|
+
import inputProblem from "tests/bug-reports/bug-report-20260905T041712Z/bug-report-20260905T041712Z.json"
|
|
11
|
+
|
|
12
|
+
test.each(["chip", "text", "trace"] as const)(
|
|
13
|
+
"rejects a local recovery elbow blocked by a %s",
|
|
14
|
+
(obstacleKind) => {
|
|
15
|
+
const pipeline = new SchematicTracePipelineSolver(
|
|
16
|
+
structuredClone(inputProblem) as InputProblem,
|
|
17
|
+
)
|
|
18
|
+
pipeline.solveUntilPhase("unroutedTraceRecoverySolver")
|
|
19
|
+
|
|
20
|
+
const connectionPair =
|
|
21
|
+
pipeline.schematicTraceLinesSolver!.failedConnectionPairs.find(
|
|
22
|
+
(pair) => pair.mspPairId === "schematic_port_101-schematic_port_125",
|
|
23
|
+
)!
|
|
24
|
+
const problem = pipeline.inputProblem
|
|
25
|
+
const existingTraces = [
|
|
26
|
+
...pipeline.longDistancePairSolver!.getOutput().allTracesMerged,
|
|
27
|
+
]
|
|
28
|
+
const blockingBounds = { minX: 3.6, maxX: 3.7, minY: -8.96, maxY: -8.94 }
|
|
29
|
+
const blockingPath = [
|
|
30
|
+
{ x: 3.6, y: -8.95 },
|
|
31
|
+
{ x: 3.7, y: -8.95 },
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
if (obstacleKind === "chip") {
|
|
35
|
+
problem.chips.push({
|
|
36
|
+
chipId: "blocking-chip",
|
|
37
|
+
center: { x: 3.65, y: -8.95 },
|
|
38
|
+
width: 0.1,
|
|
39
|
+
height: 0.02,
|
|
40
|
+
pins: [],
|
|
41
|
+
})
|
|
42
|
+
}
|
|
43
|
+
if (obstacleKind === "text") {
|
|
44
|
+
problem.textBoxes!.push({
|
|
45
|
+
center: { x: 3.65, y: -8.95 },
|
|
46
|
+
width: 0.1,
|
|
47
|
+
height: 0.02,
|
|
48
|
+
})
|
|
49
|
+
}
|
|
50
|
+
if (obstacleKind === "trace") {
|
|
51
|
+
const otherNetTrace = existingTraces.find(
|
|
52
|
+
(trace) => trace.globalConnNetId !== connectionPair.globalConnNetId,
|
|
53
|
+
)!
|
|
54
|
+
existingTraces.splice(existingTraces.indexOf(otherNetTrace), 1, {
|
|
55
|
+
...otherNetTrace,
|
|
56
|
+
tracePath: blockingPath,
|
|
57
|
+
})
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const recovery = new UnroutedTraceRecoverySolver({
|
|
61
|
+
inputProblem: problem,
|
|
62
|
+
failedConnectionPairs: [connectionPair],
|
|
63
|
+
alreadySolvedTraces: existingTraces,
|
|
64
|
+
})
|
|
65
|
+
recovery.solve()
|
|
66
|
+
|
|
67
|
+
expect(recovery.solved).toBe(true)
|
|
68
|
+
expect(recovery.solvedUnroutedTraces).toHaveLength(1)
|
|
69
|
+
const recoveredPath = recovery.solvedUnroutedTraces[0]!.tracePath
|
|
70
|
+
expect(getPathLength(recoveredPath)).toBeGreaterThan(0.8)
|
|
71
|
+
expect(findFirstCollision(recoveredPath, [blockingBounds])).toBeNull()
|
|
72
|
+
expect(countPathIntersections(recoveredPath, blockingPath)).toBe(0)
|
|
73
|
+
},
|
|
74
|
+
)
|