import math
from analyzer.epoint import EPoint
class Line:
def __init__(self,alpha,d):
self._alpha=alpha
self._d=d
self._sin=math.sin(alpha)
self._cos=math.cos(alpha)
@staticmethod
def fromNormal(a,b,c):
"""ax + by + c = 0"""
sign=-c/abs(c) if c!=0 else 1
norm=sign*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_)
@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 toPoints(self):
(a,b,c)=self.toNormal()
assert a!=0 or b!=0
if a==0:
y=-c/b
return (EPoint(0,y),EPoint(10,y))
elif b==0:
x=-c/a
return (EPoint(x,0),EPoint(x,10))
else:
return (EPoint(0,-c/b),EPoint(-c/a,0))
def intersect(self,line):
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 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 shiftBasis(self,newBasis):
(a,b,c)=self.toNormal()
if a!=0:
point=EPoint(-c/a,0)
else:
point=EPoint(0,-c/b)
(x_,y_)=point-newBasis
c_=-a*x_-b*y_
return Line.fromNormal(a,b,c_)
def transform(self,matrix):
transformed=(p.transform(matrix) for p in self.toPoints())
return Line.fromPoints(*transformed)
@property
def alpha(self): return self._alpha
@property
def d(self): return self._d
def __str__(self): return "Line({0},{1})".format(round(self._alpha,3),round(self._d))
def __repr__(self): return "Line({0},{1})".format(self._alpha,self._d)
def angleDiff(alpha,beta):
diff=abs(alpha-beta)
if diff>math.pi: diff=2*math.pi-diff
return diff