规则网格曲面着色

可以通过给网格图和曲面图着色来增强它们的表现力。MATLAB可以将特定数据值映射给指定的颜色,或者可以将整个范围内的数据映射给名为颜色图的预定义范围内的颜色。[大谦MATLAB,dqmatlab点com]

MATLAB主要采用了3种着色技术,即索引着色、真彩色着色和纹理映射。

索引着色—MATLAB通过给每个数据点一个索引值来建立与图形颜色图之间的映射关系。MATLAB应用这些颜色的方式与着色类型即采用平面着色、刻面着色还是插值着色有关。

真彩色着色—MATLAB用分别指定的颜色(即RGB分量)对曲面图进行着色。MATLAB应用这些颜色的方式与着色类型即是平面着色、刻面着色还是插值着色有关。要想精确地进行渲染,需要计算机具备24位的显示能力。

纹理映射—纹理映射将一幅二维图像映射到三维曲面上。

颜色数据的类型确定MATLAB选择什么样的技术进行着色。创建曲面图时,如果没有提供颜色数据,MATLAB根据z值生成颜色图的索引值;如果指定一个颜色数据数组,其大小与z数据的相同,使用索引着色;如果指定一个m×n×3的颜色数据数组,为m×n数据数组中的每个元素定义一个RGB颜色分量,使用真彩色着色。

颜色图

每个MATLAB图形窗口都有一个颜色图与之相连。颜色图是一个3列矩阵,其长度等于它定义的颜色数目。矩阵的每一行指定3个0和1之间的值,定义一种颜色。这些值定义RGB分量,即红色、绿色和兰色组分的强度。

使用没有变量的colormap函数可以返回当前图形的颜色图。例如,MATLAB默认的颜色图包括64种颜色,第57种是红色。

code.matlab
>> cm=colormap;
>> cm(57,:)
ans=
1 0 0

表21中列出了一些颜色的RGB定义。

表2-1 一些颜色的RGB定义

绿 颜 色
0 0 0 黑色
1 1 1 白色
1 0 0 红色
0 1 0 绿色
0 0 1 兰色
1 1 0 黄色
1 0 1 粉红
0 1 1 青色
0.5 0.5 0.5 灰色
0.5 0 0 深红色
1 0.62 0.40 紫铜色
0.49 1 0.83 碧绿色

可以通过MATLAB数组操作或生成任何有用映射,包括hsv,hot,cool,summer和gray等的函数创建颜色图。每个函数有一个可选参数,它指定生成的颜色图的行数。例如

code.matlab
hot(m)

创建一个m×3的矩阵,它的行指定一个颜色图所表示的颜色的RGB分量。这个颜色图所表示的颜色从黑色变为红色、橘红、黄色,直至白色。

如果不指定颜色图的长度,MATLAB会创建与当前颜色图长度相同的颜色图。如果在每个图形窗口中使用长颜色图(>64色),对于操作系统来说,当激活焦点在窗口内移动时在不同颜色图中进行交换是必要的。

MATLAB支持下面一些颜色图函数:

autumn 从红色向橘黄色、黄色平稳过渡。

bone 为含有较高的兰色组分的gray颜色图。

colorcube 该函数包含RGB颜色空间中尽可能多的规则间隔的颜色,它试图提供更多的灰色、纯红、纯绿和纯蓝。

cool 由青色和洋红阴影组成的颜色。它在青色和洋红之间平滑过渡。

copper 在黑色和亮铜色之间平滑过渡。

flag 由红色、白色、兰色和黑色组成。每次索引值增加时,该颜色图会完全改变颜色。

gray 返回线性灰阶颜色图。

hot 在黑色、红色、橘红色、黄色和白色之间平滑过渡。

hsv 变化HSV颜色模型中的色度组分。颜色从红色开始,然后为黄色、绿色、青色、兰色、洋红,最后返回到红色。该颜色图特别适合于显示周期性函数。hsv(m) 与 hsv2rgb([h ones(m,2)])相同,其中h 为线性梯度,h=(0:m-1)'/m。

