Skip to main content

Choosing options

This guide maps what you want a drawing to do to the options that do it. The API docs (cargo doc --open) have the full meaning of each option, and the gallery has pictures of most of them.

Everything below is a field of LayoutOptions. In JSON, send a preset name and a patch with only the fields you change. The layout merges the patch into the preset and rejects an unknown or invalid field with an error that names it:

{ "graph": { "nodes": [], "edges": [] },
"preset": "process_map",
"options": { "routing": { "merge_edges": "both" }, "effort": "thorough" } }

Presets​

presetforwhat it sets
LayoutOptions::layered_default() ("layered")Petri nets, BPMN-like models, most directed graphsleft to right, orthogonal edges, edges preferably enter from the sides, one straight branch per fork/join block
LayoutOptions::process_map() ("process_map")directly-follows graphs and other process mapsthe same, top to bottom, with tighter gaps and start and end nodes centred over their main flow
LayoutOptions::hub_and_spoke() ("hub_and_spoke")dense relationship graphs without a direction of flowtall layer gaps, a tight order axis, compaction, edges on any side
LayoutOptions::hub_and_spoke_flow() ("hub_and_spoke_flow")dense graphs that still have a flow, e.g., an object-type graph of an event loghub_and_spoke spacing with the process-map centring

LayoutOptions::default() is layered_default().

Direction and cycles​

direction is LeftRight or TopBottom. Margins, port hints and lanes mean the same thing in both.

One edge of every cycle has to point backwards. cycles.strategy = MinimumReversal (default) reverses the least total edge weight, which gives the fewest crossings. FollowFlow keeps everything outside a cycle pointing forward, which reads better when the graph has a clear start. If you know which edges are loops (a rework edge, a retry), set Edge::reverse_for_ranking = true on them and the layering treats them as backward edges without guessing. This matters most when every node sits on a cycle, because then no strategy can tell where the flow starts.

Node::rank = RankConstraint::First or Last pins a node to the first or last layer, and Fixed(k) puts nodes that share a k in one layer.

Edge::weight makes an edge shorter and straighter than its neighbours. coords.branch_style = StraightMain, the default in the process presets, draws one branch of every fork/join block straight through.

Ports​

routing.port_sides sets how readily an edge attaches to a border across the flow, e.g., the top or bottom of a node in a left-to-right drawing. From strictest to loosest the values are FacingOnly, FacingPreferred, LongEdgesAny and Any. Node::port_sides overrides it for one node.

routing.centre_ports packs the ends on a border around its middle: Round (default, ellipses only), All or Off.

Edge::source_port and Edge::target_port force a border (PortHint::Side) or a point on it (PortHint::Offset), and a hint always wins. Placement puts the far end of an offset-hinted edge level with the hinted point, so the edge can run straight. The fork/join and main-path straightening passes align node centres and can move it off again.

routing.style = Diagonal draws straight segments between ports instead of orthogonal ones.

Busy drawings​

routing.merge_edges (Forks, Joins or Both) draws the edges that fan out of or into one node on a shared trunk, with a junction dot where they split. It never adds a crossing or a bend.

routing.bundle_parallel, on by default, draws parallel edges between the same two nodes as one bundle of lanes.

effort = Thorough spends more time on crossing minimization. Fast spends less, for interactive use on large graphs.

In SVG, SceneEdge::hop_radius draws a small arc where two edges cross, so a crossing does not look like a junction.

Groups​

Node::group puts nodes into lanes, e.g., one per object type or department.

order.group_lanes = Soft (default) bands the groups where that is cheap. order.group_lane_budget_percent caps the extra crossings and order.group_lane_area_percent the extra width. Both default to 0, which keeps only the bandings that cost no crossings. Raise them for cleaner strips.

order.group_lanes = Strict draws swimlanes, a strip per group whatever it costs, and Layout::lanes returns the strips as rectangles to draw.

Node::lane_key orders the nodes inside a lane.

Nesting​

Set Node::parent to draw a node inside another. Compounds nest to any depth. spacing.compound_padding is the room around the children and spacing.compound_header the extra room at the top for a title. reroute and the tree layout take flat graphs only.

Screen fit​

wrap.viewport_aspect (e.g., 16.0 / 9.0) breaks a long drawing into rows for a viewport of that shape. It is off by default, and strict lanes turn it off.

spacing.layer_gap is the gap between layers and spacing.node_gap the gap between neighbours in a layer. Labels, self-loops and edge bundles reserve their own room on top.

Node::margin keeps room free around a node for content you draw yourself, e.g., a badge or a counter. cross_* keeps neighbours in the layer away and along_* the layers before and after. Nodes stay out of the margin, edges may still pass through it.

Stability​

To filter without the drawing jumping, lay out the full graph once. Then lay out each filtered view with Node::position set to the full drawing's positions and seed_mode = Structure. Nodes keep their layer and their order.

After the user drags a node, call reroute with every node's position. No node moves and the edges are routed around the new positions.

Give nodes a Node::key (an activity name, an id) and the drawing depends only on the graph, not on the order you added nodes and edges in.

Labels​

Edge::label_size reserves room for an edge label, and EdgeRoute::label_anchor returns the centre of that room. labels.placement picks the middle of the gap (GapCentre) or the best of several candidate slots (Candidates).

Input limits​

limits.max_nodes, limits.max_edges and limits.max_dummies reject an input that is too big with LayoutError::TooLarge, before the expensive work starts. Dummies are the routing waypoints of long edges, and they are what grows fastest.