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.

88 lines
2.8 KiB

  1. /**
  2. * Created by Alex on 2/23/2015.
  3. */
  4. class SpringSolver {
  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. * This function calculates the springforces on the nodes, accounting for the support nodes.
  15. *
  16. * @private
  17. */
  18. solve() {
  19. var edgeLength, edge;
  20. var edgeIndices = this.physicsBody.physicsEdgeIndices;
  21. var edges = this.body.edges;
  22. // forces caused by the edges, modelled as springs
  23. for (let i = 0; i < edgeIndices.length; i++) {
  24. edge = edges[edgeIndices[i]];
  25. if (edge.connected === true) {
  26. // only calculate forces if nodes are in the same sector
  27. if (this.body.nodes[edge.toId] !== undefined && this.body.nodes[edge.fromId] !== undefined) {
  28. if (edge.edgeType.via !== undefined) {
  29. edgeLength = edge.options.length === undefined ? this.options.springLength : edge.options.length;
  30. var node1 = edge.to;
  31. var node2 = edge.edgeType.via;
  32. var node3 = edge.from;
  33. this._calculateSpringForce(node1, node2, 0.5 * edgeLength);
  34. this._calculateSpringForce(node2, node3, 0.5 * edgeLength);
  35. }
  36. else {
  37. // the * 1.5 is here so the edge looks as large as a smooth edge. It does not initially because the smooth edges use
  38. // the support nodes which exert a repulsive force on the to and from nodes, making the edge appear larger.
  39. edgeLength = edge.options.length === undefined ? this.options.springLength * 1.5: edge.options.length;
  40. this._calculateSpringForce(edge.from, edge.to, edgeLength);
  41. }
  42. }
  43. }
  44. }
  45. }
  46. /**
  47. * This is the code actually performing the calculation for the function above.
  48. *
  49. * @param node1
  50. * @param node2
  51. * @param edgeLength
  52. * @private
  53. */
  54. _calculateSpringForce(node1, node2, edgeLength) {
  55. var dx, dy, fx, fy, springForce, distance;
  56. dx = (node1.x - node2.x);
  57. dy = (node1.y - node2.y);
  58. distance = Math.sqrt(dx * dx + dy * dy);
  59. distance = distance === 0 ? 0.01 : distance;
  60. // the 1/distance is so the fx and fy can be calculated without sine or cosine.
  61. springForce = this.options.springConstant * (edgeLength - distance) / distance;
  62. fx = dx * springForce;
  63. fy = dy * springForce;
  64. // handle the case where one node is not part of the physcis
  65. if (this.physicsBody.forces[node1.id] !== undefined) {
  66. this.physicsBody.forces[node1.id].x += fx;
  67. this.physicsBody.forces[node1.id].y += fy;
  68. }
  69. if (this.physicsBody.forces[node2.id] !== undefined) {
  70. this.physicsBody.forces[node2.id].x -= fx;
  71. this.physicsBody.forces[node2.id].y -= fy;
  72. }
  73. }
  74. }
  75. export default SpringSolver;