2012-10-30 92 views
1

我在3D a,b,c中有三个向量。现在我想计算一个旋转r,当它应用于a产生一个平行于b的结果时。然后,旋转r需要应用于c。3D中的旋转

如何在python中执行此操作?可以用numpy/scipy做到这一点吗?

+0

有一个关于一个问题这是更一般的范围:
http://stackoverflow.com/questions/1076778/good-geometry-library-in-python –

+0

而不是编写另一个SO问题作为答案,最好将这个问题标记为另一个问题的重复。 ;) – erikbwork

+0

@ erikb85另一个问题在范围上更一般;我的问题可能有一个不适用于Stefano Borinis问题的答案。 –

回答

0

我会假设“python的几何库”已经在问题的评论中回答了。因此,一旦你有一个平行于'b'的'a'的变换,你就可以将它应用到'c'上。矢量'a'和'b'唯一地定义一个平面。每个矢量都有一个标准表示,作为与原点之间的点差,所以你有三点:'a'的头部,'b'的头部和原点。首先计算这架飞机。它将具有形式为Ax + By + Cz = 0的方程。

该平面的法向矢量定义了旋转轴和旋转方向的符号约定。所有你需要的是一个法线矢量,因为它们都是共线的。你可以通过挑选平面上的两个非共线向量来求解这样一个向量,并将点乘积与法向量相乘。这给出了一对两个变量的线性方程,可以用Cramer法则等标准方法求解。在所有这些操作中,如果A,B或C中的任何一个都为零,则有特殊情况需要处理。

旋转角度由'a'和'b'点积及其长度的余弦关系给出。角度的符号由'a','b'和法向矢量的三重乘积决定。现在,您已经获得了所有数据,以您可以查看的许多规范形式之一构造旋转矩阵。

1

使用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