Hull Geom的API声明:“假设顶点数组的长度大于3。如果顶点长度<= 3,则返回[]。” (https://github.com/mbostock/d3/wiki/Hull-Geom)
我需要在2个节点周围绘制凸包。我正在使用力布局,因此凸包需要是动态的,因为如果我点击一个节点并将其拖动,它就会在节点周围移动。我的代码目前基于此示例:http://bl.ocks.org/donaldh/2920551
对于上下文,这就是我想要绘制凸包的内容:
当有3个节点时,它可以工作:
以下是我想要绘制凸包的内容(不适用于上面示例中的代码,因为Hull Geom只会采用3 +顶点的数组):
我理解凸壳的传统使用永远不会只涉及两个点,但我尝试在2个节点周围绘制椭圆,矩形等,它看起来并不像3个节点那样好。
据我所知,Hull Geom最终会吐出一个用于路径的字符串,所以我可能会为2个节点编写一个Hull Geom的修改版本。
非常感谢有关如何为2个节点编写修改过的Hull Geom或任何一般建议以解决我的问题的任何建议。
答案 0 :(得分:3)
基本上,您需要至少有一个非常接近线的假点才能达到预期效果。这可以在groupPath
函数中实现。
对于长度为2的d
,您可以创建一个临时数组并将其附加到map函数的结果中,如下所示:
var groupPath = function(d) {
var fakePoints = [];
if (d.values.length == 2)
{
//[dx, dy] is the direction vector of the line
var dx = d.values[1].x - d.values[0].x;
var dy = d.values[1].y - d.values[0].y;
//scale it to something very small
dx *= 0.00001; dy *= 0.00001;
//orthogonal directions to a 2D vector [dx, dy] are [dy, -dx] and [-dy, dx]
//take the midpoint [mx, my] of the line and translate it in both directions
var mx = (d.values[0].x + d.values[1].x) * 0.5;
var my = (d.values[0].y + d.values[1].y) * 0.5;
fakePoints = [ [mx + dy, my - dx],
[mx - dy, my + dx]];
//the two additional points will be sufficient for the convex hull algorithm
}
//do not forget to append the fakePoints to the input data
return "M" +
d3.geom.hull(d.values.map(function(i) { return [i.x, i.y]; })
.concat(fakePoints))
.join("L")
+ "Z";
}
这里有一个fiddle,其中有一个工作示例。
答案 1 :(得分:1)
Isolin有一个很好的解决方案,但它可以简化。它不是将虚拟点放在中点的线上,而是将虚拟点基本上添加到现有点之上......以不易察觉的量进行偏移。我修改了Isolin的代码来处理具有1或2个节点的组的情况。
var groupPath = function(d) {
var fakePoints = [];
if (d.length == 1 || d.length == 2) {
fakePoints = [ [d[0].x + 0.001, d[0].y - 0.001],
[d[0].x - 0.001, d[0].y + 0.001],
[d[0].x - 0.001, d[0].y + 0.001]]; }
return "M" + d3.geom.hull(d.map(function(i) { return [i.x, i.y]; })
.concat(fakePoints)) //do not forget to append the fakePoints to the group data
.join("L") + "Z";
};