我想在matlab中实现一个功能,我给定两个三维向量(不共线),首先先在3维图中画出这两个向量,再画...

Creado el: 8 de febrero de 2026

Respondido usando GPT-5.2 Thinking por Chat01

Pregunta

我想在matlab中实现一个功能,我给定两个三维向量(不共线),首先先在3维图中画出这两个向量,再画出这两个向量所处在的平面,假设这两个向量令为v1,v2 (3*1的向量),我该怎么写程序?

Respuesta

下面给你一份可以直接跑的 MATLAB 示例:输入两个 3×1 的非共线向量 v1, v2,它会:

  1. 在 3D 坐标系里画出两个向量(从原点出发的箭头)
  2. 画出由它们张成的平面(一个半透明的面片)
  3. 自动把显示范围调到合适大小

原理:平面就是 { a*v1 + b*v2 | a,b ∈ ℝ }。用网格的 a,b 采样生成一片面。


matlab
%% 输入:两个 3x1 向量(确保不共线) v1 = [1; 2; 1]; v2 = [2; -1; 1]; %% 基本检查 assert(all(size(v1)==[3 1]) && all(size(v2)==[3 1]), 'v1,v2 必须是 3x1 向量'); n = cross(v1, v2); assert(norm(n) > 1e-10, 'v1 和 v2 不能共线(叉积接近 0)'); %% 画向量 + 平面 figure; hold on; grid on; axis equal; xlabel('X'); ylabel('Y'); zlabel('Z'); title('Vectors v1, v2 and the plane they span'); % 1) 画两个向量(从原点出发) quiver3(0,0,0, v1(1),v1(2),v1(3), 0, 'LineWidth',2); quiver3(0,0,0, v2(1),v2(2),v2(3), 0, 'LineWidth',2); % 标注向量端点 text(v1(1),v1(2),v1(3), ' v1', 'FontSize',12); text(v2(1),v2(2),v2(3), ' v2', 'FontSize',12); % 2) 生成平面上的点:p = a*v1 + b*v2 % 面片大小:用向量长度决定一个合适尺度 L = max([norm(v1), norm(v2)]); s = 1.2 * L; % 你也可以手动改大/改小 t = linspace(-1, 1, 25); % 网格密度(越大越细) [A,B] = meshgrid(t, t); X = (A*v1(1) + B*v2(1)) * s; Y = (A*v1(2) + B*v2(2)) * s; Z = (A*v1(3) + B*v2(3)) * s; % 画平面(半透明) surf(X, Y, Z, ... 'FaceAlpha',0.25, ... 'EdgeAlpha',0.15); % 3) 画坐标轴参考线(可选) m = 1.5 * s; plot3([0 m],[0 0],[0 0],'k:'); % x轴方向虚线参考 plot3([0 0],[0 m],[0 0],'k:'); % y轴 plot3([0 0],[0 0],[0 m],'k:'); % z轴 % 视角与范围 view(45, 25); xlim([-m m]); ylim([-m m]); zlim([-m m]); legend({'v1','v2','span(v1,v2) plane'}, 'Location','best'); hold off;

你可能想要的两个小改动

1)平面不是过原点,而是过某个点 p0:
把平面点改成 p = p0 + a*v1 + b*v2,例如:

matlab
p0 = [1; 0; 2]; X = p0(1) + (A*v1(1) + B*v2(1)) * s; Y = p0(2) + (A*v1(2) + B*v2(2)) * s; Z = p0(3) + (A*v1(3) + B*v2(3)) * s;

2)让平面范围“更贴合”两向量而不是对称方形:
可以让 A,B 的范围不一样,或让 s 用你想要的尺寸。


如果你把 v1,v2 的具体数值发我(或者你希望平面显示多大、是否要显示法向量),我也可以把图做得更“论文风”(比如加法向量 n=cross(v1,v2)、加上平面方程等)。

Pregunta

我加入了你的内容,得到了很好的效果,这是我如下的代码:
clear all
clc

m(1)=3;
m(2)=1;
m(3)=0.8;

nn=1;
ee=1;
tau=1;
hbar=1;

a=1;
b=0;
c=1;
a1=a/sqrt(a^2+b^2+c^2);
b1=b/sqrt(a^2+b^2+c^2);
c1=c/sqrt(a^2+b^2+c^2);

Theta=acos(c1);
if c1==1
Phi=0;
elseif b1>0
Phi=acos(a1/sin(Theta));
else
Phi=2*pi-acos(a1/sin(Theta));
end

