【发布时间】:2016-03-17 11:53:46
【问题描述】:
我正在执行一些计算,我需要评估以某些节点为中心的 Voronoi 多边形之间的通量。为此,我需要找到多对多边形之间的共同边,例如。 V1 & V2 如下图所示。每条边只应评估一次。
为此,我获取节点的 x 和 y 坐标并执行 Delaunay triangulation 以查找相邻节点。然后我运行一个循环来找出哪些节点有共同的顶点。然后我计算 Voronoi 多边形并创建一个数组 (istr),其索引为“边缘”编号,值为中心 voronoi 多边形。然后,“neigh”数组将索引作为“edge”编号和所有相邻多边形值。在检查以确保我不会对每条边重复此评估后,我然后计算边(即每个多边形之间共享的顶点)。
我可以使用下面的代码来计算边,但是在 for...循环中计算 nodneigh 存在很大的瓶颈,因为需要迭代地访问单元数组的组件。需要更多时间的是使用单元函数计算 edge 以访问 Delaunay 三角剖分/Voronoi 多边形的输出。
我的问题是如何加快这两个瓶颈?虽然我很欣赏 Matlab 中单元阵列的灵活性,但我觉得当我不需要它时,它确实会减慢一切。我尝试用 NaN 填充单元格数组,将其转换为矩阵并执行逐行相交,但这并没有那么成功:arrayfun 需要更长的时间,而且我似乎无法使用 intersect with GPU 计算。
% Create dummy data
nstr = 1000; % number of particles
x = rand(nstr,1); % particle x coordinates
y = rand(nstr,1); % particle y coordinates
% Delaunay triangulation
DT = delaunayTriangulation(x,y);
% Determine node neighbors of the original nodes
nodneigh = cell(nstr,1);
numtotneigh = 0; % initialise total # of neighbors
bla = DT.vertexAttachments; % Get the particle/triangle IDs
% BOTTLENECK 1: Find out which particles/triangles are neighbours
for istr = 1:nstr
nodneigh{istr} = setdiff(unique(DT.ConnectivityList(bla{istr},:)),istr);
numtotneigh = numtotneigh+length(nodneigh{istr});
end
% Construct Thiessen polygons by Voronoi tessalation
[voro_V,voro_R] = DT.voronoiDiagram;
% Bookkeeping - create an index of edges with associated voronoi regions
cellsz = cellfun(@size,nodneigh,'uni',false);
cellsz = cell2mat(cellsz);
cellsz = cellsz(:,1);
temp = [1:nstr];
idx([cumsum([1 cellsz(cellsz>0)'])]) = 1;
istr = temp(cumsum(idx(1:find(idx,1,'last')-1)))'; % Region number
neigh = vertcat(nodneigh{:}); % Region neighbours
neigh_m = mod(neigh,nstr);
% Make sure neighbourship has not already been evaluated
idx = neigh_m == 0;
neigh_m(idx,:) = nstr;
neigh = vertcat(nodneigh{:});
% BOTTLENECK 2:
% Determine which edges are common to both central and neighbour regions
edge = cellfun(@intersect,voro_R(istr),voro_R(neigh),...
'UniformOutput',false);
edge = cell2mat(edge);
【问题讨论】:
标签: matlab gpu computational-geometry delaunay voronoi