uniform_insets : F64 -> Insets
Build equal insets on all four sides.
:= [
Group(
{
children : List([Node(U64), Nested(Compound)]),
algorithm : Algorithm,
insets : Insets,
header : Header,
min_width : F64,
min_height : F64,
},
),
]
Recursive composition of layout groups. A group owns nodes directly or owns completed child groups; child boxes are laid out before their parent.
uniform_insets : F64 -> Insets
Build equal insets on all four sides.
default_insets : Insets
Sixteen layout units on every side.
default_group : Compound
An empty row group with 24 units between children, 16-unit insets, and no reserved header. Replace its fields by record update when building each recursive group.
default_layered : LayeredOptions
Ordinary readable layered settings with empty optional rule lists. Use as
LayeredSweep({ ..Compound.default_layered, settings: ... }).
default_exact_layered : ExactLayeredOptions
Ordinary bounded exact settings with empty optional rule lists. Use this for small groups where ordering quality matters more than layout cost.
default_routing : Routing
Default deterministic orthogonal routing. Replace or record-update it on
Input when the whole drawing needs different routing.
default_input : Input
Empty graph and group with default orthogonal routing.
default_run : RunArgs
Fixed seed and no position hints.
Validate the complete recursive input and lay out every group bottom-up. Every global node must occur exactly once. Output positions and routes retain global node and edge order; group geometry uses root preorder.
Algorithm : [
Rows({ gap : F64 }),
Columns({ gap : F64 }),
LayeredSweep(LayeredOptions),
LayeredExact(ExactLayeredOptions),
GraphCircular(CircularSettings),
GraphForce({ settings : { node_gap : F64, repulsion : F64, gravity : F64, opening_angle : F64, max_iterations : U64, tolerance : F64 }, pins : List({ node : U64, x : F64, y : F64 }) }),
GraphStress({ settings : { node_gap : F64, mode : [Exact, Pivots(U64)], max_iterations : U64, tolerance : F64 }, pins : List({ node : U64, x : F64, y : F64 }) }),
GraphRadial({ root : [Auto, Node(U64)], ring_gap : F64, node_gap : F64, start_angle : F64, winding : [Clockwise, CounterClockwise] }),
TreeTidy(Settings),
TreeRadial(RadialSettings),
ConstrainedStress({ settings : { node_gap : F64, max_iterations : U64, tolerance : F64 }, constraints : List(Constraint), pins : List({ node : U64, x : F64, y : F64 }) }),
]
A layout family selected for one group. Rows and Columns expose only the
gap between adjacent completed children. Other variants reuse their
family's settings. Force, stress, and constrained pins identify global
nodes and use coordinates local to this group. Constrained rules likewise
identify global nodes; the group applies each rule to the direct child
containing that node. Put a rule in the lowest group that owns all of its
referenced nodes. Layered rules name global nodes or root-preorder groups
and arrange the distinct direct children containing those targets.
same_layers places siblings on one flow layer; sibling_order gives
their visible order within that layer. Non-ranking edges use global graph
edge indices and remain routed without influencing layer assignment.
Routing : [Straight, Orthogonal(Settings)]
Routing for the complete drawing. Straight connects node boundaries
directly. Orthogonal accepts the same visible spacing and path preferences
as Route.layout and additionally reserves parent-layout corridor space
from cross-group edge demand. Every crossed group boundary receives one
perpendicular portal; sparse group attachments override its side or exact
position.
A caller-visible item used by a layered group rule. Nodes use global graph
indices. Groups use the root-first preorder shared with Result.groups.
LayeredOptions : { settings : Settings, edge_weights : List({ edge : U64, weight : F64 }), min_spans : List({ edge : U64, span : U64 }), same_layers : List({ first : Target, second : Target }), sibling_order : List({ before : Target, after : Target }), non_ranking_edges : List(U64) }
Inputs specific to readable layered placement. Start with
default_layered and replace only the settings or authored rules the
diagram needs.
ExactLayeredOptions : { settings : ExactSettings, edge_weights : List({ edge : U64, weight : F64 }), min_spans : List({ edge : U64, span : U64 }), same_layers : List({ first : Target, second : Target }), sibling_order : List({ before : Target, after : Target }), non_ranking_edges : List(U64) }
Inputs specific to bounded exact layered placement. Its fields have the
same meaning as LayeredOptions; settings additionally caps search work.
Empty space reserved between a group's outer boundary and its contents.
Use uniform_insets for ordinary boxes, or change individual sides when
a diagram needs asymmetric space.
An optional geometric band reserved at the top of a group. Orthogonal routes avoid this rectangle, so callers can safely draw a measured title or other header content there. The top inset separates the bottom of this band from the group's children.
Input : {
graph : {
nodes : List({ width : F64, height : F64 }),
edges : List({ from : U64, to : U64 }),
},
attachments : List(AttachmentRule),
group_attachments : List(GroupAttachmentRule),
boundaries : List(BoundaryRule),
edge_labels : List(EdgeLabel),
root : Compound,
routing : Routing,
}
The complete graph, recursive ownership tree, routing choice, and optional
edge attachment/label data. Every graph node must occur exactly once in
root. Boundary rules use global node indices. Group attachments use the
same root-first preorder as Result.groups; group 0 is the drawing's outer
boundary and cannot be an attachment target. Routing applies after every
group has placed its children, and group attachments require Orthogonal.
The seed selects deterministic variants for force/stress groups. Hints are global-node aligned; a full finite list seeds child proxy placement.
Problem : [
InvalidNodeWidth(U64),
InvalidNodeHeight(U64),
MissingEdgeStart(U64, U64),
MissingEdgeEnd(U64, U64),
MissingMember(U64),
DuplicateMember(U64),
MissingGroupNode(U64, U64),
InvalidInset(U64, Side),
InvalidHeaderHeight(U64),
InvalidRootGroupAttachment(U64),
InvalidGroupAttachmentEdge(U64),
InvalidGroupAttachmentGroup(U64),
InvalidGroupAttachmentOffset(U64),
DuplicateGroupAttachment(U64),
GroupAttachmentNotBoundary(U64),
GroupAttachmentNeedsOrthogonal(U64),
HeaderAttachmentConflict(U64, U64),
InvalidMinimumWidth(U64),
InvalidMinimumHeight(U64),
InvalidGap(U64),
MissingPin(U64, U64),
InvalidPin(U64, U64),
MissingConstraintNode(U64, U64, U64),
MissingLayerTarget(U64, U64, Target),
LayerTargetsNotSiblings(U64, U64),
MissingNonRankingEdge(U64, U64, U64),
NonRankingEdgeNotBetweenSiblings(U64, U64, U64),
InvalidGroupAlgorithm(U64),
InvalidTreeTopology(U64),
RouteProblem(Problem),
]
All independently detectable input, group, algorithm, constraint, and routing problems. Group indices use root-first preorder; pin and constraint indices refer to their algorithm payload lists.
GroupGeometry : { rect : Rect, content : Rect, header : [None, Some(Rect)] }
The outer rectangle, child-content rectangle, and optional reserved header for one group. Group geometry is returned in root-first preorder.
Result : {
layout : {
positions : List({ x : F64, y : F64 }),
routes : List(Route),
bounds : { x : F64, y : F64, width : F64, height : F64 },
},
groups : List(GroupGeometry),
label_anchors : List({ x : F64, y : F64 }),
attachments : List(EdgeAttachments),
group_crossings : List(List(GroupCrossing)),
}
Index-aligned node and edge geometry plus root-first group geometry. The
root outer rectangle equals layout.bounds and contains every child group,
route, and label box; its content rectangle excludes its insets and header.