Matlab,比较每列以找到相同的三角形边

时间:2017-08-16 09:07:05

标签: matlab octave

我有一个名为model_vertex的矩阵3x120000。它是来自stl文件的点云。 3个点指定三角形的顶点。所有3点它开始一个新的三角形。 我想找到具有相同三角形边的三角形。 这意味着三角形应该有2个相同的点。

我希望你能帮助我。我可以通过4个for循环来解决这个问题...但计算时间难以置信。

for i=1:length((model_vertex(1,:))/3)%every triangle in model_vertex
  for n=i:length((model_vertex(1,:))/3)%every triangle besides i-triangle
    match=0;
    for j=1:3 %Search all vertex of triangle(i), 
      for k=1:3 %Search all vertex of triangle(n)
        if model_vertex(1,(i-1)*3+j) == model_vertex(1,(n-1)*3+k) &&...
           model_vertex(2,(i-1)*3+j) == model_vertex(2,(n-1)*3+k) &&...
           model_vertex(3,(i-1)*3+j) == model_vertex(3,(n-1)*3+k)
           match=match+1;
          if match == 2
            %triangle neighbour found 
            %save in an array
            break
          endif
        endif
      endfor
      if match ==2
        break
      endif
    endfor
  endfor
endfor

2 个答案:

答案 0 :(得分:2)

这是一种使用稀疏矩阵和矩阵乘法的方法。

s= sparse(reshape(repmat(1:40000,3,1),[],1),model_vertex(:),1);
out = s * s.';
[x y]=find(out);

或更多内存友好:

[x y v]=find(out);
idx = v == 2;
x2 = x(idx);
y2 = y(idx);

您可以创建[40000 40000] [3 40000]的{​​{1}}稀疏矩阵表示。然后进行矩阵乘法以计算相同点的数量。

答案 1 :(得分:0)

这是我的解决方案,利用许多内置函数来防止循环。一般想法:将每个三角形描述为一组三条线,然后搜索具有完全相同线条的其他三角形:

% generate dummy data
N = 40000;
model_vertex = randi(25,[3 3*N]);

% give vertices numbers, reduces the problem by a factor 3
[coord_label, ~, coord_id] = unique(model_vertex','rows');
triangle = reshape(coord_id,3,[]); % each column is a triangle, containing the triangle_coords id
triangle = sort(triangle); % this is important, otherwise A -> B vs B -> A is missed

% transform from coordinates to lines. A line is given by two vertices (so
% vertex1 to vertex2, vertex2 to vertex3 and 3 to 1)
[line_label, ~, line_id] = unique(reshape(triangle([1 2 2 3 1 3],:),2,[])','rows'); % a line is given by two vertices

% find matches. Speed up loop by sorting first
[s_line_id,b] = sort(line_id);

% data is sorted. Quick start search by only starting from element for
% which the next element is the same
sel = [s_line_id(1:end-1)==s_line_id(2:end); false];

% no pre-allocation, dont know how many items.
match = [];
for l = find(sel)'
    triangle_id1 = ceil(b(l)/3);

    for k=(l+1):(3*N)
        if s_line_id(l)==s_line_id(k)
            triangle_id2 = ceil(b(k)/3);
            if triangle_id2~=triangle_id1 % check for fake triangle => has same line twice. Shoudld not occur in actual data
                match = [match; [triangle_id1, triangle_id2]];
            end
        else
            continue; % move on to next
        end
    end
end

% verify first solution
model_vertex_r = reshape(model_vertex,3,3,[]);
model_vertex_r(:,:,match(1,:))

我的笔记本电脑在1秒钟内运行。