Link View: order the peers so the wires stop crossing

The picture was right and unreadable: eleven links round one component
drew twelve wire crossings, because each column was stacked in the order
the file happens to list its links and the lanes were handed out by how
far a wire had to travel.

Both columns are now stacked in the order of the chosen component's own
slots -- what feeds its first slot at the top, what feeds its fifth below
that. Nothing here is read from meta, so the view was always free to put
the peers where they read best, and this is the order that turns the set
of wires on one side into a ladder: both ends run the same way down the
page, so no wire has any reason to cross another.

That leaves which lane each wire turns in. For a ladder there is an order
that cannot produce a crossing, and read off the slots rather than off the
direction the line is drawn in, it is the same on both sides -- two fans,
each nesting outwards from the component's own row:

    reaching a peer slot above its focus slot -> turns nearer the focus
    the higher up the focus it lands

    reaching a peer slot below its focus slot -> turns nearer the focus
    the lower down the focus it lands

Two wires of one fan, the outer going round the inner, pass above and
below its vertical but never through it; and a wire of one fan can never
share a stretch of the page with a wire of the other, so the two fans
reuse each other's lanes and the gap stays as narrow as the picture
allows. Where several wires leave the same slot no order of focus heights
separates them, so the longest branch turns first and the rest carry on
along the shared run beside the pin -- a wiresheet's own fan-out. Where
two slots already line up the wire is one straight line and is settled
before anything has to be fitted past it; the layout is rounded to whole
pixels so that a pair that ought to line up does.

The reasoning is not trusted on its own: every wire is checked against the
ones already routed (routes_meet) and takes the next lane out if it
clashes. One thing genuinely breaks the ladder -- a peer whose own slots
run counter to the focus's, linking its row 4 to row 3 and its row 3 to
row 4. Ends inverted like that have to cross wherever they are drawn,
since neither box's slot order is this view's to change.

Measured over 461 linked components in four real files, 1113 wires: no
wire passes through a box at all, and ten crossings remain in six
components, every one of them an inverted pair of that kind. Before this
the same four files drew 45.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-07 19:17:20 +03:00
co-authored by Claude Opus 5
parent 56749872b4
commit b119e02b9e
3 changed files with 271 additions and 48 deletions
+60 -6
View File
@@ -379,6 +379,11 @@ derived from the links every time it is drawn and no part of it is stored in the
(`meta` records a component's place on its own sheet, which says nothing about where it
belongs relative to another one).
Each column is stacked **in the order of the chosen component's own slots**: whatever
feeds its first slot sits at the top, whatever feeds its fifth sits below that. Nothing
is read from `meta`, so the view is free to put the peers wherever they read best, and
this is the order that makes the wires readable -- see **Keeping the wires apart** below.
Every line is **grey**, because this is not a wiresheet and a wire-blue line would invite
the reader to treat it as one:
@@ -394,14 +399,58 @@ be on a sheet; a reference the document cannot resolve gets a dashed placeholder
the path, because a link the view silently dropped would be the one thing a reader could
not find out from here.
Each gap is sized by `column_gap` to hold a lane for every wire crossing it, and lanes are
handed out nearest-target-first, so a wire reaching a distant box turns outside one
reaching a near box instead of across it. A dozen links widen the gap rather than
Hovering a wire darkens it and names the link in the footer; clicking a wire or a
component follows it. `collect_links`, `sheet_display_name` and the whole of the routing
geometry -- `segments_meet`, `routes_meet`, `column_gap`, `_slot_order_key` -- are pure
functions, so both what the view reads out of a document and how it decides where a wire
goes can be exercised without a window.
### Keeping the wires apart
Ordering each column by the chosen component's slots turns the set of wires on one side
into a **ladder**: both ends run the same way down the page, so no wire has any reason to
cross another. What is left is choosing which lane each one turns in, and `column_gap`
reserves the room for that -- a lane per wire, so a dozen links widen the gap rather than
crowding a dozen verticals into a 30px band.
Hovering a wire darkens it and names the link in the footer; clicking a wire or a
component follows it. `collect_links` and `sheet_display_name` are pure DOM work, so what
the view reads out of a document can be exercised without a window.
For a ladder there is a lane order that cannot produce a crossing, and read off the slots
rather than off the direction the line happens to be drawn in, it is the same on both
sides -- two fans, each nesting outwards from the chosen component's own row:
| Wire | Turns nearer the focus |
|---|---|
| reaching a peer slot **above** its focus slot | the higher up the focus it lands |
| reaching a peer slot **below** its focus slot | the lower down the focus it lands |
Take two wires of the upper fan, the higher one nested inside the lower: the lower one's
run into the focus passes below where the higher one's vertical ends, and its run out to
its peer passes above where that vertical begins, so it goes round it and never through
it. The lower fan is the same argument upside down. A wire of one fan can never share a
stretch of the page with a wire of the other -- ordering the ladder is what rules that
out -- so the two fans reuse each other's lanes and the gap stays as narrow as the
picture allows.
Two special cases sit on top of that rule. Where several wires leave the **same** slot no
order of focus heights can separate them, so the longest branch turns first, against the
focus, and the shorter ones carry on along the shared run beside the pin and drop away
outside it -- which is how a wiresheet draws a fan-out too. And where two slots already
line up, the wire is one straight line with no vertical run to place at all; those are
settled first, because such a wire crosses the whole gap and everything else has to be
fitted past it. The layout is rounded to whole pixels so that a pair that ought to line
up does, rather than being drawn with a 1px jog in it.
Every wire is still checked against the ones already routed before it takes a lane
(`routes_meet`), and takes the next lane out if it clashes. The argument above rests on
the ladder being ordered, and one thing breaks that: a peer whose **own** slots run
counter to the focus's -- linking its row 4 to the focus's row 3 and its row 3 to the
focus's row 4. Two links with their ends inverted like that have to cross wherever they
are drawn, and no reordering can help, because the order inside each box is the
component's own. The check is what stops that one forced crossing from being made worse
by the ones around it.
Measured over 461 linked components in four real files -- 1113 wires -- this leaves **no
wire passing through a box at all**, and ten crossings in six components, every one of
them an inverted pair of the kind above.
### Following a link to its other sheet
@@ -568,3 +617,8 @@ And two things worth knowing about the manifests themselves rather than the code
display-only.
- The Link View stacks each side in one column, so a component with a dozen peers makes a
picture taller than the pane. It scrolls, but it does not wrap into a second column.
- Two links between the same pair of components whose slot rows are inverted have to
cross, since neither box's slot order is the view's to change. Six components in the
four files measured do this.
- `column_gap` budgets one lane per wire, but the router reuses lanes wherever it can, so
a side that needs few of them is drawn with a gap wider than its wires require.