使用d3 hull对d3 Voronoi进行剪裁

3
我想绘制一个 d3 Voronoi 图并像 d3 hull borders 一样对一组节点进行裁剪或任何类似的裁剪。此截图 中的红线显示了我想要实现的效果。
如何实现?

一个船体是什么?Voronoi多边形是由它们的容器定义的,因此通过剪辑不会改变任何东西。 - Lars Kotthoff
你能否更新一下你的问题并提供更多信息?或者你有一个示例链接可以展示你正在尝试做什么吗? - swenedo
我澄清了问题。 - Risingson
2个回答

4
d3.geom.hull函数将找到一个紧密包含所有节点的多边形,没有额外的间隔。这当然会取消掉Voronoi区域的很多作用,因为它们旨在为节点周围添加一些活动空间。所以你需要计算的是,在凸包多边形的所有侧面上比凸包多边形大一定距离的多边形。
我的推荐算法:
  • 使用d3.geom.hull(nodes)计算定义节点紧密边界的顶点数组。

  • 使用这些顶点创建一个d3多边形对象

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

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

  • 使用这个扩展多边形剪切由Voronoi函数返回的所有多边形数组。

示例代码:
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
这个可行!我最终在SVG的defs中使用了expandedHull作为clipPath。谢谢。 - Risingson

-1

最近我做了一个例子来说明多边形裁剪的工作原理:http://tributary.io/inlet/8263747

你可以在update函数中看到裁剪代码,在process函数中看到渲染代码。拖动点以查看裁剪效果。

需要注意的几个问题:

  1. “hull”(或者在我的例子中是裁剪路径)中点的顺序很重要。你的多边形必须是逆时针方向并且是凸多边形(没有洞)。如果不满足这些条件,就不会出现错误,只会得到一个空数组。

  2. 多边形操作会直接修改你的点数组,如果你不想让几何图形本身被裁剪,而是想要一个副本,你需要先复制一份。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接