MATLAB中voronoi图的无界单元格

时间:2016-12-02 12:14:59

标签: matlab plot voronoi

我有两组点,plot点蓝色和红色点。然后我plot两个具有voronoi(X,Y)函数的集的Voronoi图。我想指定每个单元格的颜色取决于它所属的网站集。我通过这种方式使用patch功能几乎完成了这一步:

     [v,c]=voronoin(D);
     for p=1:TheNumberOfSets
       r=rand()/2+0.5;    % random gray color
       col=[r r r];
       for s=1:PointsInSet(p)
           l=l+1;
           patch(v(c{l},1),v(c{l},2),col);  % color
           axis([0 10 0 10]);
       end
     end

其中D是集合点的坐标,TheNumberOfSets表示我们有多少集合(在此特定部分中我们只有2集),col指定随机灰色,PointsInSet指定每组中有多少个点,l用于枚举Voronoi图的单元格。

这就是结果: enter image description here

现在我的问题(正如你所看到的!)是关于无界细胞的。这段代码只是改变有界单元格的颜色,我想在轴框的范围内(即图像中可以看到的框)用指定的颜色的无界单元格着色。

有什么建议吗?

2 个答案:

答案 0 :(得分:2)

似乎在Matlab R2018a或更高版本中(R2014b可以,但是我没有测试R2015〜R2016),voronoi并没有返回与之前相同的h,尽管此函数的文档没有更改。 在R2018a中返回

 h(1)

ans = 

 handle to deleted Data

在R2014b中返回

h(1)

ans = 

  Line with properties:

              Color: [0 0.4470 0.7410]
          LineStyle: 'none'
          LineWidth: 0.5000
             Marker: '.'
         MarkerSize: 6
    MarkerFaceColor: 'none'
              XData: [1x200 double]
              YData: [1x200 double]
              ZData: [1x0 double]

  Show all properties

我只是想知道是否有一些方法可以提取新版本中无界单元格的线和顶点。

答案 1 :(得分:1)

您的示例确实为无界单元格创建了patch个对象,但由于它们包含的Inf值代表无界边的顶点,因此它们不会显示。您需要用有限顶点替换这些顶点才能完成补丁。

voronoi生成的用于绘制无界单元格边的顶点可用于此目的。绘制voronoi图时可以获得这些:

h = voronoi(D);
v1 = shiftdim(reshape([h(2).XData;h(2).YData],2,3,[]),2); % Arranged one edge per row, one vertex per slice in the third dimension

最后绘制了无界边,因此您可以通过计算c中的无界单元格来隔离它们:

nUnbounded = sum(cellfun(@(ic)ismember(1,ic),c));
v1Unbounded = v1(end-(nUnbounded-1):end,:,:);

这些边缘的第一个列出的顶点是单元格的有限顶点。由于浮点误差,它们始终与voronoin返回的坐标完全匹配,因此通过查找pdist2的最小成对距离来识别这些对应的编号顶点:

[~,iBounded] = min(pdist2(v,v1Unbounded(:,:,1))); % Index of the bounded vertex
vUnbounded = v1Unbounded(:,:,2); % Displayed coordinate of the unbounded end of the cell edge

要在这些坐标中替换,您可以使用以下内容替换patch(v(c{l},1),v(c{l},2),col);

cPatch = c{l}; % List of vertex indices
vPatch = v(cPatch,:); % Vertex coordinates which may contain Inf
idx = find(cPatch==1); % Check if cell has unbounded edges
if idx
    cPatch = circshift(cPatch,-idx); % Move the 1 to the end of the list of vertex indices
    vPatch = [vPatch(1:idx-1,:)
              vUnbounded(iBounded == cPatch(end-1),:)
              vUnbounded(iBounded == cPatch(1),:)
              vPatch(idx+1:end,:)]; % Replace Inf values at idx with coordinates from the unbounded edges that meet the two adjacent finite vertices
end
patch(vPatch(:,1),vPatch(:,2),col);