分享

9.5 动画

 小温爱怡宝 2023-07-26 发布于江西

9.5 动画

在MATLAB中有三种用于动画的工具:

  • comet和comet3函数可以用来绘制彗星图,正如我们在第7章中简要提到的那样。
  • getframe函数可用于从一系列图形生成“电影帧”。然后可以使用movie函数来播放指定次数的电影。
  • 最通用的(和令人满意的)创建动画的方法是使用Handle Graphics工具。下面是两个例子。

9.5.1 带有手柄图形(Handle Graphics)的动画

对于初学者,运行以下脚本,它应该显示跟踪正弦曲线的标记,并在其后面留下一条轨迹:

 % animated sine graph
x = 0;
y = 0;
dx = pi/40;
p = plot(x, y, 'o''EraseMode''none'); % 'xor'  shows only current point
% ' none' shows all points
axis([0 20*pi -2 2])
for x = dx:dx:20*pi;
x = x + dx;
y = sin(x);
set(p, 'XData', x, 'YData', y)
drawnow
end

在代码中,语句p = plot(x, y, 'o', 'EraseMode', 'none');实现了几个功能。具体解释如下:

  1. 绘制第一个数据点:使用plot()函数绘制了第一个数据点。'o'表示使用圆圈标记绘制数据点。此时,此语句绘制了具有初始坐标(x, y)的点,并将其显示在画布上。

  2. 保存绘图句柄:通过将plot()函数的返回值赋值给变量p,我们保存了该绘图对象的句柄。句柄是一个指向图形对象的引用,可以用来在后续的操作中引用和修改图形对象。

  3. 设置EraseMode属性:使用'EraseMode'参数将EraseMode属性设置为'none'。EraseMode属性用于控制图形对象的绘制方式。通过将其设置为'none',在图形对象绘制时不会对其进行擦除。这意味着每次重新绘制图形对象时,它将保留在画布上,而不被擦除。

要实现完整的动画效果,可以尝试将EraseMode属性设置为'xor'。在这种情况下,每次重新绘制图形对象时,它会以稍微不同的位置被擦除,从而创造出经典的动画效果。

通过将EraseMode属性设置为'xor',每次重新绘制图形对象时,之前的图形对象将被擦除,并以略微不同的位置重新绘制。这将产生动画效果,图形对象似乎在画布上移动或变化。


在代码中的语句set(p, 'XData', x, 'YData', y)用于将对象p的x和y数据值设置为在迭代循环中生成的新值,并重新绘制该对象。然而,这并不意味着它会立即在屏幕上绘制出来,而是加入了"事件队列",等待被执行。

  1. set()函数:set()函数用于设置对象的属性值。在这里,我们使用它来更新对象p的属性值。

  2. 对象p:对象p是之前通过plot()函数创建的图形对象。我们通过保存其句柄,即使用变量p引用该对象。

  3. 属性的设置:使用set()函数,我们通过指定属性名称和新的数值,将对象p的属性值进行更新。在这个语句中,属性名称是'XData'和'YData',即x和y数据。通过将x和y的新值分别传递给这两个属性,我们将更新对象的数据。

  4. 重新绘制对象:一旦对象的属性值被设置为新值,对象将被重新绘制。这意味着对象将以新的数据值在画布上显示出来。

  5. 事件队列:然而,更新后的对象不会立即在画布上绘制出来。它被添加到所谓的"事件队列"中。事件队列是一个缓冲区,用于存储未处理的绘图事件。

  6. 刷新事件队列:要将对象从事件队列中刷新出来并在画布上绘制,需要调用drawnow函数。drawnow函数用于执行等待中的绘图事件并刷新图形,并将其显示在画布上。

通过将对象的属性值设置为新值并调用drawnow函数,可以使更新的对象立即显示在画布上。这样,可以在每次迭代中更新对象的位置,并使用drawnow函数刷新事件队列以实时显示绘图。这样,就可以完成动态图形的连续绘制和更新。


