Skip to content
Merged
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 @@ -6,10 +6,11 @@ Part of the Rendering Layout system.

`InterconnectionLayoutEngine` places directed graphs and routes all connector lines using a full
Sugiyama-style pipeline. It is a thin facade that assembles and runs the reusable
`LayeredLayoutPipeline` (see *Layered Pipeline*) with its default stage sequence, the Right layout
direction, and flat hierarchy handling. Its `Place` API and `LayerResult` output are the stable
internal contract; the facade produces byte-for-byte identical geometry to the previous monolithic
implementation, proven by an equivalence test against a legacy oracle.
`LayeredLayoutPipeline` (see *Layered Pipeline*) with its default stage sequence, the requested layout
direction (defaulting to Right), and flat hierarchy handling. Its `Place` API and `LayerResult` output
are the stable internal contract; for the default Right direction the facade produces byte-for-byte
identical geometry to the previous monolithic implementation, proven by an equivalence test against a
legacy oracle.

## InterconnectionLayoutEngine Data Model

Expand All @@ -22,13 +23,21 @@ with `ConnectorWaypoints`.

## InterconnectionLayoutEngine Methods

`Place(nodes, edges)` builds a `LayeredGraph` from the inputs, assembles a `LayeredLayoutPipeline`
with the default stages, and runs it. It then reads the placed coordinates, column extents, layer
assignments, and waypoints from the graph state and assembles the `LayerResult`. Because the
pipeline drops self-loops, de-duplicates identical directed pairs, and reverses back edges,
`ConnectorWaypoints` holds one polyline per acyclic edge; consumers key a `(source, target)` lookup
on `AcyclicEdges` (reversing the polyline for a reversed back edge) to recover each input edge's
route.
`Place(nodes, edges, direction)` builds a `LayeredGraph` from the inputs, assembles a
`LayeredLayoutPipeline` with the default stages for the requested `direction` (defaulting to Right),
and runs it. It then reads the placed coordinates, column extents, layer assignments, and waypoints
from the graph state and assembles the `LayerResult`. Because the pipeline drops self-loops,
de-duplicates identical directed pairs, and reverses back edges, `ConnectorWaypoints` holds one
polyline per acyclic edge; consumers key a `(source, target)` lookup on `AcyclicEdges` (reversing the
polyline for a reversed back edge) to recover each input edge's route.

The reported total dimensions are direction-aware. The pipeline's axis-transform stage places the
nodes along the requested direction, so a top-to-bottom (Down) or bottom-to-top (Up) flow transposes
the layout relative to the left-to-right (Right) and right-to-left (Left) flows. The engine computes
the along-axis extent from the column geometry and the cross-axis extent from the placed screen
coordinates, then assigns them to `TotalWidth`/`TotalHeight` per direction: for Right/Left the
along-axis is the width and for Down/Up it is the height. The Right path is unchanged and remains
byte-identical.

## InterconnectionLayoutEngine Error Handling