A=[cos(Theta)*cos(Phi),-sin(Phi),sin(Theta)*cos(Phi);cos(Theta)*sin(Phi),cos(Phi),sin(Theta)*sin(Phi);-sin(Theta),0,cos(Theta)];

mmup=zeros(3,3);
mmdn=zeros(3,3);
mmup(1,1)=(1/m(1)+1/m(2))/2;
mmup(2,2)=(1/m(1)+1/m(2))/2;
mmup(1,2)=(1/m(1)-1/m(2))/2;
mmup(2,1)=(1/m(1)-1/m(2))/2;
mmup(3,3)=1/m(3);
mmdn=mmup;
mmdn(1,2)=(1/m(2)-1/m(1))/2;
mmdn(2,1)=(1/m(2)-1/m(1))/2;

sigma_c=nnee^2tau*(mmup+mmdn);
sigma_s=nnee^2tau*(mmup-mmdn);

phi=linspace(0,2pi,1000);
n=length(phi);
theta=pi/2
ones(1,n);
E=zeros(3,n);
Jc=zeros(3,n);
Js=zeros(3,n);
v1=3A[1;0;0];
v2=3A[0;1;0];
for i=1:n
E(:,i)=[sin(theta(i))*cos(phi(i));sin(theta(i))*sin(phi(i));cos(theta(i))];

text
Jc(:,i)=sigma_c*A*E(:,i); Js(:,i)=sigma_s*A*E(:,i); Js1(:,i)=Js(:,i)-dot(Js(:,i),Jc(:,i))*Jc(:,i)/norm(Jc(:,i))^2; Jcc(i)=norm(Jc(:,i)); Jss(i)=norm(Js(:,i)); Jss1(i)=norm(Js1(:,i));

end
figure
plot(phi,Jss1,'LineWidth',2);

figure
x = -3:0.05:3;
y = -3:0.05:3;
z = -3:0.05:3;
[X, Y, Z] = meshgrid(x, y, z);

E1 = hbar^2/2*(mmup(1,1)*X.^2+mmup(2,2)Y.^2+2mmup(1,2)*X.*Y+mmup(3,3)Z.^2);
E2 = hbar^2/2
(mmup(1,1)*X.^2+mmup(2,2)Y.^2-2mmup(1,2)*X.*Y+mmup(3,3)*Z.^2);

h1 = patch(isosurface(X, Y, Z, E1, 1));
isonormals(X, Y, Z, E1, h1);
hold on
h2 = patch(isosurface(X, Y, Z, E2, 1));
isonormals(X, Y, Z, E2, h2);

assert(all(size(v1)==[3 1]) && all(size(v2)==[3 1]), 'v1,v2 必须是 3x1 向量');
n = cross(v1, v2);
assert(norm(n) > 1e-10, 'v1 和 v2 不能共线(叉积接近 0)');

grid on; axis equal;
xlabel('X'); ylabel('Y'); zlabel('Z');
title('Vectors v1, v2 and the plane they span');

% 1) 画两个向量(从原点出发)
quiver3(0,0,0, v1(1),v1(2),v1(3), 0, 'LineWidth',2);
quiver3(0,0,0, v2(1),v2(2),v2(3), 0, 'LineWidth',2);

% 标注向量端点
text(v1(1),v1(2),v1(3), ' v1', 'FontSize',12);
text(v2(1),v2(2),v2(3), ' v2', 'FontSize',12);

% 2) 生成平面上的点:p = av1 + bv2
% 面片大小:用向量长度决定一个合适尺度
L = max([norm(v1), norm(v2)]);
s = 1.2 * L; % 你也可以手动改大/改小
t = linspace(-1, 1, 25); % 网格密度(越大越细)
[A1,B1] = meshgrid(t, t);

X = (A1v1(1) + B1v2(1)) * s;
Y = (A1v1(2) + B1v2(2)) * s;
Z = (A1v1(3) + B1v2(3)) * s;

% 画平面(半透明)
surf(X, Y, Z, ...
'FaceAlpha',0.25, ...
'EdgeAlpha',0.15);

% 3) 画坐标轴参考线(可选)
m = 1.5 * s;
plot3([0 m],[0 0],[0 0],'k:'); % x轴方向虚线参考
plot3([0 0],[0 m],[0 0],'k:'); % y轴
plot3([0 0],[0 0],[0 m],'k:'); % z轴

