source: node_modules/d3-force/dist/d3-force.js@ e4c61dd

Last change on this file since e4c61dd was e4c61dd, checked in by istevanoska <ilinastevanoska@…>, 6 months ago

Prototype 1.1

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