Optimize the quiver function in MATLAB, draw arrow diagram or vector diagram - matlab development

Posted by tullmejs on Fri, 11 Feb 2022 05:07:15 +0100

Using MATLAB to draw a better vector diagram

The basic data unit of MATLAB is matrix. Using MATLAB, it is convenient to draw vector distribution map, such as the sampling data of air flow; Gradient of function; The normal vector of the surface, and so on. Matlab's built-in quiver and quiver3 functions can meet this demand, but the arrow type of the arrow is relatively simple. The main purpose here is to further draw a better vector graph.

MATLAB vector graph function quiver

The built-in functions of quiver and quiver3 in Matlab can draw simple vector graphs. The basic syntax is Quiver (x, Y, U, V) and quiver3 (x, Y, Z, U, V, w). Arrows with directional components U and V are drawn on the Cartesian coordinates specified by X and Y. Adjust the length of the arrow and set syntax references such as linetype, mark and color MATLAB Help Center.
Example 1 (source: MATLAB Help Center)
Draw function z = x e − x 2 − y 2 z=xe^{-x^2-y^2} Z = gradient and contour of Xe − x2 − y2.
First, create an equally spaced x x x and y y A grid of y values. Use them to calculate z z z. Then, by specifying the spacing between points, the z z The gradient of z.
Code slice

spacing = 0.2;
[X,Y] = meshgrid(-2:spacing:2);
Z = X.*exp(-X.^2 - Y.^2);
[DX,DY] = gradient(Z,spacing);

Displays the gradient vector as an arrow diagram. Then, the contour lines are displayed in the same coordinate area. Adjust the display so that the gradient vector is perpendicular to the contour by calling axis equal.
Code slice

quiver(X,Y,DX,DY)
hold on
contour(X,Y,Z)
axis equal
hold off

Example 2 (source: MATLAB Help Center)
Draw perpendicular to function z = x e − x 2 − y 2 z=xe^{-x^2-y^2} The vector of the surface defined by z=xe − x2 − y2.
First, create an equally spaced x x x and y y A grid of y values. Use them to calculate z z z. Then, find the normal vector.
Code slice

[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);

Displays the vector as a three-dimensional arrow diagram. Then, the surface is displayed in the same coordinate area. Adjust the display by calling axis equal so that the vector appears perpendicular to the surface.
Code slice

quiver3(X,Y,Z,U,V,W)
hold on
surf(X,Y,Z)
axis equal

Draw 3D arrow with MATLAB

Here, we first write a simple function to draw a 3D arrow, input the position (a,b,c) and orientation (alpha,beta,gamma) of the arrow, return the 3D arrow in the coordinate area, and control the size, shape, color and other parameters of the arrow. The arrow consists of four parts: conical side + cylindrical side + conical bottom + conical bottom. Therefore, we set four parts S1, S2, S3 and S4 for the output.
The function expression is as follows
Code slice

function [s1,s2,s3,s4] = quiver_Refine(a,b,c,alpha,beta,gamma)
...
end

Drawing circular hammer with MATLAB

First draw the side and bottom of the cone:
Code slice

% 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);

In the back, the surf function is used to draw the side of the round hammer; Drawing conical bottom with fill3

Drawing cylinder with MATLAB

Then draw the side of the cylinder and the bottom of the cylinder, and the position of the top of the cylinder is connected to the bottom of the cone:
Code slice

% 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);

Using surf function to draw the side of circular hammer cylinder; Drawing the bottom surface of conical cylinder with fill3
Code slice

%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 complete arrow can be drawn here. The position is determined by (a, b, c). At this time, the direction is along by default + z +z +The z direction is the (0, 0, 1) direction, and the color is determined by the color variable.

Arrow direction and color control

The direction control of the arrow is realized by the rotate function.
Code slice

% 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

Then, coordinate transformation can be carried out for the four components of the previous arrow
Code slice

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

The color control of the arrow can customize the composition of the color variable. For example, here the arrow is in x y xy Azimuth in xy plane ϕ \phi ϕ Binding with color ring colorwheel, polar angle θ \theta θ Bound to brightness intensity. Color is in HSL space H S L HSL HSL three components and α \alpha α, β \beta β, γ \gamma γ corresponding

Code slice

% 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

Here, because the color in MATLAB is interpreted as RGB, it needs to be transformed from HSL space to RGB space. In fact, it can also be realized through hsv2rgb function.

Light parameter adjustment

MATLAB has a complete set of lighting parameter settings. The functions provided by graphics are similar to those of cameras with zoom lens, which can control the scene view created by MATLAB. For details, please refer to Camera graphics terminology . The commands provided by the MATLAB graphics environment allow you to place light sources and adjust the characteristics of objects that reflect light. For details, see Lighting overview . Here we can control the illumination to make the arrow look more three-dimensional.
Code slice

% lighting settings
axis equal 
camlight('left');
lighting phong 
view(3)

New quilver effect display

With the above settings, we can debug our own quiver_Refine function:
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);

Effect display after position / direction matrix input

Current quiver_ The refine version only supports the input of data at a single location. It needs to use the for loop to call continuously, and the running speed is slow. However, the final result looks a little better than the original quiver function. Here, take Bloch skyrmion as an example. Turn Colorwheel 120 ° clockwise and dye quiver. Well, it's pretty good.

Topics: MATLAB