在D3力导向图中有效地计算凸包

时间:2012-08-25 19:20:31

标签: javascript performance d3.js force-layout convex-hull

我有类似于force-directed graph示例的内容。主要区别在于没有力 - 除了用户拖动交互之外,布局是静态的。我添加了围绕用户定义的节点组绘制convex hulls(作为svg:path元素)的代码。移动节点(即.on("drag"))时会触发计算外壳的代码。这意味着在拖动节点时会不断触发它。通常有10到30个船体;节点可以在一个或多个船体中。见下文:

Example of hull graph

我正在试图弄清楚是否有更高效(更高性能)的方式来做我正在做的事情。暂时将其保持在高水平:

在拖动时,更新所有船体图形:

  1. 对于每个船体,创建一个组成节点坐标数组。
  2. 将上述阵列中的每个坐标对替换为距离原点距离 r 的8个点。这是为了填充/扩张船体,因此它实际上并没有触及任何节点。
  3. 将计算出的坐标输入d3.geom.hull
  4. 我在Chrome中获得了大约50 fps,这一点都不差,但它似乎是一种非常低效的设置。

    我唯一明确的想法是存储节点数组中包含节点的船体的ID,并且只更新那些/那些船体而不是所有船体。我也想知道更高效的数据结构来存储船体数据(而不是路径本身)。目前,数据结构如下所示:

    hulls = {1:{nodeIDs:[1,2,3,4,5], name:"hull1"}, 2:{...}, ...};
    

    请原谅这个开放式问题,但我希望有一些我不熟悉的编程技巧可以在这里运作良好。

1 个答案:

答案 0 :(得分:1)

最有效的方法是仅重新计算围绕正在拖动的节点的8元组坐标的位置,然后在父级船体中传播该信息以进行重绘。

您可以通过进行一些更改来完成此操作。

  • 对于每个节点的数据结构,添加以下元素。
    • 参考所有父体(如您所建议的)
    • 围绕该节点(缓存它们)的“填充”坐标的8元组
  • 在拖动时,仅考虑被拖动的节点。
  • 更新该节点的8元组。
  • 收集该节点的父船体的子节点并将它们的8元组折叠在一起并将它们提供给hull(如有必要,销毁前一个船体)。

我不熟悉d3.js的API,但我确信你可以填写我留下的任何空白。