【发布时间】:2014-02-08 13:51:52
【问题描述】:
【问题讨论】:
-
什么船体? Voronoi 多边形由它们的容器定义,因此对其进行裁剪不会改变任何内容。
-
您能用更多信息更新您的问题吗?也许你有一个你正在尝试做的例子的链接?
-
我澄清了这个问题。
【问题讨论】:
d3.geom.hull 函数将找到一个包含所有节点的多边形,没有额外的间距。这当然会抵消 Voronoi 区域的大部分用途,这些区域旨在在节点周围添加一些活动空间。所以你需要计算的是一个多边形,它比所有边上的凸包多边形都大一定的填充距离。
我推荐的算法:
使用d3.geom.hull(nodes) 计算定义节点紧密边界的顶点数组。
使用这些顶点创建d3 polygon object。
使用.centroid() 计算该多边形的中心。
对于凸包中的每个顶点,计算一个距多边形中心填充距离的点。
使用这个展开的多边形剪裁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);
});
【讨论】:
defs 中使用 expandedHull 作为 clipPath。谢谢
我最近做了一个例子来说明多边形裁剪的工作原理: http://tributary.io/inlet/8263747
您可以在update 函数中看到剪辑代码,在process 函数中看到渲染代码。拖动点以查看剪辑将如何受到影响。
需要注意的几点:
“外壳”(或我的示例中的剪切路径)中点的顺序很重要。你的多边形必须是逆时针的并且是凸的(没有洞穴)。如果不满足这些条件,则没有错误,您只需返回一个空数组。
如果您不希望几何体本身被剪裁,但想要一个副本,则需要先制作一个副本。
【讨论】: