第十八章 三维图形 为了显示三维图形,MATLAB提供了各种各样的函数。有一些函数可在三维空间中画线,而另一些可以画曲面与线格框架。另外,颜色可以用来代表第四维。当颜色以这种方式使用时,由于它不再象照片中那样显示信息的自然属性----色彩,而且也不是基本数据的内在属性,所以它称作伪彩色。为了简化对三维图形的讨论,对颜色的介绍推迟到下一章。在这一章,主要讨论绘制三维图形的基本概念。 18.1 函数plot3 plot3命令将绘制二维图形的函数plot的特性扩展到三维空间。函数格式除了包括第三维的信息(比如Z方向)之外,与二维函数plot相同。plot3一般语法调用格式是plot3(x1,y1,z1,S1,x2,y2,z2,S2,…),这里xn,yn和zn是向量或矩阵,Sn是可选的字符串,用来指定颜色、标记符号和/或线形。 总的来说,plot3可用来画一个单变量的三维函数。如下为一个三维螺旋线例子: ? t=0:pi/50:10*pi; ? plot3(sin(t),cos(t),t) ? title( ‘ Helix ‘ ),xlabel( ‘ sint(t) ‘ ),ylabel( ‘ cos(t) ‘ ),zlabel( ‘ t ‘ ) ? text(0,0,0, ‘ Origin ‘ ) ? grid ? v = axis v = -1 1 -1 1 0 40 输出见图18.1.  图18.1 螺旋线图 从上例可明显看出,二维图形的所有基本特性在三维中仍都存在。axis命令扩展到三维 只是返回Z轴界限(0和40),在数轴向量中增加两个元素。函数zlabel用来指定z轴的数据名称,函数grid在图底绘制三维网格。函数test(x,y,z, ‘ string ‘ )在由三维坐标x,y,z所指定的位置放一个字符串。另外,子图和多图形窗口可以直接应用到三维图形中。 在最后一章可以看到,通过指定plot命令的多个参量或使用hold命令,可以把多条直线或曲线重叠画出。plot3以及其它的三维图形函数都可以提供相同的能力。例如,增加维数的plot3命令可以使多个二维图形沿一个轴排列起来,而不是直接将二维图形叠到另一个的上面。 ? x=linspace(0,3*pi); % x-axis data ? z1=sin(x); % plot in x-z plane ? z2=sin(2*x); ? z3=sin(3*x); ? y1=zeros(size(x)); % spread out along y-axis ? y3=zeros(size(x)); % by giving each diffent y-axis values ? y2=y3/2; ? plot3(x,y1,z1,x,y2,z2,x,y3,z3); ? grid,xlabel( ‘ x-axis ‘ ),ylabel( ‘ y-axis ‘ ,abel( ‘ z-axis ‘ ) ? title( ‘ sin(x),sin(2x),sin(3x) ‘ ) 输出见图18.2.  图18.2 正弦曲线图 上述图形也可以沿另外方向堆列。 ? plot3(x,z1,y1,x,z2,y2,x,z3,y3) ? grid,xlabel( ‘ x-axis ‘ ,ylabel( ‘ y-axis ‘ ),zlabel( ‘ z-axis ‘ ) ? title( ‘ sin(x),sin(2x),sin(3x) ‘ ) 输出见图18.3.  图18.3 正弦曲线图 18.2 改变视角 注意两个图形,一个是以30度视角向下看z=0平面,一个是以37.5度视角向上看x=0平面。这是对所有三维图形的缺省视角。与z=0平面所成的方向角叫仰角,与x=0平面的夹角叫做方位角。这样,缺省的三维视角方向仰角为30度,方位角为-37.5度。而缺省的二维视角仰角为90度,方位角为0度。仰角和方位角的概念在图18.4中形象地画出。 图18.4 仰角和方位角示意图  图18.5 视角举例图 在MATLAB中,函数view改变所有类型的二维和三维图形的图形视角。view(az,el)和view([az,el)]将视角改变到所指定的方位角az和仰角el。考虑下面脚本M文件形式的例子。 % viewpoint example using subplots x=linspace(0,3*pi).’; Z=[sin(x) sin(2*x) sin(2*x)]; % create Y and Z axes as matrices Y=[zeros(size(x)) ones(size(x))/2 ones(size(x))]; subplot(2,2,1) plot3(x,Y,Z) % plot3 works with column-oriented matrices too grid,xlabel( ‘ X-axis ‘ ),ylabel( ‘ Y-axis ‘ ),zlabel( ‘ Z-axis ‘ ) title( ‘ Default Az = -37.5,E1 = 30 ‘ ) view(-37.5,30) subplot(2,2,2) plot3(x,Y,Z) grid,xlabel( ‘ X-axis ‘ ),ylabel( ‘ Y-axis ‘ ),zlabel( ‘ Z-axis ‘ ) title( ‘ Az Rotated to 52.5 ‘ ) view(-37.5+90,30) subplot(2,2,3) plot3(x,Y,Z) grid,xlabel( ‘ X-axis ‘ ),ylabel( ‘ Y-axis ‘ ),zlabel( ‘ Z-axis ‘ ) title( ‘ E1 Increased to 60 ‘ ) view(-37.5,60) subplot(2,2,4) plot3(x,Y,Z) grid,xlabel( ‘ X-axis ‘ ),ylabel( ‘ Y-axis ‘ ) title( ‘ Az = 0,E1 = 90 ‘ ) view(0,90) 输出见图18.5。 除了上面的形式,view还提供了综合在表18.1的其它特性: 表18.1 函数view  view(az,el) 将视图设定为方位角az和仰角el  view([az,el])   view([x,y,z]) 在笛卡儿坐标系中将视图设为沿向量[x,y,z]指向原点,例如view([0 0 1])=view(0,90)  view(2) 设置缺省的二维视角,az=0,el=90  view(3) 设置缺省的三维视角,az=-37.5,el=30  [az,el]=view 返回当前的方位角az和仰角el  view(T) 用一个4×4的转矩阵T来设置视图角  T=view 返回当前的4×4转矩阵   最后,为了演示MATLAB句柄图形能力,精通MATLAB工具箱包含了函数mmview3d。在产生二维或三维图形后调用此函数,? mmview3d,在当前图形中放置水平角和方位角滑标(滚动条)以设置视角。使用函数mmview3d的更详细的信息见在线帮助。 18.3 两个变量的标量函数 相对于plot3产生的线条图形,经常希望画出两个变量的标量函数,比如: z=f(x,y) 这里每一对x与y的值产生一个z的值。它作为x与y的函数,是三维空间中的一个曲面。为了在MATLAB里画出这个曲面,z的值存放在一个矩阵中。象在**二维插值这一节所描述的那样,给出x与y的值作为独立的变量,z是因变量矩阵,x、y与z的联系就是: z(i,:)=f(x,y(i)) and z(:,j)=f(x(j),y) 即z的第i行与的y第i个元素相关,而z的第j列与x的第个j元素相关。或者说,y沿着z的列变化,而x沿着z的行变化。 当z=f(x,y)能简化表示时,可以方便地用数组运算在单个语句中算出z的所有的值。这样做,要求我们以合适的方向创建所有x与y值的矩阵。(这种方向有时被Mathwork公司称作为方格)。MATLAB提供了函数meshgrid来执行这个步骤。 ? x=-3:3; % choose x-axisd values ? y=1:5; % y-axis values ? [X,Y]=meshgrid(x,y) X = -3 -2 -1 0 1 2 3 -3 -2 -1 0 1 2 3 -3 -2 -1 0 1 2 3 -3 -2 -1 0 1 2 3 -3 -2 -1 0 1 2 3 Y = 1 1 1 1 1 1 1 2 2 2 2 2 2 2 3 3 3 3 3 3 3 4 4 4 4 4 4 4 5 5 5 5 5 5 5 如上所见,函数meshgrid对y中行的每一行复制x,同样也对x中列的每一列复制y。这种方向与前面语句相一致,即y向下改变其列,而x横跨改变其行。给定X和Y,如果z=f(x,y)=(x+y)2,那么z便定义一个三维曲面的数据矩阵: ? Z=(X+Y).^2 Z = 4 1 0 1 4 9 16 1 0 1 4 9 16 25 0 1 4 9 16 25 36 1 4 9 16 25 36 49 4 9 16 25 36 49 64 当函数不能象上面那样简单表示出来时,便只能用 For 循环或 While 循环来计算Z的元素。在很多情况下,有可能按行或按列计算Z。例如,如果能按行计算Z,下面的脚本文件段会很有帮助: x=??? % statement defining vector of x-axis values y=??? % statement defining vector of y-axis values nx=length(x); % length of x is no. of rows in Z ny=length(y); % length of y is no. of columns in Z Z=zeros(nx,ny); % initialize Z matrix for speed for r=1:nx {preliminary commands} Z(r,:)={a function of y and x(r) defining r-th row of Z} end 相反,如果能按列计算Z,下面的脚本文件段会很有帮助: x=??? % statement defining vector of x-axis values y=??? % statement defining vector of y-axis values nx=length(x); % length of x is no. of rows in Z ny=length(y); % length of y is no. of columns in Z Z=zeros(nx,ny); % initialize Z matrix for speed for c=1:ny {preliminary commands} Z(:,c)={a function of y(c) and x defining c-th column of Z} end 只有当Z中的元素必须一个一个地计算时,就常常要求象下面的脚本文件一样,用嵌套循环进行计算。 x=??? % statement defining vector of x-axis values y=??? % statement defining vector of y-axis values nx=length(x); % length of x is no. of rows in Z ny=length(y); % length of y is no. of columns in Z Z=zeros(nx,ny); % initialize Z matrix for speed for r=1:nx for c=1:ny {preliminary commands} Z(r,c)={a function of y(c) and x(r) defining Z(r,c)} end end 18.4 杂乱或散射数据的插值 在有些情况下,两个变量的标量函数的值,如z=f(x,y),不能简单地算出。这是因为要么x和y的值是非均匀间隔的(最坏时是随机分布),要么是用了不同的坐标系,比如非长方形的网格。出现这些情况时,MATLAB中的函数griddata就用来产生经插值后的均匀间隔数据以作图。首先考虑前面的例子。假设要求较高的分辨率,但我们不想重新计算函数来得到新值。 ? x=-3:3; % original x-axis values ? y=1:5; % original y-axis values ? [X,Y]=meshgrid(x,y); % create plaid data matrices ? Z=(X+Y).^2; % original z values ? size(Z) % original array size ans = 5 7 ? xi=-3:.5:4; % interpolated x-axis values ? length(xi) % get new x-axis length ans = 15 ? yi=0:.2:5; % interpolated y-axis values ? length(yi) % get new y-axis length ans = 26 ? [Xi,Yi]=meshgrid(xi,yi); % make new data plaid ? Zi=griddata(X,Y,Z,Xi,Yi); % interpolated Z data using original data ? size(Zi) % interpolated size is correct ans = 26 15 这里函数griddata用三个原始矩阵X,Y,Z和需要插值的方格矩阵,创建一个新的因变量矩阵Zi。要注意插值不必在原始数据的范围内,比如x在-3与3间变化,而xi在-3与4间变化。 与第11章里所述的二维插值相对应,griddata对于数据非单调或不规则分布的情况也同样有效。例如,考虑随机数据: ? x=2*rand(1,20); % nonmonotonic x-axis ? y=4*rand(1,20)-2; % nonmonotonic y-axis ? [X,Y]=meshgrid(x,y); % make data plaid ? Z=(X+Y).^2; % compute function ? xi=linspace(0,2,50); % interpolated monotonic x-axis values ? yi=linspace(-2,2,30); % interpolated monotonic y-axis values ? [Xi,Yi]=meshgrid(xi,yi); % make data plaid ? Zi=griddata(X,Y,Z,Xi,Yi); % interpolated on monotonic plaid data 这里,对随机数据插值给出更适合于作图的单调数据。这对于本章后面讨论的等值线图特别重要,因为它要求数据定义在均匀间隔的网格中。 在上面的两个例子中,较容易对所需的插值重新计算函数。作为一般规则,如果容易计算出感兴趣的函数,就要避免使用函数griddata。而当感兴趣的点的函数不可得到或需要很大的计算量时,函数griddata提供了一个工具,以均匀分布的内插数据点,对基本函数进行估计。 18.5 网格图 利用在x-y平面的矩形网格点上的z轴坐标值,MATLAB定义了一个网格曲面。MATLAB通过将邻接的点用直线连接起来形成网状曲面,其结果好象在数据点有结点的鱼网。例如,用MATLAB的函数Peaks可以画一个简单的曲面。 ? [X,Y,Z]=peaks(30); ? mesh(X,Y,Z) ? grid,xlabel( ‘ x-axis ‘ ),ylabel( ‘ y-axis ‘ ),zlabel( ‘ z-axis ‘ ) ? title( ‘ MESH of PEAKS ‘ ) 输出见图18.6.  图18.6 函数PEAKS的网格图 在显示器上要注意到线的颜色与网格的高度有关。一般情况下,函数mesh有可选的参量来控制绘图中所用的颜色。关于MATLAB如何使用、改变颜色在下一章讨论。在任何情况下,由于颜色用于增加图形有效的第四维,这样使用的颜色被称做伪彩色。 除了上例中的输入参量,函数mesh和大多数三维绘图函数都可按多种输入参量调用。这里所用的句法是最详细的,它给出了所有三个坐标轴的信息。最通常的变更方法是使用向量,将它传递给meshgrid,生成x与y坐标轴,比如mesh(x,y,z)。有关其它调用语法形式的信息,参阅MATLAB参考指南或在线帮助。 如上图所示,网格线条之间的区域是不透明的。MATLAB命令hidden控制网格图的这个特性。比如,用MATLAB的函数sphere产生两个球面如下: ? [X,Y,Z]=sphere(12); ? subplot(1,2,1) ? mesh(X,Y,Z),title( ‘ Opaque ‘ ) ? hidden on ? axis off ? subplot(1,2,2),title( ‘ Transparent ‘ ) ? mesh(X,Y,Z) ? hidden off ? axis off 输出见图18.7.  不透明 透明 图18.7 左边的球是不透明的(线被隐蔽),而右边的球是透明的(线未被隐蔽)。 MATLAB的mesh有两个同种函数:meshc,它画网格图和基本的等值线图;meshz,它画包含零平面的网格图。 ? [X,Y,Z]=peaks(30); ? meshc(X,Y,Z) % mesh plot with underlying contour plot ? title( ‘ MESHC of PEAKS ‘ ) ? meshz(X,Y,Z) % mesh plot with zero plane ? tiTle( ‘ MESH of PEAKS ‘ ) ? title( ‘ MESH of PEAKS ‘ ) ? hidden off % make mesh transparent so minimums can be seen 输出分别见图18.8和图18.9.  图18.8 函数PEAKS的网格图和基本等值线图  图18.9 函数PEAKS的带零平面的网格图 关于以上函数更详细的信息参阅MATLAB参考指南或使用在线帮助。 18.6 曲面图 曲面图,除了各线条之间的空档(称作补片)用颜色填充以外,和网格图看起来是一样的。这种图一般使用函数surf来绘制。自然,函数surf使用和函数mesh相同的调用语法。比如: ? [X,Y,Z]=peaks(30); ? surf(X,Y,Z) ? grid,xlabel( ‘ x-axis ‘ ),ylabel( ‘ y-axis ‘ ),zlabel( ‘ z-axis ‘ ) ? title( ‘ SURF of PEAKS ‘ ) 输出见图18.10.  图18.10 函数PEAKS的曲面图 曲面图的一些特性正好和网格图相反:它的线条是黑色的,线条之间的补片有颜色;而在网格图里,补片是黑色的而线条有颜色。对函数mesh,颜色沿着z轴按每一补片变化,而线条颜色不变。 在曲面图里,人们不必考虑象网格图一样隐蔽线条,但要考虑用不同的方法对表面加色彩。在前面的曲面图的例子中,就是分割成块,每块就象一块染色玻璃窗口或物体,黑线便是各单色染色玻璃块之间的连接。除此以外,MATLAB还提供了平滑加颜色和插值加颜色功能。这可以通过调用函数shading来实现。 ? [X,Y,Z]=peaks(30); ? surf(X,Y,Z) % same plot as above ? grid,xlabel( ‘ x-axis ‘ ),ylabel( ‘ y-axis ‘ ),zlabel( ‘ z-axis ‘ ) ? title( ‘ SURF of PEAKS ‘ ) ? shading flat 输出见图18.11.  图18.11 函数PEAKS的平滑加彩色曲面图 如上所示平滑加色彩的例子中,每一补片仍保存着单一的颜色,但各块连接处的黑线已去掉。 ? shading interp 输出见图18.12.  图18.12 函数PEAKS的插值加彩色曲面图 如上所示内插加色彩的例子中,同样去掉了线条,但各补片以插值加颜色,即各补片的颜色根据赋予顶点的色值,对其区间进行了插值计算。很明显,插值色彩需要比分块和平滑更多的计算量。在一些计算机系统中,插值色彩会产生非常长的打印延时或打印错误。这问题不在于PostScript文件太大,而是由于在打印机上产生沿图形曲面连续变化的阴影所需的巨大计算量。通常对这个问题最简单的解决方法是使用平滑加色彩法来打印。 色彩对surf作图的视觉效果有着巨大的影响。对网格图也是如此,尽管由于只有线条有颜色,对视觉效果的影响相对要小一些。 因为曲面图不能作成透明,但在一些情况下可以很方便地移走一部分表面以便看到表面以下部分,在MATLAB中,这是通过在所期望的洞孔的所在位置,将数据置为特定的NaN来实现。由于NaN没有任何值,所有的MATLAB作图函数都忽略NaN的数据点,在该点出现的地方留下一个洞孔。例子如下: ? [X,Y,Z]=peaks(30); ? x=X(1,:); % vector of x axis ? y=Y(:,1); % vector of y axis ? i=find(y>.8 & y<1.2); % find x-axis indices of hole ? j=find(x>-.6 & x<.5); % find x-axis indices of hole ? Z(i,j)=nan*Z(i,j); % set values at hole indices to NaNs ? surf(X,Y,Z) ? grid,xlabel( ‘ x-axis ‘ ),ylabel( ‘ y-axis ‘ ),zlabel( ‘ z-axis ‘ ) ? title( ‘ SURF of PEAKS with a Hole ‘ ) 输出见图18.13.  图18.13 函数PEAKS的带洞孔曲面图 MATLAB的surf也有两个同种函数:surfc,它画出具有基本等值线的曲面图;surfl,它画出一个有亮度的曲面图。例如: ? [X,Y,Z]=peaks(30); ? surfc(X,Y,Z) % surf plot with contour plot ? grid,xlabel( ‘ x-axis ‘ ),ylabel( ‘ y-axis ‘ ),zlabel( ‘ z-axis ‘ ) ? title( ‘ SURFC of PEAKS ‘ ) 输出见图18.14.  图18.14 函数PEAKS的曲面图和基本等值线图 ? [X,Y,Z]=peaks(30); ? surfl (X,Y,Z) % surf plot with lighting ? shading interp % surfl plots look best with interp shading ? colormap pink % they also look better with shades of a single color ? grid,xlabel( ‘ X-axis ‘ ),ylabel( ‘ Y-axis ‘ ),zlabel( ‘ Z-axis ‘ ) ?title( ‘ SURFL OF PEAKS ‘ ) 输出见图18.14. 图18.16 函数PEAKS的带光线照明曲面图 关于加到曲面的亮度,函数surfl作了许多假设。有关设置亮度属性的详细信息参阅MATLAB参考指南的函数surfl或使用在线帮助。同样,在上面执行的命令中,colormap是MATLAB函数,它对图形施加一套不同的颜色。这个函数在下一章讨论。 18.7 等值线图 MATLAB提供了另一种基本的三维图形,即三维等值线图。这种图形通过函数contour3来绘制。 ? [x,y,z]=peaks(30); ? contour3(X,Y,Z,16) % draw sixteen contour lines ? grid,xlabel( ‘ x-axis ‘ ),ylabel( ‘ y-axis ‘ ),zlabel( ‘ z-axis ‘ ) ? title( ‘ CONTOUR3 of PEAKS ‘ ) 输出见图18.16. 图18.16 函数PEAKS的三维等值线图 可以看到,图形中每一条线的颜色遵循了与二维函数plot一样的次序。这种颜色次序可以表现出明显的对比,但经常模糊了所代表的数据的一些重要特性。如果能使每一条线遵循在网格图和曲面图里所用的加色方法,那么效果会好得多。也许在MATLAB的下一个版本中,这种颜色设置会成为缺省设置,但使用在下一章要讨论的MATLAB图形处理能力,也能解决这个问题。 ? [X,Y,Z]=peaks(30); ? N=16; % number of contour lines and their colors ? clf % clear the current figure ? view(3) % set view to 3-D ? hold on % hold blank screen ? set(gca, ‘ ColorOrder ‘ ,hsv(N)) % use colors from default hsv colormap ? contour3(X,Y,Z,N) % draw N contour lines ? grid,xlabel( ‘ X-axis ‘ ),ylabel( ‘ Y-axis ‘ ),zlabel( ‘ Z-axis ‘ ) ? title( ‘ CONTOUR3 of PEAKS ‘ ) ? hold off 输出见图18.17.  图18.17 函数PEAKS的三维等值线图 现在,各条等值线的颜色沿着z轴的变化和网格图和曲面图一样。为方便起见,这种策略已体现在精通MATLAB工具箱的函数mmcont3中。mmcont3具有和函数contour3相同的调用语法的变化,并允许选择可用的颜色映象。例如,? mmcont3(X,Y,Z,N,‘hsv’)复制上面的图形。mmcont3的在线帮助如下: ? help mmcont3 MMCONT3 3-Dcontour plot using a colormap MMCONT3(X,Y,Z,N,C) plots N contours of Z in 3-D using the color specified in C.C can be a linestyle and color as used in plot,e.g., ‘ r- ‘ ,or C can be the string name of a colormap.X and Y. define the axis limits. If not given default argument values are :N=10 ,C= ‘ hot ‘ ,X and Y=row and column indices of Z.Examples: MMCONT3(Z) 10 lines with hot colormap MMCONT3(Z,20) 20 lines with hot colormap MMCONT3(Z, ‘ copper ‘ ) 10 lines with copper colormap MMCONT3(Z,20, ‘ gray ‘ ) 20 lines with gray colormap MMCONT3(X,Y,Z, ‘ jet ‘ ) 10 lines with jet colormap MMCONT3(Z, ‘ c-- ‘ ) 10 dashed lines in cyan MMCONT3(X,Y,Z,25, ‘ pink ‘ ) 25 lines in pink colormap CS=MMCONT3( . . .) returns the contour matrix CS as described in CONTOURC. [CS,H]=MMCONT3( . . .) returns a column vector H of handles to line objects 帮助信息: MMCONT3(X,Y,Z,N,C)用由C指定的颜色在三维空间内画N条Z方向的等值线图。C可以是在plot中使用的线形 和颜色,例如 ‘ r- ‘ ;或者C可以是一个颜色映象的字符串名。X和Y指定了坐标轴的范围。如果 未指定参数,缺省的参数值是:N=10,C= ‘ hot ‘ ,X和Y分别是Z的行和列的下标。举例: MMCONT3(Z) 用暖色映象画10条等值线 MMCONT3(Z,20) 用暖色映象画20条等值线 MMCONT3(Z, ‘ copper ‘ ) 用铜黄色映象画10条等值线 MMCONT3(Z,20, ‘ gray ‘ ) 用灰色映象画20条等值线 MMCONT3(X,Y,Z, ‘ jet ‘ ) 用**‘jet’暖色映象画10条等值线 MMCONT3(Z, ‘ c-- ‘ ) 画10条青蓝色的虚划线等值线 MMCONT3(X,Y,Z,25, ‘ pink ‘ ) 用粉红色映象画25条等值线 CS=MMCONT3(…) 如在CONTOURC中描述,返回等值线矩阵CS。 [CS,H]=MMCONT3(…) 把句柄的列向量H返回到线条对象。 等值线也可由一种颜色给出: ? [x,y,z]=peaks(30); ? contour3(X,Y,Z,16, ‘ y ‘ ) % draw sixteen contour lines in yellow ? grid,xlabel( ‘ x-axis ‘ ),ylabel( ‘ y-axis ‘ ),zlabel( ‘ z-axis ‘ ) ? title( ‘ CONTOUR3 of PEAKS ‘ ) 输出见图18.18 图18.18 函数PEAKS的黄色三维等值线图 关于颜色使用的详细信息参阅下一章;以上函数使用的详细信息参阅MATLAB参考指南或使用在线帮助。 18.8 三维数据的二维图 有些情况下,希望得到三维数据的二维表示。在MATLAB里这一点是通过用函数view设置视角使其中一维不出现来实现的。另外,MATLAB还提供了两个函数,将contour3和surf向下正视到x-y平面。例如,函数contour3的二维图就等价于contour。 ? [X,Y,Z]=peaks(30); ? contour(X,Y,Z,16) % draw sixteen contour lines ? xlabel( ‘ X-axis ‘ ),ylabel( ‘ Y-axis ‘ ) ? title( ‘ CONTOUR of PEAKS ‘ ) 输出见图18.19  图18.19 函数PEAKS的等值线图 要注意,它如何等效于使用contour3以及如何改变视点俯视到x-y平面。如同contour3,图中的等值线利用plot命令的六种基本颜色。如前所述,因为颜色不提供视觉效果,这类图形不好使用并且引起混淆。这种缺省行为也许在MATLAB的下一版本中会改变,但也可用句柄图形来改变。 ? [X,Y,Z]=peaks(30); ? N=16; % number of contour lines and their colors ? clf % clear the current figure ? hold on % hold blank screen ? set(gca, ‘ ColorOrder ‘ ,hsv(N)) % use colors from default hsv colormap ? contour(X,Y,Z,N) % draw N contour lines ? xlabel( ‘ X-axis ‘ ),ylabel( ‘ Y-axis ‘ ),zlabel( ‘ Z-axis ‘ ) ? title( ‘ CONTOUR of PEAKS ‘ ) ? hold off 输出见图18.20  图18.20 函数PEAKS的等值线图 现在,等值线遵循hsv颜色映象里的级差,颜色提供了一种有用的效果!为方便起见,上述策略已体现在精通MATLAB工具箱的函数mmcont2中。mmcont2接受和函数contour相同的调用语法变更,并允许选择一个可用的颜色映象。例如,? mmcont2(X,Y,Z,N,‘hsv’)复制上面的图形。mmcont2的在线帮助如下: ? help mmcont2 MMCONT2 2-D contour plot using a colormap. MMCONT2(X,Y,Z,C) plots N contours of Z in 2-D using the color specified in C.C can be a linestyle and color as used in plot,e.g., ‘ r- ‘ ,or C can be the string name of a colormap.X and Y. define the axis limits. If not given default argument values are :N=10,C= ‘ hot ‘ ,X and Y =row and column indices of Z.Examples: MMCONT2(Z) 10 lines with hot colormap MMCONT2(Z,20) 20 lines with hot colormap MMCONT2(Z, ‘ copper ‘ ) 10 lines with copper colormap MMCONT2(Z,20, ‘ gray ‘ ) 20 lines with gray colormap MMCONT2(X,Y,Z, ‘ jet ‘ ) 10 lines with jet colormap MMCONT2(Z, ‘ c-- ‘ ) 10 dashed lines in cyan MMCONT2(X,Y,Z,25, ‘ pink ‘ ) 25 lines in pink colormap CS=MMCONT2( . . .) returns the contour matrix CS as described in CONTOURC. [CS,H]=MMCONT2( . . .) returns a column vector H of handles to line objects 帮助信息: MMCONT2(X,Y,Z,N,C)用由C指定的颜色在二维平面内画出关于Z方向的N条等值线。C 可以是在函数plot中使用的线形和颜色,例如 ‘ r- ‘ ;或者是一个字符串指明颜色映象名。 X和Y指定了坐标轴的范围。 如果未指定参数,缺省的参数值是:N=10,C= ‘ hot ‘ ,X和Y分别是Z的行列下标。 例子如下: MMCONT2(Z) 使用暖色颜色映象画10条等值线 MMCONT2(Z,20) 使用暖色颜色映象画20条等值线 MMCONT2(Z, ‘ copper ‘ ) 使用铜黄色颜色映象画10条等值线 MMCONT2(Z,20, ‘ gray ‘ ) 使用灰色颜色映象画20条等值线 MMCONT2(X,Y,Z, ‘ jet ‘ ) 使用‘jet’暖色颜色映象画10条等值线 MMCONT2(Z, ‘ c-- ‘ ) 使用青蓝色颜色映象用虚划线画10条等值线 MMCONT2(X,Y,Z,25, ‘ pink ‘ ) 使用粉红色颜色映象画25条等值线 CS=MMCONT2(…)返回等值线矩阵CS,它在CONTOURC中描述。 [CS,H]=MMCONT2(…)返回一个包含有线条对象的句柄的列向量。 上面讨论的三维或二维等值线图都假定数据定义在矩形网格或论域内。当不是这种情形时,数据必须被转换到矩形网格上,使等值线图看起来逼真。如本章前面18.4节所述,MATLAB函数griddata能实现所需的转换,更详细的信息参阅该节。 函数surf的二维等效函数是pcolor,它代表伪彩色。 ? [X,Y,Z]=peaks(30); ? pcolor(X,Y,Z); % surf plot view from above ? xlabel( ‘ X-axis ‘ ),ylabel( ‘ Y-axis ‘ ) ? title( ‘ PCOLOR of PEAKS ‘ ) 输出见图18.21.  图18.21 函数PEAKS的伪彩色图 由于这是一个surf图,可以使用函数shading。另外,有时在pcolor图的上面放一个单色等值线图是很有用的。 ? [X,Y,Z]=peaks(30); ? pcolor(X,Y,Z); ? shading interp ? hold on ? contour(X,Y,Z,19, ‘ k ‘ ) % add 19 contour lines in black ? xlabel( ‘ X-axis ‘ ),ylabel( ‘ Y-axis ‘ ) ? title( ‘ PCOLOR and CONTOUR of PEAKS ‘ ) ? hold off 输出见图18.22.  图18.21 函数PEAKS的伪彩色图和等值线图 18.9 其它函数 除了上面讨论的三维函数,MATLAB还提供了函数waterfall,quiver,fill3,和clabel。 函数waterfall与函数mesh一样,只是它的网格线是在x轴方向出现。例如: ? [X,Y,Z]=peaks(30); ? waterfall(X,Y,Z) ? xlabel( ‘ X-axis ‘ ),ylabel( ‘ Y-axis ‘ ),zlabel( ‘ Z-axis ‘ ) 输出见图18.23.  图18.23 函数PEAKS的waterfall图 函数quiver在等值线图上画出方向或速度箭头。例如: ? [X,Y,Z]=peaks(16); ? [DX,DY]=gradient(Z, .5, .5); ? contour(X,Y,Z,10) ? hold on ? quiver(X,Y,DX,DY) ? hld off 输出见图18.24.  图18.24 函数PEAKS的quiver图 函数fill3等效于三维函数fill,可在三维空间内画出填充过的多边形。函数fill3(x,y,z,c)使用数组x,y和z作为多边形的顶点而c指定了填充的颜色。例如,下例用随机的顶点坐标值画出五个黄色三角形。 ? fill3(rand(3,5),rand(3,5),rand(3,5), ‘ y ‘ ) 输出见图18.25.  图18.25 函数fill3图示 函数clabel给等值线图标上高度值。这样做时,函数clabel需要函数contour等值线矩阵的输出。 ? [X,Y,Z]=peaks(30); ? cs=contour(X,Y,Z,8); % request output from contour ? clabel(cs) % add labels identifying heights ? xlabel( ‘ X-axis ‘ ),ylabel( ‘ Y-axis ‘ ) ? title( ‘ CONTOUR of PEAKS with LABELS ‘ ) 输出见图18.26.  图18.26 函数PEAKS的带标志等值线图 18.10 动画 MATLAB提供了一种能力,它可以存储一系列各种类型的二维或三维图,然后象放电影一样把它们按次序重放出来。在某种意义上,动画提供的运动为图形增加另一个维数。通常图形的次序不必以任意的方式关联起来。一种明显的动画类型是取出三维图形然后缓慢地将它旋转,这样我们就可以从不同角度来观察它。另一种类型是当一个参数变化时,依次显示某些问题解的图形。 MATLAB中的函数moviein,getframe和movie提供了捕捉和播放动画的所需工具。函数moviein可以产生一个帧矩阵来存放动画中的帧;函数getframe对当前的图象进行快照;而函数movie按顺序回放各帧。照这样,捕捉和回放动画的方法是:(1)创建帧矩阵;(2)对动画中的每一帧生成图形,并把它捕捉到到帧矩阵里;(3)从帧矩阵里回放动画。 考虑下面的一段脚本M文件例子,例中绘制了函数peaks并且将它绕z轴旋转。 % movie making example: rotate a 3-D surface plot [X,Y,Z]=peaks(30); % create data surfl(X,Y,Z) % plot surface with lighting axis([-3 3 -3 3 -10 10]) % fix axes so that scaling does not change axis off % erase axes because they jump around shading interp % make it pretty with interpolated shading colormap(hot) % choose a good colormap for lighting m=moviein(15); % choose 15 movie frames for frame matrix m for I=1:15 % rotate and capture each frame view(-37.5+24*(i-1),30) % change viewpoint for this frame m(:,i)=getframe; % add figure to frame matrix end movie(m) % play the movie! 注意到动画中的每一帧在帧矩阵中占据一个不同的列。帧矩阵的大小随着动画中的帧数和图形窗口的大小而增加,而与所绘图形的复杂性无关,这是因为函数getframe仅仅是捕捉位图。按缺省,函数movie只放一遍动画。通过加入其它输入参量,它可以向前放、向后倒放、放指定次数或按特定的桢速率播放。关于这些特征的详细信息,参阅MATLAB参考指南或使用在线帮助。 由于上述的动画制作策略很有用,它已体现在精通MATLAB工具箱的函数mmspin3d中。 function M=mmspin3d(n) % MMSPIN3D Make Movie by 3D Azimuth Rotation of Current Figure. % MMSPIN3D(N) captures and plays N frames of the current figure % through one rotation about the Z-axis at the current elevation. % M=MMSPIN3D(N) returns the movie in M for later playing with movie. % If not given,N=18 is used. % MMSPIN3D fixes the axis limits and issues axis off. % Copyright (c) 1996 by Prentice-Hall,Inc. if nargin<1,n=18;end n=max(abs(round(n)),2); axis(axis); axis off incaz=round(360/n); [az,el]=view; m=movie(n); for i=1:n view(az+incaz*(i-1),el) m(:,i)=getframe; end if nargout, M=m; else, movie(m); end 使用mmspin3d,上述脚本简化如下: % movie-making example:rotate a 3-D surface plot [X,Y,Z]=peaks(30); % create data surfl(X,Y,Z) % plot surface with lighting shading interp % make it pretty with interpolated shading colormap(hot) % choose a good colormap for lighting mmspin3d(15) 18.11 小结 本章所讨论的函数和它们的特征总结在表18.2、表18.3、表18.4和表18.5中: 表18.2 三维绘图函数  contour 二维等值线图,即从上向下看contour3等值线图  contour3 等值线图  fill3 填充的多边形  mesh 网格图  meshc 具有基本等值线图的网格图  meshz 有零平面的网格图  pcolor 二维伪彩色绘图,即从上向下看surf图  plot3 直线图  quiver 二维带方向箭头的速度图  surf 曲面图  surfc 具有基本等值线图的曲面图  surfl 带亮度的曲面图  waterfall 无交叉线的网格图   表示18-3 三维绘图工具  axis 修正坐标轴属性  clf 清除图形窗口  clabel 放置等值线标签  close 关闭图形窗口  figure 创建或选择图形窗口  getframe 捕捉动画桢  grid 放置网格  griddata 对画图用的数据进行内插  hidden 隐蔽网格图线条  hold 保留当前图形  meshgrid 产生三维绘图数据  movie 放动画  moviein 创建桢矩阵,存储动画  shading 在曲面图和伪彩色图中用分块、平滑和插值加阴影  subplot 在图形窗口内画子图  text 在指定的位置放文本  title 放置标题  view 改变图形的视角  xlabel 放置x轴标记  ylabel 放置y轴标记  zlabel 放置z轴标记   表18.4 函数view  view(az,el) 设置视图的方位角az和仰角el  view([az,el])   view([x,y,z]) 在笛卡儿坐标系中沿向量[x,y,z]正视原点设置视图,例如view([0 0 1])=view(0,90)  view(2) 设置缺省的二维视图,az=0,el=90  view(3) 设置缺省的三维视图,az=-37.5,el=30  [az,el]=view 返回当前的方位角az和仰角el  view(T) 用一个4×4的转置矩阵T来设置视图  T=view 返回当前的4×4转置矩阵   表18.5 掌握MATLAB高级图形功能  mmcont2(X,Y,Z,C) 具有颜色映象的二维等值线图  mmcont3(X,Y,Z,C) 具有颜色映象的三维等值线图  mmspin3d(N) 旋转当前图形的三维方位角来制作动画  mmview3d 用滑标来调整视角   关键词索引 chap 18 pcolor 伪彩色 3-D helix 三维螺旋线 3-D grid 三维网格 subplot 子图 Figure 图形窗口 viewpoint 视角 elevation 仰角 azimuth 方位角 Handle Graphics 句柄图形 slider 滑标 plaid 方格 mesh plots 网格图 mesh surface 网状曲面 surface 曲面图 contour plot 等值线图 zero plane 零平面 patch 补片 flat shading 平滑加色彩 interpolated shading 插值加色彩 progression 级差 color map 颜色映象 directional or velocity arrows 方向或速度箭头 movie 动画 frame 帧 underlying contour plot 基本等值线图