我正在做一件事情,其中有一个在坐标系A中的平面,上面已经有一些点。我还有一个在空间中的法向量N。如何旋转坐标系A上的点,使得底层的平面与N具有相同的法向量方向?
想知道是否有人有好的想法来完成这个问题。谢谢。
M
为您当前平面法向量,N
为您想要旋转到的平面法向量。如果M == N
,您可以立即停止并保留原始点。计算旋转角度:
costheta = dot(M,N)/(norm(M)*norm(N))
axis = unitcross(M, N)
其中unitcross
是一个函数,它执行叉积并将其归一化为单位向量,即unitcross(a, b) = cross(a, b) / norm(cross(a, b))
。正如user1318499在评论中指出的那样,如果M == N
,这一步可能会导致错误,除非你的unitcross
实现在a == b
时返回(0,0,0)
。
根据轴和角度计算旋转矩阵:
c = costheta
s = sqrt(1-c*c)
C = 1-c
rmat = matrix([ x*x*C+c x*y*C-z*s x*z*C+y*s ],
[ y*x*C+z*s y*y*C+c y*z*C-x*s ]
[ z*x*C-y*s z*y*C+x*s z*z*C+c ])
其中x
、y
和z
是axis
的分量。该公式在维基百科上有描述(链接)。
对于每个点,计算其在新平面上的相应点,如下:
newpoint = dot(rmat, point)
当然,这并不是唯一的解决方案;正如peterk的答案所提到的,你可以进行无数次可能的旋转,将垂直于M
的平面变换为垂直于N
的平面。这意味着,在你按照上述步骤进行操作之后,你可以围绕N
旋转平面,而你的点将位于不同的位置,但仍在同一个平面内。(换句话说,每个满足你条件的旋转都对应于在N
周围执行上述过程后再进行另一次旋转。)但如果你不在乎你的点最终位于平面中的哪个位置,我认为这种围绕共同轴的旋转是让点进入你想要的平面的最简单方法。
如果你没有M
,但你有起始平面上点的坐标(相对于该平面中的一个原点),你可以通过两个点的位置x1
和x2
计算起始法向量:
M = cross(x1, x2)
(你也可以在这里使用unitcross
,但这并没有任何区别)。如果你有点相对于不在平面上的原点的坐标,你仍然可以这样做,但你需要三个点的位置:
M = cross(x3-x1, x3-x2)
一个单一的向量(即你的法线 - N)是不够的。你需要另外两个向量来表示其他两个维度。(想象一下,你的三维空间仍然可以围绕着法线旋转/旋转,并且你需要另外两个向量来确定它)。一旦你有了法线和平面上的另一个向量,第三个向量应该很容易找到(根据你的系统是左手系还是右手系)。
确保这三个向量都被标准化(长度为1),并将它们放入矩阵中;使用该矩阵来转换你的三维空间中的任何点(使用矩阵乘法)。这应该会给你新的坐标。
axis
的组成部分是出现在旋转矩阵公式中的x
、y
和z
。 - David Zd
分量移动平面,我该怎么做? - padawanunitcross
实现的一部分,但让我编辑一下关于它的注释。 - David Z