1.问题的灵感
最近在浏览Imaginary的主页,遇到一个比较漂亮的集合图形,如下所示:
突发奇想,在Matlab下怎样画出它的图形呢?既然给自己挖了这么一个坑,那就勇敢的走下去!看看究竟怎样解决!
2.遇到的问题
2.1用什么函数绘制
首先,柠檬的方程Imaginary上面已经提供了,但是是个隐式方程:
首先我想到的是plot3或者ezplot这样的函数,可是plot3更倾向于把矩阵对应列向量的点用直线连接起来( 当然如果是行向量就另当别论了,而且是隐式方程)。ezplot则适用于平面图形。看来这个形状的绘制的“坑”需要深挖一下了。
2.2命令的使用
上面的方程告诉我这个曲面应该是一个旋转曲面。对于旋转曲面问题,surf或者是mesh函数应该合适的。既然是旋转曲面,考虑柱坐标方程(Matlab命令Cylinder
)或者球面方程(Matlab命令Sphere
)的形式进行表达。
2.3具体代码
最开始并不知道具体的x值得范围,可以考虑采取试错的方式不断探索。
x=-0.5:0.05:1.05;%不断试错得到的一个恰当的范围
r=real(sqrt(x.^3.*(1-x).^3));%设置x-y平面上的母线方程r
[a,b,c]=cylinder(r,30);%以r为母线(profile curve),一周30个等距间隔的单位柱面
mesh(a,b,c);
得到的图形如下:
3. 一些改进
3.1 Beta版
首先,我不满意的是这是一个网格图形,希望能够使用光滑的曲面表示它。其次,cylinder
函数默认旋转对称轴是z轴。而且坐标c的范围是[-1,1]之间。这都限制了图形的表达能力。网上查了一些资料,往往说的是采用remat
,reshape
等函数将cylinder
后的的坐标矩阵进行旋转操作,很是繁琐。Matlab的用户往往都是本着“少花钱、多办事”的态度。省时省力,能借助于内置函数绝不自己DIY的精神。继续寻找互联网资源,在stackflow
上找到了一段这样的解决方案:
说白了就是利用句柄实现对已生成的图像进行适当的旋转,rotate()
命令按照指定的向量方向,按照指定的角度旋转图像。这个风格正中我意!走着!
因而得到了代码的beta version:
x=-0.5:0.05:1.05;
r=real(sqrt(x.^3.*(1-x).^3));[a,b,c]=cylinder(r,30);
c=c*0.75;%对C矩阵可以进行适当的缩放
figure(),title('Lemon Surface');
hSurface=surf(a,b,c);%hSurface用来存储句柄
rotate(hSurface,[1 0 0],90);对句柄中的数据进行指定的旋转
3.2 问题的细化
当然,你也可以对曲面的颜色、光照、坐标比率等信息进行指定,比如
set(hSurface,'FaceColor',[1,1,0],'FaceAlpha',0.5);%还是句柄,FaceAlpha指定的是曲面的色彩透明度
axis equal tight vis3d
最终得到的效果图(样子还是很丑,敬请原谅):
对应的代码最终版(Gamma version)
close all;
clear all;
clc;
x=-0.5:0.05:1.05;
r=real(sqrt(x.^3.*(1-x).^3));
[a,b,c]=cylinder(r,30);
c=c*0.75;
figure(),title('Lemon Surface');
hSurface=surfl(a,b,c);%注意surfl()可以指定光照的效果
rotate(hSurface,[1 0 0],90);
shading interp
light('Position',[0 0 1],'Style','local')%指定光源的位置,照射方式
set(hSurface,'FaceColor',[1,1,0],'FaceAlpha',0.75);
axis equal tight vis3d %设定坐标表现形式
谢谢大家观赏!
参考网页
2.http://cn.mathworks.com/help/matlab/ref/cylinder.html?refresh=true
3.http://blog.csdn.net/pdcxs007/article/details/8816109