简体   繁体   English

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

[英]How to project a point onto a plane in 3D?

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?我该如何处理?在此处输入图像描述

  1. Make a vector from your orig point to the point of interest:从您的orig创建一个向量到兴趣点:

v = point-orig (in each dimension);

  1. Take the dot product of that vector with the unit normal vector n :取该向量与单位法线向量n的点积:

dist = vx*nx + vy*ny + vz*nz; dist = scalar distance from point to plane along the normal dist = 点到平面沿法线的标量距离

  1. Multiply the unit normal vector by the distance, and subtract that vector from your point.将单位法线向量乘以距离,然后从您的点中减去该向量。

projected_point = point - dist*normal;

Edit with picture: I've modified your picture a bit.用图片编辑:我对你的图片做了一些修改。 Red is v .红色是v dist is the length of blue and green, equal to v dot normal . dist是蓝色和绿色的长度,等于v dot normal Blue is normal*dist .蓝色是normal*dist Green is the same vector as blue, they're just plotted in different places.绿色与蓝色是相同的向量,它们只是绘制在不同的地方。 To find planar_xyz, start from point and subtract the green vector.要找到plane_xyz,请从point开始并减去绿色向量。

点到平面的投影

This is really easy, all you have to do is find the perpendicular (abbr here |_ ) distance from the point P to the plane, then translate P back by the perpendicular distance in the direction of the plane normal .这真的很容易,您所要做的就是找到从点P到平面的垂直(此处缩写为|_ )距离,然后P平移平面法线方向上的垂直距离。 The result is the translated P sits in the plane.结果是翻译后的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).投影点应为 (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.您可以通过检查看到 Pproj 与平面垂直 10 个单位,如果它在平面内,则 y=10。

So how do we find this analytically?那么我们如何分析地找到这个呢?

The plane equation is Ax+By+Cz+d=0.平面方程为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" .这个等式的意思是“为了使点 (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).平面具有法线 n=(0,1,0)。 The d is found simply by using a test point already in the plane :只需使用平面中已有的测试点即可找到 d:

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

The point (0,10,0) is in the plane.点 (0,10,0) 在平面内。 Plugging in above, we find, d=-10.代入上面,我们发现,d=-10。 The plane equation is then 0x + 1y + 0z - 10 = 0 (if you simplify, you get y=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 any point 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) 0:完全在平面上(几乎不会发生浮点不准确问题)
  • +1: >0: IN FRONT of plane (on normal side) +1:>0:在平面的前面(在正常侧)
  • -1: <0: BEHIND plane (ON OPPOSITE SIDE OF NORMAL) -1:<0:在平面后面(在正常的相反侧)

Anyway,反正,

在此处输入图像描述

Which you can verify as correct by inspection in the diagram above您可以通过上图中的检查来验证其是否正确

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 n and point o由法线n和点o定义的平面的方法

This method was explained in the answer by @tmpearce. @tmpearce 在答案中解释了此方法。

Given a point-normal definition of a plane with normal n and point o on 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 p ' = p - ( n ⋅ ( p - o )) × n

Method for planes defined by normal n and scalar d由法线n和标量d定义的平面的方法

This method was explained in the answer by @bobobobo. @bobobobo 在答案中解释了这种方法。

Given a plane defined by normal n and 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的点,可以通过以下方式找到:

  1. p ' = p - ( np + d ) × n p ' = p - ( np + d ) × n

If instead you've got a point-normal definition of a plane (the plane is defined by normal n and point o on the plane) @bobobobo suggests to find d :相反,如果你有一个平面的点法线定义(平面由平面上的法线n和点o定义)@bobobobo 建议找到d

  1. d = - no d = - no

and insert this into equation 2. This yields:并将其代入等式 2。这会产生:

  1. p ' = p - ( np - no ) × n p ' = p - ( np - no ) × 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 np - no .仔细看看方程 1 和 4。通过比较它们,你会发现方程 1 使用n ⋅ ( p - o ),而方程 2 使用np - no That's actually two ways of writing down the same thing:这实际上是写下同一件事的两种方式:

  1. n ⋅ ( p - o ) = np - no = np + d n ⋅ ( p - o ) = np - no = np + d

One may thus choose to interpret the scalar d as if it were a 'pre-calculation'.因此,人们可以选择将标量d解释为好像它是“预计算”。 I'll explain: if a plane's n and o are known, but o is only used to calculate n ⋅ ( p - o ), we may as well define the plane by n and d and calculate np + d instead, because we've just seen that that's the same thing.我解释一下:如果一个平面的no已知,但o只用于计算n ⋅ ( p - o ),我们不妨用nd定义平面,然后计算np + d ,因为我们刚刚看到这是同一件事。

Additionally for programming using d has two advantages:此外,使用d进行编程有两个优点:

  1. Finding p ' now is a simpler calculation, especially for computers.现在找到p ' 是一个更简单的计算,尤其是对于计算机。 Compare:相比:
  • using n and o : 3 subtractions + 3 multiplications + 2 additions使用no :3 次减法 + 3 次乘法 + 2 次加法
  • using n and d : 0 subtractions + 3 multiplications + 3 additions.使用nd :0 次减法 + 3 次乘法 + 3 次加法。
  1. Using d limits 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 ).使用d将平面的定义限制为仅 4 个实数(3 表示n + 1 表示d ),而不是 6 (3 表示n + 3 表示o )。 This saves ⅓ memory.这样可以节省 ⅓ 内存。

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 (ie 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.从 3d 点减去原点。 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.如果您的法线向量被归一化 - 结果向量的长度等于所需的值。

EDIT编辑

A complete answer would need an extra parameter.一个完整的答案需要一个额外的参数。 Say, you supply also the vector that denotes the x-axis on your plane.比如说,您还提供了表示平面上 x 轴的向量。 So we have vectors n and x .所以我们有向量nx Assume they're normalized.假设它们是标准化的。

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 ( n cross x ) y = ( p - O ) 点 ( n交叉x )

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 + dN投影点 P = V + dN

I think you should slightly change the way you describe the plane.我认为你应该稍微改变一下描述飞机的方式。 Indeed, the best way to describe the plane is via a vector n and a scalar c事实上,描述平面的最佳方式是通过向量n和标量c

( x , n ) = c ( x , n ) = c

The (absolute value of the) constant c is the distance of the plane from the origin, and is equal to ( P , n ), where P is any point on the plane.常数 c 的(绝对值)是平面到原点的距离,等于 ( P , n ),其中P是平面上的任意点。

So, let P be your orig point and A ' be the projection of a new point A onto the plane.所以,让P是你的原点A ' 是新点A在平面上的投影。 What you need to do is find a such that A ' = A - a* n satisfies the equation of the plane, that is你需要做的是找到一个这样的A ' = A - a* n满足平面方程,即

( 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一 = (, n ) - ( P , n ) = (, 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 orig point P you store c=( P , n ), which means basically 25% less flops for each projection (in case this routine is used many times in your code).注意:如果您存储 c=( P , n ) 而不是原点P ,则您的代码将保存一个标量积,这意味着每个投影的触发器基本上减少了 25%(如果此例程在您的代码中多次使用)。

Let r be the point to project and p be the result of the projection.r为投影点, p为投影结果。 Let c be any point on the plane and let n be a normal to the plane (not necessarily normalised).c为平面上的任意点,令n为平面的法线(不一定要归一化)。 Write p = r + m d for some scalar m which will be seen to be indeterminate if their is no solution.为某个标量 m 写p = r + m d ,如果它们没有解,则该标量 m 将被视为不确定。 Since ( p - c ).由于 ( p - c )。 n = 0 because all points on the plane satisfy this restriction one has ( r - c ). n = 0,因为平面上的所有点都满足这一限制( r - c )。 n + m( d . n ) = 0 and so m = [( c - r ). n + m( d . n ) = 0 所以 m = [( c - r )。 n ]/[ d . n ]/[ d . n ] where the dot product (.) is used. n ] 使用点积 (.)。 But if d .但如果d n = 0 there is no solution. n = 0 无解。 For example if d and n are perpendicular to one another no solution is available.例如,如果dn相互垂直,则没有可用的解决方案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM