避免 D3 强制布局中节点和边之间的碰撞
Posted
技术标签:
【中文标题】避免 D3 强制布局中节点和边之间的碰撞【英文标题】:Avoid collision between nodes and edges in D3 force layout 【发布时间】:2013-07-29 01:06:38 【问题描述】:在本例中:http://bl.ocks.org/mbostock/1747543:
...Mike 向我们展示了如何避免节点之间的冲突,以使两个节点不会相互重叠。
我想知道是否有可能避免节点和边之间的冲突,以便没有节点“剪辑”或重叠边,除非它被该边连接。
以下使用 D3 force-direct 的示例显示节点 L
与连接 I
和 A
的边重叠,类似地,节点 M
与连接 L
和 D
的边重叠。我们如何防止此类情况发生?
【问题讨论】:
这对于 D3 中的强制布局实现是不可能的。你需要自己实现这个。请注意,这实际上是一个非常困难的问题(计算上),因此即使您有一个实现,它也可能不想在浏览器中运行它。 @LarsKotthoff,你是说,一般来说,没有已知的图形布局算法(包括为 D3 实现的算法)可以有效地解决这个问题? 这取决于你对高效的定义。找到一个(静态)解决方案对我来说听起来至少是 NP-hard。这并不意味着它可以在特定情况下快速解决,但这通常是困难的(对于大型图表,您可能无法快速解决)。然后更改初始解决方案以使节点稍微移动(就像模拟那样)将非常容易,因为您只需要进行本地修复。 这不是一个难题。除了节点之外,只需向边缘添加力即可。如果可能的话,简单地增加图表的大小会有很大帮助。 @tba,你对边缘施加力到底是什么意思?增加图表大小不是很灵活,因为可用于显示图表的区域可能会受到应用程序的限制。 【参考方案1】:如果您的图表没有太多节点,您可以伪造它。只需为每个链接插入一个或多个节点,并在tick
处理程序中沿链接设置它们的位置。以http://bl.ocks.org/couchand/7190660 为例,但对 Mike Bostock 版本的更改基本上只是:
var linkNodes = [];
graph.links.forEach(function(link)
linkNodes.push(
source: graph.nodes[link.source],
target: graph.nodes[link.target]
);
);
和
// force.on('tick', function()
linkNodes.forEach(function(node)
node.x = (node.source.x + node.target.x) * 0.5;
node.y = (node.source.y + node.target.y) * 0.5;
);
如果您有很多节点和边,这将引入相当严重的性能开销,但如果您的图表没有比您的示例大很多,则几乎不会被注意到。
您可能还想调整真实节点与链接节点的相对力。
再往前走一步,你会得到http://bl.ocks.org/mbostock/4600693的漂亮弯曲链接。
【讨论】:
以上是关于避免 D3 强制布局中节点和边之间的碰撞的主要内容,如果未能解决你的问题,请参考以下文章