Javascript 根据节点数量,通过电荷/重力特性优化d3力导向布局

Javascript 根据节点数量,通过电荷/重力特性优化d3力导向布局,javascript,graph,d3.js,force-layout,Javascript,Graph,D3.js,Force Layout,我一直在使用D3内置的力定向算法进行网络拓扑可视化。一切正常,但有一个重要的细节有问题。。。对于具有不同数量节点的图,我似乎无法以理想的方式将图布局。理想情况下,我的意思是节点彼此之间的间隔很好(没有重叠),节点聚集在任何有意义的地方。我一直试图通过调整部队布局的“电荷”和“重力”属性来实现这一点,但无论我尝试了什么,它似乎总是适用于一种场景(即大量节点),而不适用于另一种场景(即少量节点)。例如,如果我的布局适用于一个大型图形,那么当我使用相同的电荷/重力公式查看小型图形时,我会有一些节点远离

我一直在使用D3内置的力定向算法进行网络拓扑可视化。一切正常,但有一个重要的细节有问题。。。对于具有不同数量节点的图,我似乎无法以理想的方式将图布局。理想情况下,我的意思是节点彼此之间的间隔很好(没有重叠),节点聚集在任何有意义的地方。我一直试图通过调整部队布局的“电荷”和“重力”属性来实现这一点,但无论我尝试了什么,它似乎总是适用于一种场景(即大量节点),而不适用于另一种场景(即少量节点)。例如,如果我的布局适用于一个大型图形,那么当我使用相同的电荷/重力公式查看小型图形时,我会有一些节点远离站点的其他节点。下面是我根据另一个SO问题使用的公式示例:

这适用于具有14个节点的图形,但如果我对具有5个节点的图形进行相同的尝试,其中一些节点将完全脱离屏幕。请注意,计算“k”时使用的宽度/高度在这两种情况下没有变化。现在,基于图形可见区域的宽度/高度,我可能不应该有这些属性。老实说,这不是一个要求。我不需要图形来渲染和适应图形的视口。我只需要图形合理地进行布局,所以如果其中一些图形可能在可见区域之外,尤其是在大型图形中,就可以了。我也尝试了以下方法并取得了一些成功,但我仍然发现,对于小型图,节点渲染距离图的其余部分太远:

var charge = -1 * Math.pow(json.nodes.length, 3);
var gravity = 1 / json.nodes.length;

有人能帮我解决这个问题吗?非常感谢,因为我觉得自己被困在这个atm机上。

在这种基于强制算法的情况下,我要说的是,几乎不可能设置所有案例的匹配设置。这种布局几乎不依赖于图形密度和内部图形语义。
节点的可能数量范围是多少?密度呢?它是随机生成的具有预定义密度系数的图形,还是有一些语义在后面,并且有可能基于此语义看起来不错。
您说过节点彼此之间流动得很远。什么更高的重力给了你?
关于
linkDistance
的建议也可能对您有所帮助。例如,我正在使用d3.forceLayout绘制网络图(但它们大多是节点小于50的小型手工图形)。我刚刚从Mike Bostock的force布局示例中复制了数据。这是:

// graph force layout defaults
var linkDistance = 50,
    charge = -200;
// chart properties
var height = 720,
    width = 720;
    radius = 10;
我不指望它会帮助你,但也许它会激发其他人的讨论

UPD。我只能建议你去试验一下。选择一小组测试图,并为每个图找到最佳初始设置,然后插值给定的数字。此外,如果您处理非常大的图形(我的意思是非常大,用于“漂亮”的可视化),可能您会发现分组(colapsing)的某些部分非常有用-它减少了节点的数量(可能还降低了图形的复杂性)。

还请记住,您不需要设置恒力布局设置(电荷、重力、连接距离等都是维护功能)。可以将节点的半径设置为比可见半径稍大一点,这样它们就不会相互重叠。或设置电荷的非恒定函数,例如。或者使用Mike Bostock的建议手动在每个刻度上分布节点。

我实际上自己解决了这个问题

因此,我使用的电荷/重力/等值并不是问题所在。问题与调用tick函数调整图形的次数有关。对于我的大图,节点总是布置得相当好。我遇到的主要问题是较小的图形。我发现当图形中只有大约5-10个节点时,节点通常会被放置在视口之外

在我的代码中,我手动调用tick函数,如下所示:

force.start();

for (var i = tickLimit; i > 0; --i)
    force.tick();

force.stop();
以前,tickLimit的设置如下:

var tickLimit = Math.pow(json.nodes.length, 2);
在搞乱了电荷/重力值等之后,我最终意识到这对于小图形是不够的。如果我有一个有4个节点的图,那么这意味着只会进行16次tick()调用。这还不足以使图形完全调整自身(即稳定)。因此,我只需要添加一个检查,以确保图形的滴答次数最少(例如,至少300次),最大(例如,不超过10000次)


这可能不适用于所有人,但它解决了我的问题。

有人吗?请帮忙。:)部队布局对于这项任务来说并不理想。除了电荷/重力属性之外,您可以尝试的是
linkDistance
,甚至可以添加“幻影”链接,即未绘制但会影响节点定位方式的链接。我已经在使用link distance,尽管我发现它不会对图的布局产生很大影响。电荷/重力似乎对此更为重要。为什么说强制布局不适合网络拓扑?老实说,我认为它比任何其他网络图算法都更适合。还有其他建议吗?它不是特别合适,因为只要满足力约束,它就不会做出任何努力使布局“美观”。我对Javascript没有任何其他建议。没有最大节点数。此网络拓扑内置于产品中,因此它取决于客户在图中的节点数。我们的一些客户拥有庞大的网络,可能会生成大于5000个节点的图形。我要找的就是生成一个节点不重叠且分布均匀的图。我不想所有的节点都挤在一起。。。我不想让他们相隔太远。我曾希望force布局算法能够独立完成这项工作,或者允许我更简单地调整它。。。但事实似乎并非如此
var tickLimit = Math.pow(json.nodes.length, 2);