如何将点投影到3D平面上?

我有一个3D点(point_x,point_y,point_z),我想将其投影到3D空间中的2D平面上,该平面由点坐标(orig_x,orig_y,orig_z)和一元垂直矢量(normal_dx)定义 ,normal_dy,normal_dz)。

我该如何处理?enter image description here

George asked 2019-11-08T05:36:46Z
7个解决方案
76 votes

1)制作一个从您的v点到兴趣点的向量:

v

2)将该向量的点积与单位法向向量v进行相乘:

v dist =沿法线从点到平面的标量距离

3)将单位法向矢量乘以距离,然后从您的点减去该矢量。

v

用图片编辑:我对您的照片做了一些修改。 红色是vvnormal =蓝色和绿色的长度(上面dist)。 蓝色是normal*distGreen = blue * -1:要找到plane_xyz,从point开始并添加绿色矢量。

enter image description here

tmpearce answered 2019-11-08T05:37:39Z
38 votes

这真的很容易,您所要做的就是找到从点P到平面的垂直距离(此处为d),然后将P向垂直于平面法线的方向平移。 结果是翻译后的P坐在飞机上。

举一个简单的例子(我们可以通过检查来验证):

设置n =(0,1,0)和P =(10,20,-5)。

enter image description here

投影点应为(10,10,-5)。 通过检查,您可以看到Pproj与平面垂直10个单位,如果它在平面中,则y = 10。

那么我们如何分析地找到这个呢?

平面方程为Ax + By + Cz + d = 0。 该方程式的意思是“为了使点(x,y,z)在平面上,它必须满足Ax + By + Cz + d = 0”。

上面绘制的平面的Ax + By + Cz + d = 0方程是什么?

该平面的法线n =(0,1,0)。 d可以简单地通过使用平面中已经存在的测试点来找到:

(0)x + (1)y + (0)z + d = 0

点(0,10,0)在平面上。 插入上面,我们发现d = -10。 平面方程为0x + 1y + 0z-10 = 0(如果简化,则y = 10)。

d的一个很好的解释是它说您需要沿着平面的法线平移该平面才能使该平面穿过原点,从而达到垂直距离。

无论如何,一旦有了d,我们可以通过以下方程式找到任意点到平面的| _距离:

enter image description here

| _到平面的距离有3种可能的结果类别:

  • 0:完全在平面上(浮点误差问题几乎绝不会发生)
  • +1:> 0:在飞机的前部(法向侧)
  • -1:<0:底面(在法线的相反侧)

无论如何,

enter image description here

您可以通过上图中的检查来验证其正确性

bobobobo answered 2019-11-08T05:39:55Z
12 votes

该答案是对两个现有答案的补充。我的目的是展示@tmpearce和@bobobobo的解释是如何归结为同一件事的,同时又为那些仅对复制适合自己情况的方程式感兴趣的人提供快速解答。

法线n和点o定义的平面的方法

@tmpearce在答案中解释了此方法。

给定一个平面的点法线定义,该平面的法线为n且平面上的点为o,则点p'(即平面上最接近给定点p的点)可以通过以下公式找到:

1)p'= p-(n⋅(p-o))* n

法线n和标量d定义的平面的方法

@bobobobo在答案中解释了此方法。

给定一个由法线n和标量d定义的平面,可以通过以下方法找到一个点p',即最接近给定点p的平面上的点:

2)p'= p-(n⋅p + d)* n

相反,如果您有一个平面的点法线定义(该平面由法线n和平面上的点o定义),@ bobobobo建议找到d:

3)d = -n⋅o

并将其插入等式2。这将产生:

4)p'= p-(n⋅p-n⋅o)* n

关于差异的注释

仔细研究方程式1和4。通过比较它们,您会发现方程式1使用n⋅(p-o),方程式2使用n⋅p-n⋅o。 实际上,这是写下同一件事的两种方式:

5)n⋅(p-o)= n⋅p-n⋅o = n⋅p + d

因此,可以选择将标量d解释为好像是“预计算”。 我将说明:如果已知平面的n和o,但是o仅用于计算n⋅(p-o),我们也可以用n和d定义平面,然后计算n⋅p + d,因为我们已经看到那是同一回事。

此外,使用d进行编程有两个优点:

  1. 现在找到p'是一个更简单的计算,尤其是对于计算机而言。 相比:
    • 使用n和o:3个减法+ 3个乘法+ 2个加法
    • 使用n和d:0减+ 3乘+ 3加。
  2. 使用d将平面的定义限制为仅4个实数(对于n而言,3为3 +对于d为1),而不是6(对于n为3,对于n + 3对于o)。 这样可以节省内存。
Mr.H answered 2019-11-08T05:42:50Z
10 votes

仅提供平面原点和法线向量是不够的。 这确实定义了3d平面,但是没有定义该平面上的坐标系。

认为您可以围绕法线向量围绕其原点旋转平面(即,将法线向量置于原点处并“旋转”)。

但是,您可能会发现投影点到原点的距离(显然,旋转距离不变)。

从3d点减去原点。 然后按照法线方向做叉积。 如果法线向量已归一化,则所得向量的长度等于所需值。

编辑

一个完整的答案将需要一个额外的参数。 假设您还提供了表示飞机上x轴的向量。所以我们有向量n和x。 假设它们已标准化。

原点用O表示,您的3D点是p。

然后,您的观点将通过以下方式预测:

x =(p-O)点x

y =(p-O)点(n交叉x)

valdo answered 2019-11-08T05:44:18Z
2 votes

设V =(orig_x,orig_y,orig_z)-(point_x,point_y,point_z)

N =(normal_dx,normal_dy,normal_dz)

令d = V.dotproduct(N);

投影点P = V + d.N

PermanentGuest answered 2019-11-08T05:45:09Z
1 votes

我认为您应该稍微改变描述飞机的方式。 实际上,描述平面的最佳方法是通过向量n和标量c

[x,n)= c

常数(的绝对值)是平面到原点的距离,并且等于(P,n),其中P是平面上的任意点。

因此,令P为原点,A'为新点A在平面上的投影。 您需要做的是找到一个使得A'= A-a * n满足平面方程的表达式,即

(A-a * n,n)=(P,n)

解决一个,你发现

a =(A,n)-(P,n)=(A,n)-c

这使

A'= A-[(A,n)-c] n

用你的名字,这读

c = orig_x*normal_dx + orig_y*normal_dy+orig_z*normal_dz;
a = point_x*normal_dx + point_y*normal_dy + point_z*normal_dz - c;
planar_x = point_x - a*normal_dx;
planar_y = point_y - a*normal_dy;
planar_z = point_z - a*normal_dz;

注意:如果存储c =(P,n)而不是原始点P,则代码将节省一个标量积,这意味着基本上每个投影的触发器减少25%(以防该例程在代码中多次使用)。

bartgol answered 2019-11-08T05:46:47Z
0 votes

令r为要投影的点,而p为投影的结果。 令c为平面上的任意点,令n为平面的法线(不一定进行归一化)。 对于某些标量m,写p = r + m d,如果它们不是解,则将被视为不确定。因为(p-c).n = 0,因为平面上的所有点都满足此限制,所以一个人具有(r-c).n + m(d。n)= 0,所以m = [(c-r).n] / [dn]使用点积(。)。 但是,如果d.n = 0,就没有解。 例如,如果d和n相互垂直,则无解可用。

Peter answered 2019-11-08T05:47:20Z
translate from https://stackoverflow.com:/questions/9605556/how-to-project-a-point-onto-a-plane-in-3d