1/22/07

2.4 動畫之製作例

為配合機動學的講授,使用MATLAB的繪圖功能,可以產生物體移動的效果。前文曾討論有關座標的轉移方式,可以先將某一已設定的圖案作平移或旋轉,或者兩者合併,以達到不同的需求與目的。這些座標轉換指令為:

function xprime=trans4(x,delx,mod)

其中x代表全部的座標矩陣,mod則為轉換的模式,當mod=1時表示移動,其移動量依delx決定,此為一列矩陣,對應於座標數。Mod=5時為轉動,若為平面,此時delx代表轉動的角度,以度數表示。若為立體座標,則其內容應為三元素之列矩陣。

當一個動作包含有移動與轉動時,上述指令必須依功能需要呼叫兩次。最好的處理方法是先行處理純轉動座標變換,其後再作移動轉換,如此才不會因旋轉中心改變而產生意外的結果。

連桿之轉動


為取得特定連桿之外圍座標,可以將上節之linkshape函數稍作修改,使其輸出為一組可用之(x,y)座標(註:本程式未使用trans4函數之呼叫,但直接擷取其內容):

function [x,y]=links(A,B,d)
% Find coordinates of a link
% Inputs:
% A,B:Initial & final coordinates of link
% d:thickness of link
% Output:[x,y]:Coordinates of the link
% Example: links([0 0],[5,5])
if nargin==2,d=1;end;
AB=(B(1)+j*B(2))-(A(1)+j*A(2));
D=abs(AB);th=angle(AB);
t=linspace(pi/2,2.5*pi,20);
Cout=(d/2)*exp(j*t');Cin=Cout/2;
P=[0;Cin;Cout(1:10);D+Cout(11:20);D+Cin;D+Cout(20);Cout(1)];
xx=real(P);yy=imag(P);
x=xx*cos(th)-yy*sin(th)+A(1);
y=xx*sin(th)+yy*cos(th)+A(2);


運動之過程



利用MATLAB繪製動畫有兩種方法,其一是先儲存一定數格的圖格,然後再按順序播放,成為連續的電影;其二是在螢幕上連續繪圖及擦拭,以產生連續的動作變化。圖面內容若相當複雜,且有色彩搭配時,以採用第一種方式為宜,如此可以產生一個接近實體之連續影像。這些影像可以事先輸入或繪製,播放時只要將其一幕幕放映即可。這種方式可能會產生閃耀不穩,且所佔的記憶體也較大。

第二種技巧是利用電腦的快速繪圖功能,將影像繪製完成後,再擦去,使其產生視覺暫留的印象。利用MATLAB所提供的模式可以選擇不同的呈現方式。這種方式速度快,但正確性較差。在動力或機動學方面,可以示範組件的動作,故也相當理想。

擦拭模式


MATLAB 指令中,簡單的圖可以使用擦拭重畫法以產生動畫。產生動畫之原理是將某一物體之座標改變之後,擦去前面所繪的圖像,重新依新座標繪製一次,如此連續不斷,產生一系列的動作畫面。這個動作須令'erasemode'的參數值等於'xor'才能完成。典型的畫法是畫出該物體後,然後在迴圈中,不斷地些微改變其位置座標,然後畫出新的畫面。其座標分別以x,y,z表示。在指令中亦可直接設定'erasemode'之值達到程式控制的目的。'erasemode'的參數有三種選擇:

  • none - MATLAB 會在繪出新圖案前不將舊圖清除。
  • background - MATLAB 會用背景顏色將舊圖重新繪製一次。故此種模式除將舊圖清除外,其底下原有的繪製物如格線等亦被清除。
  • xor – 此模式僅擦拭物體部份,最常用於動畫。

這三種模式是MATLAB繪圖指令中之執行速度最快者,但仍然視圖像的細節及運算的時間而定。若變化太過快速,可利用pause指令來延遲經歷之時間。在機動學中之動作中,本節將以此功能配合各項分析結果產生動畫,使同學瞭解其中之變化過程。

程式內容


本程式呼叫links函數,以得到單桿之外形之座標點,然後依與時間相關之迴轉角度delt順序旋轉。擦拭模式可以在程式中依下述的方法在繪製時就先設定:

h1=line(x,y,'erasemode','xor','color','r','linewidth',2);

指令中,h1為其握把,以此認定所需改變的線圖。注意此時之'erasemode' 參數值設定為 'xor',表示使用擦拭模式,亦即在下一次繪製新圖時,會將上次繪製之舊圖塗去,以觀察連續變動之影像。在每次繪製前必須將新的座標指向該握把,可利用此指令為之:

 set(h1,'xdata',x2,'ydata',y2);

採用set指令與直接下 line有點不同, line指令下達後,繪圖動作立即進行,但set指令僅先設定所要的值在緩衝器上,並不立即執行。因此你可以執行set好幾次,等到滿意之後才一次執行。執行繪圖的動作須配合drawnow之下達,才能一次繪出。下面的程式中,係先執行drawnow,表示先執行第一次準備之資料,但這只是程式的應用技巧,到底drawnow事先下或後下,依使用情況而定,一般並不影響結果。故實際上應用上也可置於執行set指令之後。

function link_rot1(r,d,v)
%link_rot1.m will call links.m
%Rotating a link
%Example: link_rot1(10,3,50)
%Author:DSFon, BIME,NTU. Date:Jan. 24, 2007
clf;
if nargin==0,r=10;d=1;v=50;end
[x,y]=links([0 0],[r,0],d);
delt=pi/120; %delaying time for display
axis([-r r -r r]*1.2);
axis image;axis off;
t=0:2*pi/50:2*pi;
h0=line(r*cos(t),r*sin(t),'color','b','linestyle',':');
h1=line(x,y,'erasemode','xor','color','r','linewidth',2);
x1=get(h1,'xdata');y1=get(h1,'ydata');
title('Press Ctl-C to stop');
theta1=0;s1=delt;
while 1,
drawnow;
pause(1/v);
theta1=theta1+s1;
x2=x1*cos(theta1)-y1*sin(theta1);
y2=x1*sin(theta1)+y1*cos(theta1);
set(h1,'xdata',x2,'ydata',y2);
if theta1>2*pi,theta1=theta1-2*pi;end;
end



執行結果




按此觀賞動畫: