53

所以我已经有一个页面,它绘制了一个力导向图,就像这里显示的那样。

这很好用。我正在使用这里的 JS ,通过一些调整来更好地分散节点。

这些或多或少是唯一的区别:

d3.json("force.json", function(json) {
  var force = d3.layout.force()
      .gravity(0.1)
      .charge(-2000)
      .linkDistance(1)
      .linkStrength(0.1)
      .nodes(json.nodes)
      .links(json.links)
      .size([w, h])
      .start();

降低链接强度似乎使链接更像弹簧,因此它变得类似于经常使用的Fruchterman & Reingold技术。这工作得相当好,但仅适用于相当小的图形。对于较大的图表,交叉点的数量只会增加 - 正如人们所期望的那样,但它所采用的解决方案通常远非最佳。我不是在寻找获得最佳解决方案的方法,我知道这非常困难。我只是希望它有一些粗略的添加,试图将线条和节点分开。

有没有办法在链接之间以及节点之间添加排斥?我不熟悉 D3 force 的工作方式,我似乎找不到任何说这是可能的...

4

4 回答 4

14

不幸的是,您的问题的答案不存在。

D3 中没有内置机制可以排斥边缘或最小化边缘交叉。您会认为在边缘实施收费并不难,但我们来了。

此外,似乎没有任何机制可以减少一般的边缘交叉。我浏览了数十个可视化库和布局算法,但没有一个涉及减少通用无向图上的边交叉。

有许多算法适用于平面图、2 级图或其他简化。dagre在理论上适用于 2 级图,尽管完全缺乏文档使得它几乎无法使用。

造成这种情况的部分原因是布局图表很困难。特别是,最小化边缘交叉是 NP 难的,所以我怀疑大多数布局设计师都会遇到这个问题,用头撞键盘几次,然后放弃。

如果有人为此提出了一个好的库,请为我们其他人发布它:)

于 2016-06-30T23:08:57.557 回答
5

比试图强行排斥边缘更容易的方法是摆动节点,直到系统中的交叉线数量减少。

http://en.wikipedia.org/wiki/Simulated_annealing

从连接数量最少的节点开始,然后向下摆动。

如果您尝试将边缘用作节点,我怀疑您只会遇到相同的空间锁定问题。解决方案是找出边缘交叉点的位置以及是否可以解决它们。您可能会发现解决许多边缘交叉是不可能的

一种更横向的可视化方法是对其进行动画处理,使其一次仅显示节点和连接的子集。或者使边缘透明,直到用户将鼠标焦点放在节点上,这点关联的边缘变得更加可见。

于 2012-11-29T19:27:28.187 回答
0

I followed the Force Editor example and I saw that setting charge and linkDistance values solves the problem.

  ...
  .charge(-200)
  .linkDistance(50)
  ...

Screenshot:

enter image description here

于 2014-08-08T07:16:15.433 回答
-2

我已经“解决”了这个问题:

nodes[0].x = width / 2;
nodes[0].y = 100;
nodes[0].fixed = true;
force.on("tick", function(e) {

    var kx = .4 * e.alpha, ky = 1.4 * e.alpha;
    links.forEach(function(d, i) {
      d.target.x += (d.source.x - d.target.x) * kx;
      d.target.y += (d.source.y + 80 - d.target.y) * ky;
    });
    [...]
 }

http://mbostock.github.io/d3/talk/20110921/parent-foci.html

这不完全是我们想要的,但和以前一样好。重要的是,您定义一个“根”节点并修复它。

nodes[0].fixed = true;

它看起来更像一棵树,但更清晰。

于 2017-09-13T09:00:32.283 回答