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.

74 lines
2.1 KiB

  1. /**
  2. * Created by Alex on 2/23/2015.
  3. */
  4. class RepulsionSolver {
  5. constructor(body, physicsBody, options) {
  6. this.body = body;
  7. this.physicsBody = physicsBody;
  8. this.setOptions(options);
  9. }
  10. setOptions(options) {
  11. this.options = options;
  12. }
  13. /**
  14. * Calculate the forces the nodes apply on each other based on a repulsion field.
  15. * This field is linearly approximated.
  16. *
  17. * @private
  18. */
  19. solve() {
  20. var dx, dy, distance, fx, fy, repulsingForce, node1, node2;
  21. var nodes = this.physicsBody.calculationNodes;
  22. var nodeIndices = this.physicsBody.calculationNodeIndices;
  23. var forces = this.physicsBody.forces;
  24. // repulsing forces between nodes
  25. var nodeDistance = this.options.nodeDistance;
  26. // approximation constants
  27. var a = (-2 / 3) / nodeDistance;
  28. var b = 4 / 3;
  29. // we loop from i over all but the last entree in the array
  30. // j loops from i+1 to the last. This way we do not double count any of the indices, nor i == j
  31. for (let i = 0; i < nodeIndices.length - 1; i++) {
  32. node1 = nodes[nodeIndices[i]];
  33. for (let j = i + 1; j < nodeIndices.length; j++) {
  34. node2 = nodes[nodeIndices[j]];
  35. dx = node2.x - node1.x;
  36. dy = node2.y - node1.y;
  37. distance = Math.sqrt(dx * dx + dy * dy);
  38. // same condition as BarnesHutSolver, making sure nodes are never 100% overlapping.
  39. if (distance == 0) {
  40. distance = 0.1*Math.random();
  41. dx = distance;
  42. }
  43. if (distance < 2 * nodeDistance) {
  44. if (distance < 0.5 * nodeDistance) {
  45. repulsingForce = 1.0;
  46. }
  47. else {
  48. repulsingForce = a * distance + b; // linear approx of 1 / (1 + Math.exp((distance / nodeDistance - 1) * steepness))
  49. }
  50. repulsingForce = repulsingForce / distance;
  51. fx = dx * repulsingForce;
  52. fy = dy * repulsingForce;
  53. forces[node1.id].x -= fx;
  54. forces[node1.id].y -= fy;
  55. forces[node2.id].x += fx;
  56. forces[node2.id].y += fy;
  57. }
  58. }
  59. }
  60. }
  61. }
  62. export {RepulsionSolver};