我在 3D a,b,c 中有三个向量。现在我想计算一个旋转 r,当它应用于 a 时,会产生一个与 b 平行的结果。然后需要将旋转 r 应用于 c。
我如何在python中做到这一点?可以用 numpy/scipy 做到这一点吗?
使用numpy:
import numpy as np
from numpy import linalg as LA
from math import pi,cos,sin,acos
def rotate(v,angle=0,ref=np.array([0,0,1]),deg=False):
'''Rotates a vector a given angle respect the
given reference. Option: deg=False (default)'''
if(abs(angle) < 1e-5):
return v
if(deg):
angle = angle*pi/180
# Define rotation reference system
ref = versor(ref) # rotation axis
# n1 & n2 are perpendicular to ref, and to themselves
n1 = versor(np.cross(ref,np.array([-ref[1],ref[2],ref[0]])))
n2 = np.cross(ref,n1)
vp = np.inner(v,ref)*ref # parallel to ref vector
vn = v-vp # perpendicular to ref vector
vn_abs = LA.norm(vn)
if(vn_abs < 1e-5):
return v
alp = acos(np.inner(vn,n1)/vn_abs) # angle between vn & n1
if(triprod(ref,n1,vn) < 0):
alp = -alp # correct if necesary
return vp+vn_abs*(n1*cos(alp+angle)+n2*sin(alp+angle))
def triprod(a,b,c):
'''Triple product of vectors: a·(b x c)'''
return np.inner(a,np.cross(b,c))
def versor(v):
'''Unitary vector in the direction of the one given as input'''
v = np.array(v)
return v/LA.norm(v)
###### Test ################################################
a = np.array([3,4,1])
b = np.array([0,-1,2])
c = np.array([1,1,5])
r = acos(np.inner(a,b)/(LA.norm(a)*LA.norm(b)))
ref = versor(np.cross(a,b))
print rotate(c,angle=r,ref=ref)
print r
print ref
我假设“python 的几何库”已经在对该问题的评论中得到了回答。因此,一旦您进行了将“a”平行于“b”的转换,您只需将其应用于“c”
矢量“a”和“b”唯一地定义了一个平面。每个向量都有一个与原点的点差的规范表示,所以你有三个点:'a' 的头部、'b' 的头部和原点。首先计算这个平面。它将有一个形式为 Ax + By + Cz = 0 的方程。
该平面的法线向量定义了旋转轴和旋转方向的符号约定。你只需要一个平面的法线向量,因为它们都是共线的。您可以通过在平面中选取两个非共线向量并用法向量取点积来求解这样的向量。这给出了两个变量中的一对线性方程,您可以使用标准方法(例如 Cramer 规则)求解。在所有这些操作中,如果 A、B 或 C 中的任何一个为零,则需要处理一种特殊情况。
旋转角度由“a”和“b”的点积及其长度的余弦关系给出。角度的符号由“a”、“b”和法线向量的三重乘积确定。现在,您已经获得了所有数据,可以以您可以查找的众多规范形式之一构建旋转矩阵。