java.lang.Object
com.portingdeadmods.researchd.client.screens.research.graph.GraphLayoutManager

public class GraphLayoutManager extends Object
TW: This is not for the faint of heart

Sugiyama-style layered graph layout with 4 phases:

Phase 1 — Layer Assignment

Topological sort (Kahn's algorithm). Each node's layer = max(parent layers) + 1. Root is layer 0, children go deeper. Guarantees all parents are above their children.

Phase 2 — Crossing Minimization

Barycenter heuristic: for each layer, position each node at the average index of its connected nodes in the adjacent layer, then sort. Alternates top-down and bottom-up passes (3 iterations) to converge on a low-crossing ordering.

Phase 3 — X Coordinate Assignment

Assigns X positions from the ordering in Phase 2 with guaranteed minimum spacing. Then centers parents over their children's midpoint and resolves any resulting overlaps with a left-to-right scan. Finally centers the whole graph.

Phase 4 — Y Coordinate Assignment (dynamic spacing)

Computes the number of routing channels needed between each pair of adjacent layers (one channel per non-straight edge). Y positions are set so the gap between layers grows to accommodate channels. Channel Y positions are stored in GraphLayoutManager.LayoutResult for the edge router in ResearchGraphWidget.

Edge routing

Done externally by ResearchGraphWidget.calculateLines(), which reads the channel assignments from GraphLayoutManager.LayoutResult. Each non-straight edge gets its own horizontal channel (1px line, 1px gap) — Factorio style.