diff options
Diffstat (limited to 'source/blender/freestyle/style_modules_blender/vector.py')
-rwxr-xr-x | source/blender/freestyle/style_modules_blender/vector.py | 241 |
1 files changed, 241 insertions, 0 deletions
diff --git a/source/blender/freestyle/style_modules_blender/vector.py b/source/blender/freestyle/style_modules_blender/vector.py new file mode 100755 index 00000000000..039f262546b --- /dev/null +++ b/source/blender/freestyle/style_modules_blender/vector.py @@ -0,0 +1,241 @@ +# This module defines 3d geometrical vectors with the standard +# operations on them. +# +# Written by: Konrad Hinsen +# Last revision: 1996-1-26 +# + +"""This module defines three-dimensional geometrical vectors. Vectors support +the usual mathematical operations (v1, v2: vectors, s: scalar): + v1+v2 addition + v1-v2 subtraction + v1*v2 scalar product + s*v1 multiplication with a scalar + v1/s division by a scalar + v1.cross(v2) cross product + v1.length() length + v1.normal() normal vector in direction of v1 + v1.angle(v2) angle between two vectors + v1.x(), v1[0] first element + v1.y(), v1[1] second element + v1.z(), v1[2] third element + +The module offers the following items for export: + Vec3D(x,y,z) the constructor for vectors + isVector(x) a type check function + ex, ey, ez unit vectors along the x-, y-, and z-axes (predefined constants) + +Note: vector elements can be any kind of numbers on which the operations +addition, subtraction, multiplication, division, comparison, sqrt, and acos +are defined. Integer elements are treated as floating point elements. +""" + +import math, types + +class Vec3: + + isVec3 = 1 + + def __init__(self, x=0., y=0., z=0.): + self.data = [x,y,z] + + def __repr__(self): + return 'Vec3(%s,%s,%s)' % (`self.data[0]`,\ + `self.data[1]`,`self.data[2]`) + + def __str__(self): + return `self.data` + + def __add__(self, other): + return Vec3(self.data[0]+other.data[0],\ + self.data[1]+other.data[1],self.data[2]+other.data[2]) + __radd__ = __add__ + + def __neg__(self): + return Vec3(-self.data[0], -self.data[1], -self.data[2]) + + def __sub__(self, other): + return Vec3(self.data[0]-other.data[0],\ + self.data[1]-other.data[1],self.data[2]-other.data[2]) + + def __rsub__(self, other): + return Vec3(other.data[0]-self.data[0],\ + other.data[1]-self.data[1],other.data[2]-self.data[2]) + + def __mul__(self, other): + if isVec3(other): + return reduce(lambda a,b: a+b, + map(lambda a,b: a*b, self.data, other.data)) + else: + return Vec3(self.data[0]*other, self.data[1]*other, + self.data[2]*other) + + def __rmul__(self, other): + if isVec3(other): + return reduce(lambda a,b: a+b, + map(lambda a,b: a*b, self.data, other.data)) + else: + return Vec3(other*self.data[0], other*self.data[1], + other*self.data[2]) + + def __div__(self, other): + if isVec3(other): + raise TypeError, "Can't divide by a vector" + else: + return Vec3(_div(self.data[0],other), _div(self.data[1],other), + _div(self.data[2],other)) + + def __rdiv__(self, other): + raise TypeError, "Can't divide by a vector" + + def __cmp__(self, other): + return cmp(self.data[0],other.data[0]) \ + or cmp(self.data[1],other.data[1]) \ + or cmp(self.data[2],other.data[2]) + + def __getitem__(self, index): + return self.data[index] + + def x(self): + return self.data[0] + def y(self): + return self.data[1] + def z(self): + return self.data[2] + + def length(self): + return math.sqrt(self*self) + + def normal(self): + len = self.length() + if len == 0: + raise ZeroDivisionError, "Can't normalize a zero-length vector" + return self/len + + def cross(self, other): + if not isVec3(other): + raise TypeError, "Cross product with non-vector" + return Vec3(self.data[1]*other.data[2]-self.data[2]*other.data[1], + self.data[2]*other.data[0]-self.data[0]*other.data[2], + self.data[0]*other.data[1]-self.data[1]*other.data[0]) + + def angle(self, other): + if not isVec3(other): + raise TypeError, "Angle between vector and non-vector" + cosa = (self*other)/(self.length()*other.length()) + cosa = max(-1.,min(1.,cosa)) + return math.acos(cosa) + + +class Vec2: + + isVec2 = 1 + + def __init__(self, x=0., y=0.): + self.data = [x,y] + + def __repr__(self): + return 'Vec2(%s,%s,%s)' % (`self.data[0]`,\ + `self.data[1]`) + + def __str__(self): + return `self.data` + + def __add__(self, other): + return Vec2(self.data[0]+other.data[0],\ + self.data[1]+other.data[1]) + __radd__ = __add__ + + def __neg__(self): + return Vec2(-self.data[0], -self.data[1]) + + def __sub__(self, other): + return Vec2(self.data[0]-other.data[0],\ + self.data[1]-other.data[1]) + + def __rsub__(self, other): + return Vec2(other.data[0]-self.data[0],\ + other.data[1]-self.data[1]) + + def __mul__(self, other): + if isVec2(other): + return reduce(lambda a,b: a+b, + map(lambda a,b: a*b, self.data, other.data)) + else: + return Vec2(self.data[0]*other, self.data[1]*other) + + def __rmul__(self, other): + if isVec2(other): + return reduce(lambda a,b: a+b, + map(lambda a,b: a*b, self.data, other.data)) + else: + return Vec2(other*self.data[0], other*self.data[1]) + + def __div__(self, other): + if isVec2(other): + raise TypeError, "Can't divide by a vector" + else: + return Vec2(_div(self.data[0],other), _div(self.data[1],other)) + + def __rdiv__(self, other): + raise TypeError, "Can't divide by a vector" + + def __cmp__(self, other): + return cmp(self.data[0],other.data[0]) \ + or cmp(self.data[1],other.data[1]) + + def __getitem__(self, index): + return self.data[index] + + def x(self): + return self.data[0] + def y(self): + return self.data[1] + + def length(self): + return math.sqrt(self*self) + + def normal(self): + len = self.length() + if len == 0: + raise ZeroDivisionError, "Can't normalize a zero-length vector" + return self/len + + #def cross(self, other): +# if not isVec2(other): +# raise TypeError, "Cross product with non-vector" +# return Vec2(self.data[1]*other.data[2]-self.data[2]*other.data[1], +# self.data[2]*other.data[0]-self.data[0]*other.data[2], +# self.data[0]*other.data[1]-self.data[1]*other.data[0]) + + def angle(self, other): + if not isVec2(other): + raise TypeError, "Angle between vector and non-vector" + cosa = (self*other)/(self.length()*other.length()) + cosa = max(-1.,min(1.,cosa)) + return math.acos(cosa) + + + +# Type check + +def isVec3(x): + return hasattr(x,'isVec3') + +def isVec2(x): + return hasattr(x,'isVec2') + +# "Correct" division for arbitrary number types + +def _div(a,b): + if type(a) == types.IntType and type(b) == types.IntType: + return float(a)/float(b) + else: + return a/b + + +# Some useful constants + +ex = Vec3(1.,0.,0.) +ey = Vec3(0.,1.,0.) +ez = Vec3(0.,0.,1.) |