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.

75 lines
2.1 KiB

  1. /**
  2. *
  3. * @param {Object} body
  4. * @param {{physicsNodeIndices: Array, physicsEdgeIndices: Array, forces: {}, velocities: {}}} physicsBody
  5. * @param {Object} options
  6. * @constructor HierarchicalRepulsionSolver
  7. */
  8. class HierarchicalRepulsionSolver {
  9. constructor(body, physicsBody, options) {
  10. this.body = body;
  11. this.physicsBody = physicsBody;
  12. this.setOptions(options);
  13. }
  14. setOptions(options) {
  15. this.options = options;
  16. }
  17. /**
  18. * Calculate the forces the nodes apply on each other based on a repulsion field.
  19. * This field is linearly approximated.
  20. *
  21. * @private
  22. */
  23. solve() {
  24. var dx, dy, distance, fx, fy, repulsingForce, node1, node2, i, j;
  25. var nodes = this.body.nodes;
  26. var nodeIndices = this.physicsBody.physicsNodeIndices;
  27. var forces = this.physicsBody.forces;
  28. // repulsing forces between nodes
  29. var nodeDistance = this.options.nodeDistance;
  30. // we loop from i over all but the last entree in the array
  31. // j loops from i+1 to the last. This way we do not double count any of the indices, nor i === j
  32. for (i = 0; i < nodeIndices.length - 1; i++) {
  33. node1 = nodes[nodeIndices[i]];
  34. for (j = i + 1; j < nodeIndices.length; j++) {
  35. node2 = nodes[nodeIndices[j]];
  36. // nodes only affect nodes on their level
  37. if (node1.level === node2.level) {
  38. dx = node2.x - node1.x;
  39. dy = node2.y - node1.y;
  40. distance = Math.sqrt(dx * dx + dy * dy);
  41. var steepness = 0.05;
  42. if (distance < nodeDistance) {
  43. repulsingForce = -Math.pow(steepness * distance, 2) + Math.pow(steepness * nodeDistance, 2);
  44. }
  45. else {
  46. repulsingForce = 0;
  47. }
  48. // normalize force with
  49. if (distance === 0) {
  50. distance = 0.01;
  51. }
  52. else {
  53. repulsingForce = repulsingForce / distance;
  54. }
  55. fx = dx * repulsingForce;
  56. fy = dy * repulsingForce;
  57. forces[node1.id].x -= fx;
  58. forces[node1.id].y -= fy;
  59. forces[node2.id].x += fx;
  60. forces[node2.id].y += fy;
  61. }
  62. }
  63. }
  64. }
  65. }
  66. export default HierarchicalRepulsionSolver;