It's unlikely that you'll need to implement a custom two-layer operator as this is already a heuristic solution to decrossing. However, in the event that you do, we illustrate how to implement one where the order is stored in the original nodes. Here dummy nodes (nodes that exist on long edges between "real" nodes) are ordered according to the average value of their source and target nodes.
function myTwoLayer(topLayer: SugiNode<{ ord: number }, unknown>[], bottomLayer: SugiNode<{ ord: number }, unknown>[], topDown: boolean): void {
let mutate = topDown ? bottomLayer : topLayer;
const vals = new Map<SugiNode, number>();
for (const node of mutate) {
const { data } = node;
const val = data.role === "node" ? data.node.data.ord ? (data.link.source.data.ord + data.link.target.data.ord) / 2;
vals.set(node, val);
}
layer.sort((a, b) => vals.get(a)! - vals.get(b)!);
}
an operator for optimizing decrossings one layer at a time.
This is used to customize DecrossTwoLayer.
When called with
topDown = truetopLayershould be untouched, andbottomLayershould be rearranged to minimize crossings. WhentopDown = falsethentopLayershould be rearranged, andbottomLayershould remain fixed. There are no requirements for how these needs to order nodes, but doing so in such a way to minimize edge crossings is usually desired.