% 设置图像属性
h1.FaceColor = [0 0 1];
h1.EdgeColor = 'none';
h2.FaceColor = [1 0 0];
h2.EdgeColor = 'none';
alpha(1);
view([1, 1, 1]);
axis equal;
% axis off;
camlight('right');
lighting gouraud;
xlabel('x'); ylabel('y'); zlabel('z');

hold off;
但我想在此基础上更进一步,我想再做一张图,这张图是图2的切面图。(这个体系的背景是算RuO2这个交错磁体的能带,你注意到我使用了各向异性电子气体模型,图二画了RuO2的费米面和所切割的晶面,我想看这个图的切面图,画到第三个图上即可)

Pensamiento

Helping with 3D plot intersection in MATLAB

The user wants to plot a cross-section of a 3D figure along the plane defined by vectors v1 and v2. This will involve finding the intersection curve between two isosurfaces (E1=1, E2=1) and the plane. I’ll help create a MATLAB solution by defining an orthonormal basis, and generating a 2D grid in the plane coordinates.

Mapping points and plotting cross-section in plane coordinates

To map the 3D points, I’ll use r(u,v) = ue1 + ve2, with optional offset p0. To calculate E1 and E2, I’ll plug in the x, y, z coordinates from r into formulas. I’ll contour where E1=1 and E2=1 in the plane coordinates (u, v). The alternative is extracting isocontours by sampling the 3D volume. For R, I’ll choose s as scaling based on their code.

Calculating plane patch size and isosurface intersection

To define the extent of the plane patch, I'll multiply by s (about 3.6), which gives a span of roughly 10.8 units along the plane. The intersection focus should be on where isosurfaces exist (E=1). I'll start by using a bounding box around the cube [-3,3], picking a range for u, v that keeps points within these bounds.

Defining grid and range for mapping

To simplify the process, I’ll create a grid in the u, v range of [-3, 3], adjusting it by a factor of sqrt(3) to ensure coverage. I’ll project the cube’s corners onto e1 and e2, calculate the u,v bounds, then mask points outside the cube. Finally, I’ll plot contour lines for E1=1 and E2=1 and possibly fill the contour.

Creating 2D cross-section and avoiding variable conflicts

The user wants a 2D slice of the isosurfaces in the (x', y') plane, labeled along v1, v2 directions. I'll propose MATLAB code to generate this, with careful attention to variable names and avoiding conflicts with previous ones (like "A" and "m"). I'll show the steps for defining the unit vectors and calculating u,v bounds.

Plotting cross-section and addressing user options

The user wants a cross-section of Fermi surfaces on a plane spanned by v1 and v2. I'll include MATLAB code to plot contours for E1=1 and E2=1. I'll mask points outside the cube and offer options to visualize the background or 3D intersection curves. I'll also suggest mapping back to 3D if needed.

Clarifying approach and organizing figure3

I'll suggest an approach for creating figure3. First, I'll provide the code for plotting a 2D contour of energy states E1 and E2. I'll also warn about overwriting variables like m and n, recommending renaming these for clarity. If needed, I'll offer a more complex 3D option for showing the intersection curves with the plane—though the 2D option is simpler.

Defining code for plotting fermi surface cut

Here's the code for figure3, showing cross-sections of Fermi surfaces on a plane spanned by v1 and v2. We calculate the E1 and E2 cuts and plot them using contour plots. I'll note that we use orthonormal axes for clarity and suggest projecting onto alpha and beta for a more physical interpretation.

Thought for 1m 35s

Respuesta

可以的。你现在图2里画的是两张等能面(E1=1E2=1)+ 由 v1,v2 张成的平面。你要的“切面图”最常见的理解就是:

把 3D 等能面限制到该平面上,在平面内画出 E1=1E2=1 的交线(在 2D 平面坐标里就是两条闭合曲线/截线)。

下面这段代码直接接在你图2代码后面v1,v2,mmup,hbar 都已经有了)就能生成图3:切面截线图


图3:在 span(v1,v2) 平面内的截线(推荐做法:正交化成 2D 坐标)

