C++ 如何将点投影到 3D 平面上?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9605556/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to project a point onto a plane in 3D?
提问by George
I have a 3D point (point_x,point_y,point_z) and I want to project it onto a 2D plane in 3D space which (the plane) is defined by a point coordinates (orig_x,orig_y,orig_z) and a unary perpendicular vector (normal_dx,normal_dy,normal_dz).
我有一个 3D 点 (point_x,point_y,point_z),我想将它投影到 3D 空间中的 2D 平面上,该平面(平面)由点坐标(orig_x、orig_y、orig_z)和一元垂直向量(normal_dx)定义,normal_dy,normal_dz)。
How should I handle this?
我该如何处理?
回答by tmpearce
1) Make a vector from your orig
point to the point of interest:
1)制作从您的orig
点到兴趣点的向量:
v = point-orig (in each dimension);
v = point-orig (in each dimension);
2) Take the dot product of that vector with the unit normal vector n
:
2)取该向量与单位法向量的点积n
:
dist = vx*nx + vy*ny + vz*nz;
dist = scalar distance from point to plane along the normal
dist = vx*nx + vy*ny + vz*nz;
dist = 沿法线从点到平面的标量距离
3) Multiply the unit normal vector by the distance, and subtract that vector from your point.
3)将单位法向量乘以距离,然后从您的点中减去该向量。
projected_point = point - dist*normal;
projected_point = point - dist*normal;
Edit with picture:
I've modified your picture a bit. Red is v
; v
dot normal
= length of blue and green (dist
above). Blue is normal*dist
. Green = blue * -1
: to find planar_xyz, start from point
and add the green vector.
用图片编辑:我稍微修改了你的图片。红色是v
; v
dot normal
= 蓝色和绿色的长度(dist
上图)。蓝色是normal*dist
。 Green = blue * -1
:要找到planar_xyz,从point
绿色向量开始并添加。
回答by bobobobo
This is really easy, all you have to do is find the perpendicular (abbr here |_
) distance from the point P
to the plane, then translateP
backby the perpendicular distance in the direction of the plane normal. The result is the translated P
sits in the plane.
这是很容易,你需要做的就是找到垂直(简称这里|_
从点)距离P
的平面,然后翻译P
回用的垂直距离在正常的平面的方向。结果是翻译的P
坐在飞机上。
Taking an easy example (that we can verify by inspection) :
举一个简单的例子(我们可以通过检查来验证):
Set n=(0,1,0), and P=(10,20,-5).
设置 n=(0,1,0),并且 P=(10,20,-5)。
The projected point should be (10,10,-5). You can see by inspection that Pproj is 10 units perpendicular from the plane, and if it were in the plane, it would have y=10.
投影点应为 (10,10,-5)。通过检查可以看到 Pproj 与平面垂直 10 个单位,如果它在平面内,则 y=10。
So how do we find this analytically?
那么我们如何通过分析找到这一点呢?
The plane equation is Ax+By+Cz+d=0. What this equation means is "in order for a point (x,y,z) to be in the plane, it must satisfy Ax+By+Cz+d=0".
平面方程为Ax+By+Cz+d=0。这个等式的意思是“为了使点 (x,y,z) 在平面上,它必须满足 Ax+By+Cz+d=0”。
What is the Ax+By+Cz+d=0 equation for the plane drawn above?
上面绘制的平面的 Ax+By+Cz+d=0 方程是什么?
The plane has normal n=(0,1,0). The d is found simply by using a test point already in the plane:
该平面具有法线 n=(0,1,0)。只需使用平面中已有的测试点即可找到 d :
(0)x + (1)y + (0)z + d = 0
The point (0,10,0) is in the plane. Plugging in above, we find, d=-10. The plane equation is then 0x + 1y + 0z - 10 = 0 (if you simplify, you get y=10).
点 (0,10,0) 在平面内。插入上面,我们发现,d=-10。平面方程为 0x + 1y + 0z - 10 = 0(如果简化,则得到 y=10)。
A nice interpretation of d
is it speaks of the perpendicular distance you would need to translate the plane along its normal to have the plane pass through the origin.
一个很好的解释d
是它谈到了您需要沿其法线平移平面以使平面通过原点的垂直距离。
Anyway, once we have d
, we can find the |_ distance of anypoint to the plane by the following equation:
无论如何,一旦我们有了d
,我们就可以通过以下等式找到任何点到平面的 |_ 距离:
There are 3 possible classes of results for |_ distance to plane:
|_ 到平面的距离有 3 种可能的结果类别:
- 0: ON PLANE EXACTLY (almost never happens with floating point inaccuracy issues)
- +1: >0: IN FRONT of plane (on normal side)
- -1: <0: BEHIND plane (ON OPPOSITE SIDE OF NORMAL)
- 0: ON PLANE EXACTLY (几乎不会发生浮点不准确问题)
- +1:>0:在平面前面(法线侧)
- -1:<0:飞机后面(在正常对面)
Anyway,
反正,
Which you can verify as correct by inspection in the diagram above
您可以通过上图中的检查来验证是否正确
回答by Mr.H
This answer is an addition to two existing answers. I aim to show how the explanations by @tmpearce and @bobobobo boil down to the same thing, while at the same time providing quick answers to those who are merely interested in copying the equation best suited for their situation.
这个答案是对两个现有答案的补充。我的目标是展示 @tmpearce 和 @bobobobo 的解释如何归结为同一件事,同时为那些只对复制最适合他们情况的方程式感兴趣的人提供快速答案。
Method for planes defined by normal nand point o
由法线n和点o定义的平面的方法
This method was explained in the answer by @tmpearce.
@tmpearce 在回答中解释了此方法。
Given a point-normaldefinition of a plane with normal nand point oon the plane, a point p', being the point on the plane closest to the given point p, can be found by:
给定法线n和平面上点o的平面的点法线定义,点p',即平面上最接近给定点p的点,可以通过以下方式找到:
1) p' = p- (n? (p- o)) * n
1) p' = p- ( n? ( p- o)) * n
Method for planes defined by normal nand scalar d
由法线n和标量d定义的平面的方法
This method was explained in the answer by @bobobobo.
@bobobobo 在回答中解释了这种方法。
Given a plane defined by normal nand scalar d, a point p', being the point on the plane closest to the given point p, can be found by:
给定一个由法线n和标量d定义的平面,一个点p',即最接近给定点p的平面上的点,可以通过以下方式找到:
2) p' = p- (n? p+ d) * n
2) p' = p- ( n? p+ d) * n
If instead you've got a point-normaldefinition of a plane (the plane is defined by normal nand point oon the plane) @bobobobo suggests to find d:
相反,如果您有平面的点法线定义(平面由平面上的法线n和点o定义)@bobobobo 建议找到d:
3) d= -n? o
3) d= - n? ○
and insert this into equation 2. This yields:
并将其插入等式 2。这将产生:
4) p' = p- (n? p- n? o) * n
4) p' = p- ( n? p- n? o) * n
A note about the difference
关于差异的说明
Take a closer look at equations 1 and 4. By comparing them you'll see that equation 1 uses n? (p- o) where equation 2 uses n? p- n? o. That's actually two ways of writing down the same thing:
仔细看看等式 1 和 4。通过比较它们,您会发现等式 1 使用了n? ( p- o) 其中等式 2 使用n?p- n? 哦。这实际上是写下同一件事的两种方式:
5) n? (p- o) = n? p- n? o= n? p+ d
5)ñ?( p- o) = n? p- n? o= n? p+ d
One may thus choose to interpret the scalar das if it were a 'pre-calculation'. I'll explain: if a plane's nand oare known, but ois only used to calculate n? (p- o), we may as well define the plane by nand dand calculate n? p+ dinstead, because we've just seen that that's the same thing.
因此,人们可以选择将标量d解释为“预先计算”。我会解释一下:如果飞机的n和o是已知的,但o仅用于计算n?( p- o),我们不妨用n和d定义平面并计算n? p+ d代替,因为我们刚刚看到这是同一件事。
Additionally for programming using dhas two advantages:
此外,使用d进行编程有两个优点:
- Finding p' now is a simpler calculation, especially for computers. Compare:
- using nand o: 3 subtractions + 3 multiplications + 2 additions
- using nand d: 0 subtractions + 3 multiplications + 3 additions.
- Using dlimits the definition of a plane to only 4 real numbers (3 for n+ 1 for d), instead of 6 (3 for n+ 3 for o). This saves ? memory.
- 现在找到p' 是一个更简单的计算,特别是对于计算机。相比:
- 使用n和o:3 次减法 + 3 次乘法 + 2 次加法
- 使用n和d:0 次减法 + 3 次乘法 + 3 次加法。
- 使用d将平面的定义限制为仅 4 个实数(3 表示n+ 1 表示d),而不是 6(3 表示n+ 3 表示o)。这节省?记忆。
回答by valdo
It's not sufficient to provide only the plane origin and the normal vector. This does define the 3d plane, however this does not define the coordinate system on the plane.
仅提供平面原点和法向量是不够的。这确实定义了 3d 平面,但这并没有定义平面上的坐标系。
Think that you may rotate your plane around the normal vector with regard to its origin (i.e. put the normal vector at the origin and "rotate").
认为您可以围绕法线向量相对于其原点旋转您的平面(即,将法线向量置于原点并“旋转”)。
You may however find the distance of the projected point to the origin (which is obviously invariant to rotation).
然而,您可能会发现投影点到原点的距离(这显然对旋转是不变的)。
Subtract the origin from the 3d point. Then do a cross product with the normal direction. If your normal vector is normalized - the resulting vector's length equals to the needed value.
从 3d 点减去原点。然后与法线方向做叉积。如果您的法线向量被归一化 - 结果向量的长度等于所需的值。
EDIT
编辑
A complete answer would need an extra parameter. Say, you supply also the vector that denotes the x-axis on your plane. So we have vectors nand x. Assume they're normalized.
一个完整的答案需要一个额外的参数。比如说,您还提供了表示平面上 x 轴的向量。所以我们有向量n和x。假设它们是标准化的。
The origin is denoted by O, your 3D point is p.
原点由O表示,您的 3D 点是p。
Then your point is projected by the following:
那么你的观点是由以下预测的:
x = (p- O) dot x
x = ( p- O) 点x
y = (p- O) dot (ncross x)
y = ( p- O) 点 ( n交叉x)
回答by PermanentGuest
Let V = (orig_x,orig_y,orig_z) - (point_x,point_y,point_z)
让 V = (orig_x,orig_y,orig_z) - (point_x,point_y,point_z)
N = (normal_dx,normal_dy,normal_dz)
N = (normal_dx,normal_dy,normal_dz)
Let d = V.dotproduct(N);
让 d = V.dotproduct(N);
Projected point P = V + d.N
投影点 P = V + dN
回答by bartgol
I think you should slightly change the way you describe the plane. Indeed, the best way to describe the plane is via a vector nand a scalar c
我认为你应该稍微改变你描述飞机的方式。实际上,描述平面的最好方法是通过向量n和标量c
(x, n) = c
( x, n) = c
The (absolute value of the) constant c is the distanceof the plane from the origin, and is equal to (P, n), where Pis any point on the plane.
常数 c 的(绝对值)是平面到原点的距离,等于 ( P, n),其中P是平面上的任意点。
So, let Pbe your origpoint and A' be the projection of a new point Aonto the plane. What you need to do is find asuch that A' = A- a*nsatisfies the equation of the plane, that is
因此,让P是你的原稿点和一个'是一个新的点的投影一上飞机。你需要做的是找到一个这样一个'=一-一* ñ满足平面方程,即
(A- a*n, n) = (P, n)
( A- a* n, n) = ( P, n)
Solving for a, you find that
求解 a,你会发现
a = (A, n) - (P, n) = (A, n) - c
a = ( A, n) - ( P, n) = ( A, n) - c
which gives
这使
A' = A- [(A, n) - c]n
A' = A- [( A, n) - c] n
Using your names, this reads
使用你的名字,这读作
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;
Note: your code would save one scalar product if instead of the origpoint Pyou store c=(P, n), which means basically 25% less flops for each projection (in case this routine is used many times in your code).
注:您的代码会保存一个标产品,如果不是的原稿点P你存储C =(P,ñ),这意味着基本上减少25%的触发器对于每个投影(如果这个程序被多次使用在你的代码)。
回答by Peter
Let rbe the point to project and pbe the result of the projection. Let cbe any point on the plane and let nbe a normal to the plane (not necessarily normalised). Write p= r+ m dfor some scalar m which will be seen to be indeterminate if their is no solution. Since (p- c).n= 0 because all points on the plane satisfy this restriction one has (r- c).n+ m(d. n) = 0 and so m = [(c- r).n]/[d.n] where the dot product (.) is used. But if d.n= 0 there is no solution. For example if dand nare perpendicular to one another no solution is available.
令r为投影点,p为投影结果。设c为平面上的任意点,n为平面的法线(不一定归一化)。对于某些标量 m写p= r+ m d,如果它们没有解,则该标量将被视为不确定。因为(p- c)。n= 0 因为平面上的所有点都满足一个具有 ( r- c) 的限制。n+ m( d. n) = 0 所以 m = [( c- r)。Ñ] / [ d。n] 其中使用点积 (.)。但是如果d。n= 0 无解。例如,如果d和n相互垂直,则无解。