在 matlab 中绘制一堆 3d 线的最有效方法

发布于 2024-11-30 15:54:17 字数 545 浏览 1 评论 0原文

我需要在 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 等的相同情节会运行得更快......

I need to plot a list of 3d lines in matlab. What is the quickest way to do that?
I am currently doing something like

%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

But this is not only slow during the actual loop, but also at the end, the resulting plot is very slow and irresponsive when I try to, for instance, rotate it using the drag & rotate tool.

I know the same plot using opengl etc would run much faster...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

め可乐爱微笑 2024-12-07 15:54:17

您可以使用 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)

表面

You can use the LINE low-level function, using NaN to plot as separate segments:

%# 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)

This is very efficient as it creates a single line object. Now you can customize the line, but it is restricted to have one color for the entire thing:

set(h, 'Color',[.4 .4 1], 'Marker','.', 'MarkerSize',10, ...
    'MarkerFaceColor','g', 'MarkerEdgeColor','g')

line


According to the comments, if you want to have each edge in your graph in a specified color, consider the following code instead. It involves using the SURFACE function:

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

独木成林 2024-12-07 15:54:17

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

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

其中edges应该是一个Nx2索引和矩阵应该是一个 Mx3 坐标矩阵(points 数组的转置)。

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

举个例子,使用我的(确实很旧!)MATLAB 7.1 生成 1000 个随机生成的线段的时间如下:

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

编辑:使边缘颜色表现得如您所愿(为每个边缘指定单一颜色)的一种方法是引入重复的顶点,如下所示:

这解决了只能指定边缘颜色的问题间接通过顶点颜色数据。如果我们只依赖顶点颜色,那么共享一个公共顶点的所有边可能最终都会分配给该顶点的颜色 - 请查看'flat 'edgecolour描述此处

%% 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 允许您直接指定边缘颜色数据,那就更好了 - 但它似乎不支持这一点......

希望这会有所帮助。

I think you can do something like this (caution - brain compiled code...)

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

Where edges should be an Nx2 matrix of indices and points should be an Mx3 matrix of coordinates (the transpose of your points array).

From my experience, calling patch directly can be significantly faster than repeated calls to plot.

To give some idea, the times to generate 1000 randomly generated line segments, using my (admittedly old!) MATLAB 7.1 are as follows:

  1. Calling patch: 0.03 seconds.
  2. Calling plot: 0.5 seconds.

EDIT: One way to get the edge colour behaving as you want (specifying a single colour per edge) is to introduce duplicate vertices as follows:

This works-around the issue that the edge colour can only be specified indirectly via vertex colour data. If we were to rely only on the vertex colours then all edges sharing a common vertex might end up with the colour assigned to that vertex - check out the 'flat 'edgecolour description 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

It would be nicer if MATLAB allowed you to directly specify the edge colour data - but it doesn't seem to support that...

Hope this helps.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文