将3D点投影到2D平面

Lig*_*ink 32 math 3d geometry 2d plane

设A是我有3D坐标x,y,z的点,我想将它们转换为2D坐标:x,y.投影应在由给定法线定义的平面上正交.平凡的情况,其中法线实际上是其中一个轴,它很容易解决,只是简单地消除了一个坐标,但其他情况如何更容易发生?

ja7*_*a72 32

如果你有你的目标点P与坐标r_P = (x,y,z),并与正常飞机n=(nx,ny,nz),你需要定义上飞机的起源,以及为两个正交方向xy.例如,如果你原点在r_O = (ox, oy, oz)与您在平面上的两个坐标轴被定义e_1 = (ex_1,ey_1,ez_1),e_2 = (ex_2,ey_2,ez_2)则正交性具有Dot(n,e_1)=0, Dot(n,e_2)=0,Dot(e_1,e_2)=0(矢量点积).请注意,所有方向向量都应该归一化(幅度应为1).

你的目标点P必须遵守以下等式:

r_P = r_O + t_1*e_1 + t_2*e_2 + s*n
Run Code Online (Sandbox Code Playgroud)

其中t_1t_2是您的2D沿坐标e_1e_2s所述平面和点之间的正常间隔(距离).

根据预测发现了标量:

s = Dot(n, r_P-r_O)
t_1 = Dot(e_1, r_P-r_O)    
t_2 = Dot(e_2, r_P-r_O)
Run Code Online (Sandbox Code Playgroud)

平面原点r_O = (-1,3,1)和法线的示例:

n = r_O/|r_O| = (-1/?11, 3/?11, 1/?11)
Run Code Online (Sandbox Code Playgroud)

您必须为2D坐标选择正交方向,例如:

e_1 = (1/?2, 0 ,1/?2)
e_2 = (-3/?22, -2/?22, 3/?22)
Run Code Online (Sandbox Code Playgroud)

这样Dot(n,e_1) = 0Dot(n,e_2) = 0Dot(e_1, e_2) = 0.

P 的2D坐标r_P=(1,7,-3)是:

t_1 = Dot(e_1, r_P-r_O) = ( 1/?2,0,1/?2)·( (1,7,-3)-(-1,3,1) ) =  -?2
t_2 = Dot(e_2, r_P-r_O) = (-3/?22, -2/?22, 3/?22)·( (1,7,-3)-(-1,3,1) ) = -26/?22
Run Code Online (Sandbox Code Playgroud)

和平面外分离:

s = Dot(n, r_P-r_O) = 6/?11
Run Code Online (Sandbox Code Playgroud)


unu*_*tbu 5

找到A正常方向的投影.然后从中减去该投影A.剩下的是投影A到正交平面上.

A在单位法线方向上的投影由下式n给出:

(A · n) n
Run Code Online (Sandbox Code Playgroud)

如果A = (x, y, z)和单位法线给出n = (nx, ny, nz),那么A的投影n就是

(x*nx + y*ny + z*nz) n
Run Code Online (Sandbox Code Playgroud)

因此A在正交平面上的投影是

A - (A · n) n
= (x, y, z) - (x*nx + y*ny + z*nz) (nx, ny, nz)
Run Code Online (Sandbox Code Playgroud)

例如,如果A =(1,2,3)并且n是方向(4,5,6)的单位法线,那么

In [12]: A
Out[12]: array([1, 2, 3])
In [17]: d
Out[17]: array([4, 5, 6])

In [20]: n = d/sqrt(4*4 + 5*5 + 6*6)   # make n a unit vector
In [13]: n
Out[13]: array([ 0.45584231,  0.56980288,  0.68376346])
Run Code Online (Sandbox Code Playgroud)

因此A在正交平面上的投影是

In [15]: A - np.dot(A,n)*n
Out[15]: array([-0.66233766, -0.07792208,  0.50649351])
Run Code Online (Sandbox Code Playgroud)

如何找到2D坐标:

您需要在正交平面上定义2D坐标系.换句话说,您需要定义x-axis和的y-axis位置.例如,您可以将x-axis(1,0,0)的投影定义到正交平面上(使用上面显示的计算).除非在(1,0,0)垂直于平面的退化情况下,否则这将起作用.

一旦你有xy轴方向的单位矢量,那么你可以A直接投影到xy.这些矢量的大小是2D坐标.

例如,这是(1,0,0)投影到平面上.我们把它作为x轴方向:

In [42]: x = np.array([1,0,0])    
In [45]: x = x - np.dot(x, n) * n
In [52]: x /= sqrt((x**2).sum())   # make x a unit vector    
In [53]: x
Out[53]: array([ 0.89006056, -0.29182313, -0.35018776])
Run Code Online (Sandbox Code Playgroud)

在这里我们计算y轴方向:y-axis方向必须垂直于法线方向nx.因此,我们可以定义y叉积nx:

In [68]: y = np.cross(n, x)

In [69]: y
Out[69]: array([ -2.77555756e-17,   7.68221280e-01,  -6.40184400e-01])
Run Code Online (Sandbox Code Playgroud)

所以这是A飞机上的坐标:

In [70]: np.dot(A, x), np.dot(A, y)
Out[70]: (-0.74414898890755965, -0.38411063979868798)
Run Code Online (Sandbox Code Playgroud)