default_spec : Spec
The empty graph. Replace by record update.
:= []
General-graph layouts for data whose meaning comes from connectivity: any sized graph, no structure claimed beyond nodes and edges. Four readings of the same input:
layout_circular — all nodes on one ring, neighbors seated together.layout_force — organic clusters from a seeded physical simulation (one-call form here; the ForceLayout module has the reusable prepare/place/run surface, position hints, and pins).layout_stress — drawn distances tracking graph distances (one-call form here; the reusable surface is in StressLayout).layout_radial — concentric rings by depth from a root (one-call form here; the reusable surface is in RadialLayout).For repeated circular layouts of unchanged input, call prepare_circular
once and pass the result to layout_circular_prepared.
default_spec : Spec
The empty graph. Replace by record update.
default_input : Input
General-graph input defaults to the empty spec.
default_circular_settings : CircularSettings
Circular settings that produce a readable ring in common cases: the first node sits at twelve o'clock and seats follow clockwise.
prepare_circular : Input, CircularSettings -> [Ok(CircularPrepared), Err(List(Problem))]
Check the input and settings, then cache the layout they determine.
layout_circular_prepared : CircularPrepared -> Result
Return the previously computed circular layout. This operation cannot fail.
layout_circular : Input, CircularSettings -> [Ok(Result), Err(List(Problem))]
Check and lay out input in one call, read as a ring: every node on one circle, neighbors seated together, crossings reduced.
default_force_settings : {
node_gap : F64,
repulsion : F64,
gravity : F64,
opening_angle : F64,
max_iterations : U64,
tolerance : F64,
pins : List({ node : U64, x : F64, y : F64 }),
}
Force settings that produce a readable organic drawing in common
cases; see the ForceLayout module for what each dial changes.
default_force_run : { seed : U32, hints : List({ x : F64, y : F64 }) }
The default force run arguments: the fixed seed and no position hints.
layout_force : Input, {
node_gap : F64,
repulsion : F64,
gravity : F64,
opening_angle : F64,
max_iterations : U64,
tolerance : F64,
pins : List({ node : U64, x : F64, y : F64 }),
}, { seed : U32, hints : List({ x : F64, y : F64 }) } -> [
Ok(
{
layout : {
positions : List({ x : F64, y : F64 }),
bounds : { x : F64, y : F64, width : F64, height : F64 },
routes : List(Route),
},
components : List(U64),
convergence : { iterations : U64, converged : Bool },
},
),
Err(
List(
[
InvalidNodeWidth(U64),
InvalidNodeHeight(U64),
MissingEdgeStart(U64, U64),
MissingEdgeEnd(U64, U64),
InvalidNodeGap,
InvalidRepulsion,
InvalidGravity,
InvalidOpeningAngle,
InvalidTolerance,
MissingPin(U64),
InvalidPin(U64),
],
),
),
]
Check and lay out input in one call, read organically: connected
nodes pull together, everything else pushes apart, and clusters
emerge from the balance. The seed selects among equally valid
drawings. For repeated layouts, position hints, or pinned nodes, use
the ForceLayout module's prepare/place/run surface.
default_stress_settings : {
node_gap : F64,
mode : [Exact, Pivots(U64)],
max_iterations : U64,
tolerance : F64,
pins : List({ node : U64, x : F64, y : F64 }),
}
Stress settings that produce a readable distance-faithful drawing in
common cases; see the StressLayout module for what each dial
changes.
default_stress_run : { seed : U32, hints : List({ x : F64, y : F64 }) }
The default stress run arguments: the fixed seed and no position hints.
layout_stress : Input, {
node_gap : F64,
mode : [Exact, Pivots(U64)],
max_iterations : U64,
tolerance : F64,
pins : List({ node : U64, x : F64, y : F64 }),
}, { seed : U32, hints : List({ x : F64, y : F64 }) } -> [
Ok(
{
layout : {
positions : List({ x : F64, y : F64 }),
bounds : { x : F64, y : F64, width : F64, height : F64 },
routes : List(Route),
},
components : List(U64),
convergence : { iterations : U64, converged : Bool },
},
),
Err(
List(
[
InvalidNodeWidth(U64),
InvalidNodeHeight(U64),
MissingEdgeStart(U64, U64),
MissingEdgeEnd(U64, U64),
InvalidNodeGap,
InvalidPivotCount,
InvalidTolerance,
MissingPin(U64),
InvalidPin(U64),
],
),
),
]
Check and lay out input in one call, read metrically: how far apart
two nodes are drawn tracks how far apart they are in the graph. For
repeated layouts, position hints, or pinned nodes, use the
StressLayout module's prepare/place/run surface.
default_radial_settings : {
root : [Auto, Node(U64)],
ring_gap : F64,
node_gap : F64,
start_angle : F64,
winding : [Clockwise, CounterClockwise],
}
Radial settings that produce a readable ringed drawing in common
cases; see the RadialLayout module for what each dial changes.
layout_radial : Input, {
root : [Auto, Node(U64)],
ring_gap : F64,
node_gap : F64,
start_angle : F64,
winding : [Clockwise, CounterClockwise],
} -> [
Ok(
{
layout : {
positions : List({ x : F64, y : F64 }),
bounds : { x : F64, y : F64, width : F64, height : F64 },
routes : List(Route),
},
rings : List(U64),
components : List(U64),
},
),
Err(
List(
[
InvalidNodeWidth(U64),
InvalidNodeHeight(U64),
MissingEdgeStart(U64, U64),
MissingEdgeEnd(U64, U64),
InvalidRingGap,
InvalidNodeGap,
InvalidStartAngle,
InvalidRoot(U64),
],
),
),
]
Check and lay out input in one call, read as centrality: concentric
rings by depth from a root, everything oriented around one thing.
For the reusable prepare/run surface, use the RadialLayout module.
The shared input every layout family consumes: sized nodes and the
edges between them. A node is identified by its index in nodes and
an edge by its index in edges; every output list aligns to those
orders.
Input : Spec
General-graph input is the shared spec itself.
CircularSettings : {
node_gap : F64,
start_angle : F64,
winding : [Clockwise, CounterClockwise],
}
Space between neighbors on the ring, where the first node sits (radians), and which way around the ring the order runs. The radius is derived from node extents and the gap, not configured.
Problem : [
InvalidNodeWidth(U64),
InvalidNodeHeight(U64),
MissingEdgeStart(U64, U64),
MissingEdgeEnd(U64, U64),
InvalidNodeGap,
InvalidStartAngle,
]
Invalid sizes, spacing, or edge endpoints found while checking input.
Result : {
layout : {
positions : List({ x : F64, y : F64 }),
bounds : { x : F64, y : F64, width : F64, height : F64 },
routes : List(Route),
},
order : List(U64),
}
Geometry plus each node's seat around the ring, counted from the start angle in winding order.