利用MATLAB绘制更好看的向量图
Matlab的基本数据单位是矩阵,利用Matlab可以较方便得绘制向量分布图,比如空气流的采样数据;函数的梯度;曲面的法线向量等等。Matlab自带的quiver和quiver3函数可以满足这一需求,但是箭头的箭型较为简单,这里主要目的即是进一步绘制更好看的矢量图。
MATLAB向量图函数quiver
Matlab中自带的quiver和quiver3函数能够绘制简单的向量图,基本语法为quiver(X,Y,U,V),quiver3(X,Y,Z,U,V,W), 在由 X 和 Y 指定的笛卡尔坐标上绘制具有定向分量 U 和 V 的箭头。调整箭头的长度,设置线型、标记和颜色等语法参考MATLAB帮助中心.
示例1.(来源MATLAB帮助中心)
绘制函数
z
=
x
e
−
x
2
−
y
2
z=xe^{-x^2-y^2}
z=xe−x2−y2的梯度和等高线。
首先,创建一个由等间距的
x
x
x 和
y
y
y 值组成的网格。使用它们来计算
z
z
z。然后,通过指定点之间的间距,求得
z
z
z 的梯度。代码片
spacing = 0.2;
[X,Y] = meshgrid(-2:spacing:2);
Z = X.*exp(-X.^2 - Y.^2);
[DX,DY] = gradient(Z,spacing);
将梯度向量显示为一个箭头图。然后,在相同的坐标区中显示等高线。通过调用 axis equal,调整显示以使梯度向量垂直于等高线。代码片
quiver(X,Y,DX,DY)
hold on
contour(X,Y,Z)
axis equal
hold off
示例2.(来源MATLAB帮助中心)
绘制垂直于由函数
z
=
x
e
−
x
2
−
y
2
z=xe^{-x^2-y^2}
z=xe−x2−y2 定义的曲面的向量。
首先,创建一个由等间距的
x
x
x 和
y
y
y 值组成的网格。使用它们来计算
z
z
z。然后,求法向量。代码片
[X,Y] = meshgrid(-2:0.25:2,-1:0.2:1);
Z = X.*exp(-X.^2 - Y.^2);
[U,V,W] = surfnorm(X,Y,Z);
将向量显示为一个三维箭头图。然后,在相同的坐标区中显示曲面。通过调用 axis equal,调整显示,使向量显示为垂直于曲面。代码片
quiver3(X,Y,Z,U,V,W)
hold on
surf(X,Y,Z)
axis equal
MATLAB绘制3D箭头
这里我们首先写一个简单的绘制3D箭头的函数,输入箭头的位置(a,b,c)与朝向(alpha,beta,gamma),在坐标区中返回三维箭头,内部且可控制箭头的大小形状颜色等参数。箭头由四部分组成:圆锥侧面+圆柱侧面+圆锥底面+圆锥底面。因此输出我们设置四部分s1,s2,s3,s4。
函数表达式如下代码片
function [s1,s2,s3,s4] = quiver_Refine(a,b,c,alpha,beta,gamma)
...
end
MATLAB绘制圆锤
首先绘制圆锥侧面以及圆锥底面:代码片
% Cone
r1 = 0:0.01:0.25; % The cone radius
h1 = 0.5; % The cone height
% The cone top position
a1 = a;
b1 = b;
c1 = 0.5;
% Generate cone data
[u,v,w] = cylinder(r1,50);
u = u+a1;
v = v+b1;
w = -w*h1+c1+c;
% Cone botton
t1 = (0:0.04:2)*pi;
r = max(r1(:));
xc = a1;
yc = b1;
zc = c1-h1+c;
% Generate cone botton data
x1 = xc + cos(t1)*r;
y1 = yc + sin(t1)*r;
[m,n] = size(x1);
z1 = repmat(zc,m,n);
后边利用surf函数绘制圆锤侧面;利用fill3绘制圆锥底面
MATLAB绘制圆柱
然后绘制圆柱侧面以及圆柱底面,且圆柱顶部位置连接在圆锥底部:代码片
% Cylinder
r2 = 0.1; % The cylinder radius
h2 = 0.5; % The cylinder height
% The cylinder top position
a2 = a1;
b2 = b1;
c2 = c1-h1;
% Generate cylinder data
[x,y,z] = cylinder(r2,50);
x = x+a2;
y = y+b2;
z = -z*h2+c2+c;
% Cylinder botton
t2 = (0:0.04:2)*pi;
r = r2;
xc = a2;
yc = b2;
zc = c2-h2+c;
% Generate cylinder botton data
x2 = xc + cos(t2)*r;
y2 = yc + sin(t2)*r;
[m,n] = size(x2);
z2 = repmat(zc,m,n);
利用利用surf函数绘制圆锤圆柱侧面;利用fill3绘制圆锥圆柱底面代码片
%plot
s1 = surf(u,v,w,'Facecolor',color,'Edgecolor','none');
s2 = surf(x,y,z,'Facecolor',color,'Edgecolor','none');
s3 = fill3(x1,y1,z1,color,'Edgecolor','none');
s4 = fill3(x2,y2,z2,color,'Edgecolor','none');
这里已经可以画出来一个完整的箭头了,位置由(a,b,c)决定,此时方向默认沿 + z +z +z方向即(0,0,1)方向,颜色由color变量决定。
箭头的方向与颜色控制
箭头的方向控制利用rotate函数实现。代码片
% Rotate arrow
zc = (c1+zc)/2;
hold on
origin = [xc,yc,zc];
theta2 = acos(gamma./sqrt(alpha.^2 + beta.^2 + gamma.^2));
if beta^2 + alpha^2 == 0
direct = [0 1 0];
else
direct = [-beta,alpha,0];
end
然后对之前的箭头的四部分分量分别进行坐标变换即可代码片
if theta2 ~= 0
rotate(s1,direct,rad2deg(theta2),origin);
rotate(s2,direct,rad2deg(theta2),origin);
rotate(s3,direct,rad2deg(theta2),origin);
rotate(s4,direct,rad2deg(theta2),origin);
end
箭头的颜色控制可以自定义color变量的构成,比如这里将箭头在
x
y
xy
xy面内的方位角
ϕ
\phi
ϕ与色环colorwheel绑定,极角
θ
\theta
θ与亮度intensity绑定。即颜色HSL空间中
H
S
L
HSL
HSL三分量与
α
\alpha
α,
β
\beta
β,
γ
\gamma
γ对应
代码片
% control quiver color using HSL
H = atan2(beta,alpha);
% Get the atan2 space in 0 ~ 2*pi
if H < 0
H = 2*pi+H;
end
% rotate clockwisely
H = H + theta/180*pi;
if H < 0
H = H + 2*pi;
elseif H >2*pi
H = H - 2*pi;
end
S = sqrt(1-gamma^2);
I = (gamma+1)/2;
% change HSL to RGB
idx = find((0 <= H)&(H < 2*pi/3));
B(idx) = I(idx).*(1-S(idx));
R(idx) = I(idx).*(1+S(idx).*cos(H(idx))./cos(pi/3-H(idx)));
G(idx) = 3*I(idx)-(B(idx)+R(idx));
idx = find((2*pi/3 <= H)&(H < 4*pi/3));
R(idx) = I(idx).*(1-S(idx));
G(idx) = I(idx).*(1+S(idx).*cos(H(idx)-2*pi/3)./cos(pi-H(idx)));
B(idx) = 3*I(idx)-(G(idx)+R(idx));
idx = find((4*pi/3 <= H)&(H <= 2*pi));
G(idx) = I(idx).*(1-S(idx));
B(idx) = I(idx).*(1+S(idx).*cos(H(idx)-4*pi/3)./cos(5*pi/3-H(idx)));
R(idx) = 3*I(idx)-(G(idx)+B(idx));
color = [R G B];
color(isnan(color)) = 0;
% Get color in the right range
for i=1:3
color(i)=max(min(color(i),1),0);
end
这里由于MATLAB中颜色解释为RGB,需要额外从HSL空间变换至RGB空间。其实也可以通过hsv2rgb函数实现。
光照参数调节
MATLAB具有完整的一套光照参数设置,图形提供的功能类似于带变焦镜头的相机,可控制由 MATLAB创建的场景视图,详情请参阅相机图形术语。MATLAB图形环境提供的命令允许放置光源并调整反射光线的对象的特性,详情请参阅光照概述。这里我们可以控制光照来使得箭头看起来更立体些。代码片
% lighting settings
axis equal
camlight('left');
lighting phong
view(3)
新quiver效果展示
有了以上设置后我们可以来调试下自己的quiver_Refine函数:
quiver_Refine(0,0,0,1,0,0);quiver_Refine(0,0,0,-1,0,0);
quiver_Refine(0,0,0,0,1,0);quiver_Refine(0,0,0,0,-1,0);
文章来源:https://www.toymoban.com/news/detail-420480.html
位置/方向矩阵输入后效果展示
目前的quiver_Refine版本只支持输入单个位置的数据,需要利用for循环不断调用,运行速度较慢,不过最后结果看上去比原quiver函数要更好看一点。这里以Bloch-Skyrmion为例,把Colorwheel顺时针旋转120°后将quiver染上色,嗯还挺好看的。
文章来源地址https://www.toymoban.com/news/detail-420480.html
到了这里,关于优化MATLAB中quiver函数绘制箭头图或矢量图(1)-MATLAB开发的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!