This repository was archived by the owner on Jun 18, 2026. It is now read-only.
Commit bd7fa26
committed
feat: add Fruchterman-Reingold force-directed graph layout
Implements the classic Fruchterman-Reingold force-directed layout
algorithm for computing aesthetically pleasing 2D positions for
graph vertices. This is the foundational layout algorithm for
graph visualization — the repo's namesake.
Algorithm:
- Repulsive forces between all vertex pairs (Coulomb's law)
- Attractive forces along edges (Hooke's law with dist²/k)
- Simulated annealing cooling schedule for convergence
- Optional gravity force to keep disconnected components grouped
- Edge-weight awareness (heavier edges pull more strongly)
- Deterministic seeding for reproducible layouts
- Convergence detection via energy delta tracking
Layout quality metrics:
- Edge crossing count (line segment intersection test)
- Edge length uniformity (coefficient of variation)
- Minimum angular resolution (smallest inter-edge angle)
- Stress (Kruskal's stress: graph distance vs Euclidean distance)
Output:
- Raw positions: getPosition(vertex), getPositions()
- Normalized positions for arbitrary viewport with padding
- SVG export with styled edges, nodes, and labels
- Text summary with all quality metrics
Complexity: O(iterations × (V² + E))
Suitable for graphs up to ~5000 nodes.
29 tests covering constructor validation, deterministic seeding,
connected-vs-disconnected distance, edge weight effects, gravity
behavior, normalized positions, quality metrics, SVG export,
convergence, and idempotency.1 parent b99f763 commit bd7fa26
2 files changed
Lines changed: 1266 additions & 0 deletions
0 commit comments