将法线向量旋转到轴平面上
-
06-07-2019 - |
题
我在 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)来说,这已经失败了。
解决方案
如果你有一个平面,你就有一个法向量和一个原点。我根本不会做任何“轮换”。只需进行一些向量运算即可得到答案。
- 我们将平面的法向量称为新的 z 轴。
- 您可以通过将旧的 x 轴与新的 z 轴(平面的法线)交叉来生成新的 y 轴。
- 通过将新的 z 与新的 y 交叉来生成新的 x 轴。
- 将所有新轴向量变成单位向量(长度为 1)。
- 对于您拥有的每个点,创建一个从新原点到该点的向量(点的向量减去 -plane_origin)。只需用新的 x 和新 y 单位向量点,你就得到一对 (x,y),你可以绘制!
如果您已经有了叉积和点积函数,那么这只是几行代码。我知道它是有效的,因为我编写的大多数 3D 视频游戏都是这样工作的。
技巧:
- 注意向量指向的方向。如果它们指向错误的方向,则对所得向量取反或更改叉积的顺序。
- 如果您的平面法线与原始 x 轴完全相同,则会遇到麻烦。
其他提示
怎么样:
将法线向量分解为 XY 平面中的向量和 Z 向量。然后绕 Z 轴旋转,使 XY 向量与其中一个轴对齐。然后找到法线与 Z 轴的点积,并沿着您所对齐的 X、Y 中的任意一个旋转。
这个想法是将法线向量与 Z 对齐,这样你的平面现在就是 XY 平面。
尽管还有其他有趣的回应,但这是我们在等待答案时找到的解决方案:
function roti = magic_cosini(n)
b = acos(n(2) / sqrt(n(1)*n(1) + n(2)*n(2)));
bwinkel = b * 360 / 2 / pi;
if (n(1) >= 0)
rotb = [cos(-b) -sin(-b) 0; sin(-b) cos(-b) 0; 0 0 1];
else
rotb = [cos(-b) sin(-b) 0; -sin(-b) cos(-b) 0; 0 0 1];
end
n2 = n * rotb;
a = acos(n2(3) / sqrt(n2(2)*n2(2) + n2(3)*n2(3)));
awinkel = a * 360 / 2 / pi;
rota = [1 0 0; 0 cos(-a) -sin(-a); 0 sin(-a) cos(-a)];
roti = rotb * rota;
(它返回一个希望正确的双旋转矩阵)
我们之前遇到并在这里修复的缺陷是特别是。处理 X 分量的符号,余弦计算中未涵盖该符号。这让我们旋转了一次错误的方向(旋转180°-角度)。
我希望我也能抽出时间尝试Nosredna的解决方案!避免使用三角学总是好的。
不隶属于 StackOverflow