d3-force/src/collide.js
2016-04-25 14:00:54 -07:00

69 lines
1.7 KiB
JavaScript

import constant from "./constant";
import {quadtree} from "d3-quadtree";
import {x, y} from "./simulation";
export default function(radius) {
var nodes,
radii,
radiusMax,
strength = 0.7;
if (typeof radius !== "function") radius = constant(radius == null ? 1 : +radius);
function force() {
var i, n = nodes.length,
tree = quadtree(nodes, x, y),
node,
nx0,
ny0,
nx1,
ny1,
vx,
vy,
nr;
for (i = 0; i < n; ++i) {
node = nodes[i], nr = radii[i] + radiusMax, vx = vy = 0;
nx0 = node.x - nr, ny0 = node.y - nr;
nx1 = node.x + nr, ny1 = node.y + nr;
tree.remove(node).visit(apply);
node.x += vx * strength, node.y += vy * strength;
tree.add(node);
}
function apply(quad, x0, y0, x1, y1) {
if (x0 > nx1 || x1 < nx0 || y0 > ny1 || y1 < ny0) return true;
if (quad.length) return;
var x = node.x - quad.data.x,
y = node.y - quad.data.y,
l = x * x + y * y,
r = radii[i] + radii[quad.data.index];
if (l < r * r) {
l = (r - (l = Math.sqrt(l))) / l;
vx += x * l, vy += y * l;
}
}
}
force.initialize = function(_) {
nodes = _.nodes();
var i, n = nodes.length, r;
radii = new Array(n), radiusMax = 0;
for (i = 0; i < n; ++i) {
if ((radii[i] = r = +radius(nodes[i], i, nodes)) > radiusMax) {
radiusMax = r;
}
}
};
force.strength = function(_) {
return arguments.length ? (strength = +_, force) : strength;
};
force.radius = function(_) {
return arguments.length ? (radius = typeof _ === "function" ? _ : constant(+_), force) : radius;
};
return force;
}