Matlab是一個很常用的理工科數學軟件,我們平常會用它來畫一些平面函數或者簡單的曲線或者簡單的3D平面圖,但是通常很少用到它的稍微高級一點的畫圖功能。這里介紹一些高級渲染功能和畫圖技巧,先看結果。
寫論文中可能會經常遇到這樣的事情,想畫一些高級點的漂亮的圖不知道怎么畫。當然我們通常可能會用solidworks, 3dsmax等等軟件畫這種3D的圖,但是Matlab的好處是可以比較容易生成函數控制的復雜3D曲面形狀,就比如上面的雞蛋盒子一樣的晶格圖形,看似簡單,用其他的軟件還真的不太容易畫。還有比如像下面這樣的波浪圖。想要畫出這樣的圖,除了通常的一些畫圖命令外,還需要掌握一些小的tips,下面來逐一介紹。
1、 光照設置
以第二個圖為例,它的Matlab代碼如下
x=-6*pi:pi/100:6*pi;
y=x;
[X,Y]=meshgrid(x,y);
Z=5*(exp(-(X.^2+Y.^2)/100)+exp(-(X.^2+Y.^2)/4)).*cos(sqrt(X.^2+Y.^2));
figure;surf(X,Y,Z);shading flat; axis off;
view(15,45);axis([min(x),max(x),min(y),max(y),-6,12]);colormap('summer');
%光照渲染
light('position',[0,0,20],'style','local','color','w');lighting phong;
light('position',[0,0,20],'style','local','color','w');lighting phong;
前面四句是定義二元函數,meshgrid函數是將兩個一維數組轉化為二維數組以便定義二元函數,此時X,Y,Z都是二維矩陣。
figure;surf(X,Y,Z);是畫出3D的表面圖,但是這個圖通常是帶有網格的,而且由於定義的數據間隔小,網格也會很密,整張圖看起來一片漆黑。因此需要用shading flat命令來去掉這些網格,此時顯示的結果如下圖所示,可以看到沒什么光澤,不是很好看。上面的view命令是用來設置觀察的角度的,axis([min(x),max(x),min(y),max(y),-6,12])設置圖顯示的區域大小,axis off意思是不顯示坐標軸,colormap用來選擇Matlab自帶的一些色調,比如summer、pink、gray、winter等等。
最后要介紹的就是light命令了,在Matlab command 窗口輸入 help light命令就可以查看light函數的所有性質,讀者可以自行查詢,這里只介紹它的功能。light('position',[0,0,20],'style','local','color','w');lighting phong; 這段命令中,'position'是用來設置光源的位置,'local'表示光源是局域的光源而不是從無窮遠處射來的平行光。lighting phong是設置光照的方式。用兩次同樣的light命令是提高光照的亮度,使圖片看起來色澤更鮮亮。
2、着色設置
上面第一張的圖中的球可以在極坐標下寫出來,這里期待能夠實現更復雜的着色控制,比如像下圖這樣的,所以代碼稍微復雜些。
這個圖的代碼如下:
theta=-pi/2:pi/50:pi/2;
phi=0:pi/50:2*pi;
[Phi,Theta]=meshgrid(phi,theta);
x=R*cos(Theta).*cos(Phi);
y=R*cos(Theta).*sin(Phi);
z=R*sin(Theta);
%着色控制
color=zeros(length(theta),length(phi),3);
color(:,:,1) = cos(Theta)*cos(Theta0).*cos(Phi-Phi0)+sin(Theta)*sin(Theta0); % red
color(:,:,2) = sin(Theta)*sin(Theta0).*cos(Phi-Phi0)+cos(Theta)*cos(Theta0); % green
color(:,:,3) = sin(Theta)*sin(Theta0).*cos(Phi-Phi0); % blue
figure;
surf(x,y,z,color);shading flat;axis off;
view(15,45);axis([-1 1 -1 1 -1 1]);colormap('summer');
light('position',[0,0,20],'style','local','color','w');lighting phong;
light('position',[-20,0,0],'style','local','color','w');lighting phong;
前面到x,y,z的定義和上面一樣,都是定義二元函數。這里唯一的不同點在於color變量的使用,我們可以自定義每個數據點的紅、綠、藍三個顏色的數值,就可以組合出任意的顏色。這樣就幾乎可以把這個圖塗上任意的想要的顏色。曲面形狀拓展一下,還可以畫一個鐵蒺藜的圖。
3、材質設定
Material命令是設置3D 表面的材料的,具體點說主要是反射光的性質,它的命令格式為 material([ka kd ks]);分別設置環境光、漫反射、鏡面反射的反射程度,ka,kd,ks的值均在0到1之間。組合設置一下可以得到更細膩的3D表面的質感。
從上圖可以看到設置material后物體表面對光線的反射會更柔和點。
4、透明度設置
透明度的設置可以直接通過surf命令surf(x,y,z,color,'FaceAlpha',0.3);來設置,這里的'FaceAlpha'就是設置面的透明度,數值在0到1之間,0表示完全透明,1表示完全不透明。
5、動畫控制
最后是動畫的控制,Matlab可以直接生成動畫,動畫的每一幀都是一個圖,因此每個圖都需要畫出來。可以用getframe得到每一幀,用movie函數播放動畫。下面有個完整的例子。
x=-6*pi:pi/20:6*pi;
y=x;
[X,Y]=meshgrid(x,y);
loops=200;
for j=1:loops
Z=5*cos(j/20*pi-sqrt(X.^2+Y.^2)).*(exp(-(X.^2+Y.^2)/100)+exp(-(X.^2+Y.^2)/4));
surf(X,Y,Z);axis off;shading flat;
view(15,45);axis([min(x),max(x),min(y),max(y),-6,12]);colormap('summer');
light('position',[0,0,20],'style','local','color','w');lighting phong;
light('position',[0,0,20],'style','local','color','w');lighting phong;
drawnow;
F(j)=getframe;
end
movie(F,1,20); % 播放1次,每秒鍾20張圖
% 將動畫存為一個視頻文件
aviobj = VideoWriter('water wave.avi');
aviobj.FrameRate = 20;
open(aviobj);
writeVideo(aviobj,F);
close(aviobj);
動畫的每一幀是存在F這個變量里的,然后用movie(F,1,20)來播放動畫。首先需要用VideoWriter函數建立一個新的視頻文件,這個視頻文件在Matlab里的操作是一個對象aviobj,我們可以 設置Framerate為20,即每秒鍾播放20幀。open(aviobj)和close(aviobj)是打開和關閉文件的操作,writeVideo(aviobj,F)是把F中的動畫存在aviobj里,也就是存在water wave.avi文件里,matlab默認生成avi文件。之后打開water wave.avi文件就可以看到生成的動畫了。
6、總結
本文介紹了用Matlab畫3D 物體和3D表面的一些方法。Matlab的優勢是可以非常方便的用函數去構建復雜的3D物體和表面,使得可以非常簡單地表達復雜的3D曲面,通過一些材質和光線渲染可以畫出比較漂亮的圖或者動畫。其缺點是這樣的圖的數據量相對較大,所畫的曲面不太容易導出為3D 模型,因此Matlab畫這種圖的主要作用可能是在科研上,而非畫模型上。當然一種解決方案是,直接用Matlab寫一個程序直接生成3D模型的數據文件,或許可以實現把Matlab的編程優勢與3D建模軟件的優勢結合在一起,實現更復雜的3D建模。