根据help drawnow的说明,有四种事件可以刷新事件队列:

  1. 回到MATLAB提示符:当回到MATLAB提示符时,绘图事件队列将刷新,并将绘图对象显示在画布上。这是您在之前绘制的所有图形中看到的方式。

  2. 暂停语句:当执行到暂停语句时,绘图事件队列将刷新,并将绘图对象显示在画布上。暂停语句可以在代码中指定等待的时间,以便观察和分析图形。

  3. 执行getframe命令:当执行getframe命令时,绘图事件队列将刷新,并将绘图对象显示在画布上。getframe命令用于捕获当前的图形帧,并将其存储为帧数据。

  4. 执行drawnow命令:当执行drawnow命令时,绘图事件队列将立即刷新,并将绘图对象显示在画布上。drawnow命令用于强制刷新事件队列,并立即显示图形更新。

例如,您可以使用pause(0.05)替换drawnow来使标记以更慢的速度移动,即每0.05秒更新一次。pause(0.05)函数将在每次迭代之间添加一个短暂的时间延迟,以控制更新的速度。


洛伦兹奇异吸引子

下一个例子是基于MATLAB文档中的动画部分中的一个示例。它涉及到由三个非线性微分方程描述的混沌运动,这个系统被称为洛伦兹奇异吸引子(Lorenz strange attractor)。

洛伦兹吸引子是由爱德华·洛伦兹 (Edward Lorenz) 在1963年发现的一种非线性动力学系统。它是一个具有混沌特性的系统,描述了大气科学和流体力学中的对流现象。其微分方程的形式如下:

在这里,是系统的状态变量, 是时间,是常数。通过选择适当的初始条件和参数值,可以生成漂亮的混沌运动动画。

系统可以写成:

式中,是一个有三个分量的向量, 是一个关于 的矩阵:

这个脚本使用欧拉法(Euler's method)对系统进行近似求解(更准确的数值解法在第17章中讨论),并展示了解在两个不同的吸引子周围轨道运动的情况,而不会停留在一个稳定轨道上。在绘制了数千个点之后,下图展示了这种情况。

A = [ -8/3 0 00 -10 100 28 -1 ];
y = [35 -10 -7]';
h = 0.01;
p = plot3(y(1), y(2), y(3), 'o', ...
'erasemode''none''markersize'2);axis([0 50 -25 25 -25 25])
hold on
i = 1;
while 1
A(1,3) = y(2);
A(3,1) = -y(2);
ydot = A*y;
y=y+h*ydot;
% Change color occasionally
if rem(i,500) == 0
set(p, 'color', [randrandrand])
end
% Change co-ordinates
set(p, 'XData', y(1), 'YData', y(2), 'ZData', y(3))
drawnow
i=i+1;
end


%%警告: EraseMode 属性不再受支持,而且在以后的版本中会出错。 
%%警告: EraseMode 属性不再受支持,而且在以后的版本中会出错。 
%%2014后的版本EraseMode 属性不再受支持,而且在以后的版本中会出错。

如果所有的点都以相同的颜色绘制,你最终将无法看到生成的新点:屏幕的大片区域将被绘制的颜色填充。因此,每绘制500个点后,颜色是随机设置的。


在较新的版本中,"erasemode" 属性已不再受支持,并且在将来的版本中会产生错误。

如果你想要清除图形并绘制新的数据点,你可以使用 "clf" 命令来清除当前图形窗口,并使用 "plot3" 命令重新绘制数据点。

下面是更新后的代码示例:

A = [ -8/3 0 00 -10 100 28 -1 ];
y = [35 -10 -7]';
h = 0.01;
p = plot3(y(1), y(2), y(3), 'o''markersize'2);
axis([0 50 -25 25 -25 25])
hold on
i = 1;
while 1
    A(1,3) = y(2);
    A(3,1) = -y(2);
    ydot = A*y;
    y = y + h*ydot;
    
    % Change color occasionally
    if rem(i,500) == 0
        set(p, 'color', [randrandrand])
    end
    
    % Change co-ordinates
    set(p, 'XData', y(1), 'YData', y(2), 'ZData', y(3))
    drawnow
    i = i + 1;
end

请注意,"erasemode" 属性的移除可能会导致绘图过程中的一些变化。

    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多