d3-force.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668
  1. // https://d3js.org/d3-force/ v1.2.1 Copyright 2019 Mike Bostock
  2. (function (global, factory) {
  3. typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3-quadtree'), require('d3-collection'), require('d3-dispatch'), require('d3-timer')) :
  4. typeof define === 'function' && define.amd ? define(['exports', 'd3-quadtree', 'd3-collection', 'd3-dispatch', 'd3-timer'], factory) :
  5. (factory((global.d3 = global.d3 || {}),global.d3,global.d3,global.d3,global.d3));
  6. }(this, (function (exports,d3Quadtree,d3Collection,d3Dispatch,d3Timer) { 'use strict';
  7. function center(x, y) {
  8. var nodes;
  9. if (x == null) x = 0;
  10. if (y == null) y = 0;
  11. function force() {
  12. var i,
  13. n = nodes.length,
  14. node,
  15. sx = 0,
  16. sy = 0;
  17. for (i = 0; i < n; ++i) {
  18. node = nodes[i], sx += node.x, sy += node.y;
  19. }
  20. for (sx = sx / n - x, sy = sy / n - y, i = 0; i < n; ++i) {
  21. node = nodes[i], node.x -= sx, node.y -= sy;
  22. }
  23. }
  24. force.initialize = function(_) {
  25. nodes = _;
  26. };
  27. force.x = function(_) {
  28. return arguments.length ? (x = +_, force) : x;
  29. };
  30. force.y = function(_) {
  31. return arguments.length ? (y = +_, force) : y;
  32. };
  33. return force;
  34. }
  35. function constant(x) {
  36. return function() {
  37. return x;
  38. };
  39. }
  40. function jiggle() {
  41. return (Math.random() - 0.5) * 1e-6;
  42. }
  43. function x(d) {
  44. return d.x + d.vx;
  45. }
  46. function y(d) {
  47. return d.y + d.vy;
  48. }
  49. function collide(radius) {
  50. var nodes,
  51. radii,
  52. strength = 1,
  53. iterations = 1;
  54. if (typeof radius !== "function") radius = constant(radius == null ? 1 : +radius);
  55. function force() {
  56. var i, n = nodes.length,
  57. tree,
  58. node,
  59. xi,
  60. yi,
  61. ri,
  62. ri2;
  63. for (var k = 0; k < iterations; ++k) {
  64. tree = d3Quadtree.quadtree(nodes, x, y).visitAfter(prepare);
  65. for (i = 0; i < n; ++i) {
  66. node = nodes[i];
  67. ri = radii[node.index], ri2 = ri * ri;
  68. xi = node.x + node.vx;
  69. yi = node.y + node.vy;
  70. tree.visit(apply);
  71. }
  72. }
  73. function apply(quad, x0, y0, x1, y1) {
  74. var data = quad.data, rj = quad.r, r = ri + rj;
  75. if (data) {
  76. if (data.index > node.index) {
  77. var x = xi - data.x - data.vx,
  78. y = yi - data.y - data.vy,
  79. l = x * x + y * y;
  80. if (l < r * r) {
  81. if (x === 0) x = jiggle(), l += x * x;
  82. if (y === 0) y = jiggle(), l += y * y;
  83. l = (r - (l = Math.sqrt(l))) / l * strength;
  84. node.vx += (x *= l) * (r = (rj *= rj) / (ri2 + rj));
  85. node.vy += (y *= l) * r;
  86. data.vx -= x * (r = 1 - r);
  87. data.vy -= y * r;
  88. }
  89. }
  90. return;
  91. }
  92. return x0 > xi + r || x1 < xi - r || y0 > yi + r || y1 < yi - r;
  93. }
  94. }
  95. function prepare(quad) {
  96. if (quad.data) return quad.r = radii[quad.data.index];
  97. for (var i = quad.r = 0; i < 4; ++i) {
  98. if (quad[i] && quad[i].r > quad.r) {
  99. quad.r = quad[i].r;
  100. }
  101. }
  102. }
  103. function initialize() {
  104. if (!nodes) return;
  105. var i, n = nodes.length, node;
  106. radii = new Array(n);
  107. for (i = 0; i < n; ++i) node = nodes[i], radii[node.index] = +radius(node, i, nodes);
  108. }
  109. force.initialize = function(_) {
  110. nodes = _;
  111. initialize();
  112. };
  113. force.iterations = function(_) {
  114. return arguments.length ? (iterations = +_, force) : iterations;
  115. };
  116. force.strength = function(_) {
  117. return arguments.length ? (strength = +_, force) : strength;
  118. };
  119. force.radius = function(_) {
  120. return arguments.length ? (radius = typeof _ === "function" ? _ : constant(+_), initialize(), force) : radius;
  121. };
  122. return force;
  123. }
  124. function index(d) {
  125. return d.index;
  126. }
  127. function find(nodeById, nodeId) {
  128. var node = nodeById.get(nodeId);
  129. if (!node) throw new Error("missing: " + nodeId);
  130. return node;
  131. }
  132. function link(links) {
  133. var id = index,
  134. strength = defaultStrength,
  135. strengths,
  136. distance = constant(30),
  137. distances,
  138. nodes,
  139. count,
  140. bias,
  141. iterations = 1;
  142. if (links == null) links = [];
  143. function defaultStrength(link) {
  144. return 1 / Math.min(count[link.source.index], count[link.target.index]);
  145. }
  146. function force(alpha) {
  147. for (var k = 0, n = links.length; k < iterations; ++k) {
  148. for (var i = 0, link, source, target, x, y, l, b; i < n; ++i) {
  149. link = links[i], source = link.source, target = link.target;
  150. x = target.x + target.vx - source.x - source.vx || jiggle();
  151. y = target.y + target.vy - source.y - source.vy || jiggle();
  152. l = Math.sqrt(x * x + y * y);
  153. l = (l - distances[i]) / l * alpha * strengths[i];
  154. x *= l, y *= l;
  155. target.vx -= x * (b = bias[i]);
  156. target.vy -= y * b;
  157. source.vx += x * (b = 1 - b);
  158. source.vy += y * b;
  159. }
  160. }
  161. }
  162. function initialize() {
  163. if (!nodes) return;
  164. var i,
  165. n = nodes.length,
  166. m = links.length,
  167. nodeById = d3Collection.map(nodes, id),
  168. link;
  169. for (i = 0, count = new Array(n); i < m; ++i) {
  170. link = links[i], link.index = i;
  171. if (typeof link.source !== "object") link.source = find(nodeById, link.source);
  172. if (typeof link.target !== "object") link.target = find(nodeById, link.target);
  173. count[link.source.index] = (count[link.source.index] || 0) + 1;
  174. count[link.target.index] = (count[link.target.index] || 0) + 1;
  175. }
  176. for (i = 0, bias = new Array(m); i < m; ++i) {
  177. link = links[i], bias[i] = count[link.source.index] / (count[link.source.index] + count[link.target.index]);
  178. }
  179. strengths = new Array(m), initializeStrength();
  180. distances = new Array(m), initializeDistance();
  181. }
  182. function initializeStrength() {
  183. if (!nodes) return;
  184. for (var i = 0, n = links.length; i < n; ++i) {
  185. strengths[i] = +strength(links[i], i, links);
  186. }
  187. }
  188. function initializeDistance() {
  189. if (!nodes) return;
  190. for (var i = 0, n = links.length; i < n; ++i) {
  191. distances[i] = +distance(links[i], i, links);
  192. }
  193. }
  194. force.initialize = function(_) {
  195. nodes = _;
  196. initialize();
  197. };
  198. force.links = function(_) {
  199. return arguments.length ? (links = _, initialize(), force) : links;
  200. };
  201. force.id = function(_) {
  202. return arguments.length ? (id = _, force) : id;
  203. };
  204. force.iterations = function(_) {
  205. return arguments.length ? (iterations = +_, force) : iterations;
  206. };
  207. force.strength = function(_) {
  208. return arguments.length ? (strength = typeof _ === "function" ? _ : constant(+_), initializeStrength(), force) : strength;
  209. };
  210. force.distance = function(_) {
  211. return arguments.length ? (distance = typeof _ === "function" ? _ : constant(+_), initializeDistance(), force) : distance;
  212. };
  213. return force;
  214. }
  215. function x$1(d) {
  216. return d.x;
  217. }
  218. function y$1(d) {
  219. return d.y;
  220. }
  221. var initialRadius = 10,
  222. initialAngle = Math.PI * (3 - Math.sqrt(5));
  223. function simulation(nodes) {
  224. var simulation,
  225. alpha = 1,
  226. alphaMin = 0.001,
  227. alphaDecay = 1 - Math.pow(alphaMin, 1 / 300),
  228. alphaTarget = 0,
  229. velocityDecay = 0.6,
  230. forces = d3Collection.map(),
  231. stepper = d3Timer.timer(step),
  232. event = d3Dispatch.dispatch("tick", "end");
  233. if (nodes == null) nodes = [];
  234. function step() {
  235. tick();
  236. event.call("tick", simulation);
  237. if (alpha < alphaMin) {
  238. stepper.stop();
  239. event.call("end", simulation);
  240. }
  241. }
  242. function tick(iterations) {
  243. var i, n = nodes.length, node;
  244. if (iterations === undefined) iterations = 1;
  245. for (var k = 0; k < iterations; ++k) {
  246. alpha += (alphaTarget - alpha) * alphaDecay;
  247. forces.each(function (force) {
  248. force(alpha);
  249. });
  250. for (i = 0; i < n; ++i) {
  251. node = nodes[i];
  252. if (node.fx == null) node.x += node.vx *= velocityDecay;
  253. else node.x = node.fx, node.vx = 0;
  254. if (node.fy == null) node.y += node.vy *= velocityDecay;
  255. else node.y = node.fy, node.vy = 0;
  256. }
  257. }
  258. return simulation;
  259. }
  260. function initializeNodes() {
  261. for (var i = 0, n = nodes.length, node; i < n; ++i) {
  262. node = nodes[i], node.index = i;
  263. if (node.fx != null) node.x = node.fx;
  264. if (node.fy != null) node.y = node.fy;
  265. if (isNaN(node.x) || isNaN(node.y)) {
  266. var radius = initialRadius * Math.sqrt(i), angle = i * initialAngle;
  267. node.x = radius * Math.cos(angle);
  268. node.y = radius * Math.sin(angle);
  269. }
  270. if (isNaN(node.vx) || isNaN(node.vy)) {
  271. node.vx = node.vy = 0;
  272. }
  273. }
  274. }
  275. function initializeForce(force) {
  276. if (force.initialize) force.initialize(nodes);
  277. return force;
  278. }
  279. initializeNodes();
  280. return simulation = {
  281. tick: tick,
  282. restart: function() {
  283. return stepper.restart(step), simulation;
  284. },
  285. stop: function() {
  286. return stepper.stop(), simulation;
  287. },
  288. nodes: function(_) {
  289. return arguments.length ? (nodes = _, initializeNodes(), forces.each(initializeForce), simulation) : nodes;
  290. },
  291. alpha: function(_) {
  292. return arguments.length ? (alpha = +_, simulation) : alpha;
  293. },
  294. alphaMin: function(_) {
  295. return arguments.length ? (alphaMin = +_, simulation) : alphaMin;
  296. },
  297. alphaDecay: function(_) {
  298. return arguments.length ? (alphaDecay = +_, simulation) : +alphaDecay;
  299. },
  300. alphaTarget: function(_) {
  301. return arguments.length ? (alphaTarget = +_, simulation) : alphaTarget;
  302. },
  303. velocityDecay: function(_) {
  304. return arguments.length ? (velocityDecay = 1 - _, simulation) : 1 - velocityDecay;
  305. },
  306. force: function(name, _) {
  307. return arguments.length > 1 ? ((_ == null ? forces.remove(name) : forces.set(name, initializeForce(_))), simulation) : forces.get(name);
  308. },
  309. find: function(x, y, radius) {
  310. var i = 0,
  311. n = nodes.length,
  312. dx,
  313. dy,
  314. d2,
  315. node,
  316. closest;
  317. if (radius == null) radius = Infinity;
  318. else radius *= radius;
  319. for (i = 0; i < n; ++i) {
  320. node = nodes[i];
  321. dx = x - node.x;
  322. dy = y - node.y;
  323. d2 = dx * dx + dy * dy;
  324. if (d2 < radius) closest = node, radius = d2;
  325. }
  326. return closest;
  327. },
  328. on: function(name, _) {
  329. return arguments.length > 1 ? (event.on(name, _), simulation) : event.on(name);
  330. }
  331. };
  332. }
  333. function manyBody() {
  334. var nodes,
  335. node,
  336. alpha,
  337. strength = constant(-30),
  338. strengths,
  339. distanceMin2 = 1,
  340. distanceMax2 = Infinity,
  341. theta2 = 0.81;
  342. function force(_) {
  343. var i, n = nodes.length, tree = d3Quadtree.quadtree(nodes, x$1, y$1).visitAfter(accumulate);
  344. for (alpha = _, i = 0; i < n; ++i) node = nodes[i], tree.visit(apply);
  345. }
  346. function initialize() {
  347. if (!nodes) return;
  348. var i, n = nodes.length, node;
  349. strengths = new Array(n);
  350. for (i = 0; i < n; ++i) node = nodes[i], strengths[node.index] = +strength(node, i, nodes);
  351. }
  352. function accumulate(quad) {
  353. var strength = 0, q, c, weight = 0, x, y, i;
  354. // For internal nodes, accumulate forces from child quadrants.
  355. if (quad.length) {
  356. for (x = y = i = 0; i < 4; ++i) {
  357. if ((q = quad[i]) && (c = Math.abs(q.value))) {
  358. strength += q.value, weight += c, x += c * q.x, y += c * q.y;
  359. }
  360. }
  361. quad.x = x / weight;
  362. quad.y = y / weight;
  363. }
  364. // For leaf nodes, accumulate forces from coincident quadrants.
  365. else {
  366. q = quad;
  367. q.x = q.data.x;
  368. q.y = q.data.y;
  369. do strength += strengths[q.data.index];
  370. while (q = q.next);
  371. }
  372. quad.value = strength;
  373. }
  374. function apply(quad, x1, _, x2) {
  375. if (!quad.value) return true;
  376. var x = quad.x - node.x,
  377. y = quad.y - node.y,
  378. w = x2 - x1,
  379. l = x * x + y * y;
  380. // Apply the Barnes-Hut approximation if possible.
  381. // Limit forces for very close nodes; randomize direction if coincident.
  382. if (w * w / theta2 < l) {
  383. if (l < distanceMax2) {
  384. if (x === 0) x = jiggle(), l += x * x;
  385. if (y === 0) y = jiggle(), l += y * y;
  386. if (l < distanceMin2) l = Math.sqrt(distanceMin2 * l);
  387. node.vx += x * quad.value * alpha / l;
  388. node.vy += y * quad.value * alpha / l;
  389. }
  390. return true;
  391. }
  392. // Otherwise, process points directly.
  393. else if (quad.length || l >= distanceMax2) return;
  394. // Limit forces for very close nodes; randomize direction if coincident.
  395. if (quad.data !== node || quad.next) {
  396. if (x === 0) x = jiggle(), l += x * x;
  397. if (y === 0) y = jiggle(), l += y * y;
  398. if (l < distanceMin2) l = Math.sqrt(distanceMin2 * l);
  399. }
  400. do if (quad.data !== node) {
  401. w = strengths[quad.data.index] * alpha / l;
  402. node.vx += x * w;
  403. node.vy += y * w;
  404. } while (quad = quad.next);
  405. }
  406. force.initialize = function(_) {
  407. nodes = _;
  408. initialize();
  409. };
  410. force.strength = function(_) {
  411. return arguments.length ? (strength = typeof _ === "function" ? _ : constant(+_), initialize(), force) : strength;
  412. };
  413. force.distanceMin = function(_) {
  414. return arguments.length ? (distanceMin2 = _ * _, force) : Math.sqrt(distanceMin2);
  415. };
  416. force.distanceMax = function(_) {
  417. return arguments.length ? (distanceMax2 = _ * _, force) : Math.sqrt(distanceMax2);
  418. };
  419. force.theta = function(_) {
  420. return arguments.length ? (theta2 = _ * _, force) : Math.sqrt(theta2);
  421. };
  422. return force;
  423. }
  424. function radial(radius, x, y) {
  425. var nodes,
  426. strength = constant(0.1),
  427. strengths,
  428. radiuses;
  429. if (typeof radius !== "function") radius = constant(+radius);
  430. if (x == null) x = 0;
  431. if (y == null) y = 0;
  432. function force(alpha) {
  433. for (var i = 0, n = nodes.length; i < n; ++i) {
  434. var node = nodes[i],
  435. dx = node.x - x || 1e-6,
  436. dy = node.y - y || 1e-6,
  437. r = Math.sqrt(dx * dx + dy * dy),
  438. k = (radiuses[i] - r) * strengths[i] * alpha / r;
  439. node.vx += dx * k;
  440. node.vy += dy * k;
  441. }
  442. }
  443. function initialize() {
  444. if (!nodes) return;
  445. var i, n = nodes.length;
  446. strengths = new Array(n);
  447. radiuses = new Array(n);
  448. for (i = 0; i < n; ++i) {
  449. radiuses[i] = +radius(nodes[i], i, nodes);
  450. strengths[i] = isNaN(radiuses[i]) ? 0 : +strength(nodes[i], i, nodes);
  451. }
  452. }
  453. force.initialize = function(_) {
  454. nodes = _, initialize();
  455. };
  456. force.strength = function(_) {
  457. return arguments.length ? (strength = typeof _ === "function" ? _ : constant(+_), initialize(), force) : strength;
  458. };
  459. force.radius = function(_) {
  460. return arguments.length ? (radius = typeof _ === "function" ? _ : constant(+_), initialize(), force) : radius;
  461. };
  462. force.x = function(_) {
  463. return arguments.length ? (x = +_, force) : x;
  464. };
  465. force.y = function(_) {
  466. return arguments.length ? (y = +_, force) : y;
  467. };
  468. return force;
  469. }
  470. function x$2(x) {
  471. var strength = constant(0.1),
  472. nodes,
  473. strengths,
  474. xz;
  475. if (typeof x !== "function") x = constant(x == null ? 0 : +x);
  476. function force(alpha) {
  477. for (var i = 0, n = nodes.length, node; i < n; ++i) {
  478. node = nodes[i], node.vx += (xz[i] - node.x) * strengths[i] * alpha;
  479. }
  480. }
  481. function initialize() {
  482. if (!nodes) return;
  483. var i, n = nodes.length;
  484. strengths = new Array(n);
  485. xz = new Array(n);
  486. for (i = 0; i < n; ++i) {
  487. strengths[i] = isNaN(xz[i] = +x(nodes[i], i, nodes)) ? 0 : +strength(nodes[i], i, nodes);
  488. }
  489. }
  490. force.initialize = function(_) {
  491. nodes = _;
  492. initialize();
  493. };
  494. force.strength = function(_) {
  495. return arguments.length ? (strength = typeof _ === "function" ? _ : constant(+_), initialize(), force) : strength;
  496. };
  497. force.x = function(_) {
  498. return arguments.length ? (x = typeof _ === "function" ? _ : constant(+_), initialize(), force) : x;
  499. };
  500. return force;
  501. }
  502. function y$2(y) {
  503. var strength = constant(0.1),
  504. nodes,
  505. strengths,
  506. yz;
  507. if (typeof y !== "function") y = constant(y == null ? 0 : +y);
  508. function force(alpha) {
  509. for (var i = 0, n = nodes.length, node; i < n; ++i) {
  510. node = nodes[i], node.vy += (yz[i] - node.y) * strengths[i] * alpha;
  511. }
  512. }
  513. function initialize() {
  514. if (!nodes) return;
  515. var i, n = nodes.length;
  516. strengths = new Array(n);
  517. yz = new Array(n);
  518. for (i = 0; i < n; ++i) {
  519. strengths[i] = isNaN(yz[i] = +y(nodes[i], i, nodes)) ? 0 : +strength(nodes[i], i, nodes);
  520. }
  521. }
  522. force.initialize = function(_) {
  523. nodes = _;
  524. initialize();
  525. };
  526. force.strength = function(_) {
  527. return arguments.length ? (strength = typeof _ === "function" ? _ : constant(+_), initialize(), force) : strength;
  528. };
  529. force.y = function(_) {
  530. return arguments.length ? (y = typeof _ === "function" ? _ : constant(+_), initialize(), force) : y;
  531. };
  532. return force;
  533. }
  534. exports.forceCenter = center;
  535. exports.forceCollide = collide;
  536. exports.forceLink = link;
  537. exports.forceManyBody = manyBody;
  538. exports.forceRadial = radial;
  539. exports.forceSimulation = simulation;
  540. exports.forceX = x$2;
  541. exports.forceY = y$2;
  542. Object.defineProperty(exports, '__esModule', { value: true });
  543. })));