Expand All @@ -51,4 +60,5 @@ strategy to obtain a placement result.
| Rendering-Layout-InterconnectionEngine-NonOverlapping | InterconnectionLayoutEngine behavior described above |
| Rendering-Layout-InterconnectionEngine-DummyNodes | InterconnectionLayoutEngine behavior described above |
| Rendering-Layout-InterconnectionEngine-Waypoints | InterconnectionLayoutEngine behavior described above |
| Rendering-Layout-InterconnectionEngine-Direction | InterconnectionLayoutEngine behavior described above |
| Rendering-Layout-InterconnectionEngine-Deterministic | InterconnectionLayoutEngine behavior described above |
14 changes: 11 additions & 3 deletions docs/design/rendering-layout/layered-layout-algorithm.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,17 @@ per node followed by `LayoutLine` per edge).
`LayerNode` array from node sizes.
2. **Edge mapping.** Maps each edge to an index pair, dropping any edge that references a node
outside this graph.
3. **Placement.** Calls `InterconnectionLayoutEngine.Place` to obtain the `LayerResult`.
4. **Box emission.** Emits one `LayoutBox` per input node, in input order, at the placed rectangle,
3. **Direction resolution.** Resolves the requested flow direction from `CoreOptions.Direction`,
taking an explicit value on the graph in preference to one on the options and falling back to the
property default (`Right`), then maps the public `LayoutFlowDirection` to the engine's internal
direction. This mirrors how the algorithm resolves its other well-known options.
4. **Placement.** Calls `InterconnectionLayoutEngine.Place` with the resolved direction to obtain the
`LayerResult`. For a downward or upward flow the engine transposes the layout so the layers
progress top-to-bottom (or bottom-to-top); `Right` is the default and is byte-identical to the
original left-to-right placement.
5. **Box emission.** Emits one `LayoutBox` per input node, in input order, at the placed rectangle,
carrying the node label.
5. **Route resolution.** Builds a `(source, target)` to polyline lookup from the engine's acyclic
6. **Route resolution.** Builds a `(source, target)` to polyline lookup from the engine's acyclic
edge set, then emits one `LayoutLine` per input edge. `ResolveRoute` returns the forward polyline
when present, reverses the polyline of a reversed back edge, and otherwise falls back to a
straight segment between the two node centers (for a self-loop or duplicate edge the engine
Expand All @@ -50,4 +57,5 @@ the Engine subsystem. It is the entry point resolved by renderers through the la
| Rendering-Layout-LayeredAlgorithm-Identity | LayeredLayoutAlgorithm behavior described above |
| Rendering-Layout-LayeredAlgorithm-PlacesAndRoutes | LayeredLayoutAlgorithm behavior described above |
| Rendering-Layout-LayeredAlgorithm-EmptyGraph | LayeredLayoutAlgorithm behavior described above |
| Rendering-Layout-LayeredAlgorithm-Direction | LayeredLayoutAlgorithm behavior described above |
| Rendering-Layout-LayeredAlgorithm-Validation | LayeredLayoutAlgorithm behavior described above |
47 changes: 47 additions & 0 deletions docs/gallery/direction-down.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
47 changes: 47 additions & 0 deletions docs/gallery/direction-right.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 14 additions & 0 deletions docs/gallery/gallery.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,20 @@ Sibling boxes packed compactly by the containment algorithm.

A container node holding a nested child graph, with a cross-container edge.

## Flow direction

The same directed graph laid out in two flow directions, selected with the direction option. A rightward flow arranges
the layers left-to-right for block and pipeline diagrams; a downward flow arranges them top-to-bottom for action flows
and state machines, swapping each node's width and height so layer spacing follows node height.

![Directed flow laid out left to right](direction-right.svg)

The default rightward direction: layers progress left-to-right.

![The same directed flow laid out top to bottom](direction-down.svg)

The downward direction: the same graph's layers progress top-to-bottom.

## Edge routing

Orthogonal connectors step around the boxes between their endpoints instead of cutting through them.
Expand Down
1 change: 1 addition & 0 deletions docs/reqstream/rendering-layout/engine/engine.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ sections:
- Rendering-Layout-InterconnectionEngine-NonOverlapping
- Rendering-Layout-InterconnectionEngine-DummyNodes
- Rendering-Layout-InterconnectionEngine-Waypoints
- Rendering-Layout-InterconnectionEngine-Direction
- Rendering-Layout-InterconnectionEngine-Deterministic
tests:
- Place_LinearChain_MonotonicLayerAssignment
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,18 @@ sections:
- Place_SingleEdge_ProducesStraightTwoWaypointPath
- Place_LongEdge_RoutesViaDummyNodesWithinBounds

- id: Rendering-Layout-InterconnectionEngine-Direction
title: >-
InterconnectionLayoutEngine shall place the nodes along the requested flow direction,
transposing the layout and its reported total dimensions for a top-to-bottom or bottom-to-top
flow, and shall default to the left-to-right flow.
justification: |
Directed views request a top-to-bottom placement; the engine must honor the requested
direction and report total dimensions that match the transposed layout, while the default
leaves the established left-to-right geometry unchanged.
tests:
- Place_DownDirection_TransposesTotalsRelativeToRight

- id: Rendering-Layout-InterconnectionEngine-Deterministic
title: >-
Given identical input, InterconnectionLayoutEngine shall produce identical geometry and
Expand Down
15 changes: 15 additions & 0 deletions docs/reqstream/rendering-layout/layered-layout-algorithm.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,21 @@ sections:
tests:
- Apply_EmptyGraph_ReturnsEmptyCanvas

- id: Rendering-Layout-LayeredAlgorithm-Direction
title: >-
LayeredLayoutAlgorithm shall arrange the placed layers along the flow direction selected by
the direction option — top-to-bottom, bottom-to-top, right-to-left, or the default
left-to-right — reading the selection from the graph in preference to the options.
justification: |
Directed views such as action flows and state machines read the placed coordinates expecting
the layers to progress top-to-bottom; the layout is only correct for them when the algorithm
honors the requested flow direction rather than always flowing left-to-right.
tests:
- Apply_DownDirection_FlowsTopToBottom
- Apply_DownDirection_DiffersFromRight
- Apply_DownDirectionOnGraphScope_IsHonored
- Apply_DefaultDirection_FlowsLeftToRight

- id: Rendering-Layout-LayeredAlgorithm-Validation
title: >-
LayeredLayoutAlgorithm shall reject a null graph or null options argument with an
Expand Down
1 change: 1 addition & 0 deletions docs/reqstream/rendering-layout/rendering-layout.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ sections:
- Rendering-Layout-LayeredAlgorithm-Identity
- Rendering-Layout-LayeredAlgorithm-PlacesAndRoutes
- Rendering-Layout-LayeredAlgorithm-EmptyGraph
- Rendering-Layout-LayeredAlgorithm-Direction
- Rendering-Layout-LayeredAlgorithm-Validation
tests:
- Apply_ChainGraph_PlacesLayeredBoxesAndRoutesEdges
Expand Down
8 changes: 7 additions & 1 deletion docs/user_guide/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ on it:
```csharp
var options = new LayoutOptions();
options.Set(CoreOptions.Algorithm, "layered");
options.Set(CoreOptions.Direction, LayoutFlowDirection.Right);
options.Set(CoreOptions.Direction, LayoutFlowDirection.Down); // flow the layers top-to-bottom

// Per-element overrides: any graph element is also a property holder.
a.Set(CoreOptions.NodeSpacing, 32.0);
Expand All @@ -189,6 +189,12 @@ a.Set(CoreOptions.NodeSpacing, 32.0);
options.Set(CoreOptions.EdgeRouting, EdgeRouting.Orthogonal);
```

`CoreOptions.Direction` selects the flow direction the layered algorithm arranges its layers along:
`Right` (the default) and `Left` flow the layers left-to-right and right-to-left, while `Down` and
`Up` flow them top-to-bottom and bottom-to-top — the convention for action flows and state machines. A
downward flow swaps each node's width and height before layering so layer spacing follows node height.
As with the algorithm, a declaration on the graph takes precedence over one on the options.

## Routing connectors among placed boxes

When you have already positioned some boxes yourself — for example a free-form or containment layout
Expand Down
Loading
Loading