Skip to main content
ForceAtlas2 is a force-directed algorithm designed for network visualization.

Forces

ForceEffect
RepulsionAll nodes repel each other (prevents overlap)
AttractionConnected nodes attract each other (clusters related nodes)
GravityPulls nodes toward center (prevents drift)

Parameters

ParameterEffect
gravityCenter pull strength. Higher = tighter clusters
scalingRatioOverall layout scale
edgeWeightInfluenceHow much edge weights affect attraction
strongGravityModePrevents nodes from drifting to infinity
barnesHutThetaApproximation accuracy (performance vs quality)

Barnes-Hut Optimization

Instead of computing n² force interactions, Barnes-Hut groups distant nodes:
O(n²) → O(n log n)
This makes large graphs tractable even on modest GPUs.

Compute Shaders

The core algorithm runs in WGSL compute shaders:
@compute @workgroup_size(256)
fn compute_forces(
    @builtin(global_invocation_id) id: vec3<u32>
) {
    let node_idx = id.x;
    if (node_idx >= uniforms.node_count) { return; }

    var force = vec3<f32>(0.0);

    // Repulsion from all nodes
    for (var i = 0u; i < uniforms.node_count; i++) {
        if (i == node_idx) { continue; }
        let delta = positions[node_idx] - positions[i];
        let dist = max(length(delta), 0.001);
        force += normalize(delta) * (uniforms.repulsion / (dist * dist));
    }

    // Attraction to connected nodes
    // ... edge traversal ...

    // Gravity toward center
    force -= positions[node_idx] * uniforms.gravity;

    forces[node_idx] = force;
}

Adaptive Damping

ForceAtlas2 uses swinging-based adaptive damping:
  • Tracks previous displacement for swing calculation
  • Adaptive speed factor: speed / (1 + sqrt(speed * swing * jitter_tolerance))
  • Convergence improved from 50k to ~1900 iterations (26x faster)

Convergence

The algorithm converges when:
  • Node movements fall below threshold
  • Maximum iterations reached
  • User cancels computation