简体   繁体   English

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

[英]Efficiently calculating convex hulls in D3 force-directed graph

I've got something similar to the force-directed graph example. 我有一些类似于力导向图的例子。 The main difference is there is no force -- the layout is static except for user drag interactions. 主要区别在于没有力 - 除了用户拖动交互之外,布局是静态的。 I've added code that draws convex hulls (as svg:path elements) around user-defined groups of nodes. 我添加了在用户定义的节点组周围绘制凸包 (作为svg:path元素)的代码。 As the nodes are moved (that is, .on("drag") ) the code that calculates the hulls is fired. 随着节点的移动(即.on("drag") ),会触发计算外壳的代码。 That means it's fired constantly when the nodes are dragged. 这意味着在拖动节点时会不断触发它。 There are typically 10 to 30 hulls; 通常有10到30个船体; a node may be in one or more hull. 节点可以在一个或多个船体中。 See below: 见下文:

船体图的示例

I'm trying to figure out if there's a more efficient (higher performance) way to do what I'm doing. 我正在试图弄清楚是否有更高效(更高性能)的方式来做我正在做的事情。 Keeping this at high-level for now: 暂时将其保持在高级别:

On drag, update all hull graphics: 在拖动时,更新所有船体图形:

  1. For each hull, create an array of the coordinates of the constituent nodes. 对于每个外壳,创建组成节点坐标的数组。
  2. Replace each coordinate pair in the above array with 8 points that are some distance r away from the original point. 将上述阵列中的每个坐标对替换为距离原点一定距离r的 8个点。 This is to pad/dilate the hull so it's not actually touching any nodes. 这是为了填充/扩张船体,因此它实际上并没有接触到任何节点。
  3. Feed the calculated coordinates to d3.geom.hull . 将计算出的坐标输入d3.geom.hull

I'm getting about 50 fps in Chrome, which isn't bad at all, but it seems like a dreadfully inefficient setup. 我在Chrome中获得了大约50 fps,这一点都不差,但它似乎是一个非常低效的设置。

My only clear idea is to store the ID(s) of the hull(s) in which a node is contained in the nodes array, and only update that/those hulls instead of all of the hulls. 我唯一明确的想法是存储节点数组中包含节点的船体的ID,并且只更新那些/那些船体而不是所有船体。 I'm also wondering about more efficient data structures to store the hull data (not the paths themselves). 我也想知道更高效的数据结构来存储船体数据(而不是路径本身)。 Currently the data structure looks like this: 目前,数据结构如下所示:

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

Pardon the open-ended question, but I'm hoping there's some programming technique that I'm not familiar with that would work well here. 请原谅这个开放式问题,但我希望有一些我不熟悉的编程技术可以在这里运作良好。

The most efficient approach would be to only recalculate the position of the 8-tuple of coordinates orbiting the node that is being dragged, then propagating that information in the parent hull(s) for redrawing. 最有效的方法是仅重新计算围绕正被拖动的节点的8元组坐标的位置,然后在父船体中传播该信息以进行重绘。

You can do this by making a few changes. 您可以通过进行一些更改来完成此操作。

  • To each node's data structure, add the following elements. 对于每个节点的数据结构,添加以下元素。
    • References to all parent hulls (as you suggested) 所有父船体的参考(如您所建议的)
    • The 8-tuple of "padding" coordinates orbiting that node (cache them) 围绕该节点的“填充”坐标的8元组(缓存它们)
  • On drag, consider only the node being dragged. 在拖动时,仅考虑被拖动的节点。
  • Update that node's 8-tuple. 更新该节点的8元组。
  • Collect that node's parent hull's child nodes and collapse together their 8-tuples and feed them to hull (destroying the previous hull, if necessary). 收集该节点的父船体的子节点并将它们的8元组折叠在一起并将它们馈送到hull (如果需要,可以摧毁前一个船体)。

I'm not familar with d3.js 's API, but I'm sure you can fill in any blanks that I've left. 我不熟悉d3.js的API,但我确信你可以填写我留下的任何空白。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM