Force simulations¶
- detroit.force_simulation(nodes: list[SimulationNode] | None = None) ForceSimulation¶
A force simulation implements a velocity Verlet numerical integrator for simulating physical forces on particles (nodes). The simulation assumes a constant unit time step \(\Delta t = 1\) for each step and a constant unit mass \(m = 1\) for all particles. As a result, a force \(F\) acting on a particle is equivalent to a constant acceleration a over the time interval \(\Delta t\), and can be simulated simply by adding to the particle’s velocity, which is then added to the particle’s position.
- Parameters:
nodes (list[SimulationNode] | None) – List of nodes
- Returns:
Simulation object
- Return type:
- class detroit.force.simulation.ForceSimulation(nodes: list[SimulationNode])¶
- find(x: float, y: float, radius: float | None = None) SimulationNode¶
Returns the node closest to the position \((x,y)\) with the given search radius.
- Parameters:
x (float) – x-coordinate value of the position
y (float) – y-coordinate value of the position
radius (float | None) – Radius value
- Returns:
Closest node
- Return type:
- tick(iterations: float | None = None) ForceSimulation¶
Manually steps the simulation by the specified number of iterations, and returns the simulation. If
iterationsis not specified, it defaults to 1 (single step).For each iteration, it increments the current alpha by
(alpha_target - alpha) * alpha_decay; then invokes each registered force, passing the new alpha; then decrements each node’s velocity byvelocity * velocity_decay; lastly increments each node’s position by velocity.This method does not dispatch events; events are only dispatched by the internal timer when the simulation is started automatically upon creation or by calling simulation.restart. The natural number of ticks when the simulation is started is \(\lceil \log(\alpha_{\text{min}}) / \log(1 - \alpha_{\text{decay}}) \rceil\); by default, this is 300.
This method can be used in conjunction with simulation.stop to compute a static force layout. For large graphs, static layouts should be computed in a web worker to avoid freezing the user interface.
- Parameters:
iterations (float | None) – Number of iterations
- Returns:
Itself
- Return type:
- set_alpha(alpha: float) ForceSimulation¶
It decreases over time as the simulation “cools down”.
- Parameters:
alpha (float) – Alpha value
- Returns:
Itself
- Return type:
- set_alpha_decay(alpha_decay: float) ForceSimulation¶
Sets the alpha decay rate to the specified number in the range \([0,1]\) and returns this simulation.
The alpha decay rate determines how quickly the current alpha interpolates towards the desired target alpha; since the default target alpha is zero, by default this controls how quickly the simulation cools. Higher decay rates cause the simulation to stabilize more quickly, but risk getting stuck in a local minimum; lower values cause the simulation to take longer to run, but typically converge on a better layout. To have the simulation run forever at the current alpha, set the decay rate to zero; alternatively, set a target alpha greater than the minimum alpha.
- Parameters:
alpha_decay (float) – Alpha decay value
- Returns:
Itself
- Return type:
- set_alpha_min(alpha_min: float) ForceSimulation¶
Sets the minimum alpha to the specified number in the range \([0,1]\) and returns this simulation.
The simulation’s internal timer stops when the current alpha is less than the minimum alpha. The default alpha decay rate of ~0.0228 corresponds to 300 iterations.
- Parameters:
alpha_min (float) – Alpha minimum value
- Returns:
Itself
- Return type:
- set_alpha_target(alpha_target: float) ForceSimulation¶
Sets the current target alpha to the specified number in the range \([0,1]\) and returns this simulation.
- Parameters:
alpha_target (float) – Alpha target value
- Returns:
Itself
- Return type:
- set_nodes(nodes: list[SimulationNode]) ForceSimulation¶
Sets the simulation’s nodes to the specified array of objects, initializing their positions and velocities if necessary, and then re-initializes any bound forces; returns the simulation.
Each node must be an dictionary (
dict). The following properties are assigned by the simulation:index (
int) - the node’s zero-based index into nodesx (
float) - the node’s current x-positiony (
float) - the node’s current y-positionvx (
float) - the node’s current x-velocityvy (
float) - the node’s current y-velocityfx (
float) - the node’s fixed x-positionfy (
float) - the node’s fixed y-position
The position \((x,y)\) and velocity \((v_x,v_y)\) may be subsequently modified by forces and by the simulation. If either
vxorvyisnan, the velocity is initialized to \((0,0)\). If eitherxoryisnan, the position is initialized in a phyllotaxis arrangement, so chosen to ensure a deterministic, uniform distribution.At the end of each tick, after the application of any forces, a node with a defined
node["fx"]hasnode["x"]reset to this value andnode["vx"]set to zero; likewise, a node with a definednode["fy"]hasnode["y"]reset to this value andnode["vy"]set to zero. To unfix a node that was previously fixed, setnode["fx"]andnode["fy"]toNone, or delete these properties.If the specified array of nodes is modified, such as when nodes are added to or removed from the simulation, this method must be called again with the new (or changed) array to notify the simulation and bound forces of the change; the simulation does not make a defensive copy of the specified array.
- Parameters:
nodes (list[SimulationNode]) – Array of nodes
- Returns:
Itself
- Return type:
- set_random_source(random_source: Callable[[None], float]) ForceSimulation¶
Sets the function used to generate random numbers; this should be a function that returns a number between 0 (inclusive) and 1 (exclusive). If source is not specified, returns this simulation’s current random source which defaults to a fixed-seed linear congruential generator.
- Parameters:
random_source (Callable[[None], float]) – Random source function
- Returns:
Itself
- Return type:
- set_velocity_decay(velocity_decay: float) ForceSimulation¶
Sets the velocity decay factor to the specified number in the range \([0,1]\) and returns this simulation.
The decay factor is akin to atmospheric friction; after the application of any forces during a tick, each node’s velocity is multiplied by
1 - decay. As with lowering the alpha decay rate, less velocity decay may converge on a better solution, but risks numerical instabilities and oscillation.- Parameters:
velocity_decay (float) – Velocity decay value
- Returns:
Itself
- Return type: