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.

132 lines
3.9 KiB

  1. /**
  2. * Created by Alex on 2/10/14.
  3. */
  4. var hierarchalRepulsionMixin = {
  5. /**
  6. * Calculate the forces the nodes apply on eachother based on a repulsion field.
  7. * This field is linearly approximated.
  8. *
  9. * @private
  10. */
  11. _calculateNodeForces: function () {
  12. var dx, dy, distance, fx, fy, combinedClusterSize,
  13. repulsingForce, node1, node2, i, j;
  14. var nodes = this.calculationNodes;
  15. var nodeIndices = this.calculationNodeIndices;
  16. // approximation constants
  17. var b = 5;
  18. var a_base = 0.5 * -b;
  19. // repulsing forces between nodes
  20. var nodeDistance = this.constants.physics.hierarchicalRepulsion.nodeDistance;
  21. var minimumDistance = nodeDistance;
  22. var a = a_base / minimumDistance;
  23. // we loop from i over all but the last entree in the array
  24. // j loops from i+1 to the last. This way we do not double count any of the indices, nor i == j
  25. for (i = 0; i < nodeIndices.length - 1; i++) {
  26. node1 = nodes[nodeIndices[i]];
  27. for (j = i + 1; j < nodeIndices.length; j++) {
  28. node2 = nodes[nodeIndices[j]];
  29. if (node1.level == node2.level) {
  30. dx = node2.x - node1.x;
  31. dy = node2.y - node1.y;
  32. distance = Math.sqrt(dx * dx + dy * dy);
  33. if (distance < 2 * minimumDistance) {
  34. repulsingForce = a * distance + b;
  35. var c = 0.05;
  36. var d = 2 * minimumDistance * 2 * c;
  37. repulsingForce = c * Math.pow(distance,2) - d * distance + d*d/(4*c);
  38. // normalize force with
  39. if (distance == 0) {
  40. distance = 0.01;
  41. }
  42. else {
  43. repulsingForce = repulsingForce / distance;
  44. }
  45. fx = dx * repulsingForce;
  46. fy = dy * repulsingForce;
  47. node1.fx -= fx;
  48. node1.fy -= fy;
  49. node2.fx += fx;
  50. node2.fy += fy;
  51. }
  52. }
  53. }
  54. }
  55. },
  56. /**
  57. * this function calculates the effects of the springs in the case of unsmooth curves.
  58. *
  59. * @private
  60. */
  61. _calculateHierarchicalSpringForces: function () {
  62. var edgeLength, edge, edgeId;
  63. var dx, dy, fx, fy, springForce, distance;
  64. var edges = this.edges;
  65. // forces caused by the edges, modelled as springs
  66. for (edgeId in edges) {
  67. if (edges.hasOwnProperty(edgeId)) {
  68. edge = edges[edgeId];
  69. if (edge.connected) {
  70. // only calculate forces if nodes are in the same sector
  71. if (this.nodes.hasOwnProperty(edge.toId) && this.nodes.hasOwnProperty(edge.fromId)) {
  72. edgeLength = edge.customLength ? edge.length : this.constants.physics.springLength;
  73. // this implies that the edges between big clusters are longer
  74. edgeLength += (edge.to.clusterSize + edge.from.clusterSize - 2) * this.constants.clustering.edgeGrowth;
  75. dx = (edge.from.x - edge.to.x);
  76. dy = (edge.from.y - edge.to.y);
  77. distance = Math.sqrt(dx * dx + dy * dy);
  78. if (distance == 0) {
  79. distance = 0.01;
  80. }
  81. distance = Math.max(0.8*edgeLength,Math.min(5*edgeLength, distance));
  82. // the 1/distance is so the fx and fy can be calculated without sine or cosine.
  83. springForce = this.constants.physics.springConstant * (edgeLength - distance) / distance;
  84. fx = dx * springForce;
  85. fy = dy * springForce;
  86. edge.to.fx -= fx;
  87. edge.to.fy -= fy;
  88. edge.from.fx += fx;
  89. edge.from.fy += fy;
  90. var factor = 5;
  91. if (distance > edgeLength) {
  92. factor = 25;
  93. }
  94. if (edge.from.level > edge.to.level) {
  95. edge.to.fx -= factor*fx;
  96. edge.to.fy -= factor*fy;
  97. }
  98. else if (edge.from.level < edge.to.level) {
  99. edge.from.fx += factor*fx;
  100. edge.from.fy += factor*fy;
  101. }
  102. }
  103. }
  104. }
  105. }
  106. }
  107. };