Skip to content

fix: detour net-label connectors around blocking traces (#674)#716

Closed
DPS0340 wants to merge 4 commits into
tscircuit:mainfrom
DPS0340:followup/connector-detour-routing
Closed

fix: detour net-label connectors around blocking traces (#674)#716
DPS0340 wants to merge 4 commits into
tscircuit:mainfrom
DPS0340:followup/connector-detour-routing

Conversation

@DPS0340

@DPS0340 DPS0340 commented Jul 25, 2026

Copy link
Copy Markdown

Follow-up to #703, as offered there. Depends on #703 — it builds on that branch, so please merge #703 first (or I can rebase onto main once it lands).

This finishes off #674: the board goes from 3 different-net crossings to 0.

Why #703 alone wasn't enough

Two things were hiding crossings from the existing check.

1. Ordering. Labels are processed one at a time, so each connector is only validated against traces that exist at that moment. On this board orientation-4 is routed at index 14 but collides with orientation-9, which isn't created until index 17 — the earlier connector never had a chance to see it. Fixed by re-checking every connector once they all exist.

2. No L-shape works. For the last two, the blocking trace sits between source and target on both axes:

JP1.1-SJ3.1  x  available-net-orientation-3-V3_3
U1.1-U1.3    x  available-net-orientation-5-GND

Both L-shapes cross it, whichever corner they turn. The connector has to step away, run across, and come back — so the re-route pass now tries U-shaped detours at increasing perpendicular offsets after the mirrored L, taking the first route that's clear of other nets, chips and labels. Cheapest-first, so connectors deviate as little as possible.

Results

Different-net crossings per board, measured against origin/main:

board main this branch
bug-report-20260717T022934Z (#674) 3 0
bug-report-20260706T213649Z 11 9
bug-report-20260706T220324Z 6 5
bug-report-20260721T221026Z 5 4
bug-report-20260716T144856Z 4 3
example45 2 1
example43 1 0

No board regressed. With the #674 board clean, the repro's assertion is no longer test.failing.

Full suite 145 pass / 0 fail.

DPS0340 added 4 commits July 25, 2026 15:13
Progress on tscircuit#674.

AvailableNetOrientationSolver generated connector traces (from a label's
original anchor to its corrected position) without checking whether the
connector crosses an existing trace from a different net. Each crossing
renders as a false junction. On the tscircuit#674 board this produced 3 crossings,
e.g. the V3_3 connector slicing through the JP1.1-SJ3.1 trace; example45
and bug-report-20260708T055430Z each had one more.

Candidate evaluation now rejects candidates whose connector would cross
another net's trace, with a fallback pass that permits crossings when no
crossing-free candidate exists (so orientation constraints still win over
crossing avoidance, matching repro51's pinned behavior).

Crossings drop 2->1 on example45 and bug-report-20260708T055430Z
(snapshots updated). The tscircuit#674 board's remaining 3 crossings need
connector rerouting around blocking traces — pinned with a test.failing
for follow-up.
@mohan-bee was right that the hand-made bug report was wrong. The tscircuit#674
issue already has a bot-imported report at
tests/bug-reports/bug-report-20260717T022934Z (directory name derived from
the issue's created_at by .github/scripts/import-json-bug-report.ts), and
I had hand-created a second directory holding a byte-identical copy.

Removes the hand-made directory and points the repro at the existing bug
report, which already carries its own snapshot test.

Full suite 145 pass / 0 fail.
Labels are processed one at a time, so each connector is validated against
only the traces that exist when its own label is handled. On the tscircuit#674 board
that ordering hides a real crossing: the orientation-4 connector is routed
at index 14, but the orientation-9 connector it collides with is not created
until index 17, so the earlier one never had a chance to avoid it.

Adds a post-pass that runs once every connector exists. For each generated
connector still crossing another net, it tries the mirrored L-route (turning
on the other axis first) and adopts it when that route is crossing-free and
does not hit a chip or another label. Only connectors this solver generated
are moved; pin-to-pin traces from earlier solvers are untouched.

Crossings per board, measured against the previous commit:

  bug-report-20260717-connector-crossing-674   3 -> 2
  bug-report-20260706T213649Z                 11 -> 9
  bug-report-20260706T220324Z                  6 -> 5
  bug-report-20260721T221026Z                  5 -> 4
  bug-report-20260717T022934Z                  3 -> 2
  example43                                    1 -> 0

The two remaining on the tscircuit#674 board stay walled in — the mirrored route
crosses something as well, so those need the connector routed around the
blocking trace. Still pinned by the existing test.failing.

Full suite 146 pass / 0 fail; 10 snapshots updated.
)

Completes tscircuit#674. The previous commit tries the mirrored L-route, which clears
a crossing when the blocking trace only sits on one axis between the
endpoints. Two crossings on the tscircuit#674 board survived that:

  JP1.1-SJ3.1  x  available-net-orientation-3-V3_3
  U1.1-U1.3    x  available-net-orientation-5-GND

For both, the blocking trace lies between source and target on *both* axes,
so every L-shape crosses it regardless of which corner it turns. The
connector has to step away from the source, run across, and come back.

The re-route pass now walks candidate routes cheapest-first: the mirrored L,
then U-shaped detours at increasing perpendicular offsets in both
directions. The first route clear of other nets, chips and labels wins, so
connectors deviate as little as possible.

Different-net crossings per board, measured against origin/main:

  bug-report-20260717T022934Z (tscircuit#674 board)   3 -> 0
  bug-report-20260706T213649Z               11 -> 9
  bug-report-20260706T220324Z                6 -> 5
  bug-report-20260721T221026Z                5 -> 4
  bug-report-20260716T144856Z                4 -> 3
  example45                                  2 -> 1
  example43                                  1 -> 0

No board regressed. With the tscircuit#674 board clean, the repro's assertion is no
longer test.failing.

Full suite 145 pass / 0 fail.
@vercel

vercel Bot commented Jul 25, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
schematic-trace-solver Ready Ready Preview, Comment Jul 25, 2026 7:15am

Request Review

@DPS0340

DPS0340 commented Jul 25, 2026

Copy link
Copy Markdown
Author

@mohan-bee @seveibar — this is the follow-up I split out of #703, ready for review whenever convenient.

It's stacked on #703, so it should be reviewed/merged after that one.

What it does: #703 fixes the connector crossings it can fix by re-cornering, but two on the #674 board can't be — the blocking trace sits between source and target on both axes, so every L-shape crosses it. This adds U-shaped detours at increasing perpendicular offsets, tried cheapest-first after the mirrored L.

Measured against origin/main, different-net crossings:

20260717T022934Z (#674 board)  3 → 0
20260706T213649Z              11 → 9
20260706T220324Z               6 → 5
20260721T221026Z               5 → 4
20260716T144856Z               4 → 3
example45                      2 → 1
example43                      1 → 0

No board regressed. Full suite green, MERGEABLE / CLEAN.

@DPS0340

DPS0340 commented Jul 25, 2026

Copy link
Copy Markdown
Author

Update on this one, since #703 (which this depends on) is now closed in favour of #719.

I measured all three branches against origin/main, counting different-net crossings across the 19 imported bug reports:

origin/main   TOTAL 40
#719          TOTAL 19
#716 (this)   TOTAL 31
#703          TOTAL 39

So this branch does help, but #719 alone does better — and the two conflict in AvailableNetOrientationSolver.ts, so they cannot both land as-is.

That surprised me, because this PR was written as the finisher for #674: it adds connector detour routing on top of #703's check, and on the #674 board specifically it reaches 0 crossings. The wider measurement says that gain does not generalise — the detour logic helps that board while #719's simpler "reject the candidate and keep searching" does better across the rest.

I'd rather not have you review a branch built on a closed one, so:

I'm marking this as draft and will rebase it onto #719 once that lands, then re-measure. If detour routing still buys anything on top of #719, I'll reopen it with the numbers; if it doesn't, I'll close it. Either way it shouldn't cost you a review right now.

Sorry for the churn — I should have measured across all boards before stacking these.

@DPS0340

DPS0340 commented Jul 26, 2026

Copy link
Copy Markdown
Author

Closing this. It was built on #703, which I closed in favour of #719, and re-testing it against current main confirms it has been superseded rather than just rebased-away.

Measured across all imported bug reports, counting different-net crossings:

main                    TOTAL 41
#718 + #719             TOTAL 20
#718 + #719 + #723      TOTAL 20   (and #723 fixes the collinear case)
#716 (this, measured earlier)  TOTAL 31

The detour routing here reaches 0 crossings on the #674 board specifically, which is what made it look like the finisher. Across the full set it does worse than the simpler "reject the candidate and keep searching" approach in #719 — 31 vs 20.

It also no longer applies cleanly: cherry-picking its detour commit onto the current #719/#723 stack conflicts in AvailableNetOrientationSolver.ts, because both change the same candidate-evaluation path in incompatible ways. Reworking it would mean rewriting it against #719, and the measurement says that would be work spent to land a worse result.

Sorry for the noise on this one — it should have been measured across all boards before I opened it rather than on the single board it targeted.

#719 and #723 carry the useful part and are both ready.

@DPS0340 DPS0340 closed this Jul 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant