将法线向量旋转到轴平面上
我在 3D 空间中有一组数据点,它们显然都落在特定的平面上。 我使用 PCA 来计算平面参数。 PCA 的第三个分量给出了平面的法向量(最弱分量)。
接下来我想做的是将所有点变换到所述平面上并以二维方式查看它。
我的想法是执行以下操作:
- 在平面上找到一个中心点(平均点)
- 从所有数据点中减去它,将它们排列在原点周围
- 旋转法线,使其变为 (0,0,-1)
- 将此旋转应用于所有数据点都
- 使用正交投影(基本上,跳过 z 轴)
现在我一直在寻找正确的旋转操作。 我尝试使用 acos 或 atan 并设置两个旋转矩阵。 似乎两种方法(使用 acos、使用 atan)都给了我错误的结果。 也许你可以在这里帮助我!
Matlab 代码如下:
b = atan(n(1) / n(2));
rotb = [cos(b) -sin(b) 0; sin(b) cos(b) 0; 0 0 1];
n2 = n * rotb;
a = atan(n(1) / n(3));
rota = [cos(a) 0 sin(a); 0 1 0; -sin(a) 0 cos(a)];
n3 = n2 * rotaows:
我期望 n2 的 y 分量为零。 然而,对于向量(-0.6367、0.7697、0.0467)来说,这已经失败了。
I have a set of data points in 3D space which apparently all fall onto a specific plane. I use PCA to compute the plane parameters. The 3rd component of PCA gives me the normal vector of the plane (weakest component).
What I want to do next is to transform all the points onto said plane and look at it in 2D.
My idea was to do the following:
- Find a center point (average point) on the plane
- Substract it from all data points to arrange them around the origin
- Rotate the normal so that it becomes (0,0,-1)
- Apply this rotation to all data points
- Use orthogonal projection (basically, skip z axis)
Now I'm stuck at finding the right rotation operation. I tried working with acos or atan and setting up two rotation matrices. Seems both methods (using acos, using atan) give me the wrong result. Perhaps you can help me out here!
Matlab code follows:
b = atan(n(1) / n(2));
rotb = [cos(b) -sin(b) 0; sin(b) cos(b) 0; 0 0 1];
n2 = n * rotb;
a = atan(n(1) / n(3));
rota = [cos(a) 0 sin(a); 0 1 0; -sin(a) 0 cos(a)];
n3 = n2 * rotaows:
I expect n2
to have y component of zero. However that fails already for the vector (-0.6367, 0.7697, 0.0467).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
如果你有一个平面,你就有一个法向量和一个原点。 我根本不会做任何“轮换”。 只需进行一些向量运算即可得到答案。
如果您已经有了叉积和点积函数,那么这只是几行代码。 我知道它是有效的,因为我编写的大多数 3D 视频游戏都是这样工作的。
技巧:
If you have a plane, you have a normal vector and an origin. I wouldn't do any "rotations" at all. You're just a few vector operations away from your answer.
If you have cross and dot product functions already, this is just a few lines of code. I know it works because most of the 3D videogames I wrote worked this way.
Tricks:
怎么样:
将法线向量分解为 XY 平面上的向量和 Z 向量。 然后绕 Z 轴旋转,使 XY 向量与其中一个轴对齐。 然后找到法线与 Z 轴的点积,并沿着您所对齐的 X、Y 中的任意一个旋转。
这个想法是将法线向量与 Z 对齐,这样你的平面现在就是 XY 平面。
How about:
Decompose the normal vector into a vector in the XY-plane and a Z vector. Then apply a rotation around the Z-axis to line up the XY vector with one of the axis. Then find the dot product of the the normal with the Z-axis, and rotate along which ever of X,Y you lined up with.
The idea is to line the normal vector up with Z, and by doing that your plane is now the XY plane.
这是用 Python 做出的公认答案:
Here's the accepted answer made in Python:
尽管还有其他有趣的回应,但这是我们在等待答案时找到的解决方案:(
它返回一个希望正确的双旋转矩阵)
我们之前遇到并在这里修复的缺陷是特别是。 处理 X 分量的符号,余弦计算中未涵盖该符号。 这让我们旋转了一次错误的方向(旋转180°-角度)。
我希望我也能抽出时间尝试Nosredna的解决方案! 避免使用三角学总是好的。
Although there were other interesting responses, this is the solution we figured out while waiting for answers:
(It's returning a hopefully correct double rotation matrix)
The flaw we had before and fixed here was to esp. deal with the sign of the X component, which was not covered in the cosine computations. This made us rotate in the wrong direction once (rotating with 180° - angle).
I hope I will also find time to try Nosredna's solution! It's always good to avoid trigonometry.