import math, types
try:
import Numeric
NUMERIC = 1
except ImportError:
NUMERIC = 0
class quaternion:
def __init__(self, a = 0.0, b = 0.0, c = 0.0, d = 0.0, real = None, i = None, imag = None, j = None, k = None):
if real is not None:
a = real
if imag is not None:
b = imag
if i is not None:
b = i
if j is not None:
c = j
if k is not None:
d = k
if isinstance(a, quaternion):
self.__dict__['a'] = a.a
self.__dict__['b'] = a.b
self.__dict__['c'] = a.c
self.__dict__['d'] = a.d
elif type(a) is types.ComplexType:
self.__dict__['a'] = a.real
self.__dict__['b'] = a.imag
self.__dict__['c'] = 0.0
self.__dict__['d'] = 0.0
else:
self.__dict__['a'] = float(a)
self.__dict__['b'] = 0.0
self.__dict__['c'] = 0.0
self.__dict__['d'] = 0.0
if isinstance(b, quaternion):
self.__dict__['a'] = self.a - b.b
self.__dict__['b'] = self.b + b.a
self.__dict__['c'] = self.c - b.d
self.__dict__['d'] = self.d + b.c
elif type(b) is types.ComplexType:
self.__dict__['a'] = self.a - b.imag
self.__dict__['b'] = self.b + b.real
else:
self.__dict__['b'] = self.b + float(b)
if isinstance(c, quaternion):
self.__dict__['a'] = self.a - c.c
self.__dict__['b'] = self.b + c.d
self.__dict__['c'] = self.c + c.a
self.__dict__['d'] = self.d - c.b
elif type(c) is types.ComplexType:
self.__dict__['c'] = self.c + c.real
self.__dict__['d'] = self.d - c.imag
else:
self.__dict__['c'] = self.c + float(c)
if isinstance(d, quaternion):
self.__dict__['a'] = self.a - d.d
self.__dict__['b'] = self.b - d.c
self.__dict__['c'] = self.c + d.b
self.__dict__['d'] = self.d + d.a
elif type(d) is types.ComplexType:
self.__dict__['c'] = self.c + d.imag
self.__dict__['d'] = self.d + d.real
else:
self.__dict__['d'] = self.d + float(d)
def __getattr__(self, name):
global NUMERIC
if name == 'real':
return self.a
elif name in ('imag', 'i'):
return self.b
elif name == 'j':
return self.c
elif name == 'k':
return self.d
elif name == 'matrix3':
self.__dict__['matrix3'] = [[1.0 - 2.0*(self.c**2 + self.d**2),
2.0*(self.b*self.c - self.d*self.a),
2.0*(self.d*self.b + self.c*self.a)],
[2.0*(self.b*self.c + self.d*self.a),
1.0 - 2.0*(self.d**2 + self.b**2),
2.0*(self.c*self.d - self.b*self.a)],
[2.0*(self.d*self.b - self.c*self.a),
2.0*(self.c*self.d + self.b*self.a),
1.0 - 2.0 * (self.c**2 + self.b**2)]]
if NUMERIC:
self.__dict__['matrix3'] = Numeric.array(self.__dict__['matrix3'])
return self.__dict__['matrix3']
elif name == 'matrix4':
self.__dict__['matrix4'] = [[1.0 - 2.0*(self.c**2 + self.d**2),
2.0*(self.b*self.c - self.d*self.a),
2.0*(self.d*self.b + self.c*self.a),
0.0],
[2.0*(self.b*self.c + self.d*self.a),
1.0 - 2.0*(self.d**2 + self.b**2),
2.0*(self.c*self.d - self.b*self.a),
0.0],
[2.0*(self.d*self.b - self.c*self.a),
2.0*(self.c*self.d + self.b*self.a),
1.0 - 2.0 * (self.c**2 + self.b**2),
0.0],
[0.0,
0.0,
0.0,
1.0]]
if NUMERIC:
self.__dict__['matrix4'] = Numeric.array(self.__dict__['matrix4'])
return self.__dict__['matrix4']
else:
raise AttributeError, 'Attribute "%s" not found' % name
def __reset(self):
if self.__dict__.has_key('matrix3'):
del self.__dict__['matrix3']
if self.__dict__.has_key('matrix4'):
del self.__dict__['matrix4']
def __setattr__(self, name, value):
if name in ('a', 'real'):
self.__reset()
if isinstance(value, quaternion):
self.__dict__['a'] = value.a
self.__dict__['b'] = self.b + value.b
self.__dict__['c'] = self.c + value.c
self.__dict__['d'] = self.d + value.d
elif type(value) is types.ComplexType:
self.__dict__['a'] = value.real
self.__dict__['b'] = self.b + value.imag
else:
self.__dict__['a'] = float(value)
elif name in ('b', 'imag', 'i'):
self.__reset()
if isinstance(value, quaternion):
self.__dict__['a'] = self.a - value.b
self.__dict__['b'] = value.a
self.__dict__['c'] = self.c - value.d
self.__dict__['d'] = self.d + value.c
elif type(value) is types.ComplexType:
self.__dict__['a'] = self.a - value.imag
self.__dict__['b'] = value.real
else:
self.__dict__['b'] = float(value)
elif name in ('c', 'j'):
self.__reset()
if isinstance(value, quaternion):
self.__dict__['a'] = self.a - value.c
self.__dict__['b'] = self.b + value.d
self.__dict__['c'] = value.a
self.__dict__['d'] = self.d - value.b
elif type(value) is types.ComplexType:
self.__dict__['c'] = value.real
self.__dict__['d'] = self.d - value.imag
else:
self.__dict__['c'] = float(value)
elif name in ('d', 'k'):
self.__reset()
if isinstance(value, quaternion):
self.__dict__['a'] = self.a - value.d
self.__dict__['b'] = self.b - value.c
self.__dict__['c'] = self.c + value.b
self.__dict__['d'] = value.a
elif type(value) is types.ComplexType:
self.__dict__['c'] = self.c + value.imag
self.__dict__['d'] = value.real
else:
self.__dict__['d'] = float(value)
elif name in ('matrix3', 'matrix4'):
raise AttributeError, 'Attribute "%s" is read-only.' % name
else:
self.__dict__[name] = value
def __len__(self):
return 4
def __setitem__(self, index, value):
if index == 0:
self.a = value
elif index == 1:
self.b = value
elif index == 2:
self.c = value
elif index == 3:
self.d = value
else:
raise IndexError, 'Index %s out of range' % index
def __getitem__(self, index):
if index == 0:
return self.a
elif index == 1:
return self.b
elif index == 2:
return self.c
elif index == 3:
return self.d
else:
raise IndexError, 'Index %s out of range' % index
def __coerce__(self, x):
if isinstance(x, quaternion):
return (self, x)
x = complex(x)
return (self, quaternion(x.real, x.imag))
def __add__(self, x):
return quaternion(self.a + x.a, self.b + x.b, self.c + x.c, self.d + x.d)
def __sub__(self, x):
return quaternion(self.a - x.a, self.b - x.b, self.c - x.c, self.d - x.d)
def __mul__(self, x):
return quaternion(self.a*x.a - self.b*x.b - self.c*x.c - self.d*x.d,
self.a*x.b + self.b*x.a + self.c*x.d - self.d*x.c,
self.a*x.c + self.c*x.a + self.d*x.b - self.b*x.d,
self.a*x.d + self.d*x.a + self.b*x.c - self.c*x.b)
def __div__(self, x):
return self*x.conj()*(1.0/(x*x.conj()).a)
def __repr__(self):
return 'quaternion(%g, %g, %g, %g)' % (self.a, self.b, self.c, self.d)
def __str__(self):
m = []
for value, post in [(self.a, ''), (self.b, 'i'), (self.c, 'j'), (self.d, 'k')]:
if value:
m.append((value, post))
if len(m):
if m[0][0] == 1 and len(m[0][1]):
x = m[0][1]
else:
x = '%g%s' % m[0]
for value, post in m[1:]:
if value < 0:
x = x + ' - '
else:
x = x + ' + '
if value == 1:
x = x + post
else:
x = '%s%g%s' % (x, abs(value), post)
return x
return '0'
def __abs__(self):
return math.sqrt(self.a**2 + self.b**2 + self.c**2 + self.d**2)
def __pos__(self):
return quaternion(self.a, self.b, self.c, self.d)
def __neg__(self):
return quaternion(-self.a, -self.b, -self.c, -self.d)
def conj(self):
return quaternion(self.a, -self.b, -self.c, -self.d)
def normalize(self):
length = abs(self)
if length:
return self/length
else:
return self
|