import constant from "./constant"; import jiggle from "./jiggle"; /** * Modified link force algorithm * - simplify calculations for parameters locked for spring model * - removed other unused functions * Alpha should be constant 1 for accurate simulation */ export default function(links) { var dataSizeFactor, distance = constant(30), distances = [], nodes, iterations = 1; if (links == null) links = []; function force(alpha) { // Each iteration in a tick for (var k = 0, n = nodes.length, source, target, i, j, x, y, l; k < iterations; ++k) { // For each link for (i = 1; i < n; i++) for (j = 0; j < i; j++) { // jiggle so it wont divide / multiply by zero after this source = nodes[i]; target = nodes[j]; x = target.x + target.vx - source.x - source.vx || jiggle(); y = target.y + target.vy - source.y - source.vy || jiggle(); l = Math.sqrt(x * x + y * y); l = (l - distances[i*(i-1)/2+j]) / l * dataSizeFactor * alpha; x *= l, y *= l; target.vx -= x; target.vy -= y; source.vx += x; source.vy += y; } } } function initialize() { if (!nodes) return; dataSizeFactor = 0.5/(nodes.length-1); initializeDistance(); } function initializeDistance() { if (!nodes) return; for (let i = 1, n = nodes.length; i < n; i++) { for (let j = 0; j < i; j++) { distances.push(distanceFunction(nodes[i], nodes[j], props, norm)); } } } force.initialize = function(_) { nodes = _; initialize(); }; force.links = function(_) { return arguments.length ? (links = _, initialize(), force) : links; }; force.id = function(_) { return arguments.length ? (id = _, force) : id; }; force.iterations = function(_) { return arguments.length ? (iterations = +_, force) : iterations; }; force.distance = function(_) { return arguments.length ? (distance = typeof _ === "function" ? _ : constant(+_), initializeDistance(), force) : distance; }; return force; }