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.

1483 lines
55 KiB

  1. /**
  2. * vis.js
  3. * https://github.com/almende/vis
  4. *
  5. * A dynamic, browser-based visualization library.
  6. *
  7. * @version 4.9.1-SNAPSHOT
  8. * @date 2015-10-05
  9. *
  10. * @license
  11. * Copyright (C) 2011-2015 Almende B.V, http://almende.com
  12. *
  13. * Vis.js is dual licensed under both
  14. *
  15. * * The Apache 2.0 License
  16. * http://www.apache.org/licenses/LICENSE-2.0
  17. *
  18. * and
  19. *
  20. * * The MIT License
  21. * http://opensource.org/licenses/MIT
  22. *
  23. * Vis.js may be distributed under either license.
  24. */
  25. "use strict";
  26. /******/ (function(modules) { // webpackBootstrap
  27. /******/ // The module cache
  28. /******/ var installedModules = {};
  29. /******/ // The require function
  30. /******/ function __webpack_require__(moduleId) {
  31. /******/ // Check if module is in cache
  32. /******/ if(installedModules[moduleId])
  33. /******/ return installedModules[moduleId].exports;
  34. /******/ // Create a new module (and put it into the cache)
  35. /******/ var module = installedModules[moduleId] = {
  36. /******/ exports: {},
  37. /******/ id: moduleId,
  38. /******/ loaded: false
  39. /******/ };
  40. /******/ // Execute the module function
  41. /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
  42. /******/ // Flag the module as loaded
  43. /******/ module.loaded = true;
  44. /******/ // Return the exports of the module
  45. /******/ return module.exports;
  46. /******/ }
  47. /******/ // expose the modules object (__webpack_modules__)
  48. /******/ __webpack_require__.m = modules;
  49. /******/ // expose the module cache
  50. /******/ __webpack_require__.c = installedModules;
  51. /******/ // __webpack_public_path__
  52. /******/ __webpack_require__.p = "";
  53. /******/ // Load entry module and return exports
  54. /******/ return __webpack_require__(0);
  55. /******/ })
  56. /************************************************************************/
  57. /******/ ([
  58. /* 0 */
  59. /***/ function(module, exports, __webpack_require__) {
  60. 'use strict';
  61. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  62. var _PhysicsWorkerJs = __webpack_require__(1);
  63. var _PhysicsWorkerJs2 = _interopRequireDefault(_PhysicsWorkerJs);
  64. var physicsWorker = new _PhysicsWorkerJs2['default'](function (data) {
  65. return postMessage(data);
  66. });
  67. self.addEventListener('message', function (event) {
  68. return physicsWorker.handleMessage(event);
  69. }, false);
  70. /***/ },
  71. /* 1 */
  72. /***/ function(module, exports, __webpack_require__) {
  73. 'use strict';
  74. Object.defineProperty(exports, '__esModule', {
  75. value: true
  76. });
  77. var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
  78. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  79. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
  80. var _componentsPhysicsBarnesHutSolver = __webpack_require__(2);
  81. var _componentsPhysicsBarnesHutSolver2 = _interopRequireDefault(_componentsPhysicsBarnesHutSolver);
  82. var _componentsPhysicsRepulsionSolver = __webpack_require__(3);
  83. var _componentsPhysicsRepulsionSolver2 = _interopRequireDefault(_componentsPhysicsRepulsionSolver);
  84. var _componentsPhysicsHierarchicalRepulsionSolver = __webpack_require__(4);
  85. var _componentsPhysicsHierarchicalRepulsionSolver2 = _interopRequireDefault(_componentsPhysicsHierarchicalRepulsionSolver);
  86. var _componentsPhysicsSpringSolver = __webpack_require__(5);
  87. var _componentsPhysicsSpringSolver2 = _interopRequireDefault(_componentsPhysicsSpringSolver);
  88. var _componentsPhysicsHierarchicalSpringSolver = __webpack_require__(6);
  89. var _componentsPhysicsHierarchicalSpringSolver2 = _interopRequireDefault(_componentsPhysicsHierarchicalSpringSolver);
  90. var _componentsPhysicsCentralGravitySolver = __webpack_require__(7);
  91. var _componentsPhysicsCentralGravitySolver2 = _interopRequireDefault(_componentsPhysicsCentralGravitySolver);
  92. var _componentsPhysicsFA2BasedRepulsionSolver = __webpack_require__(8);
  93. var _componentsPhysicsFA2BasedRepulsionSolver2 = _interopRequireDefault(_componentsPhysicsFA2BasedRepulsionSolver);
  94. var _componentsPhysicsFA2BasedCentralGravitySolver = __webpack_require__(9);
  95. var _componentsPhysicsFA2BasedCentralGravitySolver2 = _interopRequireDefault(_componentsPhysicsFA2BasedCentralGravitySolver);
  96. var PhysicsWorker = (function () {
  97. function PhysicsWorker(postMessage) {
  98. _classCallCheck(this, PhysicsWorker);
  99. this.body = {};
  100. this.physicsBody = { physicsNodeIndices: [], physicsEdgeIndices: [], forces: {}, velocities: {} };
  101. this.postMessage = postMessage;
  102. this.options = {};
  103. this.stabilized = false;
  104. this.previousStates = {};
  105. this.positions = {};
  106. this.timestep = 0.5;
  107. }
  108. _createClass(PhysicsWorker, [{
  109. key: 'handleMessage',
  110. value: function handleMessage(event) {
  111. var msg = event.data;
  112. switch (msg.type) {
  113. case 'calculateForces':
  114. this.calculateForces();
  115. this.moveNodes();
  116. this.postMessage({
  117. type: 'positions',
  118. data: {
  119. positions: this.positions,
  120. stabilized: this.stabilized
  121. }
  122. });
  123. break;
  124. case 'update':
  125. var node = this.body.nodes[msg.data.id];
  126. node.x = msg.data.x;
  127. node.y = msg.data.y;
  128. break;
  129. case 'options':
  130. this.options = msg.data;
  131. this.timestep = this.options.timestep;
  132. this.init();
  133. break;
  134. case 'physicsObjects':
  135. this.body.nodes = msg.data.nodes;
  136. this.body.edges = msg.data.edges;
  137. this.updatePhysicsData();
  138. break;
  139. default:
  140. console.warn('unknown message from PhysicsEngine', msg);
  141. }
  142. }
  143. /**
  144. * configure the engine.
  145. */
  146. }, {
  147. key: 'init',
  148. value: function init() {
  149. var options;
  150. if (this.options.solver === 'forceAtlas2Based') {
  151. options = this.options.forceAtlas2Based;
  152. this.nodesSolver = new _componentsPhysicsFA2BasedRepulsionSolver2['default'](this.body, this.physicsBody, options);
  153. this.edgesSolver = new _componentsPhysicsSpringSolver2['default'](this.body, this.physicsBody, options);
  154. this.gravitySolver = new _componentsPhysicsFA2BasedCentralGravitySolver2['default'](this.body, this.physicsBody, options);
  155. } else if (this.options.solver === 'repulsion') {
  156. options = this.options.repulsion;
  157. this.nodesSolver = new _componentsPhysicsRepulsionSolver2['default'](this.body, this.physicsBody, options);
  158. this.edgesSolver = new _componentsPhysicsSpringSolver2['default'](this.body, this.physicsBody, options);
  159. this.gravitySolver = new _componentsPhysicsCentralGravitySolver2['default'](this.body, this.physicsBody, options);
  160. } else if (this.options.solver === 'hierarchicalRepulsion') {
  161. options = this.options.hierarchicalRepulsion;
  162. this.nodesSolver = new _componentsPhysicsHierarchicalRepulsionSolver2['default'](this.body, this.physicsBody, options);
  163. this.edgesSolver = new _componentsPhysicsHierarchicalSpringSolver2['default'](this.body, this.physicsBody, options);
  164. this.gravitySolver = new _componentsPhysicsCentralGravitySolver2['default'](this.body, this.physicsBody, options);
  165. } else {
  166. // barnesHut
  167. options = this.options.barnesHut;
  168. this.nodesSolver = new _componentsPhysicsBarnesHutSolver2['default'](this.body, this.physicsBody, options);
  169. this.edgesSolver = new _componentsPhysicsSpringSolver2['default'](this.body, this.physicsBody, options);
  170. this.gravitySolver = new _componentsPhysicsCentralGravitySolver2['default'](this.body, this.physicsBody, options);
  171. }
  172. this.modelOptions = options;
  173. }
  174. /**
  175. * Nodes and edges can have the physics toggles on or off. A collection of indices is created here so we can skip the check all the time.
  176. *
  177. * @private
  178. */
  179. }, {
  180. key: 'updatePhysicsData',
  181. value: function updatePhysicsData() {
  182. this.physicsBody.forces = {};
  183. this.physicsBody.physicsNodeIndices = [];
  184. this.physicsBody.physicsEdgeIndices = [];
  185. var nodes = this.body.nodes;
  186. var edges = this.body.edges;
  187. // get node indices for physics
  188. for (var nodeId in nodes) {
  189. if (nodes.hasOwnProperty(nodeId)) {
  190. this.physicsBody.physicsNodeIndices.push(nodeId);
  191. this.positions[nodeId] = {
  192. x: nodes[nodeId].x,
  193. y: nodes[nodeId].y
  194. };
  195. }
  196. }
  197. // get edge indices for physics
  198. for (var edgeId in edges) {
  199. if (edges.hasOwnProperty(edgeId)) {
  200. this.physicsBody.physicsEdgeIndices.push(edgeId);
  201. }
  202. }
  203. // get the velocity and the forces vector
  204. for (var i = 0; i < this.physicsBody.physicsNodeIndices.length; i++) {
  205. var nodeId = this.physicsBody.physicsNodeIndices[i];
  206. this.physicsBody.forces[nodeId] = { x: 0, y: 0 };
  207. // forces can be reset because they are recalculated. Velocities have to persist.
  208. if (this.physicsBody.velocities[nodeId] === undefined) {
  209. this.physicsBody.velocities[nodeId] = { x: 0, y: 0 };
  210. }
  211. }
  212. // clean deleted nodes from the velocity vector
  213. for (var nodeId in this.physicsBody.velocities) {
  214. if (nodes[nodeId] === undefined) {
  215. delete this.physicsBody.velocities[nodeId];
  216. }
  217. }
  218. // console.log(this.physicsBody);
  219. }
  220. /**
  221. * move the nodes one timestap and check if they are stabilized
  222. * @returns {boolean}
  223. */
  224. }, {
  225. key: 'moveNodes',
  226. value: function moveNodes() {
  227. var nodeIndices = this.physicsBody.physicsNodeIndices;
  228. var maxVelocity = this.options.maxVelocity ? this.options.maxVelocity : 1e9;
  229. var maxNodeVelocity = 0;
  230. for (var i = 0; i < nodeIndices.length; i++) {
  231. var nodeId = nodeIndices[i];
  232. var nodeVelocity = this._performStep(nodeId, maxVelocity);
  233. // stabilized is true if stabilized is true and velocity is smaller than vmin --> all nodes must be stabilized
  234. maxNodeVelocity = Math.max(maxNodeVelocity, nodeVelocity);
  235. }
  236. // evaluating the stabilized and adaptiveTimestepEnabled conditions
  237. this.stabilized = maxNodeVelocity < this.options.minVelocity;
  238. }
  239. /**
  240. * Perform the actual step
  241. *
  242. * @param nodeId
  243. * @param maxVelocity
  244. * @returns {number}
  245. * @private
  246. */
  247. }, {
  248. key: '_performStep',
  249. value: function _performStep(nodeId, maxVelocity) {
  250. var node = this.body.nodes[nodeId];
  251. var timestep = this.timestep;
  252. var forces = this.physicsBody.forces;
  253. var velocities = this.physicsBody.velocities;
  254. // store the state so we can revert
  255. this.previousStates[nodeId] = { x: node.x, y: node.y, vx: velocities[nodeId].x, vy: velocities[nodeId].y };
  256. if (node.options.fixed.x === false) {
  257. var dx = this.modelOptions.damping * velocities[nodeId].x; // damping force
  258. var ax = (forces[nodeId].x - dx) / node.options.mass; // acceleration
  259. velocities[nodeId].x += ax * timestep; // velocity
  260. velocities[nodeId].x = Math.abs(velocities[nodeId].x) > maxVelocity ? velocities[nodeId].x > 0 ? maxVelocity : -maxVelocity : velocities[nodeId].x;
  261. node.x += velocities[nodeId].x * timestep; // position
  262. this.positions[nodeId].x = node.x;
  263. } else {
  264. forces[nodeId].x = 0;
  265. velocities[nodeId].x = 0;
  266. }
  267. if (node.options.fixed.y === false) {
  268. var dy = this.modelOptions.damping * velocities[nodeId].y; // damping force
  269. var ay = (forces[nodeId].y - dy) / node.options.mass; // acceleration
  270. velocities[nodeId].y += ay * timestep; // velocity
  271. velocities[nodeId].y = Math.abs(velocities[nodeId].y) > maxVelocity ? velocities[nodeId].y > 0 ? maxVelocity : -maxVelocity : velocities[nodeId].y;
  272. node.y += velocities[nodeId].y * timestep; // position
  273. this.positions[nodeId].y = node.y;
  274. } else {
  275. forces[nodeId].y = 0;
  276. velocities[nodeId].y = 0;
  277. }
  278. var totalVelocity = Math.sqrt(Math.pow(velocities[nodeId].x, 2) + Math.pow(velocities[nodeId].y, 2));
  279. return totalVelocity;
  280. }
  281. /**
  282. * calculate the forces for one physics iteration.
  283. */
  284. }, {
  285. key: 'calculateForces',
  286. value: function calculateForces() {
  287. this.gravitySolver.solve();
  288. this.nodesSolver.solve();
  289. this.edgesSolver.solve();
  290. }
  291. }]);
  292. return PhysicsWorker;
  293. })();
  294. exports['default'] = PhysicsWorker;
  295. module.exports = exports['default'];
  296. /***/ },
  297. /* 2 */
  298. /***/ function(module, exports) {
  299. "use strict";
  300. Object.defineProperty(exports, "__esModule", {
  301. value: true
  302. });
  303. var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
  304. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  305. var BarnesHutSolver = (function () {
  306. function BarnesHutSolver(body, physicsBody, options) {
  307. _classCallCheck(this, BarnesHutSolver);
  308. this.body = body;
  309. this.physicsBody = physicsBody;
  310. this.barnesHutTree;
  311. this.setOptions(options);
  312. this.randomSeed = 5;
  313. }
  314. _createClass(BarnesHutSolver, [{
  315. key: "setOptions",
  316. value: function setOptions(options) {
  317. this.options = options;
  318. this.thetaInversed = 1 / this.options.theta;
  319. this.overlapAvoidanceFactor = 1 - Math.max(0, Math.min(1, this.options.avoidOverlap)); // if 1 then min distance = 0.5, if 0.5 then min distance = 0.5 + 0.5*node.shape.radius
  320. }
  321. }, {
  322. key: "seededRandom",
  323. value: function seededRandom() {
  324. var x = Math.sin(this.randomSeed++) * 10000;
  325. return x - Math.floor(x);
  326. }
  327. /**
  328. * This function calculates the forces the nodes apply on eachother based on a gravitational model.
  329. * The Barnes Hut method is used to speed up this N-body simulation.
  330. *
  331. * @private
  332. */
  333. }, {
  334. key: "solve",
  335. value: function solve() {
  336. if (this.options.gravitationalConstant !== 0 && this.physicsBody.physicsNodeIndices.length > 0) {
  337. var node = undefined;
  338. var nodes = this.body.nodes;
  339. var nodeIndices = this.physicsBody.physicsNodeIndices;
  340. var nodeCount = nodeIndices.length;
  341. // create the tree
  342. var barnesHutTree = this._formBarnesHutTree(nodes, nodeIndices);
  343. // for debugging
  344. this.barnesHutTree = barnesHutTree;
  345. // place the nodes one by one recursively
  346. for (var i = 0; i < nodeCount; i++) {
  347. node = nodes[nodeIndices[i]];
  348. if (node.options.mass > 0) {
  349. // starting with root is irrelevant, it never passes the BarnesHutSolver condition
  350. this._getForceContribution(barnesHutTree.root.children.NW, node);
  351. this._getForceContribution(barnesHutTree.root.children.NE, node);
  352. this._getForceContribution(barnesHutTree.root.children.SW, node);
  353. this._getForceContribution(barnesHutTree.root.children.SE, node);
  354. }
  355. }
  356. }
  357. }
  358. /**
  359. * This function traverses the barnesHutTree. It checks when it can approximate distant nodes with their center of mass.
  360. * If a region contains a single node, we check if it is not itself, then we apply the force.
  361. *
  362. * @param parentBranch
  363. * @param node
  364. * @private
  365. */
  366. }, {
  367. key: "_getForceContribution",
  368. value: function _getForceContribution(parentBranch, node) {
  369. // we get no force contribution from an empty region
  370. if (parentBranch.childrenCount > 0) {
  371. var dx = undefined,
  372. dy = undefined,
  373. distance = undefined;
  374. // get the distance from the center of mass to the node.
  375. dx = parentBranch.centerOfMass.x - node.x;
  376. dy = parentBranch.centerOfMass.y - node.y;
  377. distance = Math.sqrt(dx * dx + dy * dy);
  378. // BarnesHutSolver condition
  379. // original condition : s/d < theta = passed === d/s > 1/theta = passed
  380. // calcSize = 1/s --> d * 1/s > 1/theta = passed
  381. if (distance * parentBranch.calcSize > this.thetaInversed) {
  382. this._calculateForces(distance, dx, dy, node, parentBranch);
  383. } else {
  384. // Did not pass the condition, go into children if available
  385. if (parentBranch.childrenCount === 4) {
  386. this._getForceContribution(parentBranch.children.NW, node);
  387. this._getForceContribution(parentBranch.children.NE, node);
  388. this._getForceContribution(parentBranch.children.SW, node);
  389. this._getForceContribution(parentBranch.children.SE, node);
  390. } else {
  391. // parentBranch must have only one node, if it was empty we wouldnt be here
  392. if (parentBranch.children.data.id != node.id) {
  393. // if it is not self
  394. this._calculateForces(distance, dx, dy, node, parentBranch);
  395. }
  396. }
  397. }
  398. }
  399. }
  400. /**
  401. * Calculate the forces based on the distance.
  402. *
  403. * @param distance
  404. * @param dx
  405. * @param dy
  406. * @param node
  407. * @param parentBranch
  408. * @private
  409. */
  410. }, {
  411. key: "_calculateForces",
  412. value: function _calculateForces(distance, dx, dy, node, parentBranch) {
  413. if (distance === 0) {
  414. distance = 0.1;
  415. dx = distance;
  416. }
  417. if (this.overlapAvoidanceFactor < 1) {
  418. distance = Math.max(0.1 + this.overlapAvoidanceFactor * node.shape.radius, distance - node.shape.radius);
  419. }
  420. // the dividing by the distance cubed instead of squared allows us to get the fx and fy components without sines and cosines
  421. // it is shorthand for gravityforce with distance squared and fx = dx/distance * gravityForce
  422. var gravityForce = this.options.gravitationalConstant * parentBranch.mass * node.options.mass / Math.pow(distance, 3);
  423. var fx = dx * gravityForce;
  424. var fy = dy * gravityForce;
  425. this.physicsBody.forces[node.id].x += fx;
  426. this.physicsBody.forces[node.id].y += fy;
  427. }
  428. /**
  429. * This function constructs the barnesHut tree recursively. It creates the root, splits it and starts placing the nodes.
  430. *
  431. * @param nodes
  432. * @param nodeIndices
  433. * @private
  434. */
  435. }, {
  436. key: "_formBarnesHutTree",
  437. value: function _formBarnesHutTree(nodes, nodeIndices) {
  438. var node = undefined;
  439. var nodeCount = nodeIndices.length;
  440. var minX = nodes[nodeIndices[0]].x;
  441. var minY = nodes[nodeIndices[0]].y;
  442. var maxX = nodes[nodeIndices[0]].x;
  443. var maxY = nodes[nodeIndices[0]].y;
  444. // get the range of the nodes
  445. for (var i = 1; i < nodeCount; i++) {
  446. var x = nodes[nodeIndices[i]].x;
  447. var y = nodes[nodeIndices[i]].y;
  448. if (nodes[nodeIndices[i]].options.mass > 0) {
  449. if (x < minX) {
  450. minX = x;
  451. }
  452. if (x > maxX) {
  453. maxX = x;
  454. }
  455. if (y < minY) {
  456. minY = y;
  457. }
  458. if (y > maxY) {
  459. maxY = y;
  460. }
  461. }
  462. }
  463. // make the range a square
  464. var sizeDiff = Math.abs(maxX - minX) - Math.abs(maxY - minY); // difference between X and Y
  465. if (sizeDiff > 0) {
  466. minY -= 0.5 * sizeDiff;
  467. maxY += 0.5 * sizeDiff;
  468. } // xSize > ySize
  469. else {
  470. minX += 0.5 * sizeDiff;
  471. maxX -= 0.5 * sizeDiff;
  472. } // xSize < ySize
  473. var minimumTreeSize = 1e-5;
  474. var rootSize = Math.max(minimumTreeSize, Math.abs(maxX - minX));
  475. var halfRootSize = 0.5 * rootSize;
  476. var centerX = 0.5 * (minX + maxX),
  477. centerY = 0.5 * (minY + maxY);
  478. // construct the barnesHutTree
  479. var barnesHutTree = {
  480. root: {
  481. centerOfMass: { x: 0, y: 0 },
  482. mass: 0,
  483. range: {
  484. minX: centerX - halfRootSize, maxX: centerX + halfRootSize,
  485. minY: centerY - halfRootSize, maxY: centerY + halfRootSize
  486. },
  487. size: rootSize,
  488. calcSize: 1 / rootSize,
  489. children: { data: null },
  490. maxWidth: 0,
  491. level: 0,
  492. childrenCount: 4
  493. }
  494. };
  495. this._splitBranch(barnesHutTree.root);
  496. // place the nodes one by one recursively
  497. for (var i = 0; i < nodeCount; i++) {
  498. node = nodes[nodeIndices[i]];
  499. if (node.options.mass > 0) {
  500. this._placeInTree(barnesHutTree.root, node);
  501. }
  502. }
  503. // make global
  504. return barnesHutTree;
  505. }
  506. /**
  507. * this updates the mass of a branch. this is increased by adding a node.
  508. *
  509. * @param parentBranch
  510. * @param node
  511. * @private
  512. */
  513. }, {
  514. key: "_updateBranchMass",
  515. value: function _updateBranchMass(parentBranch, node) {
  516. var totalMass = parentBranch.mass + node.options.mass;
  517. var totalMassInv = 1 / totalMass;
  518. parentBranch.centerOfMass.x = parentBranch.centerOfMass.x * parentBranch.mass + node.x * node.options.mass;
  519. parentBranch.centerOfMass.x *= totalMassInv;
  520. parentBranch.centerOfMass.y = parentBranch.centerOfMass.y * parentBranch.mass + node.y * node.options.mass;
  521. parentBranch.centerOfMass.y *= totalMassInv;
  522. parentBranch.mass = totalMass;
  523. var biggestSize = Math.max(Math.max(node.height, node.radius), node.width);
  524. parentBranch.maxWidth = parentBranch.maxWidth < biggestSize ? biggestSize : parentBranch.maxWidth;
  525. }
  526. /**
  527. * determine in which branch the node will be placed.
  528. *
  529. * @param parentBranch
  530. * @param node
  531. * @param skipMassUpdate
  532. * @private
  533. */
  534. }, {
  535. key: "_placeInTree",
  536. value: function _placeInTree(parentBranch, node, skipMassUpdate) {
  537. if (skipMassUpdate != true || skipMassUpdate === undefined) {
  538. // update the mass of the branch.
  539. this._updateBranchMass(parentBranch, node);
  540. }
  541. if (parentBranch.children.NW.range.maxX > node.x) {
  542. // in NW or SW
  543. if (parentBranch.children.NW.range.maxY > node.y) {
  544. // in NW
  545. this._placeInRegion(parentBranch, node, "NW");
  546. } else {
  547. // in SW
  548. this._placeInRegion(parentBranch, node, "SW");
  549. }
  550. } else {
  551. // in NE or SE
  552. if (parentBranch.children.NW.range.maxY > node.y) {
  553. // in NE
  554. this._placeInRegion(parentBranch, node, "NE");
  555. } else {
  556. // in SE
  557. this._placeInRegion(parentBranch, node, "SE");
  558. }
  559. }
  560. }
  561. /**
  562. * actually place the node in a region (or branch)
  563. *
  564. * @param parentBranch
  565. * @param node
  566. * @param region
  567. * @private
  568. */
  569. }, {
  570. key: "_placeInRegion",
  571. value: function _placeInRegion(parentBranch, node, region) {
  572. switch (parentBranch.children[region].childrenCount) {
  573. case 0:
  574. // place node here
  575. parentBranch.children[region].children.data = node;
  576. parentBranch.children[region].childrenCount = 1;
  577. this._updateBranchMass(parentBranch.children[region], node);
  578. break;
  579. case 1:
  580. // convert into children
  581. // if there are two nodes exactly overlapping (on init, on opening of cluster etc.)
  582. // we move one node a pixel and we do not put it in the tree.
  583. if (parentBranch.children[region].children.data.x === node.x && parentBranch.children[region].children.data.y === node.y) {
  584. node.x += this.seededRandom();
  585. node.y += this.seededRandom();
  586. } else {
  587. this._splitBranch(parentBranch.children[region]);
  588. this._placeInTree(parentBranch.children[region], node);
  589. }
  590. break;
  591. case 4:
  592. // place in branch
  593. this._placeInTree(parentBranch.children[region], node);
  594. break;
  595. }
  596. }
  597. /**
  598. * this function splits a branch into 4 sub branches. If the branch contained a node, we place it in the subbranch
  599. * after the split is complete.
  600. *
  601. * @param parentBranch
  602. * @private
  603. */
  604. }, {
  605. key: "_splitBranch",
  606. value: function _splitBranch(parentBranch) {
  607. // if the branch is shaded with a node, replace the node in the new subset.
  608. var containedNode = null;
  609. if (parentBranch.childrenCount === 1) {
  610. containedNode = parentBranch.children.data;
  611. parentBranch.mass = 0;
  612. parentBranch.centerOfMass.x = 0;
  613. parentBranch.centerOfMass.y = 0;
  614. }
  615. parentBranch.childrenCount = 4;
  616. parentBranch.children.data = null;
  617. this._insertRegion(parentBranch, "NW");
  618. this._insertRegion(parentBranch, "NE");
  619. this._insertRegion(parentBranch, "SW");
  620. this._insertRegion(parentBranch, "SE");
  621. if (containedNode != null) {
  622. this._placeInTree(parentBranch, containedNode);
  623. }
  624. }
  625. /**
  626. * This function subdivides the region into four new segments.
  627. * Specifically, this inserts a single new segment.
  628. * It fills the children section of the parentBranch
  629. *
  630. * @param parentBranch
  631. * @param region
  632. * @param parentRange
  633. * @private
  634. */
  635. }, {
  636. key: "_insertRegion",
  637. value: function _insertRegion(parentBranch, region) {
  638. var minX = undefined,
  639. maxX = undefined,
  640. minY = undefined,
  641. maxY = undefined;
  642. var childSize = 0.5 * parentBranch.size;
  643. switch (region) {
  644. case "NW":
  645. minX = parentBranch.range.minX;
  646. maxX = parentBranch.range.minX + childSize;
  647. minY = parentBranch.range.minY;
  648. maxY = parentBranch.range.minY + childSize;
  649. break;
  650. case "NE":
  651. minX = parentBranch.range.minX + childSize;
  652. maxX = parentBranch.range.maxX;
  653. minY = parentBranch.range.minY;
  654. maxY = parentBranch.range.minY + childSize;
  655. break;
  656. case "SW":
  657. minX = parentBranch.range.minX;
  658. maxX = parentBranch.range.minX + childSize;
  659. minY = parentBranch.range.minY + childSize;
  660. maxY = parentBranch.range.maxY;
  661. break;
  662. case "SE":
  663. minX = parentBranch.range.minX + childSize;
  664. maxX = parentBranch.range.maxX;
  665. minY = parentBranch.range.minY + childSize;
  666. maxY = parentBranch.range.maxY;
  667. break;
  668. }
  669. parentBranch.children[region] = {
  670. centerOfMass: { x: 0, y: 0 },
  671. mass: 0,
  672. range: { minX: minX, maxX: maxX, minY: minY, maxY: maxY },
  673. size: 0.5 * parentBranch.size,
  674. calcSize: 2 * parentBranch.calcSize,
  675. children: { data: null },
  676. maxWidth: 0,
  677. level: parentBranch.level + 1,
  678. childrenCount: 0
  679. };
  680. }
  681. //--------------------------- DEBUGGING BELOW ---------------------------//
  682. /**
  683. * This function is for debugging purposed, it draws the tree.
  684. *
  685. * @param ctx
  686. * @param color
  687. * @private
  688. */
  689. }, {
  690. key: "_debug",
  691. value: function _debug(ctx, color) {
  692. if (this.barnesHutTree !== undefined) {
  693. ctx.lineWidth = 1;
  694. this._drawBranch(this.barnesHutTree.root, ctx, color);
  695. }
  696. }
  697. /**
  698. * This function is for debugging purposes. It draws the branches recursively.
  699. *
  700. * @param branch
  701. * @param ctx
  702. * @param color
  703. * @private
  704. */
  705. }, {
  706. key: "_drawBranch",
  707. value: function _drawBranch(branch, ctx, color) {
  708. if (color === undefined) {
  709. color = "#FF0000";
  710. }
  711. if (branch.childrenCount === 4) {
  712. this._drawBranch(branch.children.NW, ctx);
  713. this._drawBranch(branch.children.NE, ctx);
  714. this._drawBranch(branch.children.SE, ctx);
  715. this._drawBranch(branch.children.SW, ctx);
  716. }
  717. ctx.strokeStyle = color;
  718. ctx.beginPath();
  719. ctx.moveTo(branch.range.minX, branch.range.minY);
  720. ctx.lineTo(branch.range.maxX, branch.range.minY);
  721. ctx.stroke();
  722. ctx.beginPath();
  723. ctx.moveTo(branch.range.maxX, branch.range.minY);
  724. ctx.lineTo(branch.range.maxX, branch.range.maxY);
  725. ctx.stroke();
  726. ctx.beginPath();
  727. ctx.moveTo(branch.range.maxX, branch.range.maxY);
  728. ctx.lineTo(branch.range.minX, branch.range.maxY);
  729. ctx.stroke();
  730. ctx.beginPath();
  731. ctx.moveTo(branch.range.minX, branch.range.maxY);
  732. ctx.lineTo(branch.range.minX, branch.range.minY);
  733. ctx.stroke();
  734. /*
  735. if (branch.mass > 0) {
  736. ctx.circle(branch.centerOfMass.x, branch.centerOfMass.y, 3*branch.mass);
  737. ctx.stroke();
  738. }
  739. */
  740. }
  741. }]);
  742. return BarnesHutSolver;
  743. })();
  744. exports["default"] = BarnesHutSolver;
  745. module.exports = exports["default"];
  746. /***/ },
  747. /* 3 */
  748. /***/ function(module, exports) {
  749. "use strict";
  750. Object.defineProperty(exports, "__esModule", {
  751. value: true
  752. });
  753. var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
  754. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  755. var RepulsionSolver = (function () {
  756. function RepulsionSolver(body, physicsBody, options) {
  757. _classCallCheck(this, RepulsionSolver);
  758. this.body = body;
  759. this.physicsBody = physicsBody;
  760. this.setOptions(options);
  761. }
  762. _createClass(RepulsionSolver, [{
  763. key: "setOptions",
  764. value: function setOptions(options) {
  765. this.options = options;
  766. }
  767. /**
  768. * Calculate the forces the nodes apply on each other based on a repulsion field.
  769. * This field is linearly approximated.
  770. *
  771. * @private
  772. */
  773. }, {
  774. key: "solve",
  775. value: function solve() {
  776. var dx, dy, distance, fx, fy, repulsingForce, node1, node2;
  777. var nodes = this.body.nodes;
  778. var nodeIndices = this.physicsBody.physicsNodeIndices;
  779. var forces = this.physicsBody.forces;
  780. // repulsing forces between nodes
  781. var nodeDistance = this.options.nodeDistance;
  782. // approximation constants
  783. var a = -2 / 3 / nodeDistance;
  784. var b = 4 / 3;
  785. // we loop from i over all but the last entree in the array
  786. // j loops from i+1 to the last. This way we do not double count any of the indices, nor i === j
  787. for (var i = 0; i < nodeIndices.length - 1; i++) {
  788. node1 = nodes[nodeIndices[i]];
  789. for (var j = i + 1; j < nodeIndices.length; j++) {
  790. node2 = nodes[nodeIndices[j]];
  791. dx = node2.x - node1.x;
  792. dy = node2.y - node1.y;
  793. distance = Math.sqrt(dx * dx + dy * dy);
  794. // same condition as BarnesHutSolver, making sure nodes are never 100% overlapping.
  795. if (distance === 0) {
  796. distance = 0.1 * Math.random();
  797. dx = distance;
  798. }
  799. if (distance < 2 * nodeDistance) {
  800. if (distance < 0.5 * nodeDistance) {
  801. repulsingForce = 1.0;
  802. } else {
  803. repulsingForce = a * distance + b; // linear approx of 1 / (1 + Math.exp((distance / nodeDistance - 1) * steepness))
  804. }
  805. repulsingForce = repulsingForce / distance;
  806. fx = dx * repulsingForce;
  807. fy = dy * repulsingForce;
  808. forces[node1.id].x -= fx;
  809. forces[node1.id].y -= fy;
  810. forces[node2.id].x += fx;
  811. forces[node2.id].y += fy;
  812. }
  813. }
  814. }
  815. }
  816. }]);
  817. return RepulsionSolver;
  818. })();
  819. exports["default"] = RepulsionSolver;
  820. module.exports = exports["default"];
  821. /***/ },
  822. /* 4 */
  823. /***/ function(module, exports) {
  824. "use strict";
  825. Object.defineProperty(exports, "__esModule", {
  826. value: true
  827. });
  828. var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
  829. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  830. var HierarchicalRepulsionSolver = (function () {
  831. function HierarchicalRepulsionSolver(body, physicsBody, options) {
  832. _classCallCheck(this, HierarchicalRepulsionSolver);
  833. this.body = body;
  834. this.physicsBody = physicsBody;
  835. this.setOptions(options);
  836. }
  837. _createClass(HierarchicalRepulsionSolver, [{
  838. key: "setOptions",
  839. value: function setOptions(options) {
  840. this.options = options;
  841. }
  842. /**
  843. * Calculate the forces the nodes apply on each other based on a repulsion field.
  844. * This field is linearly approximated.
  845. *
  846. * @private
  847. */
  848. }, {
  849. key: "solve",
  850. value: function solve() {
  851. var dx, dy, distance, fx, fy, repulsingForce, node1, node2, i, j;
  852. var nodes = this.body.nodes;
  853. var nodeIndices = this.physicsBody.physicsNodeIndices;
  854. var forces = this.physicsBody.forces;
  855. // repulsing forces between nodes
  856. var nodeDistance = this.options.nodeDistance;
  857. // we loop from i over all but the last entree in the array
  858. // j loops from i+1 to the last. This way we do not double count any of the indices, nor i === j
  859. for (i = 0; i < nodeIndices.length - 1; i++) {
  860. node1 = nodes[nodeIndices[i]];
  861. for (j = i + 1; j < nodeIndices.length; j++) {
  862. node2 = nodes[nodeIndices[j]];
  863. // nodes only affect nodes on their level
  864. if (node1.level === node2.level) {
  865. dx = node2.x - node1.x;
  866. dy = node2.y - node1.y;
  867. distance = Math.sqrt(dx * dx + dy * dy);
  868. var steepness = 0.05;
  869. if (distance < nodeDistance) {
  870. repulsingForce = -Math.pow(steepness * distance, 2) + Math.pow(steepness * nodeDistance, 2);
  871. } else {
  872. repulsingForce = 0;
  873. }
  874. // normalize force with
  875. if (distance === 0) {
  876. distance = 0.01;
  877. } else {
  878. repulsingForce = repulsingForce / distance;
  879. }
  880. fx = dx * repulsingForce;
  881. fy = dy * repulsingForce;
  882. forces[node1.id].x -= fx;
  883. forces[node1.id].y -= fy;
  884. forces[node2.id].x += fx;
  885. forces[node2.id].y += fy;
  886. }
  887. }
  888. }
  889. }
  890. }]);
  891. return HierarchicalRepulsionSolver;
  892. })();
  893. exports["default"] = HierarchicalRepulsionSolver;
  894. module.exports = exports["default"];
  895. /***/ },
  896. /* 5 */
  897. /***/ function(module, exports) {
  898. "use strict";
  899. Object.defineProperty(exports, "__esModule", {
  900. value: true
  901. });
  902. var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
  903. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  904. var SpringSolver = (function () {
  905. function SpringSolver(body, physicsBody, options) {
  906. _classCallCheck(this, SpringSolver);
  907. this.body = body;
  908. this.physicsBody = physicsBody;
  909. this.setOptions(options);
  910. }
  911. _createClass(SpringSolver, [{
  912. key: "setOptions",
  913. value: function setOptions(options) {
  914. this.options = options;
  915. }
  916. /**
  917. * This function calculates the springforces on the nodes, accounting for the support nodes.
  918. *
  919. * @private
  920. */
  921. }, {
  922. key: "solve",
  923. value: function solve() {
  924. var edgeLength = undefined,
  925. edge = undefined;
  926. var edgeIndices = this.physicsBody.physicsEdgeIndices;
  927. var edges = this.body.edges;
  928. var nodes = this.body.nodes;
  929. var node1 = undefined,
  930. node2 = undefined,
  931. node3 = undefined;
  932. // forces caused by the edges, modelled as springs
  933. for (var i = 0; i < edgeIndices.length; i++) {
  934. edge = edges[edgeIndices[i]];
  935. if (edge.connected === true && edge.toId !== edge.fromId) {
  936. // only calculate forces if nodes are in the same sector
  937. if (this.body.nodes[edge.toId] !== undefined && this.body.nodes[edge.fromId] !== undefined) {
  938. if (edge.edgeType.via !== undefined) {
  939. edgeLength = edge.options.length === undefined ? this.options.springLength : edge.options.length;
  940. node1 = nodes[edge.to.id];
  941. node2 = nodes[edge.edgeType.via.id];
  942. node3 = nodes[edge.from.id];
  943. this._calculateSpringForce(node1, node2, 0.5 * edgeLength);
  944. this._calculateSpringForce(node2, node3, 0.5 * edgeLength);
  945. } else {
  946. // the * 1.5 is here so the edge looks as large as a smooth edge. It does not initially because the smooth edges use
  947. // the support nodes which exert a repulsive force on the to and from nodes, making the edge appear larger.
  948. edgeLength = edge.options.length === undefined ? this.options.springLength * 1.5 : edge.options.length;
  949. this._calculateSpringForce(nodes[edge.from.id], nodes[edge.to.id], edgeLength);
  950. }
  951. }
  952. }
  953. }
  954. }
  955. /**
  956. * This is the code actually performing the calculation for the function above.
  957. *
  958. * @param node1
  959. * @param node2
  960. * @param edgeLength
  961. * @private
  962. */
  963. }, {
  964. key: "_calculateSpringForce",
  965. value: function _calculateSpringForce(node1, node2, edgeLength) {
  966. var dx = node1.x - node2.x;
  967. var dy = node1.y - node2.y;
  968. var distance = Math.max(Math.sqrt(dx * dx + dy * dy), 0.01);
  969. // the 1/distance is so the fx and fy can be calculated without sine or cosine.
  970. var springForce = this.options.springConstant * (edgeLength - distance) / distance;
  971. var fx = dx * springForce;
  972. var fy = dy * springForce;
  973. // handle the case where one node is not part of the physcis
  974. if (this.physicsBody.forces[node1.id] !== undefined) {
  975. this.physicsBody.forces[node1.id].x += fx;
  976. this.physicsBody.forces[node1.id].y += fy;
  977. }
  978. if (this.physicsBody.forces[node2.id] !== undefined) {
  979. this.physicsBody.forces[node2.id].x -= fx;
  980. this.physicsBody.forces[node2.id].y -= fy;
  981. }
  982. }
  983. }]);
  984. return SpringSolver;
  985. })();
  986. exports["default"] = SpringSolver;
  987. module.exports = exports["default"];
  988. /***/ },
  989. /* 6 */
  990. /***/ function(module, exports) {
  991. "use strict";
  992. Object.defineProperty(exports, "__esModule", {
  993. value: true
  994. });
  995. var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
  996. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  997. var HierarchicalSpringSolver = (function () {
  998. function HierarchicalSpringSolver(body, physicsBody, options) {
  999. _classCallCheck(this, HierarchicalSpringSolver);
  1000. this.body = body;
  1001. this.physicsBody = physicsBody;
  1002. this.setOptions(options);
  1003. }
  1004. _createClass(HierarchicalSpringSolver, [{
  1005. key: "setOptions",
  1006. value: function setOptions(options) {
  1007. this.options = options;
  1008. }
  1009. /**
  1010. * This function calculates the springforces on the nodes, accounting for the support nodes.
  1011. *
  1012. * @private
  1013. */
  1014. }, {
  1015. key: "solve",
  1016. value: function solve() {
  1017. var edgeLength, edge;
  1018. var dx, dy, fx, fy, springForce, distance;
  1019. var edges = this.body.edges;
  1020. var factor = 0.5;
  1021. var edgeIndices = this.physicsBody.physicsEdgeIndices;
  1022. var nodeIndices = this.physicsBody.physicsNodeIndices;
  1023. var forces = this.physicsBody.forces;
  1024. // initialize the spring force counters
  1025. for (var i = 0; i < nodeIndices.length; i++) {
  1026. var nodeId = nodeIndices[i];
  1027. forces[nodeId].springFx = 0;
  1028. forces[nodeId].springFy = 0;
  1029. }
  1030. // forces caused by the edges, modelled as springs
  1031. for (var i = 0; i < edgeIndices.length; i++) {
  1032. edge = edges[edgeIndices[i]];
  1033. if (edge.connected === true) {
  1034. edgeLength = edge.options.length === undefined ? this.options.springLength : edge.options.length;
  1035. dx = edge.from.x - edge.to.x;
  1036. dy = edge.from.y - edge.to.y;
  1037. distance = Math.sqrt(dx * dx + dy * dy);
  1038. distance = distance === 0 ? 0.01 : distance;
  1039. // the 1/distance is so the fx and fy can be calculated without sine or cosine.
  1040. springForce = this.options.springConstant * (edgeLength - distance) / distance;
  1041. fx = dx * springForce;
  1042. fy = dy * springForce;
  1043. if (edge.to.level != edge.from.level) {
  1044. if (forces[edge.toId] !== undefined) {
  1045. forces[edge.toId].springFx -= fx;
  1046. forces[edge.toId].springFy -= fy;
  1047. }
  1048. if (forces[edge.fromId] !== undefined) {
  1049. forces[edge.fromId].springFx += fx;
  1050. forces[edge.fromId].springFy += fy;
  1051. }
  1052. } else {
  1053. if (forces[edge.toId] !== undefined) {
  1054. forces[edge.toId].x -= factor * fx;
  1055. forces[edge.toId].y -= factor * fy;
  1056. }
  1057. if (forces[edge.fromId] !== undefined) {
  1058. forces[edge.fromId].x += factor * fx;
  1059. forces[edge.fromId].y += factor * fy;
  1060. }
  1061. }
  1062. }
  1063. }
  1064. // normalize spring forces
  1065. var springForce = 1;
  1066. var springFx, springFy;
  1067. for (var i = 0; i < nodeIndices.length; i++) {
  1068. var nodeId = nodeIndices[i];
  1069. springFx = Math.min(springForce, Math.max(-springForce, forces[nodeId].springFx));
  1070. springFy = Math.min(springForce, Math.max(-springForce, forces[nodeId].springFy));
  1071. forces[nodeId].x += springFx;
  1072. forces[nodeId].y += springFy;
  1073. }
  1074. // retain energy balance
  1075. var totalFx = 0;
  1076. var totalFy = 0;
  1077. for (var i = 0; i < nodeIndices.length; i++) {
  1078. var nodeId = nodeIndices[i];
  1079. totalFx += forces[nodeId].x;
  1080. totalFy += forces[nodeId].y;
  1081. }
  1082. var correctionFx = totalFx / nodeIndices.length;
  1083. var correctionFy = totalFy / nodeIndices.length;
  1084. for (var i = 0; i < nodeIndices.length; i++) {
  1085. var nodeId = nodeIndices[i];
  1086. forces[nodeId].x -= correctionFx;
  1087. forces[nodeId].y -= correctionFy;
  1088. }
  1089. }
  1090. }]);
  1091. return HierarchicalSpringSolver;
  1092. })();
  1093. exports["default"] = HierarchicalSpringSolver;
  1094. module.exports = exports["default"];
  1095. /***/ },
  1096. /* 7 */
  1097. /***/ function(module, exports) {
  1098. "use strict";
  1099. Object.defineProperty(exports, "__esModule", {
  1100. value: true
  1101. });
  1102. var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
  1103. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  1104. var CentralGravitySolver = (function () {
  1105. function CentralGravitySolver(body, physicsBody, options) {
  1106. _classCallCheck(this, CentralGravitySolver);
  1107. this.body = body;
  1108. this.physicsBody = physicsBody;
  1109. this.setOptions(options);
  1110. }
  1111. _createClass(CentralGravitySolver, [{
  1112. key: "setOptions",
  1113. value: function setOptions(options) {
  1114. this.options = options;
  1115. }
  1116. }, {
  1117. key: "solve",
  1118. value: function solve() {
  1119. var dx = undefined,
  1120. dy = undefined,
  1121. distance = undefined,
  1122. node = undefined;
  1123. var nodes = this.body.nodes;
  1124. var nodeIndices = this.physicsBody.physicsNodeIndices;
  1125. var forces = this.physicsBody.forces;
  1126. for (var i = 0; i < nodeIndices.length; i++) {
  1127. var nodeId = nodeIndices[i];
  1128. node = nodes[nodeId];
  1129. dx = -node.x;
  1130. dy = -node.y;
  1131. distance = Math.sqrt(dx * dx + dy * dy);
  1132. this._calculateForces(distance, dx, dy, forces, node);
  1133. }
  1134. }
  1135. /**
  1136. * Calculate the forces based on the distance.
  1137. * @private
  1138. */
  1139. }, {
  1140. key: "_calculateForces",
  1141. value: function _calculateForces(distance, dx, dy, forces, node) {
  1142. var gravityForce = distance === 0 ? 0 : this.options.centralGravity / distance;
  1143. forces[node.id].x = dx * gravityForce;
  1144. forces[node.id].y = dy * gravityForce;
  1145. }
  1146. }]);
  1147. return CentralGravitySolver;
  1148. })();
  1149. exports["default"] = CentralGravitySolver;
  1150. module.exports = exports["default"];
  1151. /***/ },
  1152. /* 8 */
  1153. /***/ function(module, exports, __webpack_require__) {
  1154. "use strict";
  1155. Object.defineProperty(exports, "__esModule", {
  1156. value: true
  1157. });
  1158. var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
  1159. var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; desc = parent = getter = undefined; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; continue _function; } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } };
  1160. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
  1161. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  1162. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
  1163. var _BarnesHutSolver2 = __webpack_require__(2);
  1164. var _BarnesHutSolver3 = _interopRequireDefault(_BarnesHutSolver2);
  1165. var ForceAtlas2BasedRepulsionSolver = (function (_BarnesHutSolver) {
  1166. _inherits(ForceAtlas2BasedRepulsionSolver, _BarnesHutSolver);
  1167. function ForceAtlas2BasedRepulsionSolver(body, physicsBody, options) {
  1168. _classCallCheck(this, ForceAtlas2BasedRepulsionSolver);
  1169. _get(Object.getPrototypeOf(ForceAtlas2BasedRepulsionSolver.prototype), "constructor", this).call(this, body, physicsBody, options);
  1170. }
  1171. /**
  1172. * Calculate the forces based on the distance.
  1173. *
  1174. * @param distance
  1175. * @param dx
  1176. * @param dy
  1177. * @param node
  1178. * @param parentBranch
  1179. * @private
  1180. */
  1181. _createClass(ForceAtlas2BasedRepulsionSolver, [{
  1182. key: "_calculateForces",
  1183. value: function _calculateForces(distance, dx, dy, node, parentBranch) {
  1184. if (distance === 0) {
  1185. distance = 0.1 * Math.random();
  1186. dx = distance;
  1187. }
  1188. if (this.overlapAvoidanceFactor < 1) {
  1189. distance = Math.max(0.1 + this.overlapAvoidanceFactor * node.shape.radius, distance - node.shape.radius);
  1190. }
  1191. var degree = node.edges.length + 1;
  1192. // the dividing by the distance cubed instead of squared allows us to get the fx and fy components without sines and cosines
  1193. // it is shorthand for gravityforce with distance squared and fx = dx/distance * gravityForce
  1194. var gravityForce = this.options.gravitationalConstant * parentBranch.mass * node.options.mass * degree / Math.pow(distance, 2);
  1195. var fx = dx * gravityForce;
  1196. var fy = dy * gravityForce;
  1197. this.physicsBody.forces[node.id].x += fx;
  1198. this.physicsBody.forces[node.id].y += fy;
  1199. }
  1200. }]);
  1201. return ForceAtlas2BasedRepulsionSolver;
  1202. })(_BarnesHutSolver3["default"]);
  1203. exports["default"] = ForceAtlas2BasedRepulsionSolver;
  1204. module.exports = exports["default"];
  1205. /***/ },
  1206. /* 9 */
  1207. /***/ function(module, exports, __webpack_require__) {
  1208. "use strict";
  1209. Object.defineProperty(exports, "__esModule", {
  1210. value: true
  1211. });
  1212. var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
  1213. var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; desc = parent = getter = undefined; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; continue _function; } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } };
  1214. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
  1215. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  1216. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
  1217. var _CentralGravitySolver2 = __webpack_require__(7);
  1218. var _CentralGravitySolver3 = _interopRequireDefault(_CentralGravitySolver2);
  1219. var ForceAtlas2BasedCentralGravitySolver = (function (_CentralGravitySolver) {
  1220. _inherits(ForceAtlas2BasedCentralGravitySolver, _CentralGravitySolver);
  1221. function ForceAtlas2BasedCentralGravitySolver(body, physicsBody, options) {
  1222. _classCallCheck(this, ForceAtlas2BasedCentralGravitySolver);
  1223. _get(Object.getPrototypeOf(ForceAtlas2BasedCentralGravitySolver.prototype), "constructor", this).call(this, body, physicsBody, options);
  1224. }
  1225. /**
  1226. * Calculate the forces based on the distance.
  1227. * @private
  1228. */
  1229. _createClass(ForceAtlas2BasedCentralGravitySolver, [{
  1230. key: "_calculateForces",
  1231. value: function _calculateForces(distance, dx, dy, forces, node) {
  1232. if (distance > 0) {
  1233. var degree = node.edges.length + 1;
  1234. var gravityForce = this.options.centralGravity * degree * node.options.mass;
  1235. forces[node.id].x = dx * gravityForce;
  1236. forces[node.id].y = dy * gravityForce;
  1237. }
  1238. }
  1239. }]);
  1240. return ForceAtlas2BasedCentralGravitySolver;
  1241. })(_CentralGravitySolver3["default"]);
  1242. exports["default"] = ForceAtlas2BasedCentralGravitySolver;
  1243. module.exports = exports["default"];
  1244. /***/ }
  1245. /******/ ]);