Самый эффективный способ нарисовать кучу 3d линий в Matlab - PullRequest
6 голосов
/ 21 августа 2011

Мне нужно составить список 3d строк в Matlab. Какой самый быстрый способ сделать это? В настоящее время я делаю что-то вроде

%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 голосов
/ 21 августа 2011

Вы можете использовать низкоуровневую функцию 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

1 голос
/ 21 августа 2011

Я думаю, что вы можете сделать что-то вроде этого (осторожно - скомпилированный мозгом код ...)

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

Где edges должно быть Nx2 матрицей индексов, а points должно бытьMx3 матрица координат (транспонирование вашего points массива).

По моему опыту, прямой вызов patch может быть значительно быстрее, чем повторные вызовы plot.

Чтобы дать некоторое представление, время для генерации 1000 случайно сгенерированных отрезков линии с использованием моего (по общему признанию старого) MATLAB 7.1 выглядит следующим образом:

  1. Вызов patch: 0,03 секунды.
  2. Вызов plot: 0,5 секунды.

РЕДАКТИРОВАНИЕ : Один из способов заставить цвет ребра вести себя так, как вы хотите (указав один цвет для ребра), - ввести дубликаты вершинследующим образом:

Это обходит проблему, заключающуюся в том, что цвет края может быть задан только косвенно через данные цвета вершины.Если бы мы полагались только на цвета вершин, то все ребра, разделяющие общую вершину, могли бы в конечном итоге получить цвет, назначенный этой вершине - посмотрите '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

Было бы лучше, если бы MATLAB позволял вам напрямую указывать данные о цвете кромки - но, похоже, это не поддерживает ...

Надеюсь, это поможет.

...