vis.js is a dynamic, browser-based visualization library
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

125 lines
3.6 KiB

/**
* Calculate the forces the nodes apply on eachother based on a repulsion field.
* This field is linearly approximated.
*
* @private
*/
exports._calculateNodeForces = function () {
var dx, dy, distance, fx, fy, combinedClusterSize,
repulsingForce, node1, node2, i, j;
var nodes = this.calculationNodes;
var nodeIndices = this.calculationNodeIndices;
// approximation constants
var b = 5;
var a_base = 0.5 * -b;
// repulsing forces between nodes
var nodeDistance = this.constants.physics.hierarchicalRepulsion.nodeDistance;
var minimumDistance = nodeDistance;
var a = a_base / minimumDistance;
// we loop from i over all but the last entree in the array
// j loops from i+1 to the last. This way we do not double count any of the indices, nor i == j
for (i = 0; i < nodeIndices.length - 1; i++) {
node1 = nodes[nodeIndices[i]];
for (j = i + 1; j < nodeIndices.length; j++) {
node2 = nodes[nodeIndices[j]];
if (node1.level == node2.level) {
dx = node2.x - node1.x;
dy = node2.y - node1.y;
distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 2 * minimumDistance) {
repulsingForce = a * distance + b;
var c = 0.05;
var d = 2 * minimumDistance * 2 * c;
repulsingForce = c * Math.pow(distance,2) - d * distance + d*d/(4*c);
// normalize force with
if (distance == 0) {
distance = 0.01;
}
else {
repulsingForce = repulsingForce / distance;
}
fx = dx * repulsingForce;
fy = dy * repulsingForce;
node1.fx -= fx;
node1.fy -= fy;
node2.fx += fx;
node2.fy += fy;
}
}
}
}
};
/**
* this function calculates the effects of the springs in the case of unsmooth curves.
*
* @private
*/
exports._calculateHierarchicalSpringForces = function () {
var edgeLength, edge, edgeId;
var dx, dy, fx, fy, springForce, distance;
var edges = this.edges;
// forces caused by the edges, modelled as springs
for (edgeId in edges) {
if (edges.hasOwnProperty(edgeId)) {
edge = edges[edgeId];
if (edge.connected) {
// only calculate forces if nodes are in the same sector
if (this.nodes.hasOwnProperty(edge.toId) && this.nodes.hasOwnProperty(edge.fromId)) {
edgeLength = edge.customLength ? edge.length : this.constants.physics.springLength;
// this implies that the edges between big clusters are longer
edgeLength += (edge.to.clusterSize + edge.from.clusterSize - 2) * this.constants.clustering.edgeGrowth;
dx = (edge.from.x - edge.to.x);
dy = (edge.from.y - edge.to.y);
distance = Math.sqrt(dx * dx + dy * dy);
if (distance == 0) {
distance = 0.01;
}
distance = Math.max(0.8*edgeLength,Math.min(5*edgeLength, distance));
// the 1/distance is so the fx and fy can be calculated without sine or cosine.
springForce = this.constants.physics.springConstant * (edgeLength - distance) / distance;
fx = dx * springForce;
fy = dy * springForce;
edge.to.fx -= fx;
edge.to.fy -= fy;
edge.from.fx += fx;
edge.from.fy += fy;
var factor = 5;
if (distance > edgeLength) {
factor = 25;
}
if (edge.from.level > edge.to.level) {
edge.to.fx -= factor*fx;
edge.to.fy -= factor*fy;
}
else if (edge.from.level < edge.to.level) {
edge.from.fx += factor*fx;
edge.from.fy += factor*fy;
}
}
}
}
}
};