Drawing graphs is a difficult problem that has been studied for many years. Constellation Framework uses behavior modules to control the layout of the nodes using a force-directed approach. Each behavior module has a specific effect on each node's physics. By combining these behaviors and tweaking their settings you can effectively place nodes in the visualization.
This tutorial will look at a typical list of behaviors and go over what each one is doing.
Configuring Constellation to use a particular set of behaviors is super easy. Just set the behaviors property of the Constellation component. Here's an example.
constellation.behaviors =
[
new ZeroAccelerationBehavior(),
new AgoraphobeBehavior(0.2, 250),
new EdgeAttractionBehavior(0.2, 100),
new AccelerationLimitBehavior(6),
new BasicKinematicsBehavior(),
new DampingBehavior(0.3),
new BoundsAutoCenteringBehavior(),
new DraggingBehavior()
];
During each step of Constellation's physics engine, each behavior has a chance to affect each node's acceleration, velocity, and position. In this section we'll go over what each of the behaviors in the above code sample actually do.
Note that the ordering of the behaviors is very important and they're each processed in the given order.
The zero acceleration behavior has a very simple task. As the name implies, it sets each node's acceleration to zero. This prevents forces calculated in the previous step from affecting this step. For typical physics implementations, this behavior is the first behavior in the list.
This is the behavior that causes nodes to push away from each other. The constructor takes two arguments: a force factor for the repulsion and the comfort distance. When two nodes are far enough apart there will be no effect but if they're closer than the comfort distance, this behavior will cause them to repel each other.
This behavior is responsible for causing connected nodes to move toward each other. It takes the force factor of the attraction and the desired distance between edges as parameters. If a node is within the given distance from all its neighbors, this behavior has no effect. However, if any two connected nodes are farther apart, there will be a force exerted to bring them closer to each other.
The acceleration limit behavior does just that: it puts a cap on the node's acceleration magnitude. Any node with a higher acceleration has it reduced to the maximum.
This behavior does most of the work in simulating Newton's motion. Acceleration is added to velocity and velocity to position. Any set of behaviors used for force-directed layout will have this in there somewhere.
The damping behavior reduces the velocity of the nodes by some factor. Without damping, the nodes would oscillate endlessly. The sole parameter taken by the constructor sets the damping factor.
This behavior is used to center the visualization on the screen. It does this by measuring the bounds of the visualization using the getBounds() method. The bounds auto-centering behavior accepts the scroll rate as a parameter so you can change how fast the visualization is centered.
Many visualizations allow users to drag nodes around. This behavior is responsible for that interactivity. Since you'll want this behavior to override any of the physical forces that are affecting the node, it should be placed at the end of the list of behaviors.
Note that this behavior has no effect unless the node renderers in the visualization implement the IDraggableNodeRenderer interface.
If the built-in behaviors can't do what you need, you can override the BaseBehavior class to create your own. Then you can combine Framework's behaviors and/or your custom behaviors to get the layout algorithm that you're looking for.