diff --git a/exp/geometry.py b/exp/geometry.py --- a/exp/geometry.py +++ b/exp/geometry.py @@ -28,6 +28,18 @@ class Line: """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() @@ -51,6 +63,10 @@ class Line: 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 diff --git a/exp/tests/test_geometry.py b/exp/tests/test_geometry.py --- a/exp/tests/test_geometry.py +++ b/exp/tests/test_geometry.py @@ -2,6 +2,8 @@ import math import random from unittest import TestCase +import numpy as np + from geometry import Line,EPoint random.seed(361) @@ -89,3 +91,15 @@ class TestLine(TestCase): q_=q.shiftBasis(newBasis) self.assertAlmostEqual(q_._alpha,math.pi*7/4) self.assertAlmostEqual(q_._d,3/2*diag) + + def testTransform(self): + rot90=np.array([[0,-1,0],[1,0,0],[0,0,1]]) + p=Line(math.pi/4,10) + p_=p.transform(rot90) + self.assertAlmostEqual(p_.alpha,math.pi*3/4) + self.assertAlmostEqual(p_.d,p.d) + + shiftXY10=np.array([[1,0,10],[0,1,10],[0,0,1]]) + p_=p.transform(shiftXY10) + self.assertAlmostEqual(p_.alpha,p.alpha) + self.assertAlmostEqual(p_.d,10+10*math.sqrt(2)) diff --git a/src/analyzer/epoint.py b/src/analyzer/epoint.py --- a/src/analyzer/epoint.py +++ b/src/analyzer/epoint.py @@ -1,8 +1,10 @@ import math +import numpy as np + def homogenize(v): - for k in v: + for k in reversed(v): if k!=0: return v/k return v @@ -21,8 +23,8 @@ class EPoint: @staticmethod def fromProjective(point): - if point.item(0)==0: return None - return EPoint(point.item(1)/point.item(0),point.item(2)/point.item(0)) + 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): @@ -32,7 +34,7 @@ class EPoint: return length*EPoint(x,y)+center def toProjective(self): - return (1,self._x,self._y) + return (self._x,self._y,1) def toPolar(self,center): v=self-center @@ -41,6 +43,10 @@ class EPoint: 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)