【问题标题】:Beeswarm plot with force-directed layout in javascript/d3在 javascript/d3 中具有强制导向布局的蜂群图
【发布时间】:2011-12-18 19:10:08
【问题描述】:

这是article on creating beeswarm plots in R

还有R package for beeswarm plot。接下来的两张图片说明了该软件包提供的一些可能性:

但是,我现在尝试使用 d3.js 的强制导向布局。

我的计划是让自定义重力将这些点拉向一条垂直线及其正确的 y 值,并且碰撞检测使这些点彼此远离。

我有a semi-working prototype:

不幸的是,我找不到解决两个问题的方法——我怀疑这实际上是同一个问题:

  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;
  };
}

这是我第一次涉足强制导向的布局,如果这很愚蠢,请道歉......

【问题讨论】:

    标签: javascript layout d3.js plot force-layout


    【解决方案1】:

    简单实现

    这是另一个实现:http://bl.ocks.org/4732279

    我最初尝试使用力布局来实现这一点,但力布局模拟自然会尝试通过沿两个轴推动数据点来达到平衡,这可能会破坏数据的顺序(如果这对您很重要)这是给我的)。

    可以通过用智能策略替换正态分布的随机抖动来改进此实现。但就我的目的而言,这就足够了。

    1. 碰撞访问者的总迭代次数直接影响最终状态的碰撞概率。
    2. 提高正态分布的标准差也可以帮助可视化更快地收敛到无冲突解决方案,但最终可能需要更多的垂直空间。

    功能更全面,但更复杂...

    这里的内容更清晰一些(带有轴、缩放等):http://bl.ocks.org/4734864

    GIF 动画:

    【讨论】:

      【解决方案2】:

      您的结果在我看来相当不错。但是,如果您想减少重叠的可能性,可以尝试一些方法。

      1. 在节点之间添加一些填充。特别是,你的圆圈有一个笔划,这个笔划的一半将超出圆圈的半径。因此,如果您想避免重叠笔划,当您通过将两个半径相加来计算r 时,您将需要至少一个像素的填充。 (这假设您在每个圆上都有一个像素笔划,这会为每个半径增加 0.5 个像素。)

      2. 在计算 nudge_factor 时使用 .5 而不是 .4。这使得重叠分辨率更强,通过将任何重叠的圆圈推开足够远,使它们不再重叠。如果您使用小于 0.4 的值,则解会更稳定一些,但收敛速度会更慢,因为即使在微移之后圆圈仍然会重叠一点。

      3. 每次滴答运行多次冲突解决。您当前正在运行碰撞解决方案,然后应用自定义重力(朝向 true_x 和 true_y)。如果您每次运行多次碰撞解决方案,它会使碰撞解决方案相对于重力更强。

      另外,如果您只想要一个静态布局,您还可以考虑让强制布局运行固定数量的迭代(或稳定),然后在最后渲染一次,而不是迭代渲染。这使布局速度更快,但如果运行太多迭代,可能会导致渲染出现暂时的中断。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-08-30
        • 1970-01-01
        • 2012-10-21
        • 2013-08-13
        • 2014-05-17
        • 2014-07-09
        • 2013-06-25
        • 2016-11-13
        相关资源
        最近更新 更多