views:

249

answers:

3

Hi everyone, I've written this code which makes an animation of 2 ellipsoids.

Parameter k1 of these ellipsoids must depend on time (so they'd move asynchronously), but I need to animate them in one figure. Can I use loop for it or is it better to use timer & some kind of callback functions?

The second problem - I need to move inner ellipsoid so they would have one common side. How can I do this?

+1  A: 

You should use a loop. The majority of your time will be spent plotting and with the "getFrame" command. You can use

 profile 
to verfiy this. The for loop won't add significant overhead and is easiest to code and understand


As for your second question, I'm not sure exactly what you're asking, but if you want to keep a point in common, you should parametrize your surface in terms of the radii, skew angle, etc. and the common point, then just move the point around. You might want to consider writing a "drawEllipsoid" function, which would simplify and clarify your code.

Marc
A: 

The loop seems fine for this job. A timer would work as well.

I'm not sure quite what you mean when you say "have one common side". It looks like you're close with adding 5 to X2, but you would need a scaling term since they're not the same shape. Could you elaborate?

One suggestion though. I think that you'll be a lot happier if you move the object creation out of the loop like this:

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)

The drawnow is not strictly necessary here because the getframe contains one, but it is good to insert one so that you can see what's going on if you remove the getframe.

MPG
"One common side"- I mean that if you imagine them as 2 glasses, then put one into another not to the center, but move to a side (so that the inner one would thouch a side of the outer). Smth like that:)
Kate
Do you mean changing the +5 in the X2 calculation to +(max(a2(:))-max(a(:)))? That would make them touch at the +X side of the top rim.
MPG
Yes)how can I crop a part of the inner ellipsoid, which stands outside the outer one?
Kate
Oh, you mean that you want to trim the boundary of one surface to the other one? That is actually surprisingly tricky. One of the reasons is that the parameter space of the trimmed surface is no longer a 2D rectangle. That's really the case that surface the object is designed for. To create a surface with a more complicated boundary in parameter space you would need to use the patch object to create the quads and then trim each one to the boundary. That'd get kind of long and messy. There is a short cut that will work if you can live with a ragged edge.
MPG
A: 

OK, here's the shortcut to doing a trimmed surface I mentioned in my earlier comment. What you're going to do is put NaNs into the coordinates everywhere the surface is outside the domain. Then the surface object will drop any quads which touch those coordinates. That doesn't give you a nice clean edge, but it is really easy.

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)

Note that I also changed the range of u. That's because you were actually drawing 2 copies of the surface. That was causing some problems with how the transparency was rendered.

MPG

related questions