|
|
- /**
- * 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;
- }
- }
- }
- }
- }
- };
|