""" by K. Urner, 4D Solutions Jan 08, 2001: fixed Svector so 0<=theta<2pi vs -pi=0 and self.xyz[1]<0: theta = 360 + theta if r==0: phi=0.0 else: phi = math.acos(self.xyz[2]/r) * rad2deg return (r,phi,theta) def quadray(self): """return (a,b,c,d) quadray based on current (x,y,z)""" x=self.xyz[0] y=self.xyz[1] z=self.xyz[2] a = (2./root2) * ((x>=0)*x + (y>=0)*y + (z>=0)*z) b = (2./root2) * ((x<0)*(-x) + (y<0)*(-y) + (z>=0)*z) c = (2./root2) * ((x<0)*(-x) + (y>=0)*y + (z<0)*(-z)) d = (2./root2) * ((x>=0)*x + (y<0)*(-y) + (z<0)*(-z)) return self.norm((a,b,c,d)) def norm(self,plist): """Normalize such that 4-tuple all non-negative members.""" return tuple(map(sub,plist,[min(plist)]*4)) def norm0(self): """Normalize such that sum of 4-tuple members = 0""" q = self.quadray() return tuple(map(sub,q,[reduce(add,q)/4.0]*4)) class Qvector(Vector): """Subclass of Vector that takes quadray coordinate args""" def __init__(self,arg,*flag): """Initialize a vector at an (a,b,c,d) tuple (= arg). NOTE: in accompanying essay, xyz units = sphere diameter i.e. Vector((1,0,0)).length() is 1 D, therefore quadray inputs must be scaled by 1/2 to fit this context, i.e. tetra edge defined by 2 basis quadrays = 1 D.""" if len(arg)==3: arg = Vector(arg).quadray() # if 3-tuple passed self.coords = self.norm(arg) a,b,c,d = self.coords self.xyz = ((0.5/root2) * (a - b - c + d), (0.5/root2) * (a - b + c - d), (0.5/root2) * (a + b - c - d)) def __repr__(self): return "Qvector " + str(self.coords) def dot(self,v1): """Return the dot product of self with another vector. return a scalar""" scalar = 0 return 0.5*reduce(add,map(mul,self.norm0(),v1.norm0())) def cross(self,v1): """Return the cross product of self with another vector. return a Qvector""" A=Qvector((1,0,0,0)) B=Qvector((0,1,0,0)) C=Qvector((0,0,1,0)) D=Qvector((0,0,0,1)) a1,b1,c1,d1 = v1.quadray() a2,b2,c2,d2 = self.quadray() k= (2.0**0.5)/4.0 sum = (A*c1*d2 - A*d1*c2 - A*b1*d2 + A*b1*c2 + A*b2*d1 - A*b2*c1 - B*c1*d2 + B*d1*c2 + b1*C*d2 - b1*D*c2 - b2*C*d1 + b2*D*c1 + a1*B*d2 - a1*B*c2 - a1*C*d2 + a1*D*c2 + a1*b2*C - a1*b2*D - a2*B*d1 + a2*B*c1 + a2*C*d1 - a2*D*c1 - a2*b1*C + a2*b1*D) return k*sum def quadray(self): return self.coords class Svector(Vector): """Subclass of Vector that takes spherical coordinate args.""" def __init__(self,arg,isxyz=None): # if returning from Vector calc method, spherical is true if isxyz: arg = Vector(arg).spherical() # initialize a vector at an (r,phi,theta) tuple (= arg) r = arg[0] phi = deg2rad * arg[1] theta = deg2rad * arg[2] self.coords = tuple(map(lambda x:round(x,15), (r * math.cos(theta) * math.sin(phi), r * math.sin(theta) * math.sin(phi), r * math.cos(phi)))) self.xyz = self.coords def __repr__(self): return "Svector " + str(self.spherical()) def dot(a,b): return a.dot(b) def cross(a,b): return a.cross(b) def angle(a,b): return a.angle(b) def length(a): return a.length()