Layer assignment and ordering for the layout engine.
Assigns each node to a layer (depth from root) and orders nodes within each layer to minimize edge crossings using a barycenter heuristic.
Summary
Functions
Assign each node to a layer based on longest path from a root.
Compute extra grid cells needed between adjacent layers for crossing edges.
Order nodes within each layer using barycenter heuristic for crossing minimization.
Fix overlapping subgraph layer ranges.
Functions
@spec assign_layers(Boxart.Graph.t()) :: %{required(String.t()) => non_neg_integer()}
Assign each node to a layer based on longest path from a root.
Back-edges (edges that would create cycles) are excluded from layer computation to prevent infinite loops and excessive layers.
@spec compute_gap_expansions(Boxart.Graph.t(), [[String.t()]]) :: %{ required(non_neg_integer()) => non_neg_integer() }
Compute extra grid cells needed between adjacent layers for crossing edges.
Returns a map of gap index (between layer i and i+1) to the number of
extra grid cells to insert.
@spec order_layers(Boxart.Graph.t(), %{required(String.t()) => non_neg_integer()}) :: [[String.t()]]
Order nodes within each layer using barycenter heuristic for crossing minimization.
@spec separate_subgraph_layers(Boxart.Graph.t(), %{ required(String.t()) => non_neg_integer() }) :: %{ required(String.t()) => non_neg_integer() }
Fix overlapping subgraph layer ranges.
When cross-boundary edges cause nodes from different subgraphs to land on the same layer, the subgraph boxes overlap visually. Reassigns layers so each subgraph occupies a contiguous, non-overlapping range.