6-3 H閬﹠動畫

以電影方式產生動畫可以說是「暴力法」,因為此方法佔掉了許多記憶體空間。另一個技巧性較高的方法則是以物件方式產生動畫,此種方法不需要大量的記憶體,而且可以產生「即時」(Real-time)或「互動式」(Interactive)的動畫。

MATLAB 的所有圖形元件(曲線、曲面、圖軸等)都是物件,您可以控制這些物件的各種性質,此種特性稱為「握把式圖形」(Handle Graphics),可詳見第七章。握把式圖形包含的層面很廣,但牽涉到動畫部份的基本概念並不複雜,以下我們以曲線的動畫來說明。

每一條曲線都有下列三種性質:

  1. xdata:此為一向量,代表曲線的 x 座標值
  2. ydata:此為一向量,代表曲線的 y 座標值
  3. EraseMode:此為一字串,代表曲線被抹除的方式,亦即當 xdata 或 ydata 被改變時,對於舊曲線的處理方式。

EraseMode 對於動畫的呈現相當重要,此字串可是下列幾種選擇:

在上述四種 EraseMode 中,耗費時間的次序是

normal > xor > background > none

xor 和 background 很接近,但是 background 會抹去其他舊曲線所掃過的其他物件(如圖軸、格線、另一條曲線等),所以較少用到,所以一般在產生動畫時,最常用到的 EraseMode 就是 xor。

有了這些概念後,產生動畫就很容易了!其主要步驟有兩點:

  1. 產生一條曲線,其 EraseMode 為 xor,background,或 none。
  2. 在 for-loop 之中,改變此曲線的 xdata 或 ydata(或兩者)。
在以下的例子中,我們產生一條隨 x 而衰減的正弦曲線 $$ y=sin(x+k)e^{x/5} $$

並讓 k 隨時間而便大(即改變正弦波的相角),使整條曲線產生舞動的效果。程式碼如下:

Example 1: 06-動畫製作/movie04.mx = 0:0.1:8*pi; h = plot(x, sin(x).*exp(-x/5), 'EraseMode', 'xor'); axis([-inf inf -1 1]); % 設定圖軸的範圍 grid on % 畫出格線 tic for i = 1:5000 y = sin(x-i/50).*exp(-x/5); set(h, 'ydata', y); % 設定新的 y 座標 drawnow % 立即作圖 end toc[Warning: The EraseMode property is no longer supported and will error in a future release. Use the ANIMATEDLINE function for animating lines and points instead of EraseMode 'none'. Removing instances of EraseMode set to 'normal', 'xor', and 'background' has minimal impact.] [> In <a href="matlab:matlab.internal.language.introspective.errorDocCallback('movie04', 'd:\users\jang\books\matlabPRogramming4beginner\example\06-動畫製作\movie04.m', 2)" style="font-weight:bold">movie04</a> (<a href="matlab: opentoline('d:\users\jang\books\matlabPRogramming4beginner\example\06-動畫製作\movie04.m',2,0)">line 2</a>) In <a href="matlab:matlab.internal.language.introspective.errorDocCallback('goWriteOutputFile>dummyFunction', 'd:\users\jang\books\goWriteOutputFile.m', 85)" style="font-weight:bold">goWriteOutputFile>dummyFunction</a> (<a href="matlab: opentoline('d:\users\jang\books\goWriteOutputFile.m',85,0)">line 85</a>) In <a href="matlab:matlab.internal.language.introspective.errorDocCallback('goWriteOutputFile', 'd:\users\jang\books\goWriteOutputFile.m', 55)" style="font-weight:bold">goWriteOutputFile</a> (<a href="matlab: opentoline('d:\users\jang\books\goWriteOutputFile.m',55,0)">line 55</a>)] [Warning: The EraseMode property is no longer supported and will error in a future release. Use the ANIMATEDLINE function for animating lines and points instead of EraseMode 'none'. Removing instances of EraseMode set to 'normal', 'xor', and 'background' has minimal impact.] [> In <a href="matlab:matlab.internal.language.introspective.errorDocCallback('movie04', 'd:\users\jang\books\matlabPRogramming4beginner\example\06-動畫製作\movie04.m', 2)" style="font-weight:bold">movie04</a> (<a href="matlab: opentoline('d:\users\jang\books\matlabPRogramming4beginner\example\06-動畫製作\movie04.m',2,0)">line 2</a>) In <a href="matlab:matlab.internal.language.introspective.errorDocCallback('goWriteOutputFile>dummyFunction', 'd:\users\jang\books\goWriteOutputFile.m', 85)" style="font-weight:bold">goWriteOutputFile>dummyFunction</a> (<a href="matlab: opentoline('d:\users\jang\books\goWriteOutputFile.m',85,0)">line 85</a>) In <a href="matlab:matlab.internal.language.introspective.errorDocCallback('goWriteOutputFile', 'd:\users\jang\books\goWriteOutputFile.m', 55)" style="font-weight:bold">goWriteOutputFile</a> (<a href="matlab: opentoline('d:\users\jang\books\goWriteOutputFile.m',55,0)">line 55</a>)] Elapsed time is 20.510184 seconds.

(上圖只秀出最後一個 frame 的畫面。)在上例中,我們使用 set 指令,總共改變曲線的 y 座標 5000 次,並以 xor 的方式抹掉舊曲線。其中 drawnow 的作用是使 MATLAB 立刻處理 set 指令,若無 drawnow,MATLAB 會累積 set 指令,直到 for-loop 結束時再一併處理圖形的變化,這時就不會看到動畫的效果。

如果您將上例的 EraseMode 改成 background,則會發現曲線會“吃掉”圖形中的格線及代表圖軸的直線,請試試看!

如果您將上例的 EraseMode 改成 none,則舊的曲線會被保留下來,產生不同的效果,請試試看!(若要印出此種圖形,請記得在 print 指令加上 –zbuffer 的選項。)

有關於以物件方式呈現動畫的例子相當多,讀者可以試試下列指令:

指令說明
lorenz 以3D動畫呈現的 Lorenz 混沌方程式(Chaotic Equation),好像慧星在運行。
truss 一座橋樑在地震時的震動方式,共有 12 種喔!
travel 顯示如何以雜亂搜尋(Random Search)的方式來解 Traveling Salesperson Problem.
fitdemo 顯示如何以 Downhill Simplex Search 來解決非線性曲線擬合(Nonlinear Curve Fitting)的問題。
spinner 常見的螢幕保護程式。
xphide 試試您的眼力…。

若您有安裝 Simulink,可試試下列動態系統模擬加上動畫呈現:

指令說明
onecart 傳統的彈簧加上砝碼的動態系統。
dblcart1 一條彈簧加上兩個砝碼的動態系統。
simppend 簡單的單擺系統。
dblpend1 兩截的擺動系統。
dblpend2 更複雜的擺動系統。
penddemo 倒單擺系統。

如果您有安裝 Fuzzy Logic Toolbox,可以試試由筆者親自開發的各項模擬及動畫展示:

指令說明
fcmdemo Fuzzy C-means Clustering。
juggler 用板子接皮球。
invkine 兩截機器手臂的 Inverse Kinematics。
slcp1 倒單擺,桿子長度隨時間而變,您可以控制所欲到達的位置。
slcpp1 雙倒單擺,其中一個桿子的長度隨時間而變,您可以控制所欲到達的位置。
slbb 蹺蹺板加上滾球系統,您可以控制球的最後位置。
sltbu 倒車入庫系統


MATLAB程式設計:入門篇