Skip to content

Layouts

Cargo featurefeatures = ["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.

CsLayouts demo, first frame
CsLayouts 8 s
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:

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() })
}