def __isub__(self, q) : """ Subtraction operator (-=) that subtracts a quaternion from this one and assigns the difference to itself. Input: q - quaternion or a float value to be subtracted from this one Return: a reference to itself A QuaternionException is raised if 'q' is not an instance of Quaternion, float or int. """ # For a definition of quaternion subtraction, see __sub__ if Quaternion.isQuaternion(q) : self.o -= q.o self.i -= q.i self.j -= q.j self.k -= q.k elif InstanceCheck.isFloat(q) : self.o -= q else: raise QuaternionException("Input must be a quaternion or a float") return self
def __add__(self, q) : """ Implementation of the addition operator '+' of two quaternions. Input: q - quaternion or a float value to be added to this one Return: a new instance of Quaternion A QuaternionException is raised if 'q' is not an instance of Quaternion, float or int. """ # Addition of quaternions is trivial: # # (a1 + b1*i + c1*j + d1*k) + (a2 + b2*i + c2*j + d2*k) = # = ( (a1+a2) + (b1+b2)*i + (c1+c2)*j + (d1+d2)*k ) if Quaternion.isQuaternion(q) : return Quaternion( self.o + q.o, self.i + q.i, self.j + q.j, self.k + q.k ) elif InstanceCheck.isFloat(q) : return Quaternion( self.o + q, self.i, self.j, self.k ) else: raise QuaternionException("Input must be a quaternion or a float")
def __iadd__(self, q) : """ Addition operator (+=) that adds a quaternion to this one and assigns the sum to itself. Input: q - quaternion or a float value to be added to this one Return: a reference to itself A QuaternionException is raised if 'q' is not an instance of Quaternion, float or int. """ # For a definition of quaternion addition, see __add__ if Quaternion.isQuaternion(q) : self.o += q.o self.i += q.i self.j += q.j self.k += q.k elif InstanceCheck.isFloat(q) : self.o += q else: raise QuaternionException("Input must be a quaternion or a float") return self
def __sub__(self, q) : """ Implementation of the subtraction operator '-' of two quaternions. Input: q - quaternion or a float value to be subtracted from this one Return: a new instance of Quaternion A QuaternionException is raised if 'q' is not an instance of Quaternion, float or int. """ # Subtraction of quaternions is trivial: # # (a1 + b1*i + c1*j + d1*k) - (a2 + b2*i + c2*j + d2*k) = # = ( (a1-a2) + (b1-b2)*i + (c1-c2)*j + (d1-d2)*k ) if Quaternion.isQuaternion(q) : return Quaternion( self.o - q.o, self.i - q.i, self.j - q.j, self.k - q.k ) elif InstanceCheck.isFloat(q) : return Quaternion( self.o - q, self.i, self.j, self.k ) else: raise QuaternionException("Input must be a quaternion or a float")
def setZ(self, z=0.0): """ Sets point's z-component. Other components are not changed. A PointException is raised if x is not a float or integer value. """ if InstanceCheck.isFloat(z): self.z = z else: raise PointException("Invalid input argument")
def setQ(self, o=0.0, i=0.0, j=0.0, k=0.0) : """ Assigns values of all quaternion's components. Input: o - scalar component of the quaternion (default: 0) i - component 'i' of the quaternion (default: 0) j - component 'j' of the quaternion (default: 0) k - component 'k' of the quaternion (default: 0) Alternatively 'o' may be a quaternion. In this case, its components are copied into self's ones and all other input arguments are ignored. A QuaternionExceptionxception is raised if any argument is not an instance of supported types (int, float, Quaternion). """ if Quaternion.isQuaternion(o) : # If o is a quaternion, simply copy its components... self.o = o.o self.i = o.i self.j = o.j self.k = o.k else: # otherwise check if all inputs are floats or integers... if not ( InstanceCheck.isFloat(o) and InstanceCheck.isFloat(i) and InstanceCheck.isFloat(j) and InstanceCheck.isFloat(k) ) : raise QuaternionException("Invalid input arguments") # if they are, just assign their values to quaternion's components self.o = o; self.i = i; self.j = j; self.k = k; return self
def __init__(self, x=0.0, y=0.0, z=0.0): """ A "constructor" that initializes a point Input: x - x component of a point/vector y - y component of a point/vector z - z component of a point/vector 'x' may also be an instance of Point3D. In this case, the other arguments are ignored and the method acts as a copy constructor. A PointException is raised if input arguments are of invalid types. """ if InstanceCheck.isFloat(x) and InstanceCheck.isFloat(y) and InstanceCheck.isFloat(z): self.x = x self.y = y self.z = z elif Point3D.isPoint3D(x): self.setPoint(x) else: raise PointException("Invalid input arguments")
def setK(self, k=0.0) : """ Assigns the component 'k' of the quaternion. Input: k - value of the component 'k' (default: 0) Raises a QuaternionException if 'k' is not an instance of a supported type (float or int). """ if not InstanceCheck.isFloat(k) : raise QuaternionException("Invalid input argument") self.k = k return self
def setI(self, i=0.0) : """ Assigns the component 'i' of the quaternion. Input: i - value of the component 'i' (default: 0) Raises a QuaternionException if 'i' is not an instance of a supported type (float or int). """ if not InstanceCheck.isFloat(i) : raise QuaternionException("Invalid input argument") self.i = i; return self
def setScalar(self, o=0.0) : """ Assigns the scalar component of the quaternion. Input: o - value of the scalar component (default: 0) Raises a QuaternionException if 'o' is not an instance of a supported type (float or int). """ if not InstanceCheck.isFloat(o) : raise QuaternionException("Invalid input argument") self.o = o return self
def setAngle(self, angle=0.0): """ Sets a new angle of rotation. Rotation vector's components remain unmodified. Input: - angle - angle of rotation in radians (default: 0) A RotationException is raised if 'angle' is not a float or integer value. """ if not InstanceCheck.isFloat(angle): raise RotationException("Angle must be float value") self.__theta = angle self.__update()
def __mul__(self, q) : """ Implementation of the multiplication operator '*' of two quaternions. Note that multiplication of quaternions is not commutative: (p*q != q*p) Input: q - quaternion or a float value to be multiplied by this one Return: a new instance of Quaternion A QuaternionException is raised if 'q' is not an instance of Quaternion, float or int. """ # From the following definitions: # i*i = j*j = k*k = -1, # i*j = k, j*i = -k, j*k = i, k*j = -i, k*i = j and i*k = -j, # the following formula can be quickly derived: # # (a1 + b1*i + c1*j + d1*k) * (a2 + b2*i + c2*j + d2*k) = # = (a1*a2 - b1*b2 - c1*c2 - d1*d2) + # + (a1*b2 + b1*a2 + c1*d2 - d1*c2) * i + # + (a1*c2 - b1*d2 + c1*a2 + d1*b2) * j + # + (a1*d2 + b1*c2 - c1*b2 + d1*a2) * k # # Note: The following script for GNU Octave or Matlab can be used # for a quick unit test of the function: # http://mind.cog.jhu.edu/courses/680/octave/Installers/Octave/Octave.OSX10.6/Applications/MATLAB_R2009b.app/toolbox/aero/aero/quatmultiply.m if Quaternion.isQuaternion(q) : return Quaternion( self.o * q.o - self.i * q.i - self.j * q.j - self.k * q.k, self.o * q.i + self.i * q.o + self.j * q.k - self.k * q.j, self.o * q.j - self.i * q.k + self.j * q.o + self.k * q.i, self.o * q.k + self.i * q.j - self.j * q.i + self.k * q.o ) elif InstanceCheck.isFloat(q) : return Quaternion( self.o * q, self.i * q, self.j * q, self.k * q ) else: raise QuaternionException("Input must be a quaternion or a float")
def __imul__(self, q) : """ Multiplication operator (*=) that multiplies this by a quaternion and assigns the product to itself. Input: q - quaternion or a float value to be multiplied to this one Return: a reference to itself A QuaternionException is raised if 'q' is not an instance of Quaternion, float or int. """ # For a definition of quaternion multiplication, see __mul__ if Quaternion.isQuaternion(q) : # From maintanance poit of view, this would # a more elegant solution: #qaux = self * q; #self.o = qaux.o; #self.i = qaux.i #self.j = qaux.j #self.k = qaux.k # However, this one slightly reduces overhead with # instantiation and destruction of another instance of Quaternion: self.o, self.i, self.j, self. k = \ self.o * q.o - self.i * q.i - self.j * q.j - self.k * q.k, \ self.o * q.i + self.i * q.o + self.j * q.k - self.k * q.j, \ self.o * q.j - self.i * q.k + self.j * q.o + self.k * q.i, \ self.o * q.k + self.i * q.j - self.j * q.i + self.k * q.o elif InstanceCheck.isFloat(q) : self.o *= q self.i *= q self.j *= q self.k *= q else: raise QuaternionException("Input must be a quaternion or a float") return self
def __init__(self, rx=0.0, ry=0.0, rz=0.0, angle=0.0): """ A "constructor" that initializes an object.__class__ Input: - rx - x - component of the vector (default: 0) - ry - y - component of the vector (default: 0) - rz - z - component of the vector (default: 0) - angle - angle of rotation in radians (default: 0) 'rx' may also be an instance of a Point3D. In this case, ry and rz are ignored and rx's components are copied into this object. Note that the vector will automatically be converted into a unit vector. A RotationException is raised if input arguments are of invalid types. """ if not InstanceCheck.isFloat(angle): raise RotationException("Angle must be a float value") self.__theta = angle self.setAxis(rx, ry, rz)