import math class Vector: ''' a class that looks like a list, but has some extras for vector operations ''' def __init__(self, x=0, y=0, z=0): if type(x).__name__ == 'list': if len(x) == 3: self.x = x[0] self.y = x[1] self.z = x[2] elif len(x) == 2: self.x = x[0] self.y = x[1] self.z = 0 elif len(x) == 1: self.x = x[0] self.y = 0 self.z = 0 elif type(x).__name__ in ['int', 'float', 'float64']: self.x = x self.y = y self.z = z else: #TODO: make proper type check here! raise TypeError('Vector() doesn\'t accept {} as type.'.format(type(x).__name__)) self.v = [self.x, self.y, self.z] # # standard maths and python operations def __add__(self, other): return Vector(self.x + other.x, self.y + other.y, self.z + other.z) def __radd__(self, other): return self.__add__(other) def __sub__(self, other): return self.__add__(other * -1) def __mul__(self, other): if type(other).__name__ == 'int' or type(other).__name__ == 'float': return Vector([i*other for i in self.v]) else: raise TypeError('__mul__ only works with int and float as 2nd operand!') def __rmul__(self, other): return self.__mul__(other) def __div__(self, other): return self.__truediv__(other) def __truediv__(self, other): #TODO: make it with __mul__ if type(other).__name__ == 'int' or type(other).__name__ == 'float': return Vector(self.x / other, self.y / other, self.z / other, ) else: raise TypeError('__truediv__ only works with int and float as 2nd operand!') def __len__(self): return 3 def __repr__(self): return str(self.v) def __getitem__(self, key): return [self.x, self.y, self.z][key] def getlist(self): return [self.x, self.y, self.z] # # special vetor operations def magn(self): ''' returns the "length" of this vector ''' return math.sqrt(math.pow(self.x,2) + math.pow(self.y,2) + math.pow(self.z,2)) def magn2d(self): ''' returns the "length" of this vector, omitting the z comonent''' return math.sqrt(math.pow(self.x,2) + math.pow(self.y,2)) def norm(self): ''' returns a vector that has lenght of 1 ''' return Vector([i/self.magn() for i in self.v]) def dotp(self, other): ''' return the dot product(skalarprodukt) ''' return self.x * other.x + self.y * other.y + self.z * other.z def proj(self, other): ''' return the projection of this vector on the 'other' vector ''' dp = self.dotp(other) nrm = other / math.pow(other.magn(),2) return dp * nrm def rot(self, a): ''' return the vector that has been rotated around its z-axis ''' x = self.x * math.cos(a) - self.y * math.sin(a) y = self.x * math.sin(a) + self.y * math.cos(a) return Vector(x, y, self.z) def angle(self, a): ''' return angle between two vectors (but it lacks orientation!) ''' return math.acos(self.dotp(a) / ( self.magn() * a.magn())) def tospherical(self): ''' return cartesian self to spherical coordinates returns: radial, azimuth, polar ''' radial = math.sqrt(self.x **2 + self.y **2 + self.z **2 ) azimuth = math.acos(self.z / radial) polar = math.atan2(self.y, self.x) return [radial, azimuth, polar] def tocartesian(self): ''' if for some reason this vector is defined in sperical coordinates, this function will return the corresponding cartesian coordinates. ''' x = self.x * math.sin(self.y) * math.cos(self.z) y = self.x * math.sin(self.y) * math.sin(self.z) z = self.x * math.cos(self.y) return Vector(x, y, z) # # testing area if __name__ == "__main__": v0 = Vector(1,1,1) #print Vector(v0.tospherical()).tocartesian()