Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,22 @@ import { generateSnipAndReconnectCandidates } from "./trySnipAndReconnect"
import { generateFourPointDetourCandidates } from "./tryFourPointDetour"
import { simplifyPath } from "../TraceCleanupSolver/simplifyPath"

import { generateMoveTraceSegmentsCandidates } from "./tryMoveTraceSegments"

const getPathLength = (pts: Point[]) => {
let len = 0
for (let i = 0; i < pts.length - 1; i++) {
const dx = pts[i + 1].x - pts[i].x
const dy = pts[i + 1].y - pts[i].y
len += Math.sqrt(dx * dx + dy * dy)
}
return len
}

export const generateRerouteCandidates = ({
trace,
label,
problem,
paddingBuffer,
detourCount,
}: {
Expand Down Expand Up @@ -58,5 +71,31 @@ export const generateRerouteCandidates = ({
detourCount,
})

return [...fourPointCandidates, ...snipReconnectCandidates]
const moveTraceSegmentsCandidates = generateMoveTraceSegmentsCandidates({
initialTrace,
label,
labelBounds,
paddingBuffer,
detourCount,
})

// Return candidates in order of preference: four-point, snip-reconnect, then move trace segments
const allCandidates = [
...fourPointCandidates,
...snipReconnectCandidates,
...moveTraceSegmentsCandidates,
]

// Sort by path length within each group, but keep move trace segments at the end
const sortedFourPoint = fourPointCandidates.sort(
(a, b) => getPathLength(a) - getPathLength(b),
)
const sortedSnipReconnect = snipReconnectCandidates.sort(
(a, b) => getPathLength(a) - getPathLength(b),
)
const sortedMoveTrace = moveTraceSegmentsCandidates.sort(
(a, b) => getPathLength(a) - getPathLength(b),
)

return [...sortedFourPoint, ...sortedSnipReconnect, ...sortedMoveTrace]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import type { Point } from "@tscircuit/math-utils"
import type { SolvedTracePath } from "../SchematicTraceLinesSolver/SchematicTraceLinesSolver"
import type { NetLabelPlacement } from "../NetLabelPlacementSolver/NetLabelPlacementSolver"
import type { Bounds } from "@tscircuit/math-utils"
import { segmentIntersectsRect } from "../SchematicTraceLinesSolver/SchematicTraceSingleLineSolver2/collisions"

export const generateMoveTraceSegmentsCandidates = ({
initialTrace,
label,
labelBounds,
paddingBuffer,
detourCount,
}: {
initialTrace: SolvedTracePath
label: NetLabelPlacement
labelBounds: Bounds & { chipId: string }
paddingBuffer: number
detourCount: number
}): Point[][] => {
const candidates: Point[][] = []
const path = initialTrace.tracePath

// Only apply to simple traces (2 points = straight line)
if (path.length !== 2) {
return []
}

const p1 = path[0]
const p2 = path[1]

// Only move segments that actually intersect with the label bounds
if (!segmentIntersectsRect(p1, p2, labelBounds)) {
return []
}

const isHorizontal = p1.y === p2.y

if (isHorizontal) {
const newY = labelBounds.maxY + paddingBuffer + label.height / 2
const newPath = JSON.parse(JSON.stringify(path))
newPath[0].y = newY
newPath[1].y = newY
candidates.push(newPath)
} else {
const newX = labelBounds.maxX + paddingBuffer + label.width / 2
const newPath = JSON.parse(JSON.stringify(path))
newPath[0].x = newX
newPath[1].x = newX
candidates.push(newPath)
}

return candidates
}
57 changes: 57 additions & 0 deletions tests/assets/repro.input.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
{
"netLabelPlacements": [
{
"globalConnNetId": "connectivity_net1",
"dcConnNetId": "connectivity_net1",
"netId": ".L1 > .pin2 to .M1 > .drain",
"mspConnectionPairIds": ["L1.2-D1.1"],
"pinIds": ["L1.2", "D1.1"],
"orientation": "y+",
"anchorPoint": {
"x": 0.78,
"y": 2.97
},
"width": 0.2,
"height": 0.45,
"center": {
"x": 1.53,
"y": 2.97
}
}
],
"traces": [
{
"mspPairId": "V1.1-L1.1",
"dcConnNetId": "connectivity_net0",
"globalConnNetId": "connectivity_net0",
"pins": [
{
"pinId": "V1.1",
"x": -5.005,
"y": 2.54,
"chipId": "schematic_component_0",
"_facingDirection": "y+"
},
{
"pinId": "L1.1",
"x": -0.58,
"y": 2.98,
"_facingDirection": "x-",
"chipId": "schematic_component_1"
}
],
"tracePath": [
{
"x": 0,
"y": 2.97
},
{
"x": 2,
"y": 2.97
}
],
"mspConnectionPairIds": ["V1.1-L1.1"],
"pinIds": ["V1.1", "L1.1"]
}
]
}
135 changes: 87 additions & 48 deletions tests/examples/__snapshots__/example14.snap.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion tests/examples/example14.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { expect, test } from "bun:test"
import { SchematicTracePipelineSolver } from "lib/solvers/SchematicTracePipelineSolver/SchematicTracePipelineSolver"
import { inputProblem } from "site/examples/example14.page"

test.skip("example14 - should fail with net label placement collision error", () => {
test("example14 - net label collision resolved with trace segment moving", () => {
const solver = new SchematicTracePipelineSolver(inputProblem)

solver.solve()
Expand Down
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks broken, the labels are totally in the wrong orientation/position, and the trace is also removed

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i created the snapshot to reproduce the issue

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the trace being removed is the fix

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading