在Matlab中绘制大量3D线条的最有效方法是什么?

6
我需要在 matlab 中绘制一个 3D 线条列表。最快的方法是什么? 目前我正在进行类似以下的操作:
%edges is a MX2 matrix, holding the list of edges
%points are the vertices' coordinates
hold on; %so all the lines will be saved
for i=1:size(edges,1)
    a=edges(i,1); %get first point's index
    b=edges(i,2); %get second point's index
    p=[points(:,a) points(:,b)]; %construct a 3X2 matrix out of the 2 points
    plot3(p(1,:),p(2,:),p(3,:)); %plot a line
end

但是这不仅在实际循环过程中速度缓慢,而且在结束时,使用拖动和旋转工具旋转时,生成的图形非常缓慢和不响应。

我知道使用OpenGL等相同的绘图库可以更快地运行...

2个回答

6
您可以使用LINE低级函数,并使用NaN作为分隔符来绘制单独的线段:
%# sample graph vertices and edges (similar to your data)
[adj,XYZ] = bucky;
[r c] = find(adj);
edges = [r c];      %# M-by-2 matrix holding the vertex indices
points = XYZ';      %# 3-by-N matrix of points X/Y/Z coordinates

%# build a list of separated lines
e = edges';
e(end+1,:) = 1;
e = e(:);
p = points(:,e);
p(:,3:3:end) = NaN;

figure
h = line(p(1,:), p(2,:), p(3,:));
view(3)

这非常高效,因为它创建了一个单行对象。现在你可以自定义这条线,但是整个线条只能有一种颜色:
set(h, 'Color',[.4 .4 1], 'Marker','.', 'MarkerSize',10, ...
    'MarkerFaceColor','g', 'MarkerEdgeColor','g')

line


根据评论,如果您想要图形中每个边都有指定的颜色,请考虑使用以下代码。它涉及使用SURFACE函数:

p = p';                      %'# transpose the above p for convenience
clr = (1:size(p,1))';        %'# for each edge, color index in current colormap
figure
surface(p(:,[1 1]), p(:,[2 2]), p(:,[3 3]), [clr clr], ...
    'EdgeColor','flat', 'FaceColor','none')
colormap( hsv(numel(clr)) )  %# specify your colormap here
view(3)

surface


“surface”解决方案是最接近所需的,但如果您查看http://www.mathworks.com/help/techdoc/ref/surface_props.html,似乎“edgecolor”只能通过顶点颜色数据间接设置(这意味着每个面的所有边缘共享最低编号顶点的颜色),而不是直接为每个边缘指定颜色 - 这就是所需的。根据快速检查,这似乎与“patch”解决方案具有相同的行为。也许我错过了什么? - Darren Engwirda

1

我认为你可以像这样做(注意-这是大脑编译的代码...)

figure;
patch('faces', edges, 'vertices', points, 'edgecolor', 'b');
axis equal;

edges 应该是一个 Nx2 的索引矩阵,而 points 应该是一个 Mx3 的坐标矩阵(即你的 points 数组的转置)。

根据我的经验,直接调用 patch 可以比重复调用 plot 快得多。

举个例子,使用我(虽然有点老!)的 MATLAB 7.1 生成 1000 条随机线段所需的时间如下:

  1. 调用 patch:0.03 秒。
  2. 调用 plot:0.5 秒。

编辑:让边缘颜色按照您想要的方式(指定每条边的单一颜色)的一种方法是通过引入重复顶点来实现:

这是一个解决方案,因为边缘颜色只能通过顶点颜色数据间接指定。如果我们仅依赖于顶点颜色,则所有共享公共顶点的边缘可能会以该顶点分配的颜色结束 - 请查看此处的'flat 'edgecolour描述here

%% a "star" shape, so that we can really see what's going on 
%% with the edge colours!!
pp = [0,0,0; 1,-1,0; 1,1,0; -1,1,0; -1,-1,0];
ee = [1,2; 1,3; 1,4; 1,5];

%% important - only 1 colour known per edge, not per vertex!!
cc = (1:size(ee,1))'; 

%% setup a new set of vertices/edges/colours with duplicate vertices
%% so that each edge gets it's correct colour
nnum = 0;
pnew = zeros(2 * size(ee, 1), 3); %% new vertices
enew = zeros(1 * size(ee, 1), 2); %% new edge indices
cnew = zeros(2 * size(ee, 1), 1); %% new edge colours - via vertices
for j = 1 : size(ee, 1)
    n1 = ee(j, 1); %% old edge indices
    n2 = ee(j, 2);
    enew(j, 1) = nnum + 1; %% new edge indicies into pnew
    enew(j, 2) = nnum + 2;
    pnew(nnum + 1, :) = pp(n1, :); %% create duplicate vertices
    pnew(nnum + 2, :) = pp(n2, :);
    cnew(nnum + 1) = cc(j); %% map single edge colour onto both vertices
    cnew(nnum + 2) = cc(j);
    nnum = nnum + 2;
end

%% Draw the set efficiently via patch
tic
figure;
hold on;
patch('faces', enew, 'vertices', pnew, 'facevertexcdata', cnew, ...
    'edgecolor', 'flat', 'facecolor', 'none');
plot(pnew(:,1), pnew(:,2), 'b.');
axis equal;
toc

如果MATLAB允许您直接指定边缘颜色数据,那将更好-但它似乎不支持...

希望这有所帮助。


谢谢!您能否告诉我如何发送一个颜色数组,以便每个边缘都可以用不同的颜色着色? - olamundo
@noam:有几种不同的着色选项,具体取决于您想要什么。您可以使用“'facevertexcdata'”参数来设置从顶点插值的颜色-键入edit trimesh以了解这些内容。如果您只想要一些平面颜色(`'b','k','r'等),我猜您可以将边缘分成几个不同的组,并为每个组选择单个颜色-在此我假设您拥有比颜色更多的边缘。可能还有其他选项-请查看文档... - Darren Engwirda
我需要用许多不同的颜色给每条边着色(比如说,我要显示某个结构中所有支撑梁承受的应力)。因此,我需要按边指定颜色,而不是按顶点指定颜色,并且我不能将边分成几个不同的组,因为有很多颜色... - olamundo
@noam:看起来你可以获取单个边缘颜色,但只能通过顶点颜色索引间接实现-在这里查看edgecolor部分http://www.mathworks.com/help/techdoc/ref/patch_props.html。不幸的是,我不确定它是否能够满足你的要求... - Darren Engwirda
2
@noam:请检查我添加的两个解决方案:一个使用单色LINE,另一个使用SURFACE进行多色线条。 - Amro

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接