8

これは、R で beeswarm プロットを作成することに関する記事です。

beeswarm plot の R パッケージもあります。次の 2 つの図は、そのパッケージが提供するいくつかの可能性を示しています。

ここに画像の説明を入力

ここに画像の説明を入力

ただし、私は現在、d3.jsの強制指向レイアウトを使用して作成しようとしています。

私の計画は、カスタム重力でポイントを垂直線とその適切な y 値に向かって引き寄せ、衝突検出でポイントを互いに離すことです。

私は半作業プロトタイプを持っています:

ここに画像の説明を入力

残念ながら、私は 2 つの問題を回避する方法を見つけることができません。これらは実際には同じ問題であると思われます。

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

これは、フォース指向のレイアウトへの私の最初の進出です。

4

2 に答える 2

7

あなたの結果は私にはかなり良さそうです。ただし、オーバーラップの可能性を減らしたい場合は、いくつか試してみてください。

  1. ノード間にパディングを追加します。特に、円にはストロークがあり、このストロークの半分は円の半径を超えて伸びます。したがって、ストロークの重なりを避けたい場合はr、2 つの半径を加算して計算するときに、少なくとも 1 ピクセルのパディングが必要になります。(これは、各円に 1 つのピクセル ストロークがあり、各半径に 0.5 ピクセルが追加されることを前提としています)。

  2. nudge_factor を計算するときは、.4 ではなく .5 を使用します。これにより、オーバーラップする円が十分に離れてオーバーラップしなくなり、オーバーラップの解決が強化されます。.4 未満の値を使用すると、解は少し安定しますが、ナッジ後も円が少し重なるため、収束が遅くなります。

  3. ティックごとに衝突解決を複数回実行します。現在、衝突解決を実行してから、カスタムの重力を (true_x および true_y に向かって) 適用しています。ティックごとに衝突解決を複数回実行すると、重力に対して衝突解決が強くなります。

また、静的なレイアウトだけが必要な場合は、反復的にレンダリングするのではなく、フォース レイアウトを固定数の反復 (または安定化) で実行し、最後に 1 回レンダリングすることを検討することもできます。これにより、レイアウトが大幅に高速化されますが、繰り返しを実行しすぎるとレンダリングで一時的な問題が発生する可能性があります。

于 2011-11-07T00:21:31.567 に答える
1

簡単な実装

ここに別の実装があります: http://bl.ocks.org/4732279

ここに画像の説明を入力

最初にこれをフォース レイアウトで実装しようとしましたが、フォース レイアウト シミュレーションは当然、両方の軸に沿ってデータ ポイントをプッシュすることによって平衡に達しようとします。自分)。

この実装は、正規分布のランダム ジッタリングをインテリジェントな戦略に置き換えることで改善できます。しかし、私の目的には、これで十分でした。

  1. 衝突ビジターに対する反復の総数は、最終状態での衝突の確率に直接影響します。
  2. 正規分布の標準偏差を大きくすると、視覚化が衝突のないソリューションにすばやく収束するのに役立ちますが、もちろん、最終的にはより多くの垂直方向のスペースが必要になる場合があります。

もう少し完全な機能を備えていますが、より複雑です...

ここでは、もう少し洗い流しています (軸、ズームなどを使用): http://bl.ocks.org/4734864

ここに画像の説明を入力

GIF アニメーション:

ここに画像の説明を入力

于 2013-02-07T16:50:01.540 に答える