我在3D a,b,c中有三个向量。现在我想计算一个旋转r,当它应用于a产生一个平行于b的结果时。然后,旋转r需要应用于c。3D中的旋转
如何在python中执行此操作?可以用numpy/scipy做到这一点吗?
我在3D a,b,c中有三个向量。现在我想计算一个旋转r,当它应用于a产生一个平行于b的结果时。然后,旋转r需要应用于c。3D中的旋转
如何在python中执行此操作?可以用numpy/scipy做到这一点吗?
我会假设“python的几何库”已经在问题的评论中回答了。因此,一旦你有一个平行于'b'的'a'的变换,你就可以将它应用到'c'上。矢量'a'和'b'唯一地定义一个平面。每个矢量都有一个标准表示,作为与原点之间的点差,所以你有三点:'a'的头部,'b'的头部和原点。首先计算这架飞机。它将具有形式为Ax + By + Cz = 0的方程。
该平面的法向矢量定义了旋转轴和旋转方向的符号约定。所有你需要的是一个法线矢量,因为它们都是共线的。你可以通过挑选平面上的两个非共线向量来求解这样一个向量,并将点乘积与法向量相乘。这给出了一对两个变量的线性方程,可以用Cramer法则等标准方法求解。在所有这些操作中,如果A,B或C中的任何一个都为零,则有特殊情况需要处理。
旋转角度由'a'和'b'点积及其长度的余弦关系给出。角度的符号由'a','b'和法向矢量的三重乘积决定。现在,您已经获得了所有数据,以您可以查看的许多规范形式之一构造旋转矩阵。
使用numpy: “在Python好几何库”
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
有一个关于一个问题这是更一般的范围:
http://stackoverflow.com/questions/1076778/good-geometry-library-in-python –
而不是编写另一个SO问题作为答案,最好将这个问题标记为另一个问题的重复。 ;) – erikbwork
@ erikb85另一个问题在范围上更一般;我的问题可能有一个不适用于Stefano Borinis问题的答案。 –