"""Functions to work with vectors""" import math import maya.OpenMaya as OpenMaya from pymel.core import datatypes ############################################# # VECTOR OPERATIONS ############################################# def getDistance(v0, v1): """Get the distance between 2 vectors Arguments: v0 (vector): vector A. v1 (vector): vector B. Returns: float: Distance length. """ v = v1 - v0 return v.length() def getDistance2(obj0, obj1): """Get the distance between 2 objects. Arguments: obj0 (dagNode): Object A obj1 (dagNode): Object B Returns: float: Distance length """ v0 = obj0.getTranslation(space="world") v1 = obj1.getTranslation(space="world") v = v1 - v0 return v.length() def linearlyInterpolate(v0, v1, blend=.5): """Get the vector interpolated between 2 vectors. Arguments: v0 (vector): vector A. v1 (vector): vector B. blend (float): Blending value. Returns: vector: The interpolated vector. """ vector = v1 - v0 vector *= blend vector += v0 return vector def getPlaneNormal(v0, v1, v2): """Get the normal vector of a plane (Defined by 3 positions). Arguments: v0 (vector): First position on the plane. v1 (vector): Second position on the plane. v2 (vector): Third position on the plane. Returns: vector: The normal. """ vector0 = v1 - v0 vector1 = v2 - v0 vector0.normalize() vector1.normalize() normal = vector1 ^ vector0 normal.normalize() return normal def getPlaneBiNormal(v0, v1, v2): """Get the binormal vector of a plane (Defined by 3 positions). Arguments: v0 (vector): First position on the plane. v1 (vector): Second position on the plane. v2 (vector): Third position on the plane. Returns: vector: The binormal. """ normal = getPlaneNormal(v0, v1, v2) vector0 = v1 - v0 binormal = normal ^ vector0 binormal.normalize() return binormal def getTransposedVector(v, position0, position1, inverse=False): """Get the transposed vector. Arguments: v (vector): Input Vector. position0 (vector): Position A. position1 (vector): Position B. inverse (bool): Invert the rotation. Returns: vector: The transposed vector. >>> normal = vec.getTransposedVector(self.normal, [self.guide.apos[0], self.guide.apos[1]], [self.guide.apos[-2], self.guide.apos[-1]]) """ v0 = position0[1] - position0[0] v0.normalize() v1 = position1[1] - position1[0] v1.normalize() ra = v0.angle(v1) if inverse: ra = -ra axis = v0 ^ v1 vector = rotateAlongAxis(v, axis, ra) # Check if the rotation has been set in the right order # ra2 = (math.pi *.5 ) - v1.angle(vector) # vector = rotateAlongAxis(v, axis, -ra2) return vector def rotateAlongAxis(v, axis, a): """Rotate a vector around a given axis defined by other vector. Arguments: v (vector): The vector to rotate. axis (vector): The axis to rotate around. a (float): The rotation angle in radians. """ sa = math.sin(a / 2.0) ca = math.cos(a / 2.0) q1 = OpenMaya.MQuaternion(v.x, v.y, v.z, 0) q2 = OpenMaya.MQuaternion(axis.x * sa, axis.y * sa, axis.z * sa, ca) q2n = OpenMaya.MQuaternion(-axis.x * sa, -axis.y * sa, -axis.z * sa, ca) q = q2 * q1 q *= q2n out = OpenMaya.MVector(q.x, q.y, q.z) return out ########################################################## # CLASS ########################################################## class Blade(object): """The Blade object for shifter guides""" def __init__(self, t=datatypes.Matrix()): self.transform = t d = [t.data[j][i] for j in range(len(t.data)) for i in range(len(t.data[0]))] m = OpenMaya.MMatrix() OpenMaya.MScriptUtil.createMatrixFromList(d, m) m = OpenMaya.MTransformationMatrix(m) x = OpenMaya.MVector(1, 0, 0).rotateBy(m.rotation()) y = OpenMaya.MVector(0, 1, 0).rotateBy(m.rotation()) z = OpenMaya.MVector(0, 0, 1).rotateBy(m.rotation()) self.x = datatypes.Vector(x.x, x.y, x.z) self.y = datatypes.Vector(y.x, y.y, y.z) self.z = datatypes.Vector(z.x, z.y, z.z)