jet 在兰色、青色、黄色、橘红色、红色之间过渡。由hsv颜色图变化而来。

lines 生成颜色由坐标系对象的ColorOrder属性和灰色阴影确定的颜色图。

pink 包含品红色的柔和阴影。该颜色图使得可以对灰度照片进行棕褐色化。

prism 重复红色、橘红色、黄色、绿色、兰色和紫色等六种颜色。

spring 由洋红和黄色阴影组成。

summer 由绿色和黄色阴影组成。

white白色色图。

winter 由兰色和绿色阴影组成。

colorbar函数在图形窗口中显示当前的颜色图所表示的颜色,它或者垂直或者水平地显示在图形旁边。

下面绘制曲面图并用cool颜色图进行着色。

code.matlab
>> [x,y]=meshgrid(-3:1/5:3);
>> z=peaks(x,y);
>> surfl(x,y,z);
>> shading interp
>> colormap cool

生成图2-1。

用jet颜色图进行着色。

code.matlab
>> colormap jet

生成图2-2。

Document Image Document Image
\[\]

图2-1 用cool颜色图着色 图2-2 用jet颜色图着色

下面的语句生成一个曲面图和一个垂直的色条,该条形图对应于当前的颜色图。注意色条是如何用坐标轴标签值(作为索引值)表现数据值与颜色之间的映射关系的。

code.matlab
>> [x,y]=meshgrid([-2:.2:2]);
>> Z=x.*exp(-x.^1-y.^2);
>> surf(x,y,Z,gradient(Z))
>> colorbar

生成的图形如图2-3所示。

Document Image
\[\]

图2-3 用色条表示颜色图中的颜色

为了方便设置图形的颜色图,MATLAB提供了一个颜色图编辑器。用colormapeditor命令启动颜色图编辑器,并在编辑器中显示当前图形窗口的颜色图。如下所示,在命令窗口键入:

code.matlab
>> colormapeditor

打开“颜色图编辑器”窗口,如图2-4所示。

Document Image
\[\]

图2-4“颜色图编辑器”窗口

编辑器中,当前图形窗口颜色图中的颜色用一个横向的色条表示。在“指定颜色”选项卡中,色条上方有几个节点指针,移动节点指针,可以改变颜色图中的颜色范围,并改变当前图形的显示。在“颜色图”下拉式列表框中选择颜色图。方框中显示颜色的索引值和颜色数据。在“编辑大小和颜色空间”下拉式列表框中进行选择,可以转换颜色空间,这里提供了RGB和HSV两种颜色空间。在“设置颜色图范围”下拉式列表框中可以指定颜色图范围的最小值和最大值。

选择和移动节点指针,可以改变颜色图中颜色的范围。编辑器会在两个节点指针之间进行颜色插值。双击节点指针,并在弹出的颜色选择器中进行选择,可以改变节点单元的颜色。改变节点颜色以后,根据相邻节点的颜色重新进行插值计算。针对节点指针有多种操作,如表2-2所示。

表2-2 针对节点的操作说明

操 作 说 明
添加一个节点 在对应的节点单元下方单击
选择一个节点 单击节点
移动一个节点 用鼠标选择或拖拉节点,或者选择节点并单击向左或向右键
删除一个节点 选择节点,然后单击Delete键
显示节点的颜色选择器 双击节点

在命令窗口键入下面的命令行:

code.matlab
>> [x,y,z]=peaks(30);
>> surf(x,y,z)

生成图2-5。这是使用默认的颜色图得到的曲面图。

Document Image
\[\]

图2-5 使用默认的颜色图

用colormapeditor命令启动颜色图编辑器,在颜色图编辑器中重新设置颜色,如图2-6所示,图2-5随即变成图2-7所示的颜色。

Document Image
\[\]

图2-6 在颜色图编辑器中调整颜色

Document Image
\[\]

图2-7 调整颜色图以后的图形显示

索引着色

索引着色有两张表,一张表表示索引值及其对应的颜色,另一张表表示着色对象及其对应的索引值,结合两张表就可以给对象着色。MATLAB可以使用两种不同的方法将索引颜色数据映射到颜色图,即直接映射和比例化映射。

