d3-force-3d.js 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854
  1. // https://github.com/vasturiano/d3-force-3d v3.0.2 Copyright 2021 Vasco Asturiano
  2. (function (global, factory) {
  3. typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3-binarytree'), require('d3-quadtree'), require('d3-octree'), require('d3-dispatch'), require('d3-timer')) :
  4. typeof define === 'function' && define.amd ? define(['exports', 'd3-binarytree', 'd3-quadtree', 'd3-octree', 'd3-dispatch', 'd3-timer'], factory) :
  5. (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.d3 = global.d3 || {}, global.d3, global.d3, global.d3, global.d3, global.d3));
  6. }(this, (function (exports, d3Binarytree, d3Quadtree, d3Octree, d3Dispatch, d3Timer) { 'use strict';
  7. function center(x, y, z) {
  8. var nodes, strength = 1;
  9. if (x == null) x = 0;
  10. if (y == null) y = 0;
  11. if (z == null) z = 0;
  12. function force() {
  13. var i,
  14. n = nodes.length,
  15. node,
  16. sx = 0,
  17. sy = 0,
  18. sz = 0;
  19. for (i = 0; i < n; ++i) {
  20. node = nodes[i], sx += node.x || 0, sy += node.y || 0, sz += node.z || 0;
  21. }
  22. for (sx = (sx / n - x) * strength, sy = (sy / n - y) * strength, sz = (sz / n - z) * strength, i = 0; i < n; ++i) {
  23. node = nodes[i];
  24. if (sx) { node.x -= sx; }
  25. if (sy) { node.y -= sy; }
  26. if (sz) { node.z -= sz; }
  27. }
  28. }
  29. force.initialize = function(_) {
  30. nodes = _;
  31. };
  32. force.x = function(_) {
  33. return arguments.length ? (x = +_, force) : x;
  34. };
  35. force.y = function(_) {
  36. return arguments.length ? (y = +_, force) : y;
  37. };
  38. force.z = function(_) {
  39. return arguments.length ? (z = +_, force) : z;
  40. };
  41. force.strength = function(_) {
  42. return arguments.length ? (strength = +_, force) : strength;
  43. };
  44. return force;
  45. }
  46. function constant(x) {
  47. return function() {
  48. return x;
  49. };
  50. }
  51. function jiggle(random) {
  52. return (random() - 0.5) * 1e-6;
  53. }
  54. function x$2(d) {
  55. return d.x + d.vx;
  56. }
  57. function y$2(d) {
  58. return d.y + d.vy;
  59. }
  60. function z$2(d) {
  61. return d.z + d.vz;
  62. }
  63. function collide(radius) {
  64. var nodes,
  65. nDim,
  66. radii,
  67. random,
  68. strength = 1,
  69. iterations = 1;
  70. if (typeof radius !== "function") radius = constant(radius == null ? 1 : +radius);
  71. function force() {
  72. var i, n = nodes.length,
  73. tree,
  74. node,
  75. xi,
  76. yi,
  77. zi,
  78. ri,
  79. ri2;
  80. for (var k = 0; k < iterations; ++k) {
  81. tree =
  82. (nDim === 1 ? d3Binarytree.binarytree(nodes, x$2)
  83. :(nDim === 2 ? d3Quadtree.quadtree(nodes, x$2, y$2)
  84. :(nDim === 3 ? d3Octree.octree(nodes, x$2, y$2, z$2)
  85. :null
  86. ))).visitAfter(prepare);
  87. for (i = 0; i < n; ++i) {
  88. node = nodes[i];
  89. ri = radii[node.index], ri2 = ri * ri;
  90. xi = node.x + node.vx;
  91. if (nDim > 1) { yi = node.y + node.vy; }
  92. if (nDim > 2) { zi = node.z + node.vz; }
  93. tree.visit(apply);
  94. }
  95. }
  96. function apply(treeNode, arg1, arg2, arg3, arg4, arg5, arg6) {
  97. var args = [arg1, arg2, arg3, arg4, arg5, arg6];
  98. var x0 = args[0],
  99. y0 = args[1],
  100. z0 = args[2],
  101. x1 = args[nDim],
  102. y1 = args[nDim+1],
  103. z1 = args[nDim+2];
  104. var data = treeNode.data, rj = treeNode.r, r = ri + rj;
  105. if (data) {
  106. if (data.index > node.index) {
  107. var x = xi - data.x - data.vx,
  108. y = (nDim > 1 ? yi - data.y - data.vy : 0),
  109. z = (nDim > 2 ? zi - data.z - data.vz : 0),
  110. l = x * x + y * y + z * z;
  111. if (l < r * r) {
  112. if (x === 0) x = jiggle(random), l += x * x;
  113. if (nDim > 1 && y === 0) y = jiggle(random), l += y * y;
  114. if (nDim > 2 && z === 0) z = jiggle(random), l += z * z;
  115. l = (r - (l = Math.sqrt(l))) / l * strength;
  116. node.vx += (x *= l) * (r = (rj *= rj) / (ri2 + rj));
  117. if (nDim > 1) { node.vy += (y *= l) * r; }
  118. if (nDim > 2) { node.vz += (z *= l) * r; }
  119. data.vx -= x * (r = 1 - r);
  120. if (nDim > 1) { data.vy -= y * r; }
  121. if (nDim > 2) { data.vz -= z * r; }
  122. }
  123. }
  124. return;
  125. }
  126. return x0 > xi + r || x1 < xi - r
  127. || (nDim > 1 && (y0 > yi + r || y1 < yi - r))
  128. || (nDim > 2 && (z0 > zi + r || z1 < zi - r));
  129. }
  130. }
  131. function prepare(treeNode) {
  132. if (treeNode.data) return treeNode.r = radii[treeNode.data.index];
  133. for (var i = treeNode.r = 0; i < Math.pow(2, nDim); ++i) {
  134. if (treeNode[i] && treeNode[i].r > treeNode.r) {
  135. treeNode.r = treeNode[i].r;
  136. }
  137. }
  138. }
  139. function initialize() {
  140. if (!nodes) return;
  141. var i, n = nodes.length, node;
  142. radii = new Array(n);
  143. for (i = 0; i < n; ++i) node = nodes[i], radii[node.index] = +radius(node, i, nodes);
  144. }
  145. force.initialize = function(_nodes, ...args) {
  146. nodes = _nodes;
  147. random = args.find(arg => typeof arg === 'function') || Math.random;
  148. nDim = args.find(arg => [1, 2, 3].includes(arg)) || 2;
  149. initialize();
  150. };
  151. force.iterations = function(_) {
  152. return arguments.length ? (iterations = +_, force) : iterations;
  153. };
  154. force.strength = function(_) {
  155. return arguments.length ? (strength = +_, force) : strength;
  156. };
  157. force.radius = function(_) {
  158. return arguments.length ? (radius = typeof _ === "function" ? _ : constant(+_), initialize(), force) : radius;
  159. };
  160. return force;
  161. }
  162. function index(d) {
  163. return d.index;
  164. }
  165. function find(nodeById, nodeId) {
  166. var node = nodeById.get(nodeId);
  167. if (!node) throw new Error("node not found: " + nodeId);
  168. return node;
  169. }
  170. function link(links) {
  171. var id = index,
  172. strength = defaultStrength,
  173. strengths,
  174. distance = constant(30),
  175. distances,
  176. nodes,
  177. nDim,
  178. count,
  179. bias,
  180. random,
  181. iterations = 1;
  182. if (links == null) links = [];
  183. function defaultStrength(link) {
  184. return 1 / Math.min(count[link.source.index], count[link.target.index]);
  185. }
  186. function force(alpha) {
  187. for (var k = 0, n = links.length; k < iterations; ++k) {
  188. for (var i = 0, link, source, target, x = 0, y = 0, z = 0, l, b; i < n; ++i) {
  189. link = links[i], source = link.source, target = link.target;
  190. x = target.x + target.vx - source.x - source.vx || jiggle(random);
  191. if (nDim > 1) { y = target.y + target.vy - source.y - source.vy || jiggle(random); }
  192. if (nDim > 2) { z = target.z + target.vz - source.z - source.vz || jiggle(random); }
  193. l = Math.sqrt(x * x + y * y + z * z);
  194. l = (l - distances[i]) / l * alpha * strengths[i];
  195. x *= l, y *= l, z *= l;
  196. target.vx -= x * (b = bias[i]);
  197. if (nDim > 1) { target.vy -= y * b; }
  198. if (nDim > 2) { target.vz -= z * b; }
  199. source.vx += x * (b = 1 - b);
  200. if (nDim > 1) { source.vy += y * b; }
  201. if (nDim > 2) { source.vz += z * b; }
  202. }
  203. }
  204. }
  205. function initialize() {
  206. if (!nodes) return;
  207. var i,
  208. n = nodes.length,
  209. m = links.length,
  210. nodeById = new Map(nodes.map((d, i) => [id(d, i, nodes), d])),
  211. link;
  212. for (i = 0, count = new Array(n); i < m; ++i) {
  213. link = links[i], link.index = i;
  214. if (typeof link.source !== "object") link.source = find(nodeById, link.source);
  215. if (typeof link.target !== "object") link.target = find(nodeById, link.target);
  216. count[link.source.index] = (count[link.source.index] || 0) + 1;
  217. count[link.target.index] = (count[link.target.index] || 0) + 1;
  218. }
  219. for (i = 0, bias = new Array(m); i < m; ++i) {
  220. link = links[i], bias[i] = count[link.source.index] / (count[link.source.index] + count[link.target.index]);
  221. }
  222. strengths = new Array(m), initializeStrength();
  223. distances = new Array(m), initializeDistance();
  224. }
  225. function initializeStrength() {
  226. if (!nodes) return;
  227. for (var i = 0, n = links.length; i < n; ++i) {
  228. strengths[i] = +strength(links[i], i, links);
  229. }
  230. }
  231. function initializeDistance() {
  232. if (!nodes) return;
  233. for (var i = 0, n = links.length; i < n; ++i) {
  234. distances[i] = +distance(links[i], i, links);
  235. }
  236. }
  237. force.initialize = function(_nodes, ...args) {
  238. nodes = _nodes;
  239. random = args.find(arg => typeof arg === 'function') || Math.random;
  240. nDim = args.find(arg => [1, 2, 3].includes(arg)) || 2;
  241. initialize();
  242. };
  243. force.links = function(_) {
  244. return arguments.length ? (links = _, initialize(), force) : links;
  245. };
  246. force.id = function(_) {
  247. return arguments.length ? (id = _, force) : id;
  248. };
  249. force.iterations = function(_) {
  250. return arguments.length ? (iterations = +_, force) : iterations;
  251. };
  252. force.strength = function(_) {
  253. return arguments.length ? (strength = typeof _ === "function" ? _ : constant(+_), initializeStrength(), force) : strength;
  254. };
  255. force.distance = function(_) {
  256. return arguments.length ? (distance = typeof _ === "function" ? _ : constant(+_), initializeDistance(), force) : distance;
  257. };
  258. return force;
  259. }
  260. // https://en.wikipedia.org/wiki/Linear_congruential_generator#Parameters_in_common_use
  261. const a = 1664525;
  262. const c = 1013904223;
  263. const m = 4294967296; // 2^32
  264. function lcg() {
  265. let s = 1;
  266. return () => (s = (a * s + c) % m) / m;
  267. }
  268. var MAX_DIMENSIONS = 3;
  269. function x$1(d) {
  270. return d.x;
  271. }
  272. function y$1(d) {
  273. return d.y;
  274. }
  275. function z$1(d) {
  276. return d.z;
  277. }
  278. var initialRadius = 10,
  279. initialAngleRoll = Math.PI * (3 - Math.sqrt(5)), // Golden ratio angle
  280. initialAngleYaw = Math.PI * 20 / (9 + Math.sqrt(221)); // Markov irrational number
  281. function simulation(nodes, numDimensions) {
  282. numDimensions = numDimensions || 2;
  283. var nDim = Math.min(MAX_DIMENSIONS, Math.max(1, Math.round(numDimensions))),
  284. simulation,
  285. alpha = 1,
  286. alphaMin = 0.001,
  287. alphaDecay = 1 - Math.pow(alphaMin, 1 / 300),
  288. alphaTarget = 0,
  289. velocityDecay = 0.6,
  290. forces = new Map(),
  291. stepper = d3Timer.timer(step),
  292. event = d3Dispatch.dispatch("tick", "end"),
  293. random = lcg();
  294. if (nodes == null) nodes = [];
  295. function step() {
  296. tick();
  297. event.call("tick", simulation);
  298. if (alpha < alphaMin) {
  299. stepper.stop();
  300. event.call("end", simulation);
  301. }
  302. }
  303. function tick(iterations) {
  304. var i, n = nodes.length, node;
  305. if (iterations === undefined) iterations = 1;
  306. for (var k = 0; k < iterations; ++k) {
  307. alpha += (alphaTarget - alpha) * alphaDecay;
  308. forces.forEach(function (force) {
  309. force(alpha);
  310. });
  311. for (i = 0; i < n; ++i) {
  312. node = nodes[i];
  313. if (node.fx == null) node.x += node.vx *= velocityDecay;
  314. else node.x = node.fx, node.vx = 0;
  315. if (nDim > 1) {
  316. if (node.fy == null) node.y += node.vy *= velocityDecay;
  317. else node.y = node.fy, node.vy = 0;
  318. }
  319. if (nDim > 2) {
  320. if (node.fz == null) node.z += node.vz *= velocityDecay;
  321. else node.z = node.fz, node.vz = 0;
  322. }
  323. }
  324. }
  325. return simulation;
  326. }
  327. function initializeNodes() {
  328. for (var i = 0, n = nodes.length, node; i < n; ++i) {
  329. node = nodes[i], node.index = i;
  330. if (node.fx != null) node.x = node.fx;
  331. if (node.fy != null) node.y = node.fy;
  332. if (node.fz != null) node.z = node.fz;
  333. if (isNaN(node.x) || (nDim > 1 && isNaN(node.y)) || (nDim > 2 && isNaN(node.z))) {
  334. var radius = initialRadius * (nDim > 2 ? Math.cbrt(0.5 + i) : (nDim > 1 ? Math.sqrt(0.5 + i) : i)),
  335. rollAngle = i * initialAngleRoll,
  336. yawAngle = i * initialAngleYaw;
  337. if (nDim === 1) {
  338. node.x = radius;
  339. } else if (nDim === 2) {
  340. node.x = radius * Math.cos(rollAngle);
  341. node.y = radius * Math.sin(rollAngle);
  342. } else { // 3 dimensions: use spherical distribution along 2 irrational number angles
  343. node.x = radius * Math.sin(rollAngle) * Math.cos(yawAngle);
  344. node.y = radius * Math.cos(rollAngle);
  345. node.z = radius * Math.sin(rollAngle) * Math.sin(yawAngle);
  346. }
  347. }
  348. if (isNaN(node.vx) || (nDim > 1 && isNaN(node.vy)) || (nDim > 2 && isNaN(node.vz))) {
  349. node.vx = 0;
  350. if (nDim > 1) { node.vy = 0; }
  351. if (nDim > 2) { node.vz = 0; }
  352. }
  353. }
  354. }
  355. function initializeForce(force) {
  356. if (force.initialize) force.initialize(nodes, random, nDim);
  357. return force;
  358. }
  359. initializeNodes();
  360. return simulation = {
  361. tick: tick,
  362. restart: function() {
  363. return stepper.restart(step), simulation;
  364. },
  365. stop: function() {
  366. return stepper.stop(), simulation;
  367. },
  368. numDimensions: function(_) {
  369. return arguments.length
  370. ? (nDim = Math.min(MAX_DIMENSIONS, Math.max(1, Math.round(_))), forces.forEach(initializeForce), simulation)
  371. : nDim;
  372. },
  373. nodes: function(_) {
  374. return arguments.length ? (nodes = _, initializeNodes(), forces.forEach(initializeForce), simulation) : nodes;
  375. },
  376. alpha: function(_) {
  377. return arguments.length ? (alpha = +_, simulation) : alpha;
  378. },
  379. alphaMin: function(_) {
  380. return arguments.length ? (alphaMin = +_, simulation) : alphaMin;
  381. },
  382. alphaDecay: function(_) {
  383. return arguments.length ? (alphaDecay = +_, simulation) : +alphaDecay;
  384. },
  385. alphaTarget: function(_) {
  386. return arguments.length ? (alphaTarget = +_, simulation) : alphaTarget;
  387. },
  388. velocityDecay: function(_) {
  389. return arguments.length ? (velocityDecay = 1 - _, simulation) : 1 - velocityDecay;
  390. },
  391. randomSource: function(_) {
  392. return arguments.length ? (random = _, forces.forEach(initializeForce), simulation) : random;
  393. },
  394. force: function(name, _) {
  395. return arguments.length > 1 ? ((_ == null ? forces.delete(name) : forces.set(name, initializeForce(_))), simulation) : forces.get(name);
  396. },
  397. find: function() {
  398. var args = Array.prototype.slice.call(arguments);
  399. var x = args.shift() || 0,
  400. y = (nDim > 1 ? args.shift() : null) || 0,
  401. z = (nDim > 2 ? args.shift() : null) || 0,
  402. radius = args.shift() || Infinity;
  403. var i = 0,
  404. n = nodes.length,
  405. dx,
  406. dy,
  407. dz,
  408. d2,
  409. node,
  410. closest;
  411. radius *= radius;
  412. for (i = 0; i < n; ++i) {
  413. node = nodes[i];
  414. dx = x - node.x;
  415. dy = y - (node.y || 0);
  416. dz = z - (node.z ||0);
  417. d2 = dx * dx + dy * dy + dz * dz;
  418. if (d2 < radius) closest = node, radius = d2;
  419. }
  420. return closest;
  421. },
  422. on: function(name, _) {
  423. return arguments.length > 1 ? (event.on(name, _), simulation) : event.on(name);
  424. }
  425. };
  426. }
  427. function manyBody() {
  428. var nodes,
  429. nDim,
  430. node,
  431. random,
  432. alpha,
  433. strength = constant(-30),
  434. strengths,
  435. distanceMin2 = 1,
  436. distanceMax2 = Infinity,
  437. theta2 = 0.81;
  438. function force(_) {
  439. var i,
  440. n = nodes.length,
  441. tree =
  442. (nDim === 1 ? d3Binarytree.binarytree(nodes, x$1)
  443. :(nDim === 2 ? d3Quadtree.quadtree(nodes, x$1, y$1)
  444. :(nDim === 3 ? d3Octree.octree(nodes, x$1, y$1, z$1)
  445. :null
  446. ))).visitAfter(accumulate);
  447. for (alpha = _, i = 0; i < n; ++i) node = nodes[i], tree.visit(apply);
  448. }
  449. function initialize() {
  450. if (!nodes) return;
  451. var i, n = nodes.length, node;
  452. strengths = new Array(n);
  453. for (i = 0; i < n; ++i) node = nodes[i], strengths[node.index] = +strength(node, i, nodes);
  454. }
  455. function accumulate(treeNode) {
  456. var strength = 0, q, c, weight = 0, x, y, z, i;
  457. var numChildren = treeNode.length;
  458. // For internal nodes, accumulate forces from children.
  459. if (numChildren) {
  460. for (x = y = z = i = 0; i < numChildren; ++i) {
  461. if ((q = treeNode[i]) && (c = Math.abs(q.value))) {
  462. strength += q.value, weight += c, x += c * (q.x || 0), y += c * (q.y || 0), z += c * (q.z || 0);
  463. }
  464. }
  465. strength *= Math.sqrt(4 / numChildren); // scale accumulated strength according to number of dimensions
  466. treeNode.x = x / weight;
  467. if (nDim > 1) { treeNode.y = y / weight; }
  468. if (nDim > 2) { treeNode.z = z / weight; }
  469. }
  470. // For leaf nodes, accumulate forces from coincident nodes.
  471. else {
  472. q = treeNode;
  473. q.x = q.data.x;
  474. if (nDim > 1) { q.y = q.data.y; }
  475. if (nDim > 2) { q.z = q.data.z; }
  476. do strength += strengths[q.data.index];
  477. while (q = q.next);
  478. }
  479. treeNode.value = strength;
  480. }
  481. function apply(treeNode, x1, arg1, arg2, arg3) {
  482. if (!treeNode.value) return true;
  483. var x2 = [arg1, arg2, arg3][nDim-1];
  484. var x = treeNode.x - node.x,
  485. y = (nDim > 1 ? treeNode.y - node.y : 0),
  486. z = (nDim > 2 ? treeNode.z - node.z : 0),
  487. w = x2 - x1,
  488. l = x * x + y * y + z * z;
  489. // Apply the Barnes-Hut approximation if possible.
  490. // Limit forces for very close nodes; randomize direction if coincident.
  491. if (w * w / theta2 < l) {
  492. if (l < distanceMax2) {
  493. if (x === 0) x = jiggle(random), l += x * x;
  494. if (nDim > 1 && y === 0) y = jiggle(random), l += y * y;
  495. if (nDim > 2 && z === 0) z = jiggle(random), l += z * z;
  496. if (l < distanceMin2) l = Math.sqrt(distanceMin2 * l);
  497. node.vx += x * treeNode.value * alpha / l;
  498. if (nDim > 1) { node.vy += y * treeNode.value * alpha / l; }
  499. if (nDim > 2) { node.vz += z * treeNode.value * alpha / l; }
  500. }
  501. return true;
  502. }
  503. // Otherwise, process points directly.
  504. else if (treeNode.length || l >= distanceMax2) return;
  505. // Limit forces for very close nodes; randomize direction if coincident.
  506. if (treeNode.data !== node || treeNode.next) {
  507. if (x === 0) x = jiggle(random), l += x * x;
  508. if (nDim > 1 && y === 0) y = jiggle(random), l += y * y;
  509. if (nDim > 2 && z === 0) z = jiggle(random), l += z * z;
  510. if (l < distanceMin2) l = Math.sqrt(distanceMin2 * l);
  511. }
  512. do if (treeNode.data !== node) {
  513. w = strengths[treeNode.data.index] * alpha / l;
  514. node.vx += x * w;
  515. if (nDim > 1) { node.vy += y * w; }
  516. if (nDim > 2) { node.vz += z * w; }
  517. } while (treeNode = treeNode.next);
  518. }
  519. force.initialize = function(_nodes, ...args) {
  520. nodes = _nodes;
  521. random = args.find(arg => typeof arg === 'function') || Math.random;
  522. nDim = args.find(arg => [1, 2, 3].includes(arg)) || 2;
  523. initialize();
  524. };
  525. force.strength = function(_) {
  526. return arguments.length ? (strength = typeof _ === "function" ? _ : constant(+_), initialize(), force) : strength;
  527. };
  528. force.distanceMin = function(_) {
  529. return arguments.length ? (distanceMin2 = _ * _, force) : Math.sqrt(distanceMin2);
  530. };
  531. force.distanceMax = function(_) {
  532. return arguments.length ? (distanceMax2 = _ * _, force) : Math.sqrt(distanceMax2);
  533. };
  534. force.theta = function(_) {
  535. return arguments.length ? (theta2 = _ * _, force) : Math.sqrt(theta2);
  536. };
  537. return force;
  538. }
  539. function radial(radius, x, y, z) {
  540. var nodes,
  541. nDim,
  542. strength = constant(0.1),
  543. strengths,
  544. radiuses;
  545. if (typeof radius !== "function") radius = constant(+radius);
  546. if (x == null) x = 0;
  547. if (y == null) y = 0;
  548. if (z == null) z = 0;
  549. function force(alpha) {
  550. for (var i = 0, n = nodes.length; i < n; ++i) {
  551. var node = nodes[i],
  552. dx = node.x - x || 1e-6,
  553. dy = (node.y || 0) - y || 1e-6,
  554. dz = (node.z || 0) - z || 1e-6,
  555. r = Math.sqrt(dx * dx + dy * dy + dz * dz),
  556. k = (radiuses[i] - r) * strengths[i] * alpha / r;
  557. node.vx += dx * k;
  558. if (nDim>1) { node.vy += dy * k; }
  559. if (nDim>2) { node.vz += dz * k; }
  560. }
  561. }
  562. function initialize() {
  563. if (!nodes) return;
  564. var i, n = nodes.length;
  565. strengths = new Array(n);
  566. radiuses = new Array(n);
  567. for (i = 0; i < n; ++i) {
  568. radiuses[i] = +radius(nodes[i], i, nodes);
  569. strengths[i] = isNaN(radiuses[i]) ? 0 : +strength(nodes[i], i, nodes);
  570. }
  571. }
  572. force.initialize = function(initNodes, ...args) {
  573. nodes = initNodes;
  574. nDim = args.find(arg => [1, 2, 3].includes(arg)) || 2;
  575. initialize();
  576. };
  577. force.strength = function(_) {
  578. return arguments.length ? (strength = typeof _ === "function" ? _ : constant(+_), initialize(), force) : strength;
  579. };
  580. force.radius = function(_) {
  581. return arguments.length ? (radius = typeof _ === "function" ? _ : constant(+_), initialize(), force) : radius;
  582. };
  583. force.x = function(_) {
  584. return arguments.length ? (x = +_, force) : x;
  585. };
  586. force.y = function(_) {
  587. return arguments.length ? (y = +_, force) : y;
  588. };
  589. force.z = function(_) {
  590. return arguments.length ? (z = +_, force) : z;
  591. };
  592. return force;
  593. }
  594. function x(x) {
  595. var strength = constant(0.1),
  596. nodes,
  597. strengths,
  598. xz;
  599. if (typeof x !== "function") x = constant(x == null ? 0 : +x);
  600. function force(alpha) {
  601. for (var i = 0, n = nodes.length, node; i < n; ++i) {
  602. node = nodes[i], node.vx += (xz[i] - node.x) * strengths[i] * alpha;
  603. }
  604. }
  605. function initialize() {
  606. if (!nodes) return;
  607. var i, n = nodes.length;
  608. strengths = new Array(n);
  609. xz = new Array(n);
  610. for (i = 0; i < n; ++i) {
  611. strengths[i] = isNaN(xz[i] = +x(nodes[i], i, nodes)) ? 0 : +strength(nodes[i], i, nodes);
  612. }
  613. }
  614. force.initialize = function(_) {
  615. nodes = _;
  616. initialize();
  617. };
  618. force.strength = function(_) {
  619. return arguments.length ? (strength = typeof _ === "function" ? _ : constant(+_), initialize(), force) : strength;
  620. };
  621. force.x = function(_) {
  622. return arguments.length ? (x = typeof _ === "function" ? _ : constant(+_), initialize(), force) : x;
  623. };
  624. return force;
  625. }
  626. function y(y) {
  627. var strength = constant(0.1),
  628. nodes,
  629. strengths,
  630. yz;
  631. if (typeof y !== "function") y = constant(y == null ? 0 : +y);
  632. function force(alpha) {
  633. for (var i = 0, n = nodes.length, node; i < n; ++i) {
  634. node = nodes[i], node.vy += (yz[i] - node.y) * strengths[i] * alpha;
  635. }
  636. }
  637. function initialize() {
  638. if (!nodes) return;
  639. var i, n = nodes.length;
  640. strengths = new Array(n);
  641. yz = new Array(n);
  642. for (i = 0; i < n; ++i) {
  643. strengths[i] = isNaN(yz[i] = +y(nodes[i], i, nodes)) ? 0 : +strength(nodes[i], i, nodes);
  644. }
  645. }
  646. force.initialize = function(_) {
  647. nodes = _;
  648. initialize();
  649. };
  650. force.strength = function(_) {
  651. return arguments.length ? (strength = typeof _ === "function" ? _ : constant(+_), initialize(), force) : strength;
  652. };
  653. force.y = function(_) {
  654. return arguments.length ? (y = typeof _ === "function" ? _ : constant(+_), initialize(), force) : y;
  655. };
  656. return force;
  657. }
  658. function z(z) {
  659. var strength = constant(0.1),
  660. nodes,
  661. strengths,
  662. zz;
  663. if (typeof z !== "function") z = constant(z == null ? 0 : +z);
  664. function force(alpha) {
  665. for (var i = 0, n = nodes.length, node; i < n; ++i) {
  666. node = nodes[i], node.vz += (zz[i] - node.z) * strengths[i] * alpha;
  667. }
  668. }
  669. function initialize() {
  670. if (!nodes) return;
  671. var i, n = nodes.length;
  672. strengths = new Array(n);
  673. zz = new Array(n);
  674. for (i = 0; i < n; ++i) {
  675. strengths[i] = isNaN(zz[i] = +z(nodes[i], i, nodes)) ? 0 : +strength(nodes[i], i, nodes);
  676. }
  677. }
  678. force.initialize = function(_) {
  679. nodes = _;
  680. initialize();
  681. };
  682. force.strength = function(_) {
  683. return arguments.length ? (strength = typeof _ === "function" ? _ : constant(+_), initialize(), force) : strength;
  684. };
  685. force.z = function(_) {
  686. return arguments.length ? (z = typeof _ === "function" ? _ : constant(+_), initialize(), force) : z;
  687. };
  688. return force;
  689. }
  690. exports.forceCenter = center;
  691. exports.forceCollide = collide;
  692. exports.forceLink = link;
  693. exports.forceManyBody = manyBody;
  694. exports.forceRadial = radial;
  695. exports.forceSimulation = simulation;
  696. exports.forceX = x;
  697. exports.forceY = y;
  698. exports.forceZ = z;
  699. Object.defineProperty(exports, '__esModule', { value: true });
  700. })));