import constant from "./fconstant.js"; import jiggle from "./fjiggle.js"; const quadtree = d3.quadtree function x(d) { return d.x + d.vx; } function y(d) { return d.y + d.vy; } export default function(radius) { var nodes, radii, strength = 1, iterations = 1 if (typeof radius !== "function") radius = constant(radius == null ? 1 : +radius) function force() { var i, n = nodes.length, tree, node, xi, yi, ri, ri2; for (var k = 0; k < iterations; ++k) { // we pass to the qt, x and y as they will be computed in the // next step (see fn's above) tree = quadtree(nodes, x, y) for (i = 0; i < n; ++i) { node = nodes[i] // node left, right (a note: .bb.x- should be 0-based) var nxl = node.x + node.bb.x1 var nxr = node.x + node.bb.x2 var nyt = node.y + node.bb.y1 var nyb = node.y + node.bb.y2 // node center-by-bounding-box var cnx = (nxr - nxl) / 2 + nxl var cny = (nyb - nyt) / 2 + nyt // for each node, visit each... //console.log(`visit ${node.index}`) tree.visit(apply) } } function apply(quad, x0, y0, x1, y1) { let updated = false var data = quad.data, r if (data) { var rj = data.r r = ri + rj // prevents from op'ing twice if (data.index > node.index) { // quad.data is the node, // by domain intersections... // | -------- x ------ | // | ------------ x ------ | // | ---- x --- | // data left, right let dxl = data.x + data.bb.x1 let dxr = data.x + data.bb.x2 // dxr or dxl within nx, if(nxl < dxr && dxr < nxr || nxl < dxl && dxl < nxr){ // now write these let dyt = data.y + data.bb.y1 let dyb = data.y + data.bb.y2 // and check, if(nyt < dyt && dyt < nyb || nyt < dyb && dyb < nyb){ updated = true // ok then, compute centers to find a direction for force-exertion // maybe should also do this in prepare also (and the node data, only once) let cdx = (dxr - dxl) / 2 + dxl let cdy = (dyb - dyt) / 2 + dyt // x overlap term let xo = 0 if(cnx < cdx){ xo = nxr - dxl } else { xo = nxl - dxr } // y overlap term let yo = 0 if(cny < cdy){ yo = nyb - dyt } else { yo = nyt - dyb } // just assert one axis if(Math.abs(xo) > Math.abs(yo)){ node.vy -= yo * strength data.vy += yo * strength } else { node.vx -= xo * strength data.vx += xo * strength } } } } return } // end if-data return updated } // end apply() } function initialize() { if (!nodes) return } force.initialize = function(_) { nodes = _ initialize() } force.strength = function(_) { return arguments.length ? (strength = +_, force) : strength } return force }