给定 3D 空间中的两个向量,如何计算反射角?
我想计算两个向量 a 和 b 之间的角度。让我们假设这些是在原点。这可以通过
theta = arccos(a . b / |a| * |b|)
然而 arccos 给你 [0, pi] 中的角度,即它永远不会给你一个大于 180 度的角度,这就是我想要的。那么如何知道向量何时超过 180 度标记呢?在 2D 中,我只需让其中一个向量上的 y 分量的符号来确定该向量位于哪个象限。但是在 3D 中最简单的方法是什么?
编辑:我想保持这个问题的一般性,但我们开始了。我正在用 c 语言对其进行编程,用于获取角度的代码是 theta = acos(dot(a, b)/mag(a)*mag(b))
那么您将如何以编程方式确定方向?
I want to calculate the angle between two vectors a and b. Lets assume these are at the origin. This can be done with
theta = arccos(a . b / |a| * |b|)
However arccos gives you the angle in [0, pi], i.e. it will never give you an angle greater than 180 degrees, which is what I want. So how do you find out when the vectors have gone past the 180 degree mark? In 2D I would simply let the sign of the y-component on one of the vectors determine what quadrant the vector is in. But what is the easiest way to do it in 3D?
EDIT: I wanted to keep the question general but here we go. I'm programming this in c and the code I use to get the angle is theta = acos(dot(a, b)/mag(a)*mag(b))
so how would you programmatically determine the orientation?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
这适用于 2D,因为您定义了一个平面,可以在其中定义旋转。
如果您想在 3D 中执行此操作,则不存在这样的隐式 2D 平面。您可以将 3D 坐标转换为经过所有三个点的 2D 平面,并在该平面内进行计算。
但是,当然,该平面有两种可能的方向,这将影响哪些角度将大于 10°。 180 或更小。
This works in 2D because you have a plane defined in which you define the rotation.
If you want to do this in 3D, there is no such implicit 2D plane. You could transform your 3D coordinates to a 2D plane going through all three points, and do your calculation inside this plane.
But, there are of course two possible orientations for the plane, and that will affect which angles will be > 180 or smaller.
我提出了以下解决方案,该解决方案利用两个向量叉积的方向变化:
创建一个向量
n = a X b
并将其标准化。该向量垂直于 a 和 b 所跨越的平面。每当计算新角度时,将其与旧法线进行比较。在比较中,将旧法线和当前法线视为点并计算它们之间的距离。如果这个距离是 2 法线(即叉积 a X b 已翻转)。
您可能需要一个距离阈值,因为翻转后的距离可能小于 2,具体取决于向量 a 和 b 的方向以及更新角度的频率。
I came up with the following solution that takes advantage of the direction change of the cross product of the two vectors:
Make a vector
n = a X b
and normalize it. This vector is normal to the plane spanned by a and b.Whenever a new angle is calculated compare it with the old normal. In the comparison, treat the old and the current normals as points and compute the distance between them. If this distance is 2 the normal (i.e. the cross product a X b has flipped).
You might want to have a threshold for the distance as the distance after a flip might be shorter than 2, depending on how the vectors a and b are oriented and how often you update the angle.
您可以使用的一种解决方案:
您实际上需要做的是创建一个与其中一个向量共面的平面。
获得两个向量的叉积将创建一个平面,然后你得到这个平面的法线,你可以得到这个平面和你需要得到有符号角度的向量之间的角度,你可以使用这个角度来确定标志。
如果角度大于 90 度,则位于创建的平面下方;小于90度,大于90度
根据计算成本,在此阶段可以使用点积代替角度。
只需确保始终按相同顺序的向量计算法线即可。
如果您使用 XYZ 轴,这会更容易使用,这就是您要比较的轴,因为您已经有了平面所需的矢量。
可能有更有效的解决方案,但这是我想出的一个。
编辑:创建向量的澄清
a X b = p
。这与a
和b
都垂直。然后,执行以下任一操作:
a X p
或b X p
创建另一个向量,该向量是由 2 个向量创建的平面的法线。矢量的选择取决于您要查找的角度。One solution that you could use:
What you effectively need to do is create a plane that one of the vectors is coplanar to.
Getting the cross product of both vectors will create a plane, then is you get the normal of this plane, you can get the angle between this and the vector you need to get the signed angle for, and you can use the angle to determine the sign.
If the angle is greater than 90 degrees, then it is below the created plane; less than 90 degrees, and it is above.
Depending on cost of calculations, the dot product can be used at this stage instead of the angle.
Just make sure that you always calculate the normals by the same order of vectors.
This is useable more easily if you're using the XYZ axes, and that's what you're comparing against, since you already have the vectors needed for the plane.
There are possbly more efficient solutions, but this is one I came up with.
Edit: clarification of created vectors
a X b = p
. This is perpendicular to botha
andb
.Then, do either:
a X p
orb X p
to create another vector that is the normal to the plane created by the 2 vectors. Choice of vector depends on which you're trying to find the angle for.严格来说,两个 3D 向量之间始终有两个 角度 - 一个小于或等于 180,另一个大于或等于 180。Arccos 给出其中一个,您可以通过从360.这样想:想象两条线相交。那里有 4 个角度 - 2 个为一个值,2 个为另一个值。线之间的角度是多少?没有单一的答案。同样在这里。如果没有某种额外的标准,理论上您无法判断应考虑两个角度值中的哪一个。
编辑:所以你真正需要的是固定方向的任意示例。其一:我们从正 Z 方向看。如果两个向量之间的平面包含 Z 轴,我们从正 Y 方向看。如果平面是 YZ,我们从正 X 方向看。我会想如何用坐标形式表达它,然后再次编辑。
Strictly speaking, two 3D vectors always have two angles between them - one below or equal to 180, the other over or equal to 180. Arccos gives you one of them, you can get the other by subtracting from 360. Think of it that way: imagine two lines intersect. You have 4 angles there - 2 of one value, 2 of another. What's the angle between the lines? No single answer. Same here. Without some kind of extra criteria, you can not, in theory, tell which of the two angle values should be taken into account.
EDIT: So what you really need is an arbitrary example of fixing an orientation. Here's one: we look from the positive Z direction. If the plane between the two vectors contains the Z axis, we look from the positive Y direction. If the plane is YZ, we look from the positive X direction. I'll think how to express this in coordinate form, then edit again.