Edges and routers
The layout has two kinds of edges. Both kinds are in Layout.edges, with a route from the border of the source to the border of the target.
| Kind | Comes from | kind |
|---|---|---|
| Tree edges | The tree: a parent and its linked children | "tree" |
| Extra edges | LayoutInput.edges, or the edge statements of the text language | "extra" |
shop nested grid(columns: 2) {
web { home cart }
api nested { orders payments }
}
cart -> orders "checkout"
orders -> paymentsTree edges
Section titled “Tree edges”The option treeEdges selects the tree edges of the output. The default gives an edge to each linked child. A nested child is inside its parent, so it gets no edge by default.
org {
eng nested { web api }
ops { sre data }
}Extra edges
Section titled “Extra edges”An extra edge connects two nodes of the tree, at any depth and in any container. Give the edges in the input:
layout({ root, edges: [ { source: "cart", target: "orders", label: "checkout" }, { id: "pay", source: "orders", target: "payments", data: { weight: 3 } }, ],});idis optional. The default isedge-N, where N is the place of the edge in the list, from 0. A tree edge has the identifierparent->child.labelis optional. Each renderer draws it at the middle of the route.datais optional. The engine copies it to the output and does not read it.
An edge to a node that is not in the tree gives the finding UNKNOWN_EDGE_END, and an edge from a node to itself gives SELF_LOOP. The engine skips both.
Routers
Section titled “Routers”The router draws each edge after the engine places all boxes. The option router selects the router for the layout.
root grid(columns: 3) nested {
a b c
d e f
}
a -> f
c -> d
b -> e "down"| Router | Route |
|---|---|
straight (default) | One segment between the borders of the boxes, on the line between their centers. |
avoid | Horizontal and vertical segments that go around the other boxes, with few bends. It searches a grid for each edge, so it is slower: approximately 3 ms for each edge. When no route exists, it gives the orthogonal route. |
orthogonal | Horizontal and vertical segments. The edge leaves the side of the source that faces the target, and turns at the middle of the gap. When the boxes overlap on that axis, the router draws a straight edge. A tree edge goes in the direction of the strategy of its parent: down for children below the parent. |
An edge between a container and a node inside it goes from center to center, because the two boxes have no clear border between them.
ceo {
cto { web mobile }
cfo { audit }
coo { ops hr sales }
}Write a router
Section titled “Write a router”A router is an object with a type, a description and a route function. The function gets the absolute rectangles of the two boxes, and gives the points of the edge.
import { borderPoint, createEngine, defineRouter } from "ireko";
const curved = defineRouter({ type: "curved", description: "The curved router adds a point to the side of the line between the centers.", route({ source, target }) { const a = { x: source.x + source.width / 2, y: source.y + source.height / 2 }; const b = { x: target.x + target.width / 2, y: target.y + target.height / 2 }; const bend = { x: (a.x + b.x) / 2 - (b.y - a.y) / 6, y: (a.y + b.y) / 2 + (b.x - a.x) / 6 }; return [borderPoint(source, bend), bend, borderPoint(target, bend)]; },});
const engine = createEngine({ routers: [curved] });engine.layout(input, { router: "curved" });The engine examines each route. A router that throws or gives fewer than two finite points gives the finding ROUTER_FAILED, and the engine uses straight for that edge. An unknown router name gives UNKNOWN_ROUTER.
Draw the edges
Section titled “Draw the edges”A route is a list of points. The renderers of ireko draw it as a polyline. To draw curves in your own renderer, use the points as control points. In React Flow, PolylineEdge draws the route of ireko, and React Flow keeps its markers and its labels.