как анимировать 2 поверхности в Matlab? - PullRequest
2 голосов
/ 04 мая 2010

Я написал этот код, который создает анимацию из 2 эллипсоидов.

Параметр k1 этих эллипсоидов должен зависеть от времени (чтобы они двигались асинхронно), но мне нужно анимировать их на одной фигуре , Могу ли я использовать цикл для него или лучше использовать таймер и некоторые функции обратного вызова?

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

Ответы [ 3 ]

1 голос
/ 04 мая 2010

Вы должны использовать цикл. Большая часть вашего времени будет потрачена на прорисовку и с командой «getFrame». Вы можете использовать

profile 
, чтобы подтвердить это. Цикл for не добавляет значительных накладных расходов, его проще всего кодировать и понимать

Что касается вашего второго вопроса, я не уверен точно, о чем вы спрашиваете, но если вы хотите сохранить общую точку, вам следует параметризовать вашу поверхность с точки зрения радиусов, угла наклона и т. Д. общая точка, затем просто переместите точку вокруг. Возможно, вы захотите написать функцию «drawEllipsoid», которая упростит и прояснит ваш код.

0 голосов
/ 10 мая 2010

ОК, вот ярлык для обрезки поверхности, который я упоминал в своем предыдущем комментарии. То, что вы собираетесь сделать, это поместить NaN в координаты везде, где поверхность находится за пределами домена. Тогда поверхностный объект будет отбрасывать любые квады, которые касаются этих координат. Это не дает вам хорошего чистого края, но это действительно легко.

a=5;
b=a;
c=10;
u = (0:0.05*pi:pi)'; %'
v = [0:0.05*pi:2*pi];
X = a*sin(u)*cos(v);
Y = a*sin(u)*sin(v);
Z = c*cos(u)*ones(size(v));
Z(Z>0)=0; % cut upper
V1=4/3*pi*a*b*c;
d=1/2;
e=2^d;
a2=a/e;
b2=a/e;
c2=c;
V2=4/3*pi*a2*b2*c2;
X2 = a2*sin(u)*cos(v);%-2.5;
Y2 = b2*sin(u)*sin(v);
Z2 = c2*cos(u)*ones(size(v));%+0.25;
Z2(Z2>0)=0; % cut
h=1/3;

hS1=surf(X,Y,Z);
alpha(.11)
hold on
hS2=surf(X2,Y2,Z2);
hold off
axis([-20 20 -20 20 -20 20]);

for j = 1:20
  k1=(sin(pi*j/20)+0.5)^h;
  a=a*k1;
  c=c*k1;
  X = a*sin(u)*cos(v);
  Y = a*sin(u)*sin(v);
  Z = c*cos(u)*ones(size(v));
  Z(Z>0)=0;
  a2=a2*k1;
  b2=a2*k1;
  c2=c2*k1;
  X2 = a2*sin(u)*cos(v)+5;%-2.5;
  Y2 = b2*sin(u)*sin(v);
  Z2 = c2*cos(u)*ones(size(v));%+0.25;
  Z2(Z2>0)=0;

  set(hS1,'XData',X,'YData',Y,'ZData',Z);

  % substitute into implicit form of 1st ellipsoid
  d = (X2.^2) / a^2 + (Y2.^2) / a^2 + (Z2.^2) / c^2;
  % and zap any that are outside [0 1]
  X2(d>1) = nan;
  Y2(d>1) = nan;
  Z2(d>1) = nan;
  set(hS2,'XData',X2,'YData',Y2,'ZData',Z2);
  drawnow;
  F(j) = getframe;
end
movie(F,4)

Обратите внимание, что я также изменил диапазон u. Это потому, что вы на самом деле рисовали 2 копии поверхности. Это вызывало некоторые проблемы с прозрачностью.

0 голосов
/ 04 мая 2010

Цикл кажется подходящим для этой работы. Таймер также сработает.

Я не совсем понимаю, что вы имеете в виду, когда говорите "есть одна общая сторона". Похоже, вы близки к добавлению 5 к X2, но вам понадобится масштабирующий член, поскольку они не одинаковой формы. Не могли бы вы уточнить?

Хотя одно предложение. Я думаю, что вы будете намного счастливее, если переместите создание объекта из цикла следующим образом:

a=5;
b=a;
c=10;
u = (0:0.05*pi:2*pi)'; %'
v = [0:0.05*pi:2*pi];
X = a*sin(u)*cos(v);
Y = a*sin(u)*sin(v);
Z = c*cos(u)*ones(size(v));
Z(Z>0)=0; % cut upper
V1=4/3*pi*a*b*c;
d=1/2;
e=2^d;
a2=a/e;
b2=a/e;
c2=c;
V2=4/3*pi*a2*b2*c2;
X2 = a2*sin(u)*cos(v);%-2.5;
Y2 = b2*sin(u)*sin(v);
Z2 = c2*cos(u)*ones(size(v));%+0.25;
Z2(Z2>0)=0; % cut
h=1/3;

hS1=surf(X,Y,Z);
alpha(.11)
hold on
hS2=surf(X2,Y2,Z2);
hold off
axis([-20 20 -20 20 -20 20]);

for j = 1:20
    k1=(sin(pi*j/20)+0.5)^h;
    a=a*k1;
    c=c*k1;
    X = a*sin(u)*cos(v);
    Y = a*sin(u)*sin(v);
    Z = c*cos(u)*ones(size(v));
    Z(Z>0)=0;
    a2=a2*k1;
    b2=a2*k1;
    c2=c2*k1;
    X2 = a2*sin(u)*cos(v)+5;%-2.5;
    Y2 = b2*sin(u)*sin(v);
    Z2 = c2*cos(u)*ones(size(v));%+0.25;
    Z2(Z2>0)=0;

    set(hS1,'XData',X,'YData',Y,'ZData',Z);
    set(hS2,'XData',X2,'YData',Y2,'ZData',Z2);
    drawnow;
    F(j) = getframe;
end
movie(F,4)

Drawnow здесь не является строго необходимым, потому что getframe содержит один, но хорошо вставить его, чтобы вы могли видеть, что происходит, если вы удалите getframe.

...