图形三维立体可视化在Matlab中的实现和处理
三维图形的绘制除了常用的网格图、表面图和等高线等方法外,Matlab还提供了一些立体可视化函数用于绘制更为复杂的立体和向量对象。
这些函数通常在三维空间中构建标量和向量的图形:
由于这些函数构建的[b][color=red]是立体而不是一个简单的曲面[/color][/b],因此它们需要三维数组作为参数,其中三维数组的每一维分别代表一个坐标轴,三维数组中的点定义了坐标轴栅格和坐标轴上的坐标点。
[b][color=blue][size=4]所谓标量图形[/size][/color][/b],就是由一个数学表达式所确定的三维立体图形,比如V=sqrt(X^2+cos(Y)^2+Z^2)+Z,当V取不同值时的图像。像这样的隐式三维图形在Matlab中是没法直接绘制的。感兴趣的网友可以看看这个帖中对隐函数绘图的讨论
如果要绘制的函数是一个标量函数,则绘制函数需要4个三维数组,其中3个数组各代表一个坐标轴,第四个数组代表了这些处的标量数据,这些数组通常记做X、Y、Z和V。
[b][size=4][color=blue]所谓向量图[/color][/size][/b],就是在图形在满足某个方程同时,还具有方向性,比如散度(divergence)、旋度(curl),梯度(gradient)等
如果要绘制的函数是一个向量函数,则需要6个三维数组,其中3个各表示一个坐标轴,剩下3个用来表示坐标点处的向量,这些数组通常记做X、Y、Z、U、V和W。
要正确合理的使用Matlab提供的立体和向量可视化函数,我们必须对与立体和向量有关的一些术语有所了解。
比如散度(divergence)、旋度(curl)等用于描述向量过程,而等值面(isosurfaces)和等值顶(isocaps)则用于描述立体的视觉外观。
如果我们要生成和处理比较复杂的立体对象,就需要参考相应的文献对这些术语进行深入的了解。
[b][color=blue]由于向量立体可视化,具有相当的专业背景,比如:流体力学,空气动力学,场论和矢量等,故下面我们只是介绍[color=Red]标量三维立体可视化[/color],感兴趣的网友可以直接查看Matlab的帮助文档[/color][/b]
在下面的内容我们主要介绍以下内容:
2# 如何生成三维立体数据
3# 三维立体截面图
4# 三维立体等值面
5# 三维立体数据平滑化
如何生成三维立体数据
我们考查如下三维立体图形的性质
V=v=f(x,y,z)=(x+y+z)(xy+xz+yz)-10xyz
当V取不同值时,会对应不同的[b][color=red]曲面图形[/color][/b],但是假如说我们将V取为[b][color=red]一个区间的连续值[/color][/b]时,那么就得到了一个由许多曲面构成的[b][color=red]三维立体[/color][/b]了
我们现在感兴趣的就是那个由许多曲面组成的[b][color=red]三维立体[/color][/b],因为Matlab为它们提供了相关的直接的函数
但是有时我们不对整个立体感兴趣,[b][color=red]只对某个曲面感兴趣[/color][/b],问题就出在这里,Matlab中[b][color=red]没有提供[/color][/b]三维隐函数绘图的直接函数,但是我们可以间接的获得,那就是从立体中截取出某个我们感兴趣的曲面,[color=blue]这就是说Matlab对三维曲面的可视化(特别是隐式的)必须先立体化处理,然后再截取我们感兴趣的[/color]
下面我们看一个利用上面提到的标量函数构建立体图形的例子。首先,我们必须生成一个构建立体对象的坐标系:
[code]x=0:0.5:10;
y=x;
z=x;
[X,Y,Z]=meshgrid(x,y,z);[/code]
上面的代码演示使用meshgrid函数在三维空间中的应用。其中XYZ为定义栅格的3个三维数组,它们是由xyz经过三维栅格扩展形成的。也就是说,X是将x复制扩展成具有length(y)行和length(z)页的三维数组;Y是先将y转置为一个列向量,然后复制扩展成为具有length(x)列和length(z)页的三维数组;Z则是先将z转换为1×1×length(z)的三维向量,然后扩展成为length(y)行和length(x)列的三维数组。
下面我们还需要定义一个以三维数组为自变量的标量函数V:
[code]V=(X+Y+Z).*(X.*Y+X.*Z+Y.*Z)-10*X.*Y.*Z;[/code]
好,[b][color=blue]这就得到立体可视化的需要的数据X、Y、Z和V了[/color][/b],下面就是对我们感兴趣的部分或者曲面进行可视化和处理了
三维立体截面图
在2#中我们利用标量函数v=f(x,y,z)=(x+y+z)(xy+xz+yz)-10xyz定义一个立体对象,并准备所需的所有数据,为了使该立体对象可视化,我们可以利用下面的命令查看该立体对象的一些截面。
V=(x+y+z)(xy+xz+yz)-10xyz=0的图形大概如下:
[align=center][attach]1187[/attach][/align]
[align=center][attach]1188[/attach][/align]
[align=center][b][size=5][color=blue]三维立体平面截取[/color][/size][/b][/align][code]slice(X,Y,Z,V,[6 8],[5 9],[3 5])%截取x=6和8,y=5和9,z=3和5等6个截面视图
xlabel('x')
ylabel('y')
zlabel('z')[/code]
[align=center][attach]1184[/attach][/align]
从图中我们可以看到命令为我们截取x=6和8,y=5和9,z=3和5等6个截面视图,注意图中的颜色是根据V的自动绘制的。
[align=center][b][size=5][color=blue]立体三维曲面截取[/color][/size][/b][/align]
在上面我们演示了立体图形的平面截面,在立体图像中,也可以显示立体图形的曲面截面。[code][xs,ys]=meshgrid(x,y);
zs=sin(-xs+ys/2);
slice(X,Y,Z,V,xs,ys,zs)%采用正弦函数截取立体图形的截面,也就是截取满足方程z=sin(-x+y/2)的曲面
xlabel('x')
ylabel('y')
zlabel('z')
[/code][align=center][attach]1185[/attach][/align]
[align=center][b][size=5][color=blue]截面等高线绘制[/color][/size][/b][/align]
除了截图平面和曲面以外,还可以使用contourslice函数为截取的平面添加等高线[code]slice(X,Y,Z,V,[7 3],[5 9],[3 5])
hold on
h=contourslice(X,Y,Z,V,7,[5 9],5);%在x=7,y=5和9,z=5截面上添加等高线
set(h,'edgecolor','k','linewidth',1.5)%设置等高线的的颜色和线宽
xlabel('x')
ylabel('y')
zlabel('z')[/code][align=center][attach]1189[/attach][/align]
三维立体等值面图——三维隐函数绘图
我们总是骂mathworks真是该死,什么函数只要能想得到的就一定有,可以却偏偏没有提供三维隐函数的绘图
呵呵其实,Matlab虽然没有提供直接的绘制三维隐函数图形的函数,但是我们可以使用[b][color=Red]等值面[/color][/b]图来绘制
[b][color=Blue][size=4]所谓等值面图[/size][/color][/b],就是V=f(X,Y,Z)=C,这个C的值确定的时候的曲面图形,它只是三维立体V中的一个曲面而=,相当于3#的截取了一个特殊的曲面而已
除了查看立体对象的截面之外,寻找使V等于某个特定值的表面(等值面),也十分常见。在Matlab中,这以操作可以使用isosurface()函数来实现,该函数与delaunay函数类似,也是返回若干三角形的顶点。将isosurface函数返回的参数传递给patch函数,就可以绘制出有这些三角形构成的等值面了。[code][X,Y,Z,V]=flow(13);
fv=isosurface(X,Y,Z,V,-2);%显示V=-2等等值面
subplot(121)
p=patch(fv);
set(p,'facecolor',[0.5 0.5 0.5],'edgecolor','k');
view(3)
axis equal tight
grid on
subplot(122)
p=patch(shrinkfaces(fv,0.3));%shrinkfaces功能是使表面收缩
set(p,'facecolor',[0.5 0.5 0.5],'edgecolor','k');
view(3)
axis equal tight
grid on[/code][align=center][attach]1190[/attach][/align]
当我们显示的立体图形仅仅是为了观察大体结构时,就没有必要针对所有的数据点作图,因为数据点太多会降低显示速度。[color=Blue]利用Matlab中的reducevolume()和reducepatch()函数可以使用图形在显示之前删除一些数据点或者对一些图形显示影响很小的碎片,从而提高图形显示效率[/color]。
再比如说,我们要绘制三维隐函数x^2+y^2+z^2=5的球体的图形,由于Matlab没有提供直接的绘制三维隐函数图形的函数,故我们只能通过三维立体的等值面来截取,虽然绘制等值面比较麻烦且得到的图形不是很漂亮,但至少比没有好
[b]1、构建三维立体模型[/b]
V=X^2+Y^2+Z^2-5;
[b]2、获取三维立体数据[/b][code][X,Y,Z]=meshgrid(-10:0.5:10);
V=X.^2+Y.^2+Z.^2-5;[/code][b]3、绘制等值面[/b][code]%x^2+y^2+z^2=5相当于V=0的等值面
fv=isosurface(X,Y,Z,V,0);%显示V=0等等值面
p=patch(fv);
set(p,'FaceColor','red','EdgeColor','none');%设置图形的相关属性
view(3)
camlight
lighting gouraud
axis equal tight[/code][align=center][attach]1191[/attach][/align]
三维立体数据平滑化
三维数据也可以通过smooth3()函数来过滤而实现其平滑化[code]data=rand(10,10,10);
datas=smooth3(data,'box',3);%box是光滑方法,Matlab中提供可好几种方法,具体查看帮助
subplot(121)
p=patch(isosurface(data,0.5));
patch(isocaps(data,0.5));
isonormals(data,p);
camlight
lighting phong
axis vis3d off
view(3)
subplot(122)
p=patch(isosurface(datas,0.5));
patch(isocaps(datas,0.5));
isonormals(datas,p);
camlight
lighting phong
axis vis3d off
view(3)[/code]上面用到的isocaps和isonormals函数的用法如下:
isocaps生成块状图的外层表面,而isonormals调整所画碎片的属性,使所显示的图形有正确的光照效果