import math
number = [int, float, long, complex]
#----------------------------------------------------simple matrix 2d
class m2(list):
	#very simple 2d matrix for map making

	def __init__(self,w,h,fill=None):	#choose ure width and heitgh
		self.w, self.h = w, h
		for x in range(w*h):
			self.append(fill)
			
	def offset(self,x,y):
		if x > self.w or y > self.h:
			return -1
		return (x + (y*self.w))

	def at(self,x,y,fill=None):
		if x > self.w or y > self.h:
			return -1
		if fill != None:
			self[self.offset(x,y)] = fill
		return self[self.offset(x,y)]
		
	def where(self,fill):
		tmp = self.index(fill)
		return (tmp % self.w, tmp / self.w)
		
	def get_line(self,y,fills=[]):
		tmp = []
		if len(fills) > 0 and len(fills) != self.w:
			return -1
		for x in range(self.w):
			if len(fills) == self.w:
				self.at(x,y,fills[x])
			tmp.append( self.at(x,y))
		return tmp
		
	def get_col(self,x,fills=[]):
		tmp = []
		if len(fills) > 0 and len(fills) != self.h:
			return -1
		for y in range(self.h):
			if len(fills) == self.h:
				self.at(x,y,fills[y])
			tmp.append(self.at(x,y))
		return tmp
