2014-02-09 6 views
3

У меня есть задание сделать тору. Это мой первый раз с Matlab, и мне удалось бороться и получить 2/3 части с каким-то ужасным заглушенным кодом.matlab Оказание тора из вершин

Первый шаг задания - сделать круг как набор из 20 баллов. Для которого я произвел:

circle (IMG)

Тогда следующий шаг, чтобы повернуть и перевести этот круг и сделать это 20 раз, чтобы представить форму тора, поэтому я получил это:

torus points (IMG)

Следующий шаг - отобразить трехмерное представление этого тора из списка вершин.

Что у меня есть массивный список из вершин в 400x3 матрице, как так:

7.66478245119846 -1.84059939326890 0.292371704722737 
7.53434247103331 -1.79821687453702 0.573576436351046 
7.32764268084884 -1.73105604149887 0.798635510047293 
7.06491629627043 -1.64569106442929 0.945518575599317 
6.77188080634298 -1.55047806205660 0.999847695156391 
6.47722056651889 -1.45473714644104 0.956304755963036 
...     ...      ... 

где каждый последующие 20 строк является еще один круг.

Назначение рекомендует использовать функцию серфинга для рендеринга, но я не могу понять, как это сделать. Все примеры, которые я видел, используют surf для представления двухмерных плоскостей, которые искажаются значением высоты. Который не кажется подходящим для того, чтобы сделать этот вид 3-мерной формы вообще.

Подход, который я пытаюсь, состоит в том, чтобы создать список лиц, а затем использовать функцию патча для отображения круга. Где первые 2 точки каждого круга образуют квадрат с соответствующими двумя точками следующего круга, а затем рендеринг.

Используя что-то вроде этого:

for i=1:400 
    face = [(i) (i+1) (i+21) (i+20)]; 
    patch('Faces',face,'Vertices',torus_vertices,'FaceColor','r'); %Should do this at      the end 
end 

За что я получаю что-то вроде этого:

3d Torus (IMG)

Он крутит и некоторые из боковых и внутренних боковых граней перепутались вверх. Я думаю, что это может иметь какое-то отношение к упорядочению вершин, вращающихся в какой-то момент.

Что было бы лучшим способом подойти к этой проблеме? Если это вообще возможно, я хочу сделать это с помощью функции серфинга.

Ex1.m

%Initial positions 
position = [2 0 0]; 
normal = [0 1 0]; 

%Rotation matrix 
rotate18 = [cos(todeg(18)) -sin(todeg(18))  0; 
      sin(todeg(18)) cos(todeg(18))  0; 
      0    0     1]; 

% translate along the x axis by 5   
translate = [5 0 0]; 

%% iterate 20 times to get a list of all the vertices 
taurus_vertices = zeros(0, 3); 
for i=0:20 

    %rotate translation by 18 degrees 
    translate = translate * rotate18; 

    %translate 
    position = position + translate; 

    %rotate the normal so it faces the right direction 
    normal = normal * rotate18; 

    %Get vertices for the circle and append to vertices list 
    circle_vertices = circle_3D(1, position, normal); 
    taurus_vertices = cat(1, taurus_vertices, circle_vertices); 

    %translate back to original position 
    position = position - translate; 

end 

%scatter3(taurus_vertices(1:end, 1), taurus_vertices(1:end, 2), taurus_vertices(1:end, 3)); 


%% Render each face 
for i=1:400 
    face = [(i) (i+1) (i+21) (i+20)]; 
    patch('Faces',face,'Vertices',taurus_vertices,'FaceColor','r'); 
end 

circle.m

function h_circle=circle_3D(r, M, n) 

%% Prepare input parameters 
if size(n,2)>size(n,1) 
    n=n'; 
end 

if size(M,2)>size(M,1) 
    M=M'; 
end 

%% Define unit vectors u and v 
% u and v define a new coordinate system in a plane perpendicular to n 
a=[1;0;0]; 
b=[0;1;0]; 

if isempty(find(cross(a,n), 1))==1 
    a=[0;0;1]; 
elseif isempty(find(cross(b,n), 1))==1 
    b=[0;0;1]; 
end 
alpha=dot(n,a)/dot(n,n); 
u=a-alpha*n; 
v=cross(u,n);%b-beta*n-gamma*u; 

u=u/sqrt(sum(u.*u)); 
v=v/sqrt(sum(v.*v)); 

%% Plot the circle 
hold on 
axis equal 

degs = 0; 
points = 0; 
verts = zeros(20, 3); 

for phi=0: pi()/180 : 2*pi() 
    degs=degs+1; 
    if (mod(degs,18) == 0) 
     points = points + 1; 
     verts(points,1)=M(1,1)+r*cos(phi)*u(1,1)+r*sin(phi)*v(1,1); 
     verts(points,2)=M(2,1)+r*cos(phi)*u(2,1)+r*sin(phi)*v(2,1); 
     verts(points,3)=M(3,1)+r*cos(phi)*u(3,1)+r*sin(phi)*v(3,1); 
    end 
end 

h_circle= verts; 

ответ

2

Ваша задача идеально подходит для trisurf- дан набор точек, необходимо построить триплет соединить сетку с. Для вашей проблемы, вы можете использовать:

