基于法线向量和Matlab或matplotlib中的点绘制平面

Xzh*_*hsh 33 matlab plot matplotlib scipy

如何从法线向量和点绘制matlab或matplotlib中的平面?

Sim*_*her 50

对于所有的复制/粘贴,这里是使用matplotlib的Python的类似代码:

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

point  = np.array([1, 2, 3])
normal = np.array([1, 1, 2])

# a plane is a*x+b*y+c*z+d=0
# [a,b,c] is the normal. Thus, we have to calculate
# d and we're set
d = -point.dot(normal)

# create x,y
xx, yy = np.meshgrid(range(10), range(10))

# calculate corresponding z
z = (-normal[0] * xx - normal[1] * yy - d) * 1. /normal[2]

# plot the surface
plt3d = plt.figure().gca(projection='3d')
plt3d.plot_surface(xx, yy, z)
plt.show()
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述


Jon*_*nas 29

对于Matlab:

point = [1,2,3];
normal = [1,1,2];

%# a plane is a*x+b*y+c*z+d=0
%# [a,b,c] is the normal. Thus, we have to calculate
%# d and we're set
d = -point*normal'; %'# dot product for less typing

%# create x,y
[xx,yy]=ndgrid(1:10,1:10);

%# calculate corresponding z
z = (-normal(1)*xx - normal(2)*yy - d)/normal(3);

%# plot the surface
figure
surf(xx,yy,z)
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

注意:此解决方案仅在法线(3)不为0时才有效.如果平面与z轴平行,则可以旋转尺寸以保持相同的方法:

z = (-normal(3)*xx - normal(1)*yy - d)/normal(2); %% assuming normal(3)==0 and normal(2)~=0

%% plot the surface
figure
surf(xx,yy,z)

%% label the axis to avoid confusion
xlabel('z')
ylabel('x')
zlabel('y')
Run Code Online (Sandbox Code Playgroud)

  • 如果“正常[3] == 0”怎么办? (2认同)

Dan*_*ien 5

对于想在表面上使用渐变的复制贴纸:

from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
import numpy as np
import matplotlib.pyplot as plt

point = np.array([1, 2, 3])
normal = np.array([1, 1, 2])

# a plane is a*x+b*y+c*z+d=0
# [a,b,c] is the normal. Thus, we have to calculate
# d and we're set
d = -point.dot(normal)

# create x,y
xx, yy = np.meshgrid(range(10), range(10))

# calculate corresponding z
z = (-normal[0] * xx - normal[1] * yy - d) * 1. / normal[2]

# plot the surface
plt3d = plt.figure().gca(projection='3d')

Gx, Gy = np.gradient(xx * yy)  # gradients with respect to x and y
G = (Gx ** 2 + Gy ** 2) ** .5  # gradient magnitude
N = G / G.max()  # normalize 0..1

plt3d.plot_surface(xx, yy, z, rstride=1, cstride=1,
                   facecolors=cm.jet(N),
                   linewidth=0, antialiased=False, shade=False
)
plt.show()
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述


qin*_*010 5

以上答案都足够好了.有一点需要提及的是,他们使用相同的方法来计算给定(x,y)的z值.回退是因为它们使平面网格化并且空间中的平面可能变化(仅保持其投影相同).例如,你不能在3D空间中获得一个正方形(但是一个扭曲的正方形).

为避免这种情况,使用旋转有不同的方法.如果你首先在xy平面上生成数据(可以是任何形状),然后将它旋转相等的数量([0 0 1]到你的向量),那么你将得到你想要的.只需在代码下方运行以供参考.

point = [1,2,3];
normal = [1,2,2];
t=(0:10:360)';
circle0=[cosd(t) sind(t) zeros(length(t),1)];
r=vrrotvec2mat(vrrotvec([0 0 1],normal));
circle=circle0*r'+repmat(point,length(circle0),1);
patch(circle(:,1),circle(:,2),circle(:,3),.5);
axis square; grid on;
%add line
line=[point;point+normr(normal)]
hold on;plot3(line(:,1),line(:,2),line(:,3),'LineWidth',5)
Run Code Online (Sandbox Code Playgroud)

它在3D中得到一个圆圈: 结果图片