| 1 | // https://d3js.org/d3-force/ v3.0.0 Copyright 2010-2021 Mike Bostock
|
|---|
| 2 | (function (global, factory) {
|
|---|
| 3 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3-quadtree'), require('d3-dispatch'), require('d3-timer')) :
|
|---|
| 4 | typeof 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 |
|
|---|
| 8 | function 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 |
|
|---|
| 49 | function constant(x) {
|
|---|
| 50 | return function() {
|
|---|
| 51 | return x;
|
|---|
| 52 | };
|
|---|
| 53 | }
|
|---|
| 54 |
|
|---|
| 55 | function jiggle(random) {
|
|---|
| 56 | return (random() - 0.5) * 1e-6;
|
|---|
| 57 | }
|
|---|
| 58 |
|
|---|
| 59 | function x$2(d) {
|
|---|
| 60 | return d.x + d.vx;
|
|---|
| 61 | }
|
|---|
| 62 |
|
|---|
| 63 | function y$2(d) {
|
|---|
| 64 | return d.y + d.vy;
|
|---|
| 65 | }
|
|---|
| 66 |
|
|---|
| 67 | function 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 |
|
|---|
| 156 | function index(d) {
|
|---|
| 157 | return d.index;
|
|---|
| 158 | }
|
|---|
| 159 |
|
|---|
| 160 | function find(nodeById, nodeId) {
|
|---|
| 161 | var node = nodeById.get(nodeId);
|
|---|
| 162 | if (!node) throw new Error("node not found: " + nodeId);
|
|---|
| 163 | return node;
|
|---|
| 164 | }
|
|---|
| 165 |
|
|---|
| 166 | function 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
|
|---|
| 272 | const a = 1664525;
|
|---|
| 273 | const c = 1013904223;
|
|---|
| 274 | const m = 4294967296; // 2^32
|
|---|
| 275 |
|
|---|
| 276 | function lcg() {
|
|---|
| 277 | let s = 1;
|
|---|
| 278 | return () => (s = (a * s + c) % m) / m;
|
|---|
| 279 | }
|
|---|
| 280 |
|
|---|
| 281 | function x$1(d) {
|
|---|
| 282 | return d.x;
|
|---|
| 283 | }
|
|---|
| 284 |
|
|---|
| 285 | function y$1(d) {
|
|---|
| 286 | return d.y;
|
|---|
| 287 | }
|
|---|
| 288 |
|
|---|
| 289 | var initialRadius = 10,
|
|---|
| 290 | initialAngle = Math.PI * (3 - Math.sqrt(5));
|
|---|
| 291 |
|
|---|
| 292 | function 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 |
|
|---|
| 434 | function 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 |
|
|---|
| 546 | function 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 |
|
|---|
| 602 | function 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 |
|
|---|
| 642 | function 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 |
|
|---|
| 682 | exports.forceCenter = center;
|
|---|
| 683 | exports.forceCollide = collide;
|
|---|
| 684 | exports.forceLink = link;
|
|---|
| 685 | exports.forceManyBody = manyBody;
|
|---|
| 686 | exports.forceRadial = radial;
|
|---|
| 687 | exports.forceSimulation = simulation;
|
|---|
| 688 | exports.forceX = x;
|
|---|
| 689 | exports.forceY = y;
|
|---|
| 690 |
|
|---|
| 691 | Object.defineProperty(exports, '__esModule', { value: true });
|
|---|
| 692 |
|
|---|
| 693 | })));
|
|---|