@tscircuit/schematic-trace-solver 0.0.96 → 0.0.98
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 +9 -0
- package/dist/index.js +986 -479
- package/lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/SchematicTraceSingleLineSolver2.ts +55 -14
- package/lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/collisions.ts +31 -0
- package/lib/solvers/SchematicTracePipelineSolver/SchematicTracePipelineSolver.ts +45 -1
- package/lib/solvers/TraceCleanupSolver/TraceCleanupSolver.ts +55 -13
- package/lib/solvers/TraceCleanupSolver/alignSameNetRails.ts +66 -0
- package/lib/solvers/TraceCleanupSolver/sameNetRailAlignment/evaluateRailGroup.ts +124 -0
- package/lib/solvers/TraceCleanupSolver/sameNetRailAlignment/geometry.ts +108 -0
- package/lib/solvers/TraceCleanupSolver/sameNetRailAlignment/getComponentSideRailSegments.ts +121 -0
- package/lib/solvers/TraceCleanupSolver/sameNetRailAlignment/getRailGroups.ts +114 -0
- package/lib/solvers/TraceCleanupSolver/sameNetRailAlignment/moveRailSegments.ts +27 -0
- package/lib/solvers/TraceCleanupSolver/sameNetRailAlignment/preservesLabelAnchors.ts +30 -0
- package/lib/solvers/TraceCleanupSolver/sameNetRailAlignment/scoreRailAlignment.ts +67 -0
- package/lib/solvers/TraceCleanupSolver/sameNetRailAlignment/types.ts +34 -0
- package/lib/solvers/TraceLabelOverlapAvoidanceSolver/sub-solvers/SingleOverlapSolver/SingleOverlapSolver.ts +1 -60
- package/lib/utils/doesPathCoincideWithTraces.ts +61 -0
- package/package.json +1 -1
- package/tests/bug-reports/bug-report-20260706T220324Z/__snapshots__/bug-report-20260706T220324Z.snap.svg +1 -1
- package/tests/bug-reports/bug-report-20260707T141025Z/__snapshots__/bug-report-20260707T141025Z.snap.svg +1 -1
- package/tests/examples/__snapshots__/example02.snap.svg +1 -1
- package/tests/examples/__snapshots__/example14.snap.svg +1 -1
- package/tests/examples/__snapshots__/example18.snap.svg +1 -1
- package/tests/examples/__snapshots__/example46.snap.svg +1 -1
- package/tests/repros/__snapshots__/repro-cc2340r5.snap.svg +1 -1
- package/tests/repros/__snapshots__/repro-rp2040-gamepad-trace-alignment.snap.svg +178 -0
- package/tests/repros/__snapshots__/repro-rp2040-zero-crystal-fallback-netlabels.snap.svg +54 -0
- package/tests/repros/__snapshots__/repro130-bq27441-fuel-gauge-trace-through-c1.snap.svg +1 -1
- package/tests/repros/assets/repro-rp2040-gamepad-trace-alignment.input.json +237 -0
- package/tests/repros/assets/repro-rp2040-zero-crystal-fallback-netlabels.input.json +121 -0
- package/tests/repros/repro-rp2040-gamepad-trace-alignment.test.ts +38 -0
- package/tests/repros/repro-rp2040-zero-crystal-fallback-netlabels.test.ts +16 -0
- package/tests/solvers/SchematicTraceSingleLineSolver2/segment-intersects-rect-interior.test.ts +15 -0
- package/tests/solvers/SchematicTraceSingleLineSolver2/segment-overlaps-rect-boundary-boundary.test.ts +18 -0
- package/tests/solvers/SchematicTraceSingleLineSolver2/segment-overlaps-rect-boundary-interior.test.ts +18 -0
- package/tests/solvers/TraceCleanupSolver/alignSameNetRails-component-scope.test.ts +38 -0
- package/tests/solvers/TraceCleanupSolver/alignSameNetRails-eligible-traces.test.ts +28 -0
- package/tests/solvers/TraceCleanupSolver/alignSameNetRails-horizontal.test.ts +62 -0
- package/tests/solvers/TraceCleanupSolver/alignSameNetRails-label-anchor.test.ts +36 -0
- package/tests/solvers/TraceCleanupSolver/alignSameNetRails-label-junction.test.ts +42 -0
- package/tests/solvers/TraceCleanupSolver/alignSameNetRails-obstacle.test.ts +28 -0
- package/tests/solvers/TraceCleanupSolver/alignSameNetRails-pipeline-label-connector.test.ts +52 -0
- package/tests/solvers/TraceCleanupSolver/alignSameNetRails-vertical.test.ts +25 -0
- package/tests/solvers/TraceCleanupSolver/alignSameNetRails-visible-length.test.ts +40 -0
- package/tests/solvers/TraceCleanupSolver/fixtures/alignSameNetRails.ts +89 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { expect, test } from "bun:test"
|
|
2
|
+
import {
|
|
3
|
+
align,
|
|
4
|
+
getVerticalRailTraces,
|
|
5
|
+
verticalProblem,
|
|
6
|
+
} from "./fixtures/alignSameNetRails"
|
|
7
|
+
|
|
8
|
+
test("does not align through an obstacle", () => {
|
|
9
|
+
const traces = getVerticalRailTraces()
|
|
10
|
+
const result = align(traces, {
|
|
11
|
+
inputProblem: {
|
|
12
|
+
...verticalProblem,
|
|
13
|
+
chips: [
|
|
14
|
+
...verticalProblem.chips,
|
|
15
|
+
{
|
|
16
|
+
chipId: "barrier",
|
|
17
|
+
center: { x: -2.5, y: 0 },
|
|
18
|
+
width: 0.4,
|
|
19
|
+
height: 0.4,
|
|
20
|
+
pins: [],
|
|
21
|
+
},
|
|
22
|
+
],
|
|
23
|
+
},
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
expect(result.alignedRailGroupCount).toBe(0)
|
|
27
|
+
expect(result.traces).toEqual(traces)
|
|
28
|
+
})
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { expect, test } from "bun:test"
|
|
2
|
+
import { SchematicTracePipelineSolver } from "lib/solvers/SchematicTracePipelineSolver/SchematicTracePipelineSolver"
|
|
3
|
+
import type { InputProblem } from "lib/types/InputProblem"
|
|
4
|
+
|
|
5
|
+
test("pipeline does not stretch a real loop toward a generated label connector", () => {
|
|
6
|
+
const inputProblem: InputProblem = {
|
|
7
|
+
chips: [
|
|
8
|
+
{
|
|
9
|
+
chipId: "U3",
|
|
10
|
+
center: { x: 0, y: 0 },
|
|
11
|
+
width: 2.8,
|
|
12
|
+
height: 1.4,
|
|
13
|
+
pins: [
|
|
14
|
+
{ pinId: "U3.3", x: 1.4, y: -0.3 },
|
|
15
|
+
{ pinId: "U3.7", x: 1.4, y: -0.5 },
|
|
16
|
+
],
|
|
17
|
+
},
|
|
18
|
+
],
|
|
19
|
+
directConnections: [],
|
|
20
|
+
netConnections: [
|
|
21
|
+
{
|
|
22
|
+
netId: "V3_3",
|
|
23
|
+
pinIds: ["U3.3", "U3.7"],
|
|
24
|
+
netLabelWidth: 0.42,
|
|
25
|
+
netLabelHeight: 0.6,
|
|
26
|
+
},
|
|
27
|
+
],
|
|
28
|
+
textBoxes: [],
|
|
29
|
+
availableNetLabelOrientations: { V3_3: ["y+"] },
|
|
30
|
+
maxMspPairDistance: 2.4,
|
|
31
|
+
}
|
|
32
|
+
const solver = new SchematicTracePipelineSolver(inputProblem)
|
|
33
|
+
|
|
34
|
+
solver.solve()
|
|
35
|
+
|
|
36
|
+
const traces = solver.traceCleanupSolver2!.getOutput().traces
|
|
37
|
+
const realTrace = traces.find((trace) => trace.mspPairId === "U3.3-U3.7")!
|
|
38
|
+
const labelConnector = traces.find((trace) =>
|
|
39
|
+
trace.mspPairId.startsWith("available-net-orientation-"),
|
|
40
|
+
)!
|
|
41
|
+
expect(realTrace.tracePath).toEqual([
|
|
42
|
+
{ x: 1.4, y: -0.3 },
|
|
43
|
+
{ x: 1.5999999999999999, y: -0.3 },
|
|
44
|
+
{ x: 1.5999999999999999, y: -0.5 },
|
|
45
|
+
{ x: 1.4, y: -0.5 },
|
|
46
|
+
])
|
|
47
|
+
expect(labelConnector.mspPairId).toBe("available-net-orientation-0-V3_3")
|
|
48
|
+
expect(solver.traceCleanupSolver2!.stats).toMatchObject({
|
|
49
|
+
alignedRailGroupCount: 0,
|
|
50
|
+
alignedTraceCount: 0,
|
|
51
|
+
})
|
|
52
|
+
})
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { expect, test } from "bun:test"
|
|
2
|
+
import { align, getVerticalRailTraces } from "./fixtures/alignSameNetRails"
|
|
3
|
+
|
|
4
|
+
test("aligns same-net rails on one component side", () => {
|
|
5
|
+
const result = align(getVerticalRailTraces())
|
|
6
|
+
|
|
7
|
+
expect(result).toMatchObject({
|
|
8
|
+
alignedRailGroupCount: 1,
|
|
9
|
+
alignedTraceCount: 1,
|
|
10
|
+
})
|
|
11
|
+
expect(result.traces.map((trace) => trace.tracePath)).toEqual([
|
|
12
|
+
[
|
|
13
|
+
{ x: -1, y: 2 },
|
|
14
|
+
{ x: -2, y: 2 },
|
|
15
|
+
{ x: -2, y: 0 },
|
|
16
|
+
{ x: -1, y: 0 },
|
|
17
|
+
],
|
|
18
|
+
[
|
|
19
|
+
{ x: -1, y: 0 },
|
|
20
|
+
{ x: -2, y: 0 },
|
|
21
|
+
{ x: -2, y: -2 },
|
|
22
|
+
{ x: -1, y: -2 },
|
|
23
|
+
],
|
|
24
|
+
])
|
|
25
|
+
})
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { expect, test } from "bun:test"
|
|
2
|
+
import {
|
|
3
|
+
align,
|
|
4
|
+
createTrace,
|
|
5
|
+
getVerticalPin,
|
|
6
|
+
getVerticalRailTraces,
|
|
7
|
+
verticalProblem,
|
|
8
|
+
} from "./fixtures/alignSameNetRails"
|
|
9
|
+
|
|
10
|
+
test("keeps the baseline when alignment would only lengthen visible geometry", () => {
|
|
11
|
+
const traces = getVerticalRailTraces()
|
|
12
|
+
traces[1] = createTrace(
|
|
13
|
+
"lower",
|
|
14
|
+
[
|
|
15
|
+
{ x: -1, y: 0 },
|
|
16
|
+
{ x: -10, y: 0 },
|
|
17
|
+
{ x: -10, y: -2 },
|
|
18
|
+
{ x: -1, y: -2 },
|
|
19
|
+
],
|
|
20
|
+
[getVerticalPin("U1.2"), getVerticalPin("U1.3")],
|
|
21
|
+
)
|
|
22
|
+
const result = align(traces, {
|
|
23
|
+
inputProblem: {
|
|
24
|
+
...verticalProblem,
|
|
25
|
+
chips: [
|
|
26
|
+
...verticalProblem.chips,
|
|
27
|
+
{
|
|
28
|
+
chipId: "blocks-short-candidate",
|
|
29
|
+
center: { x: -2, y: -1 },
|
|
30
|
+
width: 0.2,
|
|
31
|
+
height: 0.4,
|
|
32
|
+
pins: [],
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
},
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
expect(result.alignedRailGroupCount).toBe(0)
|
|
39
|
+
expect(result.traces).toEqual(traces)
|
|
40
|
+
})
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import type { NetLabelPlacement } from "lib/solvers/NetLabelPlacementSolver/NetLabelPlacementSolver"
|
|
2
|
+
import type { SolvedTracePath } from "lib/solvers/SchematicTraceLinesSolver/SchematicTraceLinesSolver"
|
|
3
|
+
import { alignSameNetRails } from "lib/solvers/TraceCleanupSolver/alignSameNetRails"
|
|
4
|
+
import type { InputPin, InputProblem } from "lib/types/InputProblem"
|
|
5
|
+
|
|
6
|
+
export const verticalProblem: InputProblem = {
|
|
7
|
+
chips: [
|
|
8
|
+
{
|
|
9
|
+
chipId: "U1",
|
|
10
|
+
center: { x: 0, y: 0 },
|
|
11
|
+
width: 2,
|
|
12
|
+
height: 6,
|
|
13
|
+
pins: [
|
|
14
|
+
{ pinId: "U1.1", x: -1, y: 2, _facingDirection: "x-" },
|
|
15
|
+
{ pinId: "U1.2", x: -1, y: 0, _facingDirection: "x-" },
|
|
16
|
+
{ pinId: "U1.3", x: -1, y: -2, _facingDirection: "x-" },
|
|
17
|
+
],
|
|
18
|
+
},
|
|
19
|
+
],
|
|
20
|
+
directConnections: [],
|
|
21
|
+
netConnections: [],
|
|
22
|
+
textBoxes: [],
|
|
23
|
+
availableNetLabelOrientations: {},
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export const getVerticalPin = (
|
|
27
|
+
pinId: string,
|
|
28
|
+
): InputPin & { chipId: string } => {
|
|
29
|
+
const inputPin = verticalProblem.chips[0]!.pins.find(
|
|
30
|
+
(candidate) => candidate.pinId === pinId,
|
|
31
|
+
)!
|
|
32
|
+
return { ...inputPin, chipId: "U1" }
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export const createTrace = (
|
|
36
|
+
mspPairId: string,
|
|
37
|
+
tracePath: Array<{ x: number; y: number }>,
|
|
38
|
+
pins: SolvedTracePath["pins"],
|
|
39
|
+
globalConnNetId = "power-net",
|
|
40
|
+
): SolvedTracePath => ({
|
|
41
|
+
mspPairId,
|
|
42
|
+
globalConnNetId,
|
|
43
|
+
dcConnNetId: mspPairId,
|
|
44
|
+
userNetId: "POWER",
|
|
45
|
+
pins,
|
|
46
|
+
tracePath,
|
|
47
|
+
mspConnectionPairIds: [mspPairId],
|
|
48
|
+
pinIds: pins.map((item) => item.pinId),
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
export const getVerticalRailTraces = () => [
|
|
52
|
+
createTrace(
|
|
53
|
+
"upper",
|
|
54
|
+
[
|
|
55
|
+
{ x: -1, y: 2 },
|
|
56
|
+
{ x: -2, y: 2 },
|
|
57
|
+
{ x: -2, y: 0 },
|
|
58
|
+
{ x: -1, y: 0 },
|
|
59
|
+
],
|
|
60
|
+
[getVerticalPin("U1.1"), getVerticalPin("U1.2")],
|
|
61
|
+
),
|
|
62
|
+
createTrace(
|
|
63
|
+
"lower",
|
|
64
|
+
[
|
|
65
|
+
{ x: -1, y: 0 },
|
|
66
|
+
{ x: -3, y: 0 },
|
|
67
|
+
{ x: -3, y: -2 },
|
|
68
|
+
{ x: -1, y: -2 },
|
|
69
|
+
],
|
|
70
|
+
[getVerticalPin("U1.2"), getVerticalPin("U1.3")],
|
|
71
|
+
),
|
|
72
|
+
]
|
|
73
|
+
|
|
74
|
+
export const align = (
|
|
75
|
+
traces: SolvedTracePath[],
|
|
76
|
+
options: {
|
|
77
|
+
inputProblem?: InputProblem
|
|
78
|
+
netLabelPlacements?: NetLabelPlacement[]
|
|
79
|
+
eligibleTraceIds?: ReadonlySet<string>
|
|
80
|
+
} = {},
|
|
81
|
+
) =>
|
|
82
|
+
alignSameNetRails({
|
|
83
|
+
inputProblem: options.inputProblem ?? verticalProblem,
|
|
84
|
+
traces,
|
|
85
|
+
netLabelPlacements: options.netLabelPlacements ?? [],
|
|
86
|
+
eligibleTraceIds:
|
|
87
|
+
options.eligibleTraceIds ??
|
|
88
|
+
new Set(traces.map((trace) => trace.mspPairId)),
|
|
89
|
+
})
|