@tscircuit/schematic-trace-solver 0.0.97 → 0.0.99
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 +10 -0
- package/dist/index.js +1077 -519
- package/lib/solvers/MspConnectionPairSolver/MspConnectionPairSolver.ts +19 -9
- package/lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/SchematicTraceSingleLineSolver2.ts +30 -0
- package/lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/generateEndpointCollisionDetours.ts +84 -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 +18 -18
- package/tests/bug-reports/bug-report-20260707T092615Z/__snapshots__/bug-report-20260707T092615Z.snap.svg +7 -7
- package/tests/bug-reports/bug-report-20260707T134549Z/__snapshots__/bug-report-20260707T134549Z.snap.svg +5 -7
- package/tests/bug-reports/bug-report-20260707T140410Z/__snapshots__/bug-report-20260707T140410Z.snap.svg +6 -12
- 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__/example09.snap.svg +9 -13
- package/tests/examples/__snapshots__/example14.snap.svg +1 -1
- package/tests/examples/__snapshots__/example18.snap.svg +1 -1
- package/tests/examples/__snapshots__/example21.snap.svg +30 -32
- package/tests/examples/__snapshots__/example29.snap.svg +13 -19
- 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 +1 -1
- package/tests/repros/__snapshots__/repro129-host-custom-symbol-passives.snap.svg +60 -0
- package/tests/repros/__snapshots__/repro130-bq27441-fuel-gauge-trace-through-c1.snap.svg +1 -1
- package/tests/repros/assets/repro129-host-custom-symbol-passives.input.json +94 -0
- package/tests/repros/repro-rp2040-gamepad-trace-alignment.test.ts +24 -0
- package/tests/repros/repro129-host-custom-symbol-passives.test.ts +16 -0
- package/tests/solvers/MspConnectionPairSolver/msp-connection-pair-solver-direct-connection-distance.test.ts +46 -0
- package/tests/solvers/SchematicTraceSingleLineSolver2/generate-endpoint-collision-detours.test.ts +38 -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
package/tests/solvers/SchematicTraceSingleLineSolver2/generate-endpoint-collision-detours.test.ts
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { expect, test } from "bun:test"
|
|
2
|
+
import { generateEndpointCollisionDetours } from "lib/solvers/SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/generateEndpointCollisionDetours"
|
|
3
|
+
|
|
4
|
+
test("endpoint collision detours preserve both endpoint anchors", () => {
|
|
5
|
+
const path = [
|
|
6
|
+
{ x: 0, y: 1 },
|
|
7
|
+
{ x: 2, y: 1 },
|
|
8
|
+
{ x: 2, y: -1 },
|
|
9
|
+
]
|
|
10
|
+
|
|
11
|
+
const obstacle = {
|
|
12
|
+
minX: 1,
|
|
13
|
+
maxX: 3,
|
|
14
|
+
minY: 0,
|
|
15
|
+
maxY: 2,
|
|
16
|
+
kind: "chip" as const,
|
|
17
|
+
chipId: "U1",
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const detours = [0, 1].flatMap((collidingSegmentIndex) =>
|
|
21
|
+
generateEndpointCollisionDetours({
|
|
22
|
+
path,
|
|
23
|
+
collidingSegmentIndex,
|
|
24
|
+
obstacle,
|
|
25
|
+
}),
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
expect(detours.length).toBeGreaterThan(0)
|
|
29
|
+
expect(
|
|
30
|
+
detours.every(
|
|
31
|
+
(detour) =>
|
|
32
|
+
detour[0]?.x === path[0]?.x &&
|
|
33
|
+
detour[0]?.y === path[0]?.y &&
|
|
34
|
+
detour.at(-1)?.x === path.at(-1)?.x &&
|
|
35
|
+
detour.at(-1)?.y === path.at(-1)?.y,
|
|
36
|
+
),
|
|
37
|
+
).toBe(true)
|
|
38
|
+
})
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { expect, test } from "bun:test"
|
|
2
|
+
import type { SolvedTracePath } from "lib/solvers/SchematicTraceLinesSolver/SchematicTraceLinesSolver"
|
|
3
|
+
import type { InputProblem } from "lib/types/InputProblem"
|
|
4
|
+
import {
|
|
5
|
+
align,
|
|
6
|
+
getVerticalRailTraces,
|
|
7
|
+
verticalProblem,
|
|
8
|
+
} from "./fixtures/alignSameNetRails"
|
|
9
|
+
|
|
10
|
+
test("does not combine rails from different component sides", () => {
|
|
11
|
+
const traces = getVerticalRailTraces()
|
|
12
|
+
traces[1] = {
|
|
13
|
+
...traces[1]!,
|
|
14
|
+
pins: traces[1]!.pins.map((item) => ({ ...item, chipId: "U2" })) as [
|
|
15
|
+
SolvedTracePath["pins"][0],
|
|
16
|
+
SolvedTracePath["pins"][1],
|
|
17
|
+
],
|
|
18
|
+
}
|
|
19
|
+
const inputProblem: InputProblem = {
|
|
20
|
+
...verticalProblem,
|
|
21
|
+
chips: [
|
|
22
|
+
...verticalProblem.chips,
|
|
23
|
+
{
|
|
24
|
+
...verticalProblem.chips[0]!,
|
|
25
|
+
chipId: "U2",
|
|
26
|
+
pins: verticalProblem.chips[0]!.pins.map((item) => ({
|
|
27
|
+
...item,
|
|
28
|
+
pinId: item.pinId.replace("U1", "U2"),
|
|
29
|
+
})),
|
|
30
|
+
},
|
|
31
|
+
],
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const result = align(traces, { inputProblem })
|
|
35
|
+
|
|
36
|
+
expect(result.alignedRailGroupCount).toBe(0)
|
|
37
|
+
expect(result.traces).toEqual(traces)
|
|
38
|
+
})
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { expect, test } from "bun:test"
|
|
2
|
+
import {
|
|
3
|
+
align,
|
|
4
|
+
createTrace,
|
|
5
|
+
getVerticalPin,
|
|
6
|
+
getVerticalRailTraces,
|
|
7
|
+
} from "./fixtures/alignSameNetRails"
|
|
8
|
+
|
|
9
|
+
test("uses routed-trace provenance to exclude generated label connectors", () => {
|
|
10
|
+
const realTrace = getVerticalRailTraces()[0]!
|
|
11
|
+
const connector = createTrace(
|
|
12
|
+
"label-connector",
|
|
13
|
+
[
|
|
14
|
+
{ x: -1, y: 0 },
|
|
15
|
+
{ x: -5, y: 0 },
|
|
16
|
+
{ x: -5, y: -2 },
|
|
17
|
+
{ x: -1, y: -2 },
|
|
18
|
+
],
|
|
19
|
+
[getVerticalPin("U1.2"), getVerticalPin("U1.3")],
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
const result = align([realTrace, connector], {
|
|
23
|
+
eligibleTraceIds: new Set([realTrace.mspPairId]),
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
expect(result.alignedRailGroupCount).toBe(0)
|
|
27
|
+
expect(result.traces).toEqual([realTrace, connector])
|
|
28
|
+
})
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { expect, test } from "bun:test"
|
|
2
|
+
import type { InputProblem } from "lib/types/InputProblem"
|
|
3
|
+
import {
|
|
4
|
+
align,
|
|
5
|
+
createTrace,
|
|
6
|
+
verticalProblem,
|
|
7
|
+
} from "./fixtures/alignSameNetRails"
|
|
8
|
+
|
|
9
|
+
test("applies the same component-side rule to horizontal rails", () => {
|
|
10
|
+
const inputProblem: InputProblem = {
|
|
11
|
+
...verticalProblem,
|
|
12
|
+
chips: [
|
|
13
|
+
{
|
|
14
|
+
chipId: "U2",
|
|
15
|
+
center: { x: 0, y: 0 },
|
|
16
|
+
width: 6,
|
|
17
|
+
height: 2,
|
|
18
|
+
pins: [
|
|
19
|
+
{ pinId: "U2.1", x: -2, y: 1, _facingDirection: "y+" },
|
|
20
|
+
{ pinId: "U2.2", x: 0, y: 1, _facingDirection: "y+" },
|
|
21
|
+
{ pinId: "U2.3", x: 2, y: 1, _facingDirection: "y+" },
|
|
22
|
+
],
|
|
23
|
+
},
|
|
24
|
+
],
|
|
25
|
+
}
|
|
26
|
+
const inputPins = inputProblem.chips[0]!.pins.map((inputPin) => ({
|
|
27
|
+
...inputPin,
|
|
28
|
+
chipId: "U2",
|
|
29
|
+
}))
|
|
30
|
+
const traces = [
|
|
31
|
+
createTrace(
|
|
32
|
+
"left",
|
|
33
|
+
[
|
|
34
|
+
{ x: -2, y: 1 },
|
|
35
|
+
{ x: -2, y: 2 },
|
|
36
|
+
{ x: 0, y: 2 },
|
|
37
|
+
{ x: 0, y: 1 },
|
|
38
|
+
],
|
|
39
|
+
[inputPins[0]!, inputPins[1]!],
|
|
40
|
+
),
|
|
41
|
+
createTrace(
|
|
42
|
+
"right",
|
|
43
|
+
[
|
|
44
|
+
{ x: 0, y: 1 },
|
|
45
|
+
{ x: 0, y: 3 },
|
|
46
|
+
{ x: 2, y: 3 },
|
|
47
|
+
{ x: 2, y: 1 },
|
|
48
|
+
],
|
|
49
|
+
[inputPins[1]!, inputPins[2]!],
|
|
50
|
+
),
|
|
51
|
+
]
|
|
52
|
+
|
|
53
|
+
const result = align(traces, { inputProblem })
|
|
54
|
+
|
|
55
|
+
expect(result.alignedRailGroupCount).toBe(1)
|
|
56
|
+
expect(result.traces[1]!.tracePath).toEqual([
|
|
57
|
+
{ x: 0, y: 1 },
|
|
58
|
+
{ x: 0, y: 2 },
|
|
59
|
+
{ x: 2, y: 2 },
|
|
60
|
+
{ x: 2, y: 1 },
|
|
61
|
+
])
|
|
62
|
+
})
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { expect, test } from "bun:test"
|
|
2
|
+
import type { NetLabelPlacement } from "lib/solvers/NetLabelPlacementSolver/NetLabelPlacementSolver"
|
|
3
|
+
import { align, getVerticalRailTraces } from "./fixtures/alignSameNetRails"
|
|
4
|
+
|
|
5
|
+
test("preserves existing label anchors", () => {
|
|
6
|
+
const traces = getVerticalRailTraces()
|
|
7
|
+
const labels: NetLabelPlacement[] = [
|
|
8
|
+
{
|
|
9
|
+
globalConnNetId: "power-net",
|
|
10
|
+
netId: "POWER",
|
|
11
|
+
mspConnectionPairIds: ["upper"],
|
|
12
|
+
pinIds: ["U1.1", "U1.2"],
|
|
13
|
+
orientation: "x+",
|
|
14
|
+
anchorPoint: { x: -2, y: 1 },
|
|
15
|
+
center: { x: -1.8, y: 1 },
|
|
16
|
+
width: 0.4,
|
|
17
|
+
height: 0.2,
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
globalConnNetId: "power-net",
|
|
21
|
+
netId: "POWER",
|
|
22
|
+
mspConnectionPairIds: ["lower"],
|
|
23
|
+
pinIds: ["U1.2", "U1.3"],
|
|
24
|
+
orientation: "x+",
|
|
25
|
+
anchorPoint: { x: -3, y: -1 },
|
|
26
|
+
center: { x: -2.8, y: -1 },
|
|
27
|
+
width: 0.4,
|
|
28
|
+
height: 0.2,
|
|
29
|
+
},
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
const result = align(traces, { netLabelPlacements: labels })
|
|
33
|
+
|
|
34
|
+
expect(result.alignedRailGroupCount).toBe(0)
|
|
35
|
+
expect(result.traces).toEqual(traces)
|
|
36
|
+
})
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { expect, test } from "bun:test"
|
|
2
|
+
import type { NetLabelPlacement } from "lib/solvers/NetLabelPlacementSolver/NetLabelPlacementSolver"
|
|
3
|
+
import {
|
|
4
|
+
align,
|
|
5
|
+
createTrace,
|
|
6
|
+
getVerticalRailTraces,
|
|
7
|
+
} from "./fixtures/alignSameNetRails"
|
|
8
|
+
|
|
9
|
+
test("preserves every trace joined at a net-label anchor", () => {
|
|
10
|
+
const rails = getVerticalRailTraces()
|
|
11
|
+
const anchorKeeper = createTrace(
|
|
12
|
+
"anchor-keeper",
|
|
13
|
+
[
|
|
14
|
+
{ x: -3, y: -1 },
|
|
15
|
+
{ x: -4, y: -1 },
|
|
16
|
+
],
|
|
17
|
+
[
|
|
18
|
+
{ pinId: "X1.1", chipId: "X1", x: -3, y: -1 },
|
|
19
|
+
{ pinId: "X2.1", chipId: "X2", x: -4, y: -1 },
|
|
20
|
+
],
|
|
21
|
+
)
|
|
22
|
+
const traces = [...rails, anchorKeeper]
|
|
23
|
+
const label: NetLabelPlacement = {
|
|
24
|
+
globalConnNetId: "power-net",
|
|
25
|
+
netId: "POWER",
|
|
26
|
+
mspConnectionPairIds: [anchorKeeper.mspPairId],
|
|
27
|
+
pinIds: anchorKeeper.pinIds,
|
|
28
|
+
orientation: "x-",
|
|
29
|
+
anchorPoint: { x: -3, y: -1 },
|
|
30
|
+
center: { x: -3.2, y: -1 },
|
|
31
|
+
width: 0.4,
|
|
32
|
+
height: 0.2,
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const result = align(traces, {
|
|
36
|
+
netLabelPlacements: [label],
|
|
37
|
+
eligibleTraceIds: new Set(rails.map((trace) => trace.mspPairId)),
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
expect(result.alignedRailGroupCount).toBe(0)
|
|
41
|
+
expect(result.traces).toEqual(traces)
|
|
42
|
+
})
|
|
@@ -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
|
+
})
|