用d3船体夹d3 voronoi

时间:2014-02-08 13:51:52

标签: d3.js voronoi

我想绘制一个d3 voronoi图并像d3 hull borders一样剪辑它绑定一组节点或任何类似的剪辑。

Screenshot中的红线显示了我想要实现的目标。 Screenshot showing outline around collection of nodes with Voronoi borders

怎么做?

2 个答案:

答案 0 :(得分:4)

d3.geom.hull函数将找到一个包含所有节点的多边形,没有多余的间距。这当然会抵消Voronoi区域的大部分目的,这些区域旨在在节点周围添加一些活动空间。所以你需要计算的是一个多边形,它的填充距离大于所有边上的凸包多边形。

我推荐的算法:

  • 使用d3.geom.hull(nodes)计算定义节点紧密边界的顶点数组。

  • 使用这些顶点创建d3 polygon object

  • 使用.centroid()计算该多边形的中心。

  • 对于凸包中的每个顶点,计算 padding 距离多边形中心更远的点。

  • 使用此扩展多边形剪裁Voronoi function返回的数组中的所有多边形。

示例代码:

var hullFunction = d3.geom.hull()
                     .x(/*x accessor function*/)
                     .y(/*y accessor function*/);

var tightHull = hullFunction(nodes); //returns an array of vertices

var centerPoint = d3.geom.polygon(tightHullArray).centroid();

var expandedHull = tightHullArray.map( function(vertex) {
             //Create a new array of vertices, each of which is the result
             //of running this function on the corresponding vertex of the
             //original hull.
             //Each vertex is of the form [x,y]

             var vector = [vertex[0] - centerPoint[0], 
                           vertex[1] - centerPoint[1] ];
             //the vector representing the line from center to this point

             var vectorLength = Math.sqrt(vector[0]*vector[0] 
                                          + vector[1]*vector[1]);
             //Pythagorus' theorem to get the length of the line

             var normalizedVector = [vector[0] / vectorLength, 
                                     vector[1] / vectorLength];
             //the vector scaled down to length 1, but with the same angle
             //as the original vector

             return [vertex[0] + normalizedVector[0]*padding,
                     vertex[1] + normalizedVector[1]*padding ];
             //use the normalized vector to adjust the vertex point away from
             //the center point by a distance of `padding` 

         });

var clippedVoronoi = voronoiPolygons.map(function(voronoi) {
       //voronoiPolygons would be the array returned by the voronoi function

              return expandedHull.clip(voronoi);
              //I think this is correct; if you get weird results, try
              // return voronoi.clip(expandedHull);
         });

答案 1 :(得分:0)

我最近做了一个例子来向自己说明多边形裁剪是如何工作的: http://tributary.io/inlet/8263747

您可以在update函数中查看剪辑代码,并在process函数中查看渲染代码。拖动点以查看剪辑将如何受到影响。

需要注意的几件事情:

  1. “船体”(或我的示例中的剪切路径)中的点的顺序很重要。你的多边形必须是逆时针和凸面(没有洞穴)。如果不满足这些条件,则没有错误,您只需返回一个空数组。

  2. 多边形操作在适当的位置操作点阵列,如果您不希望几何体本身被剪裁,但想要复制,则需要先复制。