我在3D空间中有一组数据点,显然都落在特定的平面上。我使用PCA来计算平面参数。 PCA的第3个组成部分给出了平面的法向矢量(最弱的分量)。
接下来我要做的是将所有点转换到所述平面上并在2D中查看它。
我的想法是做以下事情:
现在我一直在寻找正确的旋转操作。我尝试使用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.7767,0.0467)已经失败了。
答案 0 :(得分:11)
如果你有一架飞机,你有一个法线向量和一个原点。我根本不会做任何“轮换”。你的答案只是一些矢量操作。
如果您已经有交叉和点产品功能,那么这只是几行代码。我知道它有效,因为我写的大多数3D电子游戏都是这样工作的。
技巧:
答案 1 :(得分:1)
怎么样:
将法向量分解为XY平面中的向量和Z向量。然后围绕Z轴应用旋转以将XY矢量与其中一个轴对齐。然后找到带有Z轴的法线的点积,并沿着你排列的X,Y旋转。
我们的想法是将法线向量与Z对齐,并且通过这样做,您的平面现在是XY平面。
答案 2 :(得分:1)
这是在 Python 中得到的公认答案:
import numpy as np
def rotate(points, normal, around):
# Let's rotate the points such that the normal is the new Z axis
# Following https://stackoverflow.com/questions/1023948/rotate-normal-vector-onto-axis-plane
old_x_axis = np.array([1, 0, 0])
z_axis = normal
y_axis = np.cross(old_x_axis, z_axis)
x_axis = np.cross(z_axis, y_axis)
axis = np.stack([x_axis, y_axis, z_axis])
return np.dot(points - around, axis.T)
points = np.array([
[0, 1, 1],
[0, 1, 0.2],
[1, 0, -7]
])
v1 = points[1] - points[0]
v2 = points[2] - points[0]
normal = np.cross(v1, v2)
print("rotated points", rotate(points, normal, points[0]))
答案 3 :(得分:0)
虽然还有其他有趣的回答,但这是我们在等待答案时想出的解决方案:
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;
(它正在返回一个有希望的正确的双旋转矩阵)
我们之前和之前修复的缺陷是esp。处理X分量的符号,余弦计算中没有涉及。这使我们向错误的方向旋转一次(以180°角旋转)。
我希望我也有时间尝试Nosredna的解决方案!避免三角学总是好的。