@tscircuit/schematic-trace-solver 0.0.202 → 0.0.203

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.
@@ -0,0 +1,43 @@
1
+ import { expect, test } from "bun:test"
2
+ import { SchematicTracePipelineSolver } from "lib/solvers/SchematicTracePipelineSolver/SchematicTracePipelineSolver"
3
+ import type { InputProblem } from "lib/types/InputProblem"
4
+ import { tracePathContainsPoint } from "lib/solvers/RailNetLabelCornerPlacementSolver/geometry"
5
+ import { findPerpendicularPathCrossings } from "lib/solvers/TraceCleanupSolver/sub-solver/findIntersectionsWithObstacles"
6
+ import "tests/fixtures/matcher"
7
+ import input from "./assets/repro-am3352-06-boot.input.json"
8
+
9
+ // Full sheet from am3352-dev-board-4layer-dogbone.json; routing uses core defaults.
10
+ test("repro complete AM3352 06-Boot sheet", async () => {
11
+ const problem = structuredClone(input) as InputProblem
12
+ const solver = new SchematicTracePipelineSolver(problem, {
13
+ hideRatsNet: true,
14
+ })
15
+ solver.solve()
16
+ expect(solver.solved).toBe(true)
17
+ expect(solver.failed).toBe(false)
18
+ const { traces, inlineNetLabelPlacements } =
19
+ solver.netLabelToTraceSolver!.getOutput()
20
+ for (const netId of ["BOOT_SEL1", "BOOT_SEL2", "BOOT_SEL3"]) {
21
+ const trace = traces.find((trace) => trace.userNetId === netId)!
22
+ expect(trace).toBeDefined()
23
+ expect(trace.tracePath).toHaveLength(4)
24
+ expect(trace.tracePath[1]!.y).toBe(trace.tracePath[0]!.y)
25
+ expect(trace.tracePath[2]!.y).toBe(trace.tracePath[3]!.y)
26
+ const label = inlineNetLabelPlacements.find(
27
+ (label) => label.globalConnNetId === trace.globalConnNetId,
28
+ )!
29
+ expect(label).toBeDefined()
30
+ expect(tracePathContainsPoint(trace.tracePath, label.anchorPoint)).toBe(
31
+ true,
32
+ )
33
+ for (const otherTrace of traces) {
34
+ if (otherTrace.globalConnNetId === trace.globalConnNetId) continue
35
+ expect(
36
+ findPerpendicularPathCrossings(trace.tracePath, otherTrace.tracePath, {
37
+ includeTerminalSegments: true,
38
+ }),
39
+ ).toEqual([])
40
+ }
41
+ }
42
+ await expect(solver).toMatchSolverSnapshot(import.meta.path)
43
+ })
@@ -158,3 +158,52 @@ test("allows crossings between generated label connectors", () => {
158
158
  expect(result.reroutedTraceCount).toBe(0)
159
159
  expect(result.traces).toEqual([connectorTrace, otherConnector])
160
160
  })
161
+
162
+ test.each([false, true])(
163
+ "removes the old loop when rerouting a connector crossing (reversed: %s)",
164
+ (reversed) => {
165
+ let tracePath = [
166
+ { x: 0, y: 0 },
167
+ { x: 1, y: 0 },
168
+ { x: 1, y: 3 },
169
+ { x: 4, y: 3 },
170
+ { x: 4, y: -3 },
171
+ { x: 0, y: -3 },
172
+ ]
173
+ if (reversed) tracePath = tracePath.toReversed()
174
+ const trace = makeTrace({
175
+ mspPairId: "loop",
176
+ globalConnNetId: "signal",
177
+ pinIds: ["a", "b"],
178
+ tracePath,
179
+ })
180
+ const connector = makeTrace({
181
+ mspPairId: "connector",
182
+ globalConnNetId: "power",
183
+ pinIds: ["c"],
184
+ tracePath: [
185
+ { x: 0, y: 1 },
186
+ { x: 2, y: 1 },
187
+ ],
188
+ })
189
+ const result = rerouteGeneratedNetLabelConnectorCrossings({
190
+ inputProblem,
191
+ traces: [trace, connector],
192
+ netLabelPlacements: [],
193
+ mergedLabelNetIdMap: {},
194
+ clearance: 0.1,
195
+ connectorTraceIds: new Set([connector.mspPairId]),
196
+ })
197
+ const path = result.traces[0]!.tracePath
198
+ expect(result.reroutedTraceCount).toBe(1)
199
+ expect(path).toHaveLength(4)
200
+ expect(path[0]).toEqual(tracePath[0])
201
+ expect(path.at(-1)).toEqual(tracePath.at(-1))
202
+ expect(getPathLength(path)).toBeLessThan(getPathLength(tracePath))
203
+ expect(
204
+ findPerpendicularPathCrossings(path, connector.tracePath, {
205
+ includeTerminalSegments: true,
206
+ }),
207
+ ).toEqual([])
208
+ },
209
+ )