直接映射是直接将颜色数据作为索引值进行映射。例如,值1指向颜色图中的第1种颜色,值2指向第2种颜色,如此类推。如果颜色数据不是非整型的,则MATLAB将它圆整到0。大于颜色图中的颜色个数的值设置为等于颜色图中的最后一种颜色。小于1的值设置为1。

比例化映射用一个2元素矢量[cmin cmax]控制颜色数据向图形颜色图的映射。cmin指定将数据值映射到颜色图中的第一种颜色,cmax指定将数据值映射到颜色图中的最后一种颜色。cmin和cmax之间的数据值线性映射到表中第一种和最后一种之间的颜色。可以用下面的表达式表示:

code.matlab
colormap_index=fix((color_data-cmin)/(cmax-cmin)*cm_length)+1

其中,cm_length是颜色图的长度。

默认时,MATLAB设置cmin和cmax时会包括所有图形对象的颜色数据。但是也可以设置为其他范围。这样,可以在一个图形窗口中显示多个坐标系,以及用颜色图的不同部分显示各个坐标系。

默认时,MATLAB使用比例化映射。使用直接映射,必须在创建图形时取消比例化。例如:

code.matlab
surf(Z,C,'CDataMapping','direct')

用单个矩阵变量创建曲面图时,比如surf(Z),其中参数Z同时指定高度和曲面颜色,MATLAB会对Z进行转换,以获取进入当前颜色图的索引值。

也可以使用两个矩阵参数,如下面的语句用第2个变量单独指定颜色。

code.matlab
surf(Z,C)

曲面曲率向颜色映射。

曲面图的拉普拉斯算子与它的曲率有关,对于生成类似函数i^2+j^2确定的形状的函数,该算子为正;对于生成类似函数-(i^2+j^2)确定的形状的函数,该算子为负。函数del2计算任何矩阵的离散拉普拉斯算子。例如,下面用del2函数确定peaks函数返回的数据的颜色。

code.matlab
>> P=peaks(40);
>> C=del2(P);
>> surf(P,C)
>> colormap hot

生成的图形如图2-8所示。通过将拉普拉斯算子用于数据来创建颜色数组很有用,因为它会使得具有相似曲率的区域用相同的颜色进行描绘。

Document Image Document Image
\[\]

图2-8 生成的曲面图 图2-9 修改颜色后的曲面图

试将图2-8与下面语句生成的曲面图进行比较,它使用了相同的颜色图,但是将z值相近的区域映射为具有相同的颜色。

code.matlab
>> surf(P)
>> colormap hot

生成图2-9。

真彩色着色

24位显示的计算机系统可以显示超过1600万种颜色。有了这种能力,可以将颜色数据直接定义成RGB值,而不需要用索引值进行颜色映射。RGB值包括颜色的红色分量、绿色分量和兰色分量。

如图2-10所示,用一个m×n×3的数组指定真彩色,其中z的大小为m×n。图中左图为定义曲面图的矩阵,右图为定义该图RGB值的矩阵。

Document Image
\[\]

图2-10 定义曲面图及其真彩色的矩阵

下面的语句用peaks矩阵数据创建一个随机着色的曲面图。

code.matlab
>> Z=peaks(25);
>> C(:,:,1)=rand(25);
>> C(:,:,2)=rand(25);
>> C(:,:,3)=rand(25);
>> surf(Z,C)

效果如图2-11所示。

Document Image Document Image
\[\]

图2-11 一个随机着色的曲面图 图2-12 用索引值设置曲面属性

也可以用索引值设置曲面属性,如下面进行插值着色并添加Phong光照。

code.matlab
>> surf(Z,C,'FaceColor','interp','FaceLighting','phong')
>> camlight right

绘图效果如图2-12所示。

显示真彩色图形时,MATLAB总是使用OpenGL或zbuffer渲染法。如果Figure对象的RendererMode属性设置为auto,则不管什么时候指定真彩色数据,MATLAB会自动将Renderer属性的值转换为zbuffer。