matlab
%% ===== Figure 3: Cut (cross-section) of the Fermi surfaces by plane span(v1,v2) ===== box = 3; % 你图2里 meshgrid 的范围是 -3~3,这里保持一致 Eiso = 1; % 等能面取值(你图2里 isosurface 用的是 1) % 1) 构造平面内的正交单位基 e1,e2(e1沿v1,e2在平面内且与e1正交) e1 = v1 / norm(v1); tmp = v2 - dot(v2,e1)*e1; e2 = tmp / norm(tmp); % e3 = cross(e1,e2); % 如果你想要法向量可用这个 % 2) 为了让切面覆盖你 3D 盒子 [-box,box]^3,把盒子 8 个角点投影到 (u,v) 得到范围 corners = box * [ -1 -1 -1; -1 -1 1; -1 1 -1; -1 1 1; 1 -1 -1; 1 -1 1; 1 1 -1; 1 1 1 ]'; u_c = e1.' * corners; % 1x8 v_c = e2.' * corners; % 1x8 u_min = min(u_c); u_max = max(u_c); v_min = min(v_c); v_max = max(v_c); % 3) 在平面内建立 2D 网格 (U,V),映射回 3D 坐标 (Xp,Yp,Zp) Nu = 700; Nv = 700; % 分辨率(想更细就调大) [U,V] = meshgrid(linspace(u_min,u_max,Nu), linspace(v_min,v_max,Nv)); Xp = e1(1)*U + e2(1)*V; Yp = e1(2)*U + e2(2)*V; Zp = e1(3)*U + e2(3)*V; % 可选:只保留落在你原来 3D box 内的点(避免图上出现“盒子外”的无关区域) mask = abs(Xp)<=box & abs(Yp)<=box & abs(Zp)<=box; Xp(~mask) = NaN; Yp(~mask) = NaN; Zp(~mask) = NaN; % 4) 直接用解析式在切面上算能量(比从 3D 网格插值更干净) E1_cut = hbar^2/2*( mmup(1,1)*Xp.^2 + mmup(2,2)*Yp.^2 + 2*mmup(1,2)*Xp.*Yp + mmup(3,3)*Zp.^2 ); E2_cut = hbar^2/2*( mmup(1,1)*Xp.^2 + mmup(2,2)*Yp.^2 - 2*mmup(1,2)*Xp.*Yp + mmup(3,3)*Zp.^2 ); % 5) 画切面截线:E1=Eiso 与 E2=Eiso figure; hold on; grid on; axis equal; [C1,hc1] = contour(U, V, E1_cut, [Eiso Eiso], 'LineWidth', 2); [C2,hc2] = contour(U, V, E2_cut, [Eiso Eiso], 'LineWidth', 2, 'LineStyle','--'); xlabel('u (along v1)'); ylabel('v (in-plane, orthogonalized from v2)'); title('Cross-section on plane span(v1,v2): E1=1 and E2=1'); legend([hc1 hc2], {'E1=1 cut','E2=1 cut'}, 'Location','best');

你这份代码里有两个“小坑”,建议顺手避开(不影响切面,但容易埋雷)

你前面 m 既当了质量数组 m(1)=3...,后面又写了 m = 1.5*s;(标尺),这会把质量数组覆盖掉。
同理你也把 n=length(phi) 后面又 n=cross(v1,v2) 覆盖了。

建议你把质量改名,例如:

  • mmass
  • n(length)→ nphi
  • n(法向量)→ nvec

这样后面扩展会省很多麻烦。


如果你还想“在图2里也画出交线”(用于核对)

你如果想把图3算出来的截线再映射回 3D,并叠加到图2的 3D 画面里,我也可以给你一段把 contour 输出 C1/C2 解析成曲线点,再 plot3 回去的代码(这样能直观看交线是不是就在你那块平面上)。

只要你告诉我:你希望交线也叠加在图2上,还是只要图3即可。

Pregunta

好了,你能帮我把最后两条线一个改为蓝色,一个改为红色吗

Respuesta

可以,contour 返回的句柄 hc1 / hc2 直接改颜色就行。把你图3里画两条线那几行改成下面这样(我也顺手把线型保留成实线/虚线方便区分):

matlab
% 5) 画切面截线:E1=Eiso 与 E2=Eiso figure; hold on; grid on; axis equal; [C1,hc1] = contour(U, V, E1_cut, [Eiso Eiso], 'LineWidth', 2); hc1.LineColor = 'b'; % 蓝色 [C2,hc2] = contour(U, V, E2_cut, [Eiso Eiso], 'LineWidth', 2, 'LineStyle','--'); hc2.LineColor = 'r'; % 红色 xlabel('u (along v1)'); ylabel('v (in-plane, orthogonalized from v2)'); title('Cross-section on plane span(v1,v2): E1=1 and E2=1'); legend([hc1 hc2], {'E1=1 cut','E2=1 cut'}, 'Location','best');

如果你想两条都是实线,只要把第二条里的 'LineStyle','--' 删掉即可。

Compartir este Q&A