Initial revision
This commit is contained in:
109
intern/python/modules/util/quat.py
Normal file
109
intern/python/modules/util/quat.py
Normal file
@@ -0,0 +1,109 @@
|
||||
"""Quaternion module
|
||||
|
||||
This module provides conversion routines between Matrices, Quaternions (rotations around
|
||||
an axis) and Eulers.
|
||||
|
||||
(c) 2000, onk@section5.de """
|
||||
|
||||
# NON PUBLIC XXX
|
||||
|
||||
from math import sin, cos, acos
|
||||
from util import vect
|
||||
reload(vect)
|
||||
|
||||
Vector = vect.Vector
|
||||
|
||||
Matrix = vect.Matrix
|
||||
|
||||
class Quat:
|
||||
"""Simple Quaternion class
|
||||
|
||||
Usually, you create a quaternion from a rotation axis (x, y, z) and a given
|
||||
angle 'theta', defining the right hand rotation:
|
||||
|
||||
q = fromRotAxis((x, y, z), theta)
|
||||
|
||||
This class supports multiplication, providing an efficient way to
|
||||
chain rotations"""
|
||||
|
||||
def __init__(self, w = 1.0, x = 0.0, y = 0.0, z = 0.0):
|
||||
self.v = (w, x, y, z)
|
||||
|
||||
def asRotAxis(self):
|
||||
"""returns rotation axis (x, y, z) and angle phi (right hand rotation)"""
|
||||
phi2 = acos(self.v[0])
|
||||
if phi2 == 0.0:
|
||||
return Vector(0.0, 0.0, 1.0), 0.0
|
||||
else:
|
||||
s = 1 / (sin(phi2))
|
||||
|
||||
v = Vector(s * self.v[1], s * self.v[2], s * self.v[3])
|
||||
return v, 2.0 * phi2
|
||||
|
||||
def __mul__(self, other):
|
||||
w1, x1, y1, z1 = self.v
|
||||
w2, x2, y2, z2 = other.v
|
||||
|
||||
w = w1*w2 - x1*x2 - y1*y2 - z1*z2
|
||||
x = w1*x2 + x1*w2 + y1*z2 - z1*y2
|
||||
y = w1*y2 - x1*z2 + y1*w2 + z1*x2
|
||||
z = w1*z2 + x1*y2 - y1*x2 + z1*w2
|
||||
return Quat(w, x, y, z)
|
||||
|
||||
def asMatrix(self):
|
||||
w, x, y, z = self.v
|
||||
|
||||
v1 = Vector(1.0 - 2.0 * (y*y + z*z), 2.0 * (x*y + w*z), 2.0 * (x*z - w*y))
|
||||
v2 = Vector(2.0 * (x*y - w*z), 1.0 - 2.0 * (x*x + z*z), 2.0 * (y*z + w*x))
|
||||
v3 = Vector(2.0 * (x*z + w*y), 2.0 * (y*z - w*x), 1.0 - 2.0 * (x*x + y*y))
|
||||
|
||||
return Matrix(v1, v2, v3)
|
||||
|
||||
# def asEuler1(self, transp = 0):
|
||||
# m = self.asMatrix()
|
||||
# if transp:
|
||||
# m = m.transposed()
|
||||
# return m.asEuler()
|
||||
|
||||
def asEuler(self, transp = 0):
|
||||
from math import atan, asin, atan2
|
||||
w, x, y, z = self.v
|
||||
x2 = x*x
|
||||
z2 = z*z
|
||||
tmp = x2 - z2
|
||||
r = (w*w + tmp - y*y )
|
||||
phi_z = atan2(2.0 * (x * y + w * z) , r)
|
||||
phi_y = asin(2.0 * (w * y - x * z))
|
||||
phi_x = atan2(2.0 * (w * x + y * z) , (r - 2.0*tmp))
|
||||
|
||||
return phi_x, phi_y, phi_z
|
||||
|
||||
def fromRotAxis(axis, phi):
|
||||
"""computes quaternion from (axis, phi)"""
|
||||
phi2 = 0.5 * phi
|
||||
s = sin(phi2)
|
||||
return Quat(cos(phi2), axis[0] * s, axis[1] * s, axis[2] * s)
|
||||
|
||||
#def fromEuler1(eul):
|
||||
#qx = fromRotAxis((1.0, 0.0, 0.0), eul[0])
|
||||
#qy = fromRotAxis((0.0, 1.0, 0.0), eul[1])
|
||||
#qz = fromRotAxis((0.0, 0.0, 1.0), eul[2])
|
||||
#return qz * qy * qx
|
||||
|
||||
def fromEuler(eul):
|
||||
from math import sin, cos
|
||||
e = eul[0] / 2.0
|
||||
cx = cos(e)
|
||||
sx = sin(e)
|
||||
e = eul[1] / 2.0
|
||||
cy = cos(e)
|
||||
sy = sin(e)
|
||||
e = eul[2] / 2.0
|
||||
cz = cos(e)
|
||||
sz = sin(e)
|
||||
|
||||
w = cx * cy * cz - sx * sy * sz
|
||||
x = sx * cy * cz - cx * sy * sz
|
||||
y = cx * sy * cz + sx * cy * sz
|
||||
z = cx * cy * sz + sx * sy * cz
|
||||
return Quat(w, x, y, z)
|
Reference in New Issue
Block a user