【问题标题】:Clip d3 voronoi with d3 hull用 d3 船体夹住 d3 voronoi
【发布时间】:2014-02-08 13:51:52
【问题描述】:

我想绘制一个 d3 voronoi 图并像 d3 hull borders 那样对它进行剪辑,并绑定节点集合或任何类似的剪辑。

Screenshot 中的红线显示了我想要实现的目标。

怎么做?

【问题讨论】:

  • 什么船体? Voronoi 多边形由它们的容器定义,因此对其进行裁剪不会改变任何内容。
  • 您能用更多信息更新您的问题吗?也许你有一个你正在尝试做的例子的链接?
  • 我澄清了这个问题。

标签: d3.js voronoi


【解决方案1】:

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

【讨论】:

  • 这行得通!我最终在 svg defs 中使用 expandedHull 作为 clipPath。谢谢
【解决方案2】:

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

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

需要注意的几点:

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

  2. 如果您不希望几何体本身被剪裁,但想要一个副本,则需要先制作一个副本。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多