3D旋转

时间:2012-10-30 10:15:21

标签: python 3d geometry

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

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

2 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:0)

我将假设“python的几何库”已在问题的评论中得到解答。因此,一旦你进行了一个'a'并行'b'的转换,你只需将它应用于'c'

矢量'a'和'b'唯一地定义一个平面。每个向量都有一个规范表示作为与原点的点差,所以你有三个点:'a'的头部,'b'的头部和原点。首先计算这个平面。它将具有Ax + By + Cz = 0形式的等式。

此平面的法线向量定义旋转轴和旋转方向的符号约定。你需要的只是平面的一个法向量,因为它们都是共线的。您可以通过在平面中拾取两个非共线矢量并使用正常矢量获取点积来求解这样的矢量。这给出了两个变量中的线性方程组,您可以使用标准方法(如Cramer规则)解决这两个方程。在所有这些操作中,如果A,B或C中的任何一个为零,则需要处理特殊情况。

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