# Layouts

> Two layouts in fframes_kit::layout place the nodes of the tree and graph figures.

Page: https://fframes-kit.pages.dev/docs/computer-science/layouts/
Cargo feature: `cs` (`fframes-kit = { version = "..", features = ["cs"] }`)

Two layouts in `fframes_kit::layout` place the nodes of the tree and graph figures. Both
compute once and give the same result on every run and machine. The shared graph layouts of
`layout::graph_layout` are a third choice, through `Graph::layout` and `TreeTrace::with_layout`.

- `tidy_tree(children, root)` places a tree: `children[i]` lists the children of node `i`.
  `x` is in slots (siblings and neighbouring subtrees are at least one slot apart at every
  depth), `y` is the depth. Parents sit midway over their children, and the leftmost node is
  at `x = 0`.
- `layered(count, edges)` (with `cs`) places a directed graph in layers with
  Sugiyama's method: `y` is the layer, sources at 0 and edges pointing down, and `x` the slot
  in the layer, with crossings reduced. Cycles are fine. Connected parts sit side by side,
  and nodes without edges follow in layer 0.

Gallery scene: `CsLayouts` compares the two layouts on the same graph.

Gallery clip of `CsLayouts`: https://fframes-kit.pages.dev/media/scenes/CsLayouts-a2da6f80.mp4

```rust
use fframes_kit::layout::{layered, tidy_tree};

// a root with two children, the first with two of its own
let tree = tidy_tree(&[vec![1, 2], vec![3, 4], vec![], vec![], vec![]], 0);
assert_eq!(tree[1], (0.5, 1.0));
assert_eq!(tree[0].0, f64::midpoint(tree[1].0, tree[2].0));

let graph = layered(4, &[(0, 1), (0, 2), (1, 3), (2, 3)]);
assert_eq!((graph[0].1, graph[3].1), (0.0, 2.0));
```

To draw the tree layout, apply its positions to a graph and build the trace once:

```rust
use fframes_kit::layout::tidy_tree;
use fframes_kit::prelude::*;

let positions = tidy_tree(&[vec![1, 2], vec![3, 4], vec![], vec![], vec![]], 0);
let graph = Graph::new(&["A", "B", "C", "D", "E"], &[(0, 1), (0, 2), (1, 3), (1, 4)], true)
    .at(&positions);
let trace = GraphTrace::bfs(&graph, 0);

fn draw<'a>(ui: &mut Ui<'a, '_, '_>, trace: &'a GraphTrace) -> Svgr<'a> {
    ui.show(GraphView { trace: Some(trace), step_time: 0.8, ..ui.defaults() })
}
```