%inner circle points and radius 
N1=20; 
r1=1; 
%outer circle points and radius 
N2=30; 
r2=5; 
%inner cicle angles 
thC=linspace(0,2*pi*(1-1/N1),N1)'; 
%inner cicle points 
xyzC=[r1*sin(thC), zeros(N1,1),r1*cos(thC)]'; 


%torus points 
xyzT = zeros(3,N1*N2); 
for i=1:N2 
    %circle transformation 
    thT = 2*pi*i/N2; 
    T = [1 0 0 r2*cos(thT); 0 1 0 r2*sin(thT);0 0 1 0]*[cos(thT) -sin(thT) 0 0;sin(thT) cos(thT) 0 0 ; 0 0 1 0; 0 0 0 1]; 
    %add points 
    xyzT(:,(i-1)*N1+1:i*N1)=T*[xyzC ;ones(1,N1)]; 

end 

%build patch triples 
tri=[]; 
for i=1:N2 
    for j=1:N1 
     %get three points: 
     % jth from ith circle 
     % j+1th from ith circle 
     % jth from i+1th circle 
     tri(end+1,:)=[(i-1)*N1+j (i-1)*N1+j+1 i*N1+j]; 
     %get three points: 
     % j+1th from ith circle 
     % j+1th from i+1th circle 
     % jth from i+1th circle 
     tri(end+1,:)=[ i*N1+j (i-1)*N1+j+1 i*N1+j+1]; 

    end 
end 
tri=mod(tri-1,N1*N2)+1; 
trisurf(tri,xyzT(1,:),xyzT(2,:),xyzT(3,:));axis equal 
%fancy 

shading interp 
camlight left 

и получите: enter image description here

+0

Спасибо, я не добирался, чтобы включить свой подход, как мне удалось выработать мой собственный в то же время. Мне жаль, что у меня не было, хотя у вас намного элегантнее. – Callum

1

Спасибо за пример. Было бы лучше сделать тор, используя треугольник вместо прямоугольников, но крайний срок - как час, и мне удалось заставить моего текущего работать!

Я понял, что вызвало мои проблемы. Вращение матрицы перевода отрицательно влияло на ориентацию каждой точки окружности (они не выстраиваются в линию), заставляя ее скручиваться.

Просматривая заметки более подробно (это значит, что в течение нескольких лет стоит обратить внимание на онлайн-заметку), мне удалось найти какой-то код psuedo для функции развертки, которую я использовал, чтобы полностью переписать. Теперь я создаю 20 кругов в одном и том же месте и поворачиваю каждый вокруг начала, увеличивая количество. Что привело к этому:

%% Settings 

points = 20; %Number of points in each circle 
circles = 20; %Number of circles making up the torus 
radius = 1; %Radius of the circle 
scale = 0.75; %Scale to apply to the whole torus 
center = [2 0 0]; %Center point of the first circle to sweep into a torus 

%% Create (circles+1) circles after the other in an array at point [2 0 0] 

%The extra circle overlaps the first, this is to make face generation much 
%simpler. 

V = zeros(circles*points, 3); 
for i=0:points:points*circles 
    for k=1:points 
     V(i+k,1) = center(1) + radius * cosd((k-1)*(360/points)); 
     V(i+k,2) = center(2) + 0; 
     V(i+k,3) = center(3) + radius * sind((k-1)*(360/points)); 
    end 
end 

%% Sweep the circles, rotate each circle 18 degrees more than the previous 

for n=0:points:circles*points 

    %Calculate degrees for current circle 
    D = (n/points) * 360/circles; 

    %Create a Z-rotation matrix 
    Rz = [ 
     cosd(D) sind(D) 0; 
     -sind(D) cosd(D) 0; 
     0  0  1; 
    ]; 

    %Rotate each point of the circle 
    for i=1:points 
     V(n+i, :) = Rz * V(n+i, :)'; 
    end 

end 

%% Scale the torus 

%Create a scalar matrix 
S = [ 
    scale 0  0; 
    0  scale 0; 
    0  0  scale 
]; 

%Scale each point 
for n=0:points:circles*points 
    for i=1:points 
     V(n+i, :) = S * V(n+i, :)'; 
    end 
end 

%% Generate faces 

F = zeros(circles*points, 4); 
for n=1:points:circles*points 
    for k=1:points 

     %If it's an endface then have destination face vertices wrap around to the first face of the current circle 
     if(mod(k, points) == 0) 
      F((n-1)+k,2)= (n-1)+k+1 - points; 
      F((n-1)+k,3)= n+points+k - points; 
     else 
      %otherwise use the next faces starting vertices 
      F((n-1)+k,2)= (n-1)+k+1; 
      F((n-1)+k,3)= n+points+k; 
     end 

     %Set the points coming from the previous face 
     F((n-1)+k,1)= (n-1)+k; 
     F((n-1)+k,4)= n+points+k-1; 

    end 
end 

%% Render 

%Configure renderer 
axis equal; 
hold on; 

%Render points 
scatter3(V(1:end, 1), V(1:end, 2), V(1:end, 3), 'MarkerEdgeColor', 'b'); 

%Render faces 
patch('Faces', F, 'Vertices', V, 'FaceColor', 'g'); 

Что делает:

torus

Смежные вопросы