import math
import numpy as np
def homogenize(v):
for k in reversed(v):
if k!=0: return v/k
return v
## Euclidean 2D plane point: (x,y).
class EPoint:
def __init__(self,x,y):
self._x=x
self._y=y
@property
def x(self): return self._x
@property
def y(self): return self._y
@staticmethod
def fromProjective(point):
if point.item(2)==0: return None
return EPoint(point.item(0)/point.item(2),point.item(1)/point.item(2))
@staticmethod
def fromPolar(point,center):
(alpha,length)=point
x=math.cos(alpha)
y=math.sin(alpha)
return length*EPoint(x,y)+center
def toProjective(self):
return (self._x,self._y,1)
def toPolar(self,center):
v=self-center
alpha=math.atan2(v.y,v.x)
if alpha<0: alpha+=2*math.pi
k=self.dist(center)
return (alpha,k)
def transform(self,matrix):
transformed=np.matmul(matrix,np.array(self.toProjective()).transpose())
return EPoint.fromProjective(transformed)
def dist(self,a):
return math.sqrt((self._x-a._x)**2+(self._y-a._y)**2)
def __add__(self,a):
return EPoint(self._x+a._x,self._y+a._y)
def __sub__(self,a):
return EPoint(self._x-a._x,self._y-a._y)
def __mul__(self,k):
return EPoint(self._x*k,self._y*k)
def __rmul__(self,k):
return self*k
def __truediv__(self,k):
return EPoint(self._x/k,self._y/k)
def __floordiv__(self,k):
return EPoint(self._x//k,self._y//k)
def __neg__(self):
return EPoint(-self._x,-self._y)
def __getitem__(self,key):
if key==0: return self._x
elif key==1: return self._y
raise IndexError(key)
def __hash__(self):
return hash((self._x,self._y))
def __lt__(self,a): return self._x<a._x or (self._x==a._x and self._y<a._y)
def __le__(self,a): return self._x<a._x or (self._x==a._x and self._y<=a._y)
def __gt__(self,a): return self._x>a._x or (self._x==a._x and self._y>a._y)
def __ge__(self,a): return self._x>a._x or (self._x==a._x and self._y>=a._y)
def __eq__(self,a): return self._x==a._x and self._y==a._y
def __ne__(self,a): return self._x!=a._x or self._y!=a._y
def __str__(self): return "({0},{1})".format(round(self._x,3),round(self._y,3))
def __repr__(self): return "EPoint({0},{1})".format(round(self._x,3),round(self._y,3))