diff --git a/exp/geometry.py b/exp/geometry.py --- a/exp/geometry.py +++ b/exp/geometry.py @@ -1,59 +1,47 @@ import math -import numpy as np - -from analyzer.epoint import EPoint, homogenize -from analyzer.grid import transformPoint +from analyzer.epoint import EPoint -class Line(): - def __init__(self,a,b): - self.a=a - self.b=b - self.points={a,b} +class Line: + def __init__(self,alpha,d): + self._alpha=alpha + self._d=d + self._sin=math.sin(alpha) + self._cos=math.cos(alpha) - def getSortedPoints(self): - return tuple(sorted(self.points)) + @staticmethod + def fromNormal(a,b,c): + """ax + by + c = 0""" + norm=-c/abs(c)*math.sqrt(a**2+b**2) + (a_,b_,c_)=(a/norm,b/norm,c/norm) + alpha=math.acos(a_) if b_>=0 else 2*math.pi-math.acos(a_) + return Line(alpha,-c_) - def computeAngle(self,line): - ab=self.a-self.b - cd=line.a-line.b - alpha=math.atan(ab.y/ab.x) - gamma=math.atan(cd.y/cd.x) - fi=max(alpha,gamma)-min(alpha,gamma) - return min(fi,math.pi-fi) + @staticmethod + def fromPoints(a,b): + return Line.fromNormal(a.y-b.y, b.x-a.x, (b.y-a.y)*a.x+(a.x-b.x)*a.y) + + def toNormal(self): + # https://en.wikipedia.org/wiki/Line_(mathematics)#In_normal_form + """ax + by + c = 0""" + return (self._cos, self._sin, -self._d) def intersect(self,line): - p=self.toProjective() - q=line.toProjective() - return EPoint.fromProjective(np.cross(p,q)) - - def toProjective(self): - return homogenize(np.cross(self.a.toProjective(),self.b.toProjective())) - - def transform(self,matrix): - a=EPoint.fromProjective(transformPoint(self.a.toProjective(),matrix)) - b=EPoint.fromProjective(transformPoint(self.b.toProjective(),matrix)) - if a is None or b is None: return None - return Line(a,b) + if self._alpha==line._alpha: return None + (a,b,c)=self.toNormal() + (d,e,f)=line.toNormal() + x=(b*f-c*e)/(a*e-b*d) + y=(c*d-a*f)/(a*e-b*d) + return EPoint(x,y) - def score(self,points): - score=len(self.points) - for a in self.points: - closest=sorted(points,key=lambda b: a.dist(b))[:4] - score+=sum(0.01 for b in closest if b in self.points) - return score + def distanceTo(self,point): + # https://en.wikipedia.org/wiki/Point-line_distance#Line_defined_by_an_equation + (a,b,c)=self.toNormal() + return abs(a*point.x+b*point.y+c) # a**2 + b**2 == 1 for Hesse normal form - def __str__(self): return "({0},{1})".format(self.a,self.b) - def __repr__(self): return "Line({0},{1})".format(repr(self.a),repr(self.b)) - - -def point2lineDistance(a,b,p): - # https://en.wikipedia.org/wiki/Point-line_distance#Line_defined_by_two_points - ab=b-a - num=abs(ab.y*p.x - ab.x*p.y + b.x*a.y - a.x*b.y) - denum=math.sqrt(ab.y**2+ab.x**2) - return num/denum # double_area / side_length == height + def __str__(self): return "({0},{1})".format(self._alpha,self._d) + def __repr__(self): return "Line({0},{1})".format(repr(self._alpha),repr(self._d)) def angleDiff(alpha,beta):