Edge Bundling
Groups edges with similar paths into bundles, reducing visual clutter. Two algorithms: FDEB (high quality, expensive) and merge (cheap aggregation).
Usage
Enable bundling at creation via the edgeBundling option, or
toggle at runtime via app.bundleEdges() /
app.unbundleEdges().
import { create } from '@topokit/renderer-canvas';
const app = create(container, {
nodes: networkData.nodes,
edges: networkData.edges,
layout: 'force',
theme: 'dark',
// Boolean — auto-pivot between fdeb and merge by edge count
edgeBundling: true,
// Or pick an algorithm explicitly
// edgeBundling: 'fdeb',
// edgeBundling: 'merge',
// Or pass an options object
// edgeBundling: { algorithm: 'fdeb', strength: 0.85 },
});
// Toggle at runtime
app.bundleEdges({ strength: 0.9 });
app.unbundleEdges(); edgeBundling option values
| Value | Behavior |
|---|---|
false (default) | Off. Edges render straight. |
true | Auto-pivot: fdeb when edge count < 150, merge at ≥ 150. See Auto-pivot. |
'fdeb' | Force-Directed Edge Bundling (Holten & van Wijk 2009). Best visual quality. |
'merge' | Aggregate edges sharing the same source/target cluster pair into a single representative path. Cheap O(E). |
{ algorithm, ...rest } | Object form. algorithm selects fdeb/merge; remaining keys tune the chosen algorithm. |
Auto-pivot rule
FDEB is O(E²·I) and gets impractical beyond ~150 edges. With
edgeBundling: true (no explicit algorithm), TopoKit picks
fdeb below the
FDEB_AUTO_FALLBACK_EDGE_COUNT threshold (150) and falls back
to merge at or above it. Pass
algorithm: 'fdeb' explicitly to bypass the pivot.
FDEB tuning knobs
| Option | Type | Default | Description |
|---|---|---|---|
strength | number | 0.85 | Edge attraction (0–1). Higher = tighter bundles. |
compatibility | number | 0.65 | Minimum pairwise compatibility for two edges to attract. |
subdivisions | number | 8 | Edge subdivision count. |
iterations | number | 60 | Iteration budget across all cycles (FDEB runs 4 cycles). |
Defaults are tuned for visual quality. Lowering them produces noticeably
less convincing curves — if FDEB is too slow, prefer
algorithm: 'merge' over weakened FDEB.
merge tuning knobs
| Option | Type | Default | Description |
|---|---|---|---|
groupKey | (nodeId: string) => string | group by node.parent ?? nodeId | Maps a node id to its cluster id. When omitted, merge groups by raw (source, target) — useful for parallel-edge merge. |
// Collapse fan-in by region into a single bundle per (region, region) pair
app.bundleEdges({
algorithm: 'merge',
groupKey: (nodeId) => app.graph.getNode(nodeId)?.data.region ?? nodeId,
}); Synthetic combo edges are excluded
When a combo is collapsed (see Core Concepts → Combo edge synthesis),
TopoKit replaces real cross-boundary edges with synthetic
__combo_edge_* aggregates. The bundler skips these automatically
in both fdeb and merge — no user action needed.
Performance
- FDEB scales poorly with edge count: ~2s at 100 edges, ~40s at 1,000 edges with the locked-default quality knobs.
- merge is O(E) and runs in milliseconds at any practical size.
- Combine with Web Worker for large graphs.
Next Steps
- Clustering -- group nodes to simplify graphs
- Filtering -- reduce edge count before bundling
- Web Worker -- offload bundling computation