【问题标题】:D3.js Convex Hull With 2 Data Points具有 2 个数据点的 D3.js 凸包
【发布时间】:2015-08-19 18:42:33
【问题描述】:

Hull Geom 的 API 声明:“假设顶点数组的长度大于 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 的建议或任何解决我的问题的一般建议。

【问题讨论】:

  • 你可以简单地在两个节点之间画一个椭圆,然后旋转它以匹配方向。

标签: javascript d3.js visualization convex-hull


【解决方案1】:

基本上,您至少需要一个非常接近线的假点才能达到预期的效果。这可以在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 的工作示例。

【讨论】:

    【解决方案2】:

    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";
    };
    

    【讨论】:

    • 效果很好。
    猜你喜欢
    • 1970-01-01
    • 2016-02-09
    • 2018-06-29
    • 2013-10-09
    • 2022-01-23
    • 2013-05-24
    • 2015-02-18
    • 2013-10-21
    • 1970-01-01
    相关资源
    最近更新 更多