2014-02-08 29 views
2

我想繪製一個d3 voronoi圖並將其剪輯爲d3 hull borders做了一系列節點或任何類似的剪輯。剪輯d3 voronoi與d3船體

Screenshot中的紅線顯示了我想達到的效果。 Screenshot showing outline around collection of nodes with Voronoi borders

如何能不能做到?

+0

一個什麼樣的船體? Voronoi多邊形是由它們的容器定義的,所以通過剪裁不會改變任何東西。 –

+0

你能用更多的信息更新你的問題嗎?也許你有一個你想要做什麼的例子的鏈接? – swenedo

+0

我澄清了這個問題。 – Risingson

回答

4

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

這個工程!我在'svg'defs'中使用'expandedHull'作爲'clipPath'。謝謝 – Risingson

0

我最近做了一個例子來說明對自己多邊形裁剪是如何工作的: http://tributary.io/inlet/8263747

你可以看到在update功能裁剪的代碼,以及渲染代碼中的process函數。拖動周圍的點以查看剪切將如何受到影響。

幾件事情要注意:

  1. 點中的「船體」命令(或夾在我的例子路徑)的事項。你的多邊形必須是逆時針以及凸面(沒有洞穴)。如果這些條件不符合,則不會出現錯誤,您只需返回一個空數組。

  2. 多邊形運算操作的點陣列的地方,如果你不想讓你的幾何體本身剪切,但想你需要先製作一個副本複印件。