如果将Renderer属性设置为Painters,并试图用真彩色定义一个图像、面片或Surface对象,则MATLAB会返回一个警告信息并不对对象进行渲染。

规则网格曲面着色:纹理映射

纹理映射技术通过变换颜色数据将二维图像映射到三维曲面上。它允许颜色数据数组的维数与定义曲面图的数据不同。可以将图像映射到任意大小的曲面上。MATLAB会对纹理颜色数据进行插值,使它可以映射到整个曲面上。

下面的例子用sphere函数创建一个球形曲面,然后将一个图片映射到这个曲面上。

code.matlab
>> C=imread('d:\pic.jpg');
>> [x,y,z]=sphere;
>> surface(x,y,z,'CData',flipud(C),'FaceColor','texturemap')
>> axis equal
>> view([65 30])

纹理映射效果如图2-13所示。

Document Image
\[\]

图2-13 球体的纹理映射效果

多边形对象模型的着色

使用面片可以构造多边形对象模型,1.1.4小节介绍了二维面片的创建和着色。面片着色与Surface对象的着色方式不同,主要体现在面片不会根据每个顶点的z坐标自动生成颜色数据。用户必须另外对面片进行着色,否则MATLAB会用默认颜色进行绘制。

给面片着色,通常有3种方法:

给所有小面着一种颜色;

给每个小面着不同的颜色,用于刻面着色;

给每个顶点着一种颜色,用于插值着色。

多边形对象模型中面片的着色有两种方式,即索引着色方式和真彩色着色方式。MATLAB根据颜色数据的维数确定如何进行解释。如果每个面片、每个小面或每个顶点只指定1个数值值,则MATLAB将数据解释为索引颜色数据。如果每个面片、小面或顶点都有3个数值值,则MATLAB将数据解释为RGB值。

如果将x,y和z坐标变量指定为矢量,则MATLAB通过连接这些点来绘制单独的多边形。如果变量是矩阵,则MATLAB根据每列的数据绘一个多边形,用多个小面生成一个面片。这些小面不需要彼此连接并且可以是自相交的。

另外,也可以通过指定每个顶点的坐标和组成小面的连接顺序来生成面片。

下面的例子演示了这两种技巧。

1.用patch函数创建一个立方体

下面用顶点/小面方式创建一个白色立方体。

code.matlab
>> vert=[1 1 1;1 2 1;2 2 1;2 1 1;1 1 2;1 2 2;2 2 2;2 1 2];
>> fac=[1 2 3 4;2 6 7 3;4 3 7 8;1 5 8 4;1 2 6 5;5 6 7 8];
>> patch('Faces',fac,'Vertices',vert,'FaceColor','w');
>> view(3);
>> axis square;

结果如图2-14所示。

2.刻面着色

刻面着色是给每个小面指定一种颜色以后得到的一种视觉效果。例如,用顶点/小面方式和FaceVertexCData属性定义颜色,下面的语句给每个小面指定一种颜色,并将FaceColor属性的值设置为flat。

code.matlab
>> patch('faces',fac,'vertices',vert, 'FaceVertexCData',…
hsv(6),'FaceColor','flat');

因为FaceVertexCData属性指定的真实颜色与MATLAB颜色图具有相同的格式,即都是元素为RGB值的n×3的数组。刻面着色效果如图2-15所示。

Document Image Document Image
\[\]

图2-14 创建一个立方体 图2-15 刻面着色效果

3.插值着色

插值着色是利用每个小面顶点的颜色进行插值计算,得到小面各边和小面内部各点上的颜色值,然后进行着色。所以,进行插值着色,必须给每个顶点指定一种颜色,并设置FaceColor属性的值为interp,即

code.matlab
>> patch('faces',fac,'vertices',vert, 'FaceVertexCData',…
hsv(8),'FaceColor','interp');

生成的效果如图2-16所示。

Document Image
\[\]

图2-16 插值着色的效果

使用高级语法格式,用x,y,z和c参数可以进行同样的着色,其中,c必须是一个m×n×3的数组,x,y和z的维数为m×n。