#----------------------------------------------------simple vector 2d
class v2(object):
	#very simple 2d vector class
	def __init__(self, x=0.0, y=0.0):
		if type(x) == (tuple or list):
			x,y = x[0],x[1]
		elif type(x) == p2:
			x,y = math.sin(x.radians)*x.radius, math.cos(x.radians)*x.radius
		if (type(x) in number) and (type(y) in number):
        		self.x, self.y = x*1.0, y*1.0
		else:
			self.x,self.y = 0.0, 0.0

 	def __len__(self):
		return 2
	def __repr__(self):
		return 'vector( x=%s y=%s )'%(self.x,self.y)
	#list tuple func
	def __getitem__(self, index):
		if index == 0:
			return self.x
		elif index == 1:
			return self.y

	def __setitem__(self, index, val):
		if type(val) in number:
			if index == 0:
				self.x = val
			elif index == 1:
				self.y = val

	#if statement
	def __eq__(self, other):
		if type(other) == v2:
			if self.x == other.x and self.y == other.y:
				return True
			else:
				return False
	def __ne__(self, other):
		if type(other) == v2:
			if self.x != other.x and self.y != other.y:
				return True
			else:
				return False
	#add
    	def __add__(self, other):
		if type(other) == v2:
			return v2(self.x+other.x,self.y+other.y)
	__radd__ = __add__
    	def __iadd__(self, other):
		if type(other) == v2:
			self.x += other.x
			self.y += other.y
	#sub
	def __sub__(self, other):
		if type(other) == v2:
			return v2(self.x-other.x,self.y-other.y)
	def __rsub__(self, other):
		if type(other) == v2:
			return v2(other.x-self.x,other.y-self.y)
    	def __isub__(self, other):
		if type(other) == v2:
			self.x -= other.x
			self.y -= other.y
	#mul
	def __mul__(self, other):
		if type(other) == v2:
			return v2(self.x*other.x,self.y*other.y)
	__rmul__ = __mul__
	def __imul__(self, other):
		if type(other) == v2:
			self.x *= other.x
			self.y *= other.y
	#div
	def __div__(self, other):
		if type(other) == v2:
			return v2(self.x/other.x,self.y/other.y)
	def __rdiv__(self, other):
		if type(other) == v2:
			return v2(other.x/self.x,other.y/self.y)
	def __idiv__(self, other):
		if type(other) == v2:
			self.x /= other.x
			self.y /= other.y
	def __floordiv__(self, other):
		if type(other) == v2:
			return v2(self.x//other.x,self.y//other.y)
	def __rfloordiv__(self, other):
		if type(other) == v2:
			return v2((other.x//self.x),(other.y//self.y))
	def __ifloordiv__(self, other):
		if type(other) == v2:
			self.x = (self.x // other.x)
			self.y = (self.y // other.y)
	def __truediv__(self, other):
		if type(other) == v2:
			return v2(float(self.x/other.x),float(self.y/other.y))
	def __rtruediv__(self, other):
		if type(other) == v2:
			return v2(float(other.x/self.x),float(other.y/self.y))
	def __itruediv__(self, other):
		if type(other) == v2:
			self.x = float(self.x / other.x)
			self.y = float(self.y / other.y)
	#mod
	def __mod__(self, other):
		if type(other) == v2:
			return v2(self.x%other.x,self.y%other.y)
	def __rmod__(self, other):
		if type(other) == v2:
			return v2(other.x%self.x,other.y%self.y)
	#pow
	def __pow__(self, other):
		if type(other) == v2:
			return v2(self.x**other.x,self.y**other.y)
	def __rpow__(self, other):
		if type(other) == v2:
			return v2(other.x**self.x,other.y**self.y)
	#uno
	def __neg__(self):
		return v2(-abs(self.x),-abs(self.y))
	def __pos__(self):
		return v2(abs(self.x),abs(self.y))
	def __abs__(self):
		return v2(abs(self.x),abs(self.y))
	def __invert__(self):
		return v2(-self.x,-self.y)
	#type
	def __complex__(self):
		return v2(complex(self.x),complex(self.y))
	def __int__(self):
		return v2(int(self.x),int(self.y))
	def __long__(self):
		return v2(long(self.x),long(self.y))
	def __float__(self):
		return v2(float(self.x),float(self.y))
	#some funk
	def get_tuple(self):
		return (self.x,self.y)
	def get_list(self):
		return [self.x,self.y]

#-------------------------------------------------------POXEL 2d

class p2(object):
	def __init__(self, radians=0.0, radius=0.0):
		if type(radians) == (tuple or list):
			radians,radius = radians[0],radians[1]
		elif type(radians) == v2:
			radians, radius = math.atan2(radians.x,radians.y) , math.hypot(radians.x,radians.y)
		if (type(radians) in number) and (type(radius) in number):
        		self.radians, self.radius = radians*1.0, radius*1.0
		else:
			self.radians,self.radius = 0.0, 0.0

 	def __len__(self):
		return 2
	def __repr__(self):
		return 'poxel( radians=%s radius=%s )'%(self.radians,self.radius)
	#list tuple func
	def get_tuple(self):
		return (self.radians, self.radius)
	def get_list(self):
		return [self.radians, self.radius]
	def __getitem__(self, index):
		if index == 0:
			return self.radians
		elif index == 1:
			return self.radius
	def __setitem__(self, index, val):
		if type(val) in number:
			if index == 0:
				self.radians = val
			elif index == 1:
				self.radius = val
	#ZOOM
	def zoom(self,factor=1.0):
		self.radius*=factor
	def __mul__(self, factor):
		if type(factor) in number:
			return p2(self.radians,self.radius*factor)
	def __imul__(self, factor):
		if type(factor) in number:
			self.radius*=factor
	#ROTATE
	def rotate(self,radians=0.0):
		self.radians+=radians
    	def __add__(self, radians):
		if type(radians) in number:
			return p2(self.radians+radians,self.radius)
    	def __iadd__(self, radians):
		if type(radians) in number:
			self.radians+=radians
	def __sub__(self, radians):
		if type(radians) in number:
			return p2(self.radians-radians,self.radius)
    	def __isub__(self, radians):
		if type(radians) in number:
			self.radians-=radians

	#uno
	def __neg__(self):
		return v2(self.radians,-abs(self.radius))
	def __pos__(self):
		return v2(self.radians,abs(self.radius))
	def __abs__(self):
		return v2(self.radians,abs(self.radius))
	def __invert__(self):
		return v2(-self.radians,self.radius)

#------------------------------------------------------------main

if __name__ == "__main__":
	a = v2()
	a.x = 5.0
	a.y = 5.0
	b = p2()
	b.radians = math.radians(45)
	b.radius = 7.071067812
	print 'a = ',a
	print 'b = ',b
	c = p2(a)
	d = v2(b)
	print 'c = ',c
	print 'c = ',d
	print 'a + (1,1) = ', a + v2(1,1)
	print 'b * 2 = ',b * 2
	e = v2(3,4)
	f = p2(e)
	print e, f
	g = p2(0.643501108793,5)
	h = v2(g)
	print g,h
		

	
