在javascript/d3中使用强制定向布局的怪异情节

Nat*_*ate 7 javascript layout plot d3.js force-layout

这是一篇关于在R中创建beeswarm情节文章.

还有R包为beeswarm情节.接下来的两张图片说明了该软件包提供的一些可能性:

在此输入图像描述

在此输入图像描述

但是,我现在正试图使用d3.js的强制定向布局.

我的计划是让自定义重力将点拉向垂直线及其正确的y值,并且碰撞检测使点彼此保持不变.

我有一个半工作原型:

在此输入图像描述

不幸的是,我无法找到解决两个问题的方法 - 我怀疑它们确实是同一个问题:

  1. 我的观点不断重叠,至少有点重叠.

  2. 在布局中心堆积积分之后,正在进行"洗牌",因为防撞力量和"来到中心"部队的战斗.

我希望这些要点可以很快就他们应该居住的地方达成协议,最终不会重叠.

我正在使用的强制代码(如果你想在这里看到它而不是bl.ocks.org):

force.on("tick", function(e) {
  var q,
    node,
    i = 0,
    n = nodes.length;

  var q = d3.geom.quadtree(nodes);

  while (++i < n) {
    node = nodes[i];
    q.visit(collide(node));
    xerr = node.x - node.true_x;
    yerr = node.y - node.true_y;
    node.x -= xerr*0.005;
    node.y -= yerr*0.9;
  }

  svg.selectAll("circle")
      .attr("cx", function(d) { return d.x; })
      .attr("cy", function(d) { return d.y; });
});

function collide(node) {
  var r = node.radius,
    nx1,
    nx2,
    ny1,
    ny2,
    xerr,
    yerr;

  nx1 = node.x - r;
  nx2 = node.x + r;
  ny1 = node.y - r;
  ny2 = node.y + r;

  return function(quad, x1, y1, x2, y2) {
    if (quad.point && (quad.point !== node)) {
      var x = node.x - quad.point.x,
          y = node.y - quad.point.y,
          l = Math.sqrt(x * x + y * y),
          r = node.radius + quad.point.radius;
      if (l < r) {
        // we're colliding.
        var xnudge, ynudge, nudge_factor;
        nudge_factor = (l - r) / l * .4;
        xnudge = x*nudge_factor;
        ynudge = y*nudge_factor;
        node.x -= xnudge;
        node.y -= ynudge;
        quad.point.x += xnudge;
        quad.point.y += ynudge;
      }
    }
    return x1 > nx2
        || x2 < nx1
        || y1 > ny2
        || y2 < ny1;
  };
}
Run Code Online (Sandbox Code Playgroud)

这是我第一次涉足强制导向的布局,所以如果这是诺贝尔的话,请道歉......

mbo*_*ock 6

您的结果对我来说看起来不错。但是,如果要减少重叠的可能性,可以尝试一些方法。

  1. 在节点之间添加一些填充。特别是,您的圆具有笔触,并且此笔触的一半将延伸到圆半径之外。因此,如果要避免笔触重叠,则在r通过将两个半径加在一起进行计算时,至少需要填充一个像素。(这假设您在每个圆上有一个像素笔触,这会为每个半径增加0.5像素。)

  2. 计算nudge_factor时,请使用.5而不是.4。通过将任何重叠的圆推开足够远,使它们不再重叠,可以使重叠分辨率更强。如果使用小于.4的值,则解决方案会更稳定,但收敛速度会更慢,因为即使在微调之后,圆仍会有些重叠。

  3. 每个刻度多次运行碰撞解决方案。您当前正在运行碰撞解决方案,然后应用自定义重力(朝向true_x和true_y)。如果每个刻度多次运行碰撞分辨率,则它使碰撞分辨率相对于重力更强。

另外,如果只需要静态布局,则还可以考虑让强制布局运行固定次数的迭代(或稳定),然后在末尾渲染一次,而不是迭代渲染。这样可以加快布局速度,但是如果运行太多的迭代,则可能会暂时影响渲染。