def test_reflect_entity_overrides(): x = Symbol('x', real=True) y = Symbol('y', real=True) b = Symbol('b') m = Symbol('m') l = Line((0, b), slope=m) p = Point(x, y) r = p.reflect(l) c = Circle((x, y), 3) cr = c.reflect(l) assert cr == Circle(r, -3) assert c.area == -cr.area pent = RegularPolygon((1, 2), 1, 5) l = Line(pent.vertices[1], slope=Rational(random() - .5, random() - .5)) rpent = pent.reflect(l) assert rpent.center == pent.center.reflect(l) rvert = [i.reflect(l) for i in pent.vertices] for v in rpent.vertices: for i in range(len(rvert)): ri = rvert[i] if ri.equals(v): rvert.remove(ri) break assert not rvert assert pent.area.equals(-rpent.area)
def test_second_moment_of_area(): x, y = symbols('x, y') # triangle p1, p2, p3 = [(0, 0), (4, 0), (0, 2)] p = (0, 0) # equation of hypotenuse eq_y = (1-x/4)*2 I_yy = integrate((x**2) * (integrate(1, (y, 0, eq_y))), (x, 0, 4)) I_xx = integrate(1 * (integrate(y**2, (y, 0, eq_y))), (x, 0, 4)) I_xy = integrate(x * (integrate(y, (y, 0, eq_y))), (x, 0, 4)) triangle = Polygon(p1, p2, p3) assert (I_xx - triangle.second_moment_of_area(p)[0]) == 0 assert (I_yy - triangle.second_moment_of_area(p)[1]) == 0 assert (I_xy - triangle.second_moment_of_area(p)[2]) == 0 # rectangle p1, p2, p3, p4=[(0, 0), (4, 0), (4, 2), (0, 2)] I_yy = integrate((x**2) * integrate(1, (y, 0, 2)), (x, 0, 4)) I_xx = integrate(1 * integrate(y**2, (y, 0, 2)), (x, 0, 4)) I_xy = integrate(x * integrate(y, (y, 0, 2)), (x, 0, 4)) rectangle = Polygon(p1, p2, p3, p4) assert (I_xx - rectangle.second_moment_of_area(p)[0]) == 0 assert (I_yy - rectangle.second_moment_of_area(p)[1]) == 0 assert (I_xy - rectangle.second_moment_of_area(p)[2]) == 0 r = RegularPolygon(Point(0, 0), 5, 3) assert r.second_moment_of_area() == (1875*sqrt(3)/S(32), 1875*sqrt(3)/S(32), 0)
def test_reflect(): b = Symbol('b') m = Symbol('m') l = Line((0, b), slope=m) p = Point(x, y) r = p.reflect(l) dp = l.perpendicular_segment(p).length dr = l.perpendicular_segment(r).length assert test_numerically(dp, dr) t = Triangle((0, 0), (1, 0), (2, 3)) assert t.area == -t.reflect(l).area e = Ellipse((1, 0), 1, 2) assert e.area == -e.reflect(Line((1, 0), slope=0)).area assert e.area == -e.reflect(Line((1, 0), slope=oo)).area raises(NotImplementedError, lambda: e.reflect(Line((1, 0), slope=m))) # test entity overrides c = Circle((x, y), 3) cr = c.reflect(l) assert cr == Circle(r, -3) assert c.area == -cr.area pent = RegularPolygon((1, 2), 1, 5) l = Line((0, pi), slope=sqrt(2)) rpent = pent.reflect(l) poly_pent = Polygon(*pent.vertices) assert rpent.center == pent.center.reflect(l) assert str([w.n(3) for w in rpent.vertices ]) == ('[Point(-0.586, 4.27), Point(-1.69, 4.66), ' 'Point(-2.41, 3.73), Point(-1.74, 2.76), ' 'Point(-0.616, 3.10)]') assert pent.area.equals(-rpent.area)
def test_reflect(): b = Symbol('b') m = Symbol('m') l = Line((0, b), slope=m) p = Point(x, y) r = p.reflect(l) dp = l.perpendicular_segment(p).length dr = l.perpendicular_segment(r).length assert test_numerically(dp, dr) t = Triangle((0, 0), (1, 0), (2, 3)) assert t.area == -t.reflect(l).area e = Ellipse((1, 0), 1, 2) assert e.area == -e.reflect(Line((1, 0), slope=0)).area assert e.area == -e.reflect(Line((1, 0), slope=oo)).area raises(NotImplementedError, lambda: e.reflect(Line((1,0), slope=m))) # test entity overrides c = Circle((x, y), 3) cr = c.reflect(l) assert cr == Circle(r, -3) assert c.area == -cr.area pent = RegularPolygon((1, 2), 1, 5) l = Line((0, pi), slope=sqrt(2)) rpent = pent.reflect(l) poly_pent = Polygon(*pent.vertices) assert rpent.center == pent.center.reflect(l) assert str([w.n(3) for w in rpent.vertices]) == ( '[Point(-0.586, 4.27), Point(-1.69, 4.66), ' 'Point(-2.41, 3.73), Point(-1.74, 2.76), ' 'Point(-0.616, 3.10)]') assert pent.area.equals(-rpent.area)
def test_transform(): pts = [Point(0, 0), Point(S.Half, Rational(1, 4)), Point(1, 1)] pts_out = [Point(-4, -10), Point(-3, Rational(-37, 4)), Point(-2, -7)] assert Triangle(*pts).scale(2, 3, (4, 5)) == Triangle(*pts_out) assert RegularPolygon((0, 0), 1, 4).scale(2, 3, (4, 5)) == \ Polygon(Point(-2, -10), Point(-4, -7), Point(-6, -10), Point(-4, -13)) # Checks for symmetric scaling assert RegularPolygon((0, 0), 1, 4).scale(2, 2) == \ RegularPolygon(Point2D(0, 0), 2, 4, 0)
def test_section_modulus_and_polar_second_moment_of_area(): a, b = symbols('a, b', positive=True) x, y = symbols('x, y') rectangle = Polygon((0, b), (0, 0), (a, 0), (a, b)) assert rectangle.section_modulus(Point(x, y)) == (a*b**3/12/(-b/2 + y), a**3*b/12/(-a/2 + x)) assert rectangle.polar_second_moment_of_area() == a**3*b/12 + a*b**3/12 convex = RegularPolygon((0, 0), 1, 6) assert convex.section_modulus() == (5/S(8), 5*sqrt(3)/S(16)) assert convex.polar_second_moment_of_area() == 5*sqrt(3)/S(8) concave = Polygon((0, 0), (1, 8), (3, 4), (4, 6), (7, 1)) assert concave.section_modulus() == (-6371/S(429), -9778/S(519)) assert concave.polar_second_moment_of_area() == -38669/S(252)
def test_convex_hull(): p = [Point(-5, -1), Point(-2, 1), Point(-2, -1), Point(-1, -3), \ Point(0, 0), Point(1, 1), Point(2, 2), Point(2, -1), Point(3, 1), \ Point(4, -1), Point(6, 2)] ch = Polygon(p[0], p[3], p[9], p[10], p[6], p[1]) #test handling of duplicate points p.append(p[3]) #more than 3 collinear points another_p = [Point(-45, -85), Point(-45, 85), Point(-45, 26), \ Point(-45, -24)] ch2 = Segment(another_p[0], another_p[1]) assert convex_hull(*another_p) == ch2 assert convex_hull(*p) == ch assert convex_hull(p[0]) == p[0] assert convex_hull(p[0], p[1]) == Segment(p[0], p[1]) # no unique points assert convex_hull(*[p[-1]]*3) == p[-1] # collection of items assert convex_hull(*[Point(0, 0), \ Segment(Point(1, 0), Point(1, 1)), \ RegularPolygon(Point(2, 0), 2, 4)]) == \ Polygon(Point(0, 0), Point(2, -2), Point(4, 0), Point(2, 2))
def test_intersection(): poly1 = Triangle(Point(0, 0), Point(1, 0), Point(0, 1)) poly2 = Polygon(Point(0, 1), Point(-5, 0), Point(0, -4), Point(0, Rational(1, 5)), Point(S.Half, -0.1), Point(1, 0), Point(0, 1)) assert poly1.intersection(poly2) == [Point2D(Rational(1, 3), 0), Segment(Point(0, Rational(1, 5)), Point(0, 0)), Segment(Point(1, 0), Point(0, 1))] assert poly2.intersection(poly1) == [Point(Rational(1, 3), 0), Segment(Point(0, 0), Point(0, Rational(1, 5))), Segment(Point(1, 0), Point(0, 1))] assert poly1.intersection(Point(0, 0)) == [Point(0, 0)] assert poly1.intersection(Point(-12, -43)) == [] assert poly2.intersection(Line((-12, 0), (12, 0))) == [Point(-5, 0), Point(0, 0), Point(Rational(1, 3), 0), Point(1, 0)] assert poly2.intersection(Line((-12, 12), (12, 12))) == [] assert poly2.intersection(Ray((-3, 4), (1, 0))) == [Segment(Point(1, 0), Point(0, 1))] assert poly2.intersection(Circle((0, -1), 1)) == [Point(0, -2), Point(0, 0)] assert poly1.intersection(poly1) == [Segment(Point(0, 0), Point(1, 0)), Segment(Point(0, 1), Point(0, 0)), Segment(Point(1, 0), Point(0, 1))] assert poly2.intersection(poly2) == [Segment(Point(-5, 0), Point(0, -4)), Segment(Point(0, -4), Point(0, Rational(1, 5))), Segment(Point(0, Rational(1, 5)), Point(S.Half, Rational(-1, 10))), Segment(Point(0, 1), Point(-5, 0)), Segment(Point(S.Half, Rational(-1, 10)), Point(1, 0)), Segment(Point(1, 0), Point(0, 1))] assert poly2.intersection(Triangle(Point(0, 1), Point(1, 0), Point(-1, 1))) \ == [Point(Rational(-5, 7), Rational(6, 7)), Segment(Point2D(0, 1), Point(1, 0))] assert poly1.intersection(RegularPolygon((-12, -15), 3, 3)) == []
def test_cut_section(): # concave polygon p = Polygon((-1, -1), (1, S(5)/2), (2, 1), (3, S(5)/2), (4, 2), (5, 3), (-1, 3)) l = Line((0, 0), (S(9)/2, 3)) p1 = p.cut_section(l)[0] p2 = p.cut_section(l)[1] assert p1 == Polygon( Point2D(-S(9)/13, -S(6)/13), Point2D(1, S(5)/2), Point2D(S(24)/13, S(16)/13), Point2D(S(12)/5, S(8)/5), Point2D(3, S(5)/2), Point2D(S(24)/7, S(16)/7), Point2D(S(9)/2, 3), Point2D(-1, 3), Point2D(-1, -S(2)/3)) assert p2 == Polygon(Point2D(-1, -1), Point2D(-S(9)/13, -S(6)/13), Point2D(S(24)/13, S(16)/13), Point2D(2, 1), Point2D(S(12)/5, S(8)/5), Point2D(S(24)/7, S(16)/7), Point2D(4, 2), Point2D(5, 3), Point2D(S(9)/2, 3), Point2D(-1, -S(2)/3)) # convex polygon p = RegularPolygon(Point2D(0,0), 6, 6) s = p.cut_section(Line((0, 0), slope=1)) assert s[0] == Polygon(Point2D(-3*sqrt(3) + 9, -3*sqrt(3) + 9), Point2D(3, 3*sqrt(3)), Point2D(-3, 3*sqrt(3)), Point2D(-6, 0), Point2D(-9 + 3*sqrt(3), -9 + 3*sqrt(3))) assert s[1] == Polygon(Point2D(6, 0), Point2D(-3*sqrt(3) + 9, -3*sqrt(3) + 9), Point2D(-9 + 3*sqrt(3), -9 + 3*sqrt(3)), Point2D(-3, -3*sqrt(3)), Point2D(3, -3*sqrt(3))) # case where line does not intersects but coincides with the edge of polygon a, b = 20, 10 t1, t2, t3, t4 = [(0, b), (0, 0), (a, 0), (a, b)] p = Polygon(t1, t2, t3, t4) p1, p2 = p.cut_section(Line((0, b), slope=0)) assert p1 == None assert p2 == Polygon(Point2D(0, 10), Point2D(0, 0), Point2D(20, 0), Point2D(20, 10)) p3, p4 = p.cut_section(Line((0, 0), slope=0)) assert p3 == Polygon(Point2D(0, 10), Point2D(0, 0), Point2D(20, 0), Point2D(20, 10)) assert p4 == None
def test_intersection(): poly1 = Triangle(Point(0, 0), Point(1, 0), Point(0, 1)) poly2 = Polygon(Point(0, 1), Point(-5, 0), Point(0, -4), Point(0, S(1)/5), Point(S(1)/2, -0.1), Point(1,0), Point(0, 1)) assert poly1.intersection(poly2) == [Point2D(S(1)/3, 0), Segment(Point(0, S(1)/5), Point(0, 0)), Segment(Point(1, 0), Point(0, 1))] assert poly2.intersection(poly1) == [Point(S(1)/3, 0), Segment(Point(0, 0), Point(0, S(1)/5)), Segment(Point(1, 0), Point(0, 1))] assert poly1.intersection(Point(0, 0)) == [Point(0, 0)] assert poly1.intersection(Point(-12, -43)) == [] assert poly2.intersection(Line((-12, 0), (12, 0))) == [Point(-5, 0), Point(0, 0),Point(S(1)/3, 0), Point(1, 0)] assert poly2.intersection(Line((-12, 12), (12, 12))) == [] assert poly2.intersection(Ray((-3,4), (1,0))) == [Segment(Point(1, 0), Point(0, 1))] assert poly2.intersection(Circle((0, -1), 1)) == [Point(0, -2), Point(0, 0)] assert poly1.intersection(poly1) == [Segment(Point(0, 0), Point(1, 0)), Segment(Point(0, 1), Point(0, 0)), Segment(Point(1, 0), Point(0, 1))] assert poly2.intersection(poly2) == [Segment(Point(-5, 0), Point(0, -4)), Segment(Point(0, -4), Point(0, S(1)/5)), Segment(Point(0, S(1)/5), Point(S(1)/2, -S(1)/10)), Segment(Point(0, 1), Point(-5, 0)), Segment(Point(S(1)/2, -S(1)/10), Point(1, 0)), Segment(Point(1, 0), Point(0, 1))] assert poly2.intersection(Triangle(Point(0, 1), Point(1, 0), Point(-1, 1))) \ == [Point(-S(5)/7, S(6)/7), Segment(Point2D(0, 1), Point(1, 0))] assert poly1.intersection(RegularPolygon((-12, -15), 3, 3)) == []
def test_cut_section(): # concave polygon p = Polygon((-1, -1), (1, Rational(5, 2)), (2, 1), (3, Rational(5, 2)), (4, 2), (5, 3), (-1, 3)) l = Line((0, 0), (Rational(9, 2), 3)) p1 = p.cut_section(l)[0] p2 = p.cut_section(l)[1] assert p1 == Polygon( Point2D(Rational(-9, 13), Rational(-6, 13)), Point2D(1, Rational(5, 2)), Point2D(Rational(24, 13), Rational(16, 13)), Point2D(Rational(12, 5), Rational(8, 5)), Point2D(3, Rational(5, 2)), Point2D(Rational(24, 7), Rational(16, 7)), Point2D(Rational(9, 2), 3), Point2D(-1, 3), Point2D(-1, Rational(-2, 3))) assert p2 == Polygon(Point2D(-1, -1), Point2D(Rational(-9, 13), Rational(-6, 13)), Point2D(Rational(24, 13), Rational(16, 13)), Point2D(2, 1), Point2D(Rational(12, 5), Rational(8, 5)), Point2D(Rational(24, 7), Rational(16, 7)), Point2D(4, 2), Point2D(5, 3), Point2D(Rational(9, 2), 3), Point2D(-1, Rational(-2, 3))) # convex polygon p = RegularPolygon(Point2D(0,0), 6, 6) s = p.cut_section(Line((0, 0), slope=1)) assert s[0] == Polygon(Point2D(-3*sqrt(3) + 9, -3*sqrt(3) + 9), Point2D(3, 3*sqrt(3)), Point2D(-3, 3*sqrt(3)), Point2D(-6, 0), Point2D(-9 + 3*sqrt(3), -9 + 3*sqrt(3))) assert s[1] == Polygon(Point2D(6, 0), Point2D(-3*sqrt(3) + 9, -3*sqrt(3) + 9), Point2D(-9 + 3*sqrt(3), -9 + 3*sqrt(3)), Point2D(-3, -3*sqrt(3)), Point2D(3, -3*sqrt(3))) # case where line does not intersects but coincides with the edge of polygon a, b = 20, 10 t1, t2, t3, t4 = [(0, b), (0, 0), (a, 0), (a, b)] p = Polygon(t1, t2, t3, t4) p1, p2 = p.cut_section(Line((0, b), slope=0)) assert p1 == None assert p2 == Polygon(Point2D(0, 10), Point2D(0, 0), Point2D(20, 0), Point2D(20, 10)) p3, p4 = p.cut_section(Line((0, 0), slope=0)) assert p3 == Polygon(Point2D(0, 10), Point2D(0, 0), Point2D(20, 0), Point2D(20, 10)) assert p4 == None
def test_subs(): x = Symbol('x', real=True) y = Symbol('y', real=True) p = Point(x, 2) q = Point(1, 1) r = Point(3, 4) for o in [ p, Segment(p, q), Ray(p, q), Line(p, q), Triangle(p, q, r), RegularPolygon(p, 3, 6), Polygon(p, q, r, Point(5, 4)), Circle(p, 3), Ellipse(p, 3, 4) ]: assert 'y' in str(o.subs(x, y)) assert p.subs({x: 1}) == Point(1, 2) assert Point(1, 2).subs(Point(1, 2), Point(3, 4)) == Point(3, 4) assert Point(1, 2).subs((1, 2), Point(3, 4)) == Point(3, 4) assert Point(1, 2).subs(Point(1, 2), Point(3, 4)) == Point(3, 4) assert Point(1, 2).subs(set([(1, 2)])) == Point(2, 2) raises(ValueError, lambda: Point(1, 2).subs(1)) raises(ValueError, lambda: Point(1, 1).subs( (Point(1, 1), Point(1, 2)), 1, 2))
def regular_polygons(draw, not_centre=None): centre = points() if not_centre: centre = centre.filter(centre.__ne__) return RegularPolygon(draw(centre), draw(integers(min_value=1, max_value=100)), draw(integers(min_value=3, max_value=6)))
def test_reflect_entity_overrides(): x = Symbol('x', real=True) y = Symbol('y', real=True) b = Symbol('b') m = Symbol('m') l = Line((0, b), slope=m) p = Point(x, y) r = p.reflect(l) c = Circle((x, y), 3) cr = c.reflect(l) assert cr == Circle(r, -3) assert c.area == -cr.area pent = RegularPolygon((1, 2), 1, 5) l = Line((0, pi), slope=sqrt(2)) rpent = pent.reflect(l) assert rpent.center == pent.center.reflect(l) assert str([w.n(3) for w in rpent.vertices]) == ( '[Point2D(-0.586, 4.27), Point2D(-1.69, 4.66), ' 'Point2D(-2.41, 3.73), Point2D(-1.74, 2.76), ' 'Point2D(-0.616, 3.10)]') assert pent.area.equals(-rpent.area)
def test_reflect_entity_overrides(): x = Symbol('x', real=True) y = Symbol('y', real=True) b = Symbol('b') m = Symbol('m') l = Line((0, b), slope=m) p = Point(x, y) r = p.reflect(l) c = Circle((x, y), 3) cr = c.reflect(l) assert cr == Circle(r, -3) assert c.area == -cr.area pent = RegularPolygon((1, 2), 1, 5) l = Line((0, pi), slope=sqrt(2)) rpent = pent.reflect(l) assert rpent.center == pent.center.reflect(l) assert str([w.n(3) for w in rpent.vertices ]) == ('[Point2D(-0.586, 4.27), Point2D(-1.69, 4.66), ' 'Point2D(-2.41, 3.73), Point2D(-1.74, 2.76), ' 'Point2D(-0.616, 3.10)]') assert pent.area.equals(-rpent.area)
def test_subs(): p = Point(x, 2) q = Point(1, 1) r = Point(3, 4) for o in [p, Segment(p, q), Ray(p, q), Line(p, q), Triangle(p, q, r), RegularPolygon(p, 3, 6), Polygon(p, q, r, Point(5,4)), Circle(p, 3), Ellipse(p, 3, 4)]: assert 'y' in str(o.subs(x, y))
def test_free_symbols(): a, b, c, d, e, f, s = symbols('a:f,s') assert Point(a,b).free_symbols == set([a, b]) assert Line((a,b),(c,d)).free_symbols == set([a, b, c, d]) assert Ray((a,b),(c,d)).free_symbols == set([a, b, c, d]) assert Ray((a,b),angle=c).free_symbols == set([a, b, c]) assert Segment((a,b),(c,d)).free_symbols == set([a, b, c, d]) assert Line((a,b),slope=c).free_symbols == set([a, b, c]) assert Curve((a*s,b*s),(s,c,d)).free_symbols == set([a, b, c, d]) assert Ellipse((a,b),c,d).free_symbols == set([a, b, c, d]) assert Ellipse((a,b),c, eccentricity=d).free_symbols == set([a, b, c, d]) assert Ellipse((a,b),vradius=c, eccentricity=d).free_symbols == set([a, b, c, d]) assert Circle((a,b),c).free_symbols == set([a, b, c]) assert Circle((a,b),(c,d),(e,f)).free_symbols == set([e, d, c, b, f, a]) assert Polygon((a,b),(c,d),(e,f)).free_symbols == set([e, b, d, f, a, c]) assert RegularPolygon((a,b),c,d,e).free_symbols == set([e, a, b, c, d])
def test_entity(): x = Symbol('x', real=True) y = Symbol('y', real=True) assert GeometryEntity(x, y) in GeometryEntity(x, y) raises(NotImplementedError, lambda: Point(0, 0) in GeometryEntity(x, y)) assert GeometryEntity(x, y) == GeometryEntity(x, y) assert GeometryEntity(x, y).equals(GeometryEntity(x, y)) c = Circle((0, 0), 5) assert GeometryEntity.encloses(c, Point(0, 0)) assert GeometryEntity.encloses(c, Segment((0, 0), (1, 1))) assert GeometryEntity.encloses(c, Line((0, 0), (1, 1))) is False assert GeometryEntity.encloses(c, Circle((0, 0), 4)) assert GeometryEntity.encloses(c, Polygon(Point(0, 0), Point(1, 0), Point(0, 1))) assert GeometryEntity.encloses(c, RegularPolygon(Point(8, 8), 1, 3)) is False
def test_geometry_EvalfMixin(): x = pi t = Symbol('t') for g in [ Point(x, x), Plane(Point(0, x, 0), (0, 0, x)), Curve((x * t, x), (t, 0, x)), Ellipse((x, x), x, -x), Circle((x, x), x), Line((0, x), (x, 0)), Segment((0, x), (x, 0)), Ray((0, x), (x, 0)), Parabola((0, x), Line((-x, 0), (x, 0))), Polygon((0, 0), (0, x), (x, 0), (x, x)), RegularPolygon((0, x), x, 4, x), Triangle((0, 0), (x, 0), (x, x)), ]: assert str(g).replace('pi', '3.1') == str(g.n(2))
def test_geometry_transforms(): from sympy import Tuple c = Curve((x, x**2), (x, 0, 1)) pts = [Point(0, 0), Point(S(1) / 2, S(1) / 4), Point(1, 1)] cout = Curve((2 * x - 4, 3 * x**2 - 10), (x, 0, 1)) pts_out = [Point(-4, -10), Point(-3, -S(37) / 4), Point(-2, -7)] assert c.scale(2, 3, (4, 5)) == cout assert [c.subs(x, xi / 2) for xi in Tuple(0, 1, 2)] == pts assert [cout.subs(x, xi / 2) for xi in Tuple(0, 1, 2)] == pts_out assert Triangle(*pts).scale(2, 3, (4, 5)) == Triangle(*pts_out) assert Ellipse((0, 0), 2, 3).scale(2, 3, (4, 5)) == \ Ellipse(Point(-4, -10), 4, 9) assert Circle((0, 0), 2).scale(2, 3, (4, 5)) == \ Ellipse(Point(-4, -10), 4, 6) assert Ellipse((0, 0), 2, 3).scale(3, 3, (4, 5)) == \ Ellipse(Point(-8, -10), 6, 9) assert Circle((0, 0), 2).scale(3, 3, (4, 5)) == \ Circle(Point(-8, -10), 6) assert Circle(Point(-8, -10), 6).scale(S(1)/3, S(1)/3, (4, 5)) == \ Circle((0, 0), 2) assert Curve((x + y, 3*x), (x, 0, 1)).subs(y, S.Half) == \ Curve((x + S(1)/2, 3*x), (x, 0, 1)) assert Curve((x, 3*x), (x, 0, 1)).translate(4, 5) == \ Curve((x + 4, 3*x + 5), (x, 0, 1)) assert Circle((0, 0), 2).translate(4, 5) == \ Circle((4, 5), 2) assert Circle((0, 0), 2).scale(3, 3) == \ Circle((0, 0), 6) assert Point(1, 1).scale(2, 3, (4, 5)) == \ Point(-2, -7) assert Point(1, 1).translate(4, 5) == \ Point(5, 6) assert scale(1, 2, (3, 4)).tolist() == \ [[1, 0, 0], [0, 2, 0], [0, -4, 1]] assert RegularPolygon((0, 0), 1, 4).scale(2, 3, (4, 5)) == \ Polygon(Point(-2, -10), Point(-4, -7), Point(-6, -10), Point(-4, -13))
def test_ellipse(): p1 = Point(0, 0) p2 = Point(1, 1) p4 = Point(0, 1) e1 = Ellipse(p1, 1, 1) e2 = Ellipse(p2, half, 1) e3 = Ellipse(p1, y1, y1) c1 = Circle(p1, 1) c2 = Circle(p2, 1) c3 = Circle(Point(sqrt(2), sqrt(2)), 1) # Test creation with three points cen, rad = Point(3 * half, 2), 5 * half assert Circle(Point(0, 0), Point(3, 0), Point(0, 4)) == Circle(cen, rad) raises(GeometryError, "Circle(Point(0,0), Point(1,1), Point(2,2))") raises(ValueError, "Ellipse(None, None, None, 1)") raises(GeometryError, "Circle(Point(0,0))") # Basic Stuff assert Ellipse(None, 1, 1).center == Point(0, 0) assert e1 == c1 assert e1 != e2 assert p4 in e1 assert p2 not in e2 assert e1.area == pi assert e2.area == pi / 2 assert e3.area == pi * (y1**2) assert c1.area == e1.area assert c1.circumference == e1.circumference assert e3.circumference == 2 * pi * y1 assert e1.plot_interval() == e2.plot_interval() == [t, -pi, pi] assert e1.plot_interval(x) == e2.plot_interval(x) == [x, -pi, pi] assert Ellipse(None, 1, None, 1).circumference == 2 * pi assert c1.minor == 1 # Private Functions assert hash(c1) == hash(Circle(Point(1, 0), Point(0, 1), Point(0, -1))) assert c1 in e1 assert (Line(p1, p2) in e1) == False assert e1.__cmp__(e1) == 0 assert e1.__cmp__(Point(0, 0)) > 0 # Encloses assert e1.encloses(Segment(Point(-0.5, -0.5), Point(0.5, 0.5))) == True assert e1.encloses(Line(p1, p2)) == False assert e1.encloses(Ray(p1, p2)) == False assert e1.encloses(e1) == False assert e1.encloses( Polygon(Point(-0.5, -0.5), Point(-0.5, 0.5), Point(0.5, 0.5))) == True assert e1.encloses(RegularPolygon(p1, 0.5, 3)) == True assert e1.encloses(RegularPolygon(p1, 5, 3)) == False assert e1.encloses(RegularPolygon(p2, 5, 3)) == False # with generic symbols, the hradius is assumed to contain the major radius M = Symbol('M') m = Symbol('m') c = Ellipse(p1, M, m).circumference _x = c.atoms(Dummy).pop() assert c == \ 4*M*C.Integral(sqrt((1 - _x**2*(M**2 - m**2)/M**2)/(1 - _x**2)), (_x, 0, 1)) assert e2.arbitrary_point() in e2 # Foci f1, f2 = Point(sqrt(12), 0), Point(-sqrt(12), 0) ef = Ellipse(Point(0, 0), 4, 2) assert ef.foci in [(f1, f2), (f2, f1)] # Tangents v = sqrt(2) / 2 p1_1 = Point(v, v) p1_2 = p2 + Point(half, 0) p1_3 = p2 + Point(0, 1) assert e1.tangent_lines(p4) == c1.tangent_lines(p4) assert e2.tangent_lines(p1_2) == [Line(p1_2, p2 + Point(half, 1))] assert e2.tangent_lines(p1_3) == [Line(p1_3, p2 + Point(half, 1))] assert c1.tangent_lines(p1_1) == [Line(p1_1, Point(0, sqrt(2)))] assert c1.tangent_lines(p1) == [] assert e2.is_tangent(Line(p1_2, p2 + Point(half, 1))) assert e2.is_tangent(Line(p1_3, p2 + Point(half, 1))) assert c1.is_tangent(Line(p1_1, Point(0, sqrt(2)))) assert e1.is_tangent(Line(Point(0, 0), Point(1, 1))) == False assert c1.is_tangent(e1) == False assert c1.is_tangent(Ellipse(Point(2, 0), 1, 1)) == True assert c1.is_tangent(Polygon(Point(1, 1), Point(1, -1), Point(2, 0))) == True assert c1.is_tangent(Polygon(Point(1, 1), Point(1, 0), Point(2, 0))) == False assert Ellipse(Point(5, 5), 2, 1).tangent_lines(Point(0, 0)) == \ [Line(Point(0, 0), Point(S(77)/25, S(132)/25)), Line(Point(0, 0), Point(S(33)/5, S(22)/5))] assert Ellipse(Point(5, 5), 2, 1).tangent_lines(Point(3, 4)) == \ [Line(Point(3, 4), Point(4, 4)), Line(Point(3, 4), Point(3, 5))] assert Circle(Point(5, 5), 2).tangent_lines(Point(3, 3)) == \ [Line(Point(3, 3), Point(4, 3)), Line(Point(3, 3), Point(3, 4))] assert Circle(Point(5, 5), 2).tangent_lines(Point(5 - 2*sqrt(2), 5)) == \ [Line(Point(5 - 2*sqrt(2), 5), Point(5 - sqrt(2), 5 - sqrt(2))), Line(Point(5 - 2*sqrt(2), 5), Point(5 - sqrt(2), 5 + sqrt(2))),] # Properties major = 3 minor = 1 e4 = Ellipse(p2, minor, major) assert e4.focus_distance == sqrt(major**2 - minor**2) ecc = e4.focus_distance / major assert e4.eccentricity == ecc assert e4.periapsis == major * (1 - ecc) assert e4.apoapsis == major * (1 + ecc) # independent of orientation e4 = Ellipse(p2, major, minor) assert e4.focus_distance == sqrt(major**2 - minor**2) ecc = e4.focus_distance / major assert e4.eccentricity == ecc assert e4.periapsis == major * (1 - ecc) assert e4.apoapsis == major * (1 + ecc) # Intersection l1 = Line(Point(1, -5), Point(1, 5)) l2 = Line(Point(-5, -1), Point(5, -1)) l3 = Line(Point(-1, -1), Point(1, 1)) l4 = Line(Point(-10, 0), Point(0, 10)) pts_c1_l3 = [ Point(sqrt(2) / 2, sqrt(2) / 2), Point(-sqrt(2) / 2, -sqrt(2) / 2) ] assert intersection(e2, l4) == [] assert intersection(c1, Point(1, 0)) == [Point(1, 0)] assert intersection(c1, l1) == [Point(1, 0)] assert intersection(c1, l2) == [Point(0, -1)] assert intersection(c1, l3) in [pts_c1_l3, [pts_c1_l3[1], pts_c1_l3[0]]] assert intersection(c1, c2) in [[(1, 0), (0, 1)], [(0, 1), (1, 0)]] assert intersection(c1, c3) == [(sqrt(2) / 2, sqrt(2) / 2)] assert e1.intersection(l1) == [Point(1, 0)] assert e2.intersection(l4) == [] assert e1.intersection(Circle(Point(0, 2), 1)) == [Point(0, 1)] assert e1.intersection(Circle(Point(5, 0), 1)) == [] assert e1.intersection(Ellipse(Point(2, 0), 1, 1)) == [Point(1, 0)] assert e1.intersection(Ellipse( Point(5, 0), 1, 1, )) == [] assert e1.intersection(Point(2, 0)) == [] assert e1.intersection(e1) == e1 # some special case intersections csmall = Circle(p1, 3) cbig = Circle(p1, 5) cout = Circle(Point(5, 5), 1) # one circle inside of another assert csmall.intersection(cbig) == [] # separate circles assert csmall.intersection(cout) == [] # coincident circles assert csmall.intersection(csmall) == csmall v = sqrt(2) t1 = Triangle(Point(0, v), Point(0, -v), Point(v, 0)) points = intersection(t1, c1) assert len(points) == 4 assert Point(0, 1) in points assert Point(0, -1) in points assert Point(v / 2, v / 2) in points assert Point(v / 2, -v / 2) in points circ = Circle(Point(0, 0), 5) elip = Ellipse(Point(0, 0), 5, 20) assert intersection(circ, elip) in \ [[Point(5, 0), Point(-5, 0)], [Point(-5, 0), Point(5, 0)]] assert elip.tangent_lines(Point(0, 0)) == [] elip = Ellipse(Point(0, 0), 3, 2) assert elip.tangent_lines(Point(3, 0)) == [Line(Point(3, 0), Point(3, -12))] e1 = Ellipse(Point(0, 0), 5, 10) e2 = Ellipse(Point(2, 1), 4, 8) a = S(53) / 17 c = 2 * sqrt(3991) / 17 ans = [Point(a - c / 8, a / 2 + c), Point(a + c / 8, a / 2 - c)] assert e1.intersection(e2) == ans e2 = Ellipse(Point(x, y), 4, 8) ans = list(reversed(ans)) assert [p.subs({x: 2, y: 1}) for p in e1.intersection(e2)] == ans # Combinations of above assert e3.is_tangent(e3.tangent_lines(p1 + Point(y1, 0))[0]) e = Ellipse((1, 2), 3, 2) assert e.tangent_lines(Point(10, 0)) == \ [Line(Point(10, 0), Point(1, 0)), Line(Point(10, 0), Point(S(14)/5, S(18)/5))] # encloses_point e = Ellipse((0, 0), 1, 2) assert e.encloses_point(e.center) assert e.encloses_point(e.center + Point(0, e.vradius - Rational(1, 10))) assert e.encloses_point(e.center + Point(e.hradius - Rational(1, 10), 0)) assert e.encloses_point(e.center + Point(e.hradius, 0)) is False assert e.encloses_point(e.center + Point(e.hradius + Rational(1, 10), 0)) is False e = Ellipse((0, 0), 2, 1) assert e.encloses_point(e.center) assert e.encloses_point(e.center + Point(0, e.vradius - Rational(1, 10))) assert e.encloses_point(e.center + Point(e.hradius - Rational(1, 10), 0)) assert e.encloses_point(e.center + Point(e.hradius, 0)) is False assert e.encloses_point(e.center + Point(e.hradius + Rational(1, 10), 0)) is False assert c1.encloses_point(Point(1, 0)) is False assert c1.encloses_point(Point(0.3, 0.4)) is True
def HexArray(Separation = 14.6, hexNum = 11, SplitCore = False, NineWaySplitCore = False, SplitCoreOutriggers = False, JoshsOutriggers = False, RedundantOutriggers = False, LoadHERAOutriggers = False, fiducialInriggers = False, redundantTriangleInriggers = False, redundantPairInriggers = False, redundantHexInriggers = False, halfCornerInriggers = False, fullCornerInriggers = False, **kwargs): precisionFactor = 1000000 #Calculating Positions: #Main Hex positions = []; for row in range(hexNum-1,-(hexNum)+SplitCore,-1): # for row in range(hexNum-1,-(hexNum),-1): for col in range(2*hexNum-abs(row)-1): xPos = ((-(2*hexNum-abs(row))+2)/2.0 + col)*Separation; yPos = row*Separation*3**.5/2; positions.append([xPos, yPos, 0]) nCore = len(positions) right = Separation*np.asarray([1,0,0]) up = Separation*np.asarray([0,1,0]) upRight = Separation*np.asarray([.5,3**.5/2,0]) upLeft = Separation*np.asarray([-.5,3**.5/2,0]) # #Split the core into 3 pieces if SplitCore: for i,pos in enumerate(positions): theta = np.arctan2(pos[1],pos[0]) if not (pos[0]==0 and pos[1]==0): if (theta > -np.pi/3 and theta < np.pi/3): positions[i] = np.asarray(pos) + (upRight + upLeft)/3 if (theta >= np.pi/3 and theta < np.pi): positions[i] = np.asarray(pos) +upLeft - (upRight + upLeft)/3 if NineWaySplitCore: from sympy.geometry import RegularPolygon, Point, Polygon distances = np.asarray([np.linalg.norm(pos) for pos in positions]) fullRadius = np.max(distances) interiorHex = RegularPolygon(Point(0, 0), 1.001*3**-.5*fullRadius, 6) interiorHex.spin(np.pi/6) interiorHex = Polygon(*[Point(vert.x.evalf(), vert.y.evalf()) for vert in interiorHex.vertices]) positions.remove(positions[76]) isInterior = np.zeros(len(positions),dtype=bool) for i,pos in enumerate(positions): if distances[i] < fullRadius/2.0: isInterior[i] = True elif distances[i] <= 3**-.5*fullRadius and interiorHex.encloses_point(Point(pos[0],pos[1])): isInterior[i] = True v1 = (upRight + upLeft)/3 v2 = right/3 for i,pos in enumerate(positions): theta = np.arctan2(pos[1],pos[0]) if isInterior[i]: if not (pos[0]==0 and pos[1]==0): if (theta > -np.pi/3 and theta < np.pi/3): #right positions[i] = np.asarray(pos) +v1 if (theta >= np.pi/3 and theta < np.pi): #top left positions[i] = np.asarray(pos) +upLeft - v1 else: if (theta > -np.pi/6 and theta < np.pi/6): #right positions[i] = np.asarray(pos) + 2*v2 if (theta <= -5*np.pi/6 or theta >= 5*np.pi/6): #left positions[i] = np.asarray(pos) -v2 - right if (theta > -np.pi/2 and theta <= -np.pi/6): #bottom right positions[i] = np.asarray(pos) -v1 +v2 if (theta > -5*np.pi/6 and theta <= -np.pi/2): #bottom left positions[i] = np.asarray(pos) -v1-v2 if (theta >= np.pi/6 and theta < np.pi/2): #top right positions[i] = np.asarray(pos) + v1 + 2*v2 if (theta >= np.pi/2 and theta < 5*np.pi/6): #top left positions[i] = np.asarray(pos) +v1-2*v2 nCore = len(positions) #Aaron's fiducial inriggers if fiducialInriggers: print "adding Aaron's inriggers" if hexNum % 2 == 1: positions.append(upRight + ((hexNum-1)/2 + 1.0/3**.5/2.0) * (upLeft + upRight)) positions.append(right + ((hexNum-1)/2 + 1.0/3**.5/2.0) * (right + upRight)) positions.append(right + ((hexNum+1)/2 + 1.0/3**.5/2.0) * (-right + upLeft)) else: positions.append(((hexNum)/2 + 1.0/3**.5/2.0) * (upLeft + upRight)) positions.append(((hexNum)/2 + 1.0/3**.5/2.0) * (right + upRight)) positions.append(((hexNum)/2 + 1.0/3**.5/2.0) * (-right + upLeft)) #Redundant Inriggers if redundantTriangleInriggers or redundantPairInriggers or redundantHexInriggers: hexNumInrigger = 2 if hexNum % 2 == 1: inriggerCenters = [((hexNum-1)/2) * (upLeft + upRight) + upLeft + upLeft + right + (right + upRight)/3, #top -((hexNum-1)/2) * (upLeft + upRight) - upLeft - upLeft - 2*(right + upRight)/3, #bottom -(-(hexNum-1)/2 * (upRight + right) - upRight - right - (right + upRight)/3), #top right -((hexNum-1)/2 * (upRight + right) + upRight + 2*(right + upRight)/3), #bottom left (hexNum-1)/2 * (upLeft - right) + upLeft + upRight - right - 2*(right + upRight)/3, #top left -(hexNum-1)/2 * (upLeft - right) - upLeft + right + (right + upRight)/3] #top right else: inriggerCenters = [hexNum/2 * (upLeft + upRight) + upLeft + (right + upRight)/3, #top -hexNum/2 * (upLeft + upRight) - upLeft - 2*(right + upRight)/3, #bottom hexNum/2 * (upRight + right) + 2*(right + upRight)/3, #top right -hexNum/2 * (upRight + right) - right - (right + upRight)/3, #bottom left hexNum/2 * (upLeft - right) + upRight - right - 2*(right + upRight)/3, #top left -hexNum/2 * (upLeft - right) - upLeft + (right + upRight)/3] #top right for newCenter in inriggerCenters: for row in range(hexNumInrigger-1,-(hexNumInrigger),-1): for col in range(2*hexNumInrigger-abs(row)-1): xPos = ((-(2*hexNumInrigger-abs(row))+2)/2.0 + col)*Separation + newCenter[0] yPos = row*Separation*3**.5/2 + newCenter[1] if redundantHexInriggers: positions.append([xPos, yPos, 0]) elif redundantTriangleInriggers: if (xPos**2+yPos**2)**.5 < np.linalg.norm(newCenter) or np.array_equal(np.array([xPos, yPos, 0]), newCenter): positions.append([xPos, yPos, 0]) elif redundantPairInriggers: if (xPos**2+yPos**2)**.5 < np.linalg.norm(newCenter): positions.append([xPos, yPos, 0]) #Redundantly calibratable inriggers with full UV coverage if fullCornerInriggers or halfCornerInriggers: positions.append(hexNum * (upLeft) + (right + upRight)/3) positions.append(hexNum * (upLeft) - (right + upRight)/3) positions.append(hexNum * (upRight) + (-right + upLeft)/3) positions.append(hexNum * (upRight) - (-right + upLeft)/3) positions.append(hexNum * (right) + (upRight + upLeft)/3) positions.append(hexNum * (right) - (upRight + upLeft)/3) if fullCornerInriggers: positions.append(-(hexNum * (upLeft) + (right + upRight)/3)) positions.append(-(hexNum * (upLeft) - (right + upRight)/3)) positions.append(-(hexNum * (upRight) + (-right + upLeft)/3)) positions.append(-(hexNum * (upRight) - (-right + upLeft)/3)) positions.append(-(hexNum * (right) + (upRight + upLeft)/3)) positions.append(-(hexNum * (right) - (upRight + upLeft)/3)) #Half Wavelength Stuff # for i in range(1,14): # positions.append(i*(upLeft + upRight)/27) #%% #Outriggers if SplitCoreOutriggers: exteriorHexNum = 4 for row in range(exteriorHexNum-1,-(exteriorHexNum),-1): for col in range(2*exteriorHexNum-abs(row)-1): xPos = ((-(2*exteriorHexNum-abs(row))+2)/2.0 + col)*Separation*(hexNum-1) yPos = row*Separation*(hexNum-1)*3**.5/2 theta = np.arctan2(yPos,xPos) if ((xPos**2 + yPos**2)**.5 > Separation*(hexNum+1)): if (theta > -np.pi/3 and theta < np.pi/3): positions.append(np.asarray([xPos, yPos, 0]) + (upRight + upLeft)/3) elif (theta >= np.pi/3 and theta < np.pi): positions.append(np.asarray([xPos, yPos, 0]) +upLeft - (upRight + upLeft)/3) else: positions.append([xPos, yPos, 0]) if JoshsOutriggers: outriggerHexNum = 3 for row in range(outriggerHexNum-1,-(outriggerHexNum),-1): for col in range(2*outriggerHexNum-abs(row)-1): xPos = ((-(2*outriggerHexNum-abs(row))+2)/2.0 + col)*Separation*(np.floor(1.5*hexNum)); yPos = row*Separation*(np.floor(1.5*hexNum))*3**.5/2; if xPos != 0 or yPos != 0: positions.append([xPos, yPos, 0]) if RedundantOutriggers: outriggerHexNum = 3 for row in range(outriggerHexNum-1,-(outriggerHexNum),-1): for col in range(2*outriggerHexNum-abs(row)-1): yPos = ((-(2*outriggerHexNum-abs(row))+2)/2.0 + col)*Separation*(3**.5*(hexNum-1)); xPos = row*Separation*(3**.5*(hexNum-1))*3**.5/2; if xPos != 0 or yPos != 0: positions.append([xPos, yPos, 0]) if LoadHERAOutriggers: outriggerPositions = np.loadtxt(os.path.dirname(os.path.abspath(__file__)) + '/hexconfig352_outriggers_only.dat') for outrigger in outriggerPositions: positions.append(np.append(outrigger,0)) precisionFactor = 10000 #Calculating Baselines nAntennas = len(positions) baselines = [] baselinePairs = [] #print "WARNING: DOUBLING UNIQUE BASELINES!!!" for ant1 in range(nAntennas): for ant2 in range(ant1+1,nAntennas): deltax = int(np.round(precisionFactor*(positions[ant1][0]-positions[ant2][0]))) deltay = int(np.round(precisionFactor*(positions[ant1][1]-positions[ant2][1]))) deltaz = int(np.round(precisionFactor*(positions[ant1][2]-positions[ant2][2]))) if (deltax**2+deltay**2+deltaz**2 < precisionFactor**2*Separation**2): print "WARNING: antennas " + str(ant1) + " and " + str(ant2) + " are too close together!" if deltay > 0 or (deltay == 0 and deltax > 0): baselines.append((deltax, deltay, deltaz)) baselinePairs.append((ant1, ant2)) else: baselines.append((-deltax, -deltay, -deltaz)) baselinePairs.append((ant2, ant1)) #Calculating Unique Baselines baselineDict = {} for b in range(len(baselines)): if baselineDict.has_key(baselines[b]): baselineDict[baselines[b]].append(baselinePairs[b]) else: baselineDict[baselines[b]] = [baselinePairs[b]] print "With", len(positions), "antennas there are", len(baselineDict.items()), "unique baselines." #Saving results scriptDirectory = os.path.dirname(os.path.abspath(__file__)) np.savetxt(scriptDirectory + "/antenna_positions.dat",np.asarray(positions)) np.savetxt(scriptDirectory + "/all_baselines.dat",np.asarray(baselines)/(1.0*precisionFactor)) np.savetxt(scriptDirectory + "/all_baseline_pairs.dat",np.asarray(baselinePairs),fmt='%i') np.savetxt(scriptDirectory + "/unique_baselines.dat",np.asarray([uniqueBaseline[0] for uniqueBaseline in baselineDict.items()])/(1.0*precisionFactor)) np.savetxt(scriptDirectory + "/redundancy.dat",np.asarray([len(uniqueBaseline[1]) for uniqueBaseline in baselineDict.items()]),fmt='%i') antennaPairDict = {} for uniqueIndex in range(len(baselineDict.items())): allItems = baselineDict.items() for antennaPair in allItems[uniqueIndex][1]: antennaPairDict[antennaPair] = uniqueIndex pickle.dump(antennaPairDict, open(scriptDirectory + "/antennaPairUniqueBaselineIndexDict.p", 'w')) if __name__ == "__main__": from mpldatacursor import datacursor uniqueBaselines = np.asarray([uniqueBaseline[0] for uniqueBaseline in baselineDict.items()])/(1.0*precisionFactor) redundancy = np.asarray([len(uniqueBaseline[1]) for uniqueBaseline in baselineDict.items()]) uniqueBaselines = np.append(uniqueBaselines, -uniqueBaselines, axis=0) redundancy = np.append(redundancy, redundancy, axis=0) plt.figure(1) plt.clf() plt.scatter(np.asarray(positions)[:,0]/Separation,np.asarray(positions)[:,1]/Separation) plt.axis('equal') plt.figure(2) plt.clf() # plt.scatter(uniqueBaselines[:,0]/1.0/Separation, uniqueBaselines[:,1]/1.0/Separation,c=np.minimum(redundancy,100000),s=40) plt.scatter(uniqueBaselines[:,0]/1.0/1.5, uniqueBaselines[:,1]/1.0/1.5,c=np.minimum(redundancy,100000),s=40) plt.colorbar() plt.title('Baseline Redundancy') #datacursor(display='single',formatter="x={x:.4f}\ny={y:.4f}".format) plt.show() plt.axis('equal') return np.asarray(positions)
def test_polygon(): t = Triangle(Point(0, 0), Point(2, 0), Point(3, 3)) assert Polygon(Point(0, 0), Point(1, 0), Point(2, 0), Point(3, 3)) == t assert Polygon(Point(1, 0), Point(2, 0), Point(3, 3), Point(0, 0)) == t assert Polygon(Point(2, 0), Point(3, 3), Point(0, 0), Point(1, 0)) == t p1 = Polygon(Point(0, 0), Point(3, -1), Point(6, 0), Point(4, 5), Point(2, 3), Point(0, 3)) p2 = Polygon(Point(6, 0), Point(3, -1), Point(0, 0), Point(0, 3), Point(2, 3), Point(4, 5)) p3 = Polygon(Point(0, 0), Point(3, 0), Point(5, 2), Point(4, 4)) p4 = Polygon(Point(0, 0), Point(4, 4), Point(5, 2), Point(3, 0)) # # General polygon # assert p1 == p2 assert len(p1) == 6 assert len(p1.sides) == 6 assert p1.perimeter == 5 + 2 * sqrt(10) + sqrt(29) + sqrt(8) assert p1.area == 22 assert not p1.is_convex() assert p3.is_convex() assert p4.is_convex( ) # ensure convex for both CW and CCW point specification # # Regular polygon # p1 = RegularPolygon(Point(0, 0), 10, 5) p2 = RegularPolygon(Point(0, 0), 5, 5) assert p1 != p2 assert p1.interior_angle == 3 * pi / 5 assert p1.exterior_angle == 2 * pi / 5 assert p2.apothem == 5 * cos(pi / 5) assert p2.circumcircle == Circle(Point(0, 0), 5) assert p2.incircle == Circle(Point(0, 0), p2.apothem) assert p1.is_convex() assert p1.rotation == 0 p1.spin(pi / 3) assert p1.rotation == pi / 3 assert p1[0] == Point(5, 5 * sqrt(3)) # while spin works in place (notice that rotation is 2pi/3 below) # rotate returns a new object p1_old = p1 assert p1.rotate(pi / 3) == RegularPolygon(Point(0, 0), 10, 5, 2 * pi / 3) assert p1 == p1_old # # Angles # angles = p4.angles assert feq(angles[Point(0, 0)].evalf(), Float("0.7853981633974483")) assert feq(angles[Point(4, 4)].evalf(), Float("1.2490457723982544")) assert feq(angles[Point(5, 2)].evalf(), Float("1.8925468811915388")) assert feq(angles[Point(3, 0)].evalf(), Float("2.3561944901923449")) angles = p3.angles assert feq(angles[Point(0, 0)].evalf(), Float("0.7853981633974483")) assert feq(angles[Point(4, 4)].evalf(), Float("1.2490457723982544")) assert feq(angles[Point(5, 2)].evalf(), Float("1.8925468811915388")) assert feq(angles[Point(3, 0)].evalf(), Float("2.3561944901923449")) # # Triangle # p1 = Point(0, 0) p2 = Point(5, 0) p3 = Point(0, 5) t1 = Triangle(p1, p2, p3) t2 = Triangle(p1, p2, Point(Rational(5, 2), sqrt(Rational(75, 4)))) t3 = Triangle(p1, Point(x1, 0), Point(0, x1)) s1 = t1.sides # Basic stuff assert Triangle(p1, p1, p1) == p1 assert Triangle(p2, p2 * 2, p2 * 3) == Segment(p2, p2 * 3) assert t1.area == Rational(25, 2) assert t1.is_right() assert t2.is_right() == False assert t3.is_right() assert p1 in t1 assert t1.sides[0] in t1 assert Segment((0, 0), (1, 0)) in t1 assert Point(5, 5) not in t2 assert t1.is_convex() assert feq(t1.angles[p1].evalf(), pi.evalf() / 2) assert t1.is_equilateral() == False assert t2.is_equilateral() assert t3.is_equilateral() == False assert are_similar(t1, t2) == False assert are_similar(t1, t3) assert are_similar(t2, t3) == False # Bisectors bisectors = t1.bisectors() assert bisectors[p1] == Segment(p1, Point(Rational(5, 2), Rational(5, 2))) ic = (250 - 125 * sqrt(2)) / 50 assert t1.incenter == Point(ic, ic) # Inradius assert t1.inradius == 5 - 5 * sqrt(2) / 2 assert t2.inradius == 5 * sqrt(3) / 6 assert t3.inradius == x1**2 / ((2 + sqrt(2)) * Abs(x1)) # Medians + Centroid m = t1.medians assert t1.centroid == Point(Rational(5, 3), Rational(5, 3)) assert m[p1] == Segment(p1, Point(Rational(5, 2), Rational(5, 2))) assert t3.medians[p1] == Segment(p1, Point(x1 / 2, x1 / 2)) assert intersection(m[p1], m[p2], m[p3]) == [t1.centroid] # Perpendicular altitudes = t1.altitudes assert altitudes[p1] == Segment(p1, Point(Rational(5, 2), Rational(5, 2))) assert altitudes[p2] == s1[0] assert altitudes[p3] == s1[2] # Ensure assert len(intersection(*bisectors.values())) == 1 assert len(intersection(*altitudes.values())) == 1 assert len(intersection(*m.values())) == 1 # Distance p1 = Polygon(Point(0, 0), Point(1, 0), Point(1, 1), Point(0, 1)) p2 = Polygon(Point(0, Rational(5) / 4), Point(1, Rational(5) / 4), Point(1, Rational(9) / 4), Point(0, Rational(9) / 4)) p3 = Polygon(Point(1, 2), Point(2, 2), Point(2, 1)) p4 = Polygon(Point(1, 1), Point(Rational(6) / 5, 1), Point(1, Rational(6) / 5)) pt1 = Point(half, half) pt2 = Point(1, 1) '''Polygon to Point''' assert p1.distance(pt1) == half assert p1.distance(pt2) == 0 assert p2.distance(pt1) == Rational(3) / 4 assert p3.distance(pt2) == sqrt(2) / 2
def test_polygon(): p1 = Polygon(Point(0, 0), Point(3, -1), Point(6, 0), Point(4, 5), Point(2, 3), Point(0, 3)) p2 = Polygon(Point(6, 0), Point(3, -1), Point(0, 0), Point(0, 3), Point(2, 3), Point(4, 5)) p3 = Polygon(Point(0, 0), Point(3, 0), Point(5, 2), Point(4, 4)) p4 = Polygon(Point(0, 0), Point(4, 4), Point(5, 2), Point(3, 0)) # # General polygon # assert p1 == p2 assert len(p1) == Rational(6) assert len(p1.sides) == 6 assert p1.perimeter == 5 + 2 * sqrt(10) + sqrt(29) + sqrt(8) assert p1.area == 22 assert not p1.is_convex() assert p3.is_convex() assert p4.is_convex( ) # ensure convex for both CW and CCW point specification # # Regular polygon # p1 = RegularPolygon(Point(0, 0), 10, 5) p2 = RegularPolygon(Point(0, 0), 5, 5) assert p1 != p2 assert p1.interior_angle == 3 * pi / 5 assert p1.exterior_angle == 2 * pi / 5 assert p2.apothem == 5 * cos(pi / 5) assert p2.circumcircle == Circle(Point(0, 0), 5) assert p2.incircle == Circle(Point(0, 0), p2.apothem) assert p1.is_convex() # # Angles # angles = p4.angles assert feq(angles[Point(0, 0)].evalf(), Real("0.7853981633974483")) assert feq(angles[Point(4, 4)].evalf(), Real("1.2490457723982544")) assert feq(angles[Point(5, 2)].evalf(), Real("1.8925468811915388")) assert feq(angles[Point(3, 0)].evalf(), Real("2.3561944901923449")) angles = p3.angles assert feq(angles[Point(0, 0)].evalf(), Real("0.7853981633974483")) assert feq(angles[Point(4, 4)].evalf(), Real("1.2490457723982544")) assert feq(angles[Point(5, 2)].evalf(), Real("1.8925468811915388")) assert feq(angles[Point(3, 0)].evalf(), Real("2.3561944901923449")) # # Triangle # p1 = Point(0, 0) p2 = Point(5, 0) p3 = Point(0, 5) t1 = Triangle(p1, p2, p3) t2 = Triangle(p1, p2, Point(Rational(5, 2), sqrt(Rational(75, 4)))) t3 = Triangle(p1, Point(x1, 0), Point(0, x1)) s1 = t1.sides s2 = t2.sides s3 = t3.sides # Basic stuff assert t1.area == Rational(25, 2) assert t1.is_right() assert t2.is_right() == False assert t3.is_right() assert p1 in t1 assert Point(5, 5) not in t2 assert t1.is_convex() assert feq(t1.angles[p1].evalf(), pi.evalf() / 2) assert t1.is_equilateral() == False assert t2.is_equilateral() assert t3.is_equilateral() == False assert are_similar(t1, t2) == False assert are_similar(t1, t3) assert are_similar(t2, t3) == False # Bisectors bisectors = t1.bisectors assert bisectors[p1] == Segment(p1, Point(Rational(5, 2), Rational(5, 2))) ic = (250 - 125 * sqrt(2)) / 50 assert t1.incenter == Point(ic, ic) # Inradius assert t1.inradius == 5 - 5 * 2**(S(1) / 2) / 2 assert t2.inradius == 5 * 3**(S(1) / 2) / 6 assert t3.inradius == (2 * x1**2 * Abs(x1) - 2**(S(1) / 2) * x1**2 * Abs(x1)) / (2 * x1**2) # Medians + Centroid m = t1.medians assert t1.centroid == Point(Rational(5, 3), Rational(5, 3)) assert m[p1] == Segment(p1, Point(Rational(5, 2), Rational(5, 2))) assert t3.medians[p1] == Segment(p1, Point(x1 / 2, x1 / 2)) assert intersection(m[p1], m[p2], m[p3]) == [t1.centroid] # Perpendicular altitudes = t1.altitudes assert altitudes[p1] == Segment(p1, Point(Rational(5, 2), Rational(5, 2))) assert altitudes[p2] == s1[0] assert altitudes[p3] == s1[2] # Ensure assert len(intersection(*bisectors.values())) == 1 assert len(intersection(*altitudes.values())) == 1 assert len(intersection(*m.values())) == 1 # Distance p1 = Polygon(Point(0, 0), Point(1, 0), Point(1, 1), Point(0, 1)) p2 = Polygon(Point(0, Rational(5) / 4), Point(1, Rational(5) / 4), Point(1, Rational(9) / 4), Point(0, Rational(9) / 4)) p3 = Polygon(Point(1, 2), Point(2, 2), Point(2, 1)) p4 = Polygon(Point(1, 1), Point(Rational(6) / 5, 1), Point(1, Rational(6) / 5)) p5 = Polygon(Point(half, 3**(half) / 2), Point(-half, 3**(half) / 2), Point(-1, 0), Point(-half, -(3)**(half) / 2), Point(half, -(3)**(half) / 2), Point(1, 0)) p6 = Polygon(Point(2, Rational(3) / 10), Point(Rational(17) / 10, 0), Point(2, -Rational(3) / 10), Point(Rational(23) / 10, 0)) pt1 = Point(half, half) pt2 = Point(1, 1) '''Polygon to Point''' assert p1.distance(pt1) == half assert p1.distance(pt2) == 0 assert p2.distance(pt1) == Rational(3) / 4 assert p3.distance(pt2) == sqrt(2) / 2 '''Polygon to Polygon''' assert p1.distance(p2) == half / 2 assert p1.distance(p3) == sqrt(2) / 2 assert p3.distance(p4) == (sqrt(2) / 2 - sqrt(Rational(2) / 25) / 2) assert p5.distance(p6) == Rational(7) / 10
def test_polygon(): t = Triangle(Point(0, 0), Point(2, 0), Point(3, 3)) assert Polygon(Point(0, 0), Point(1, 0), Point(2, 0), Point(3, 3)) == t assert Polygon(Point(1, 0), Point(2, 0), Point(3, 3), Point(0, 0)) == t assert Polygon(Point(2, 0), Point(3, 3), Point(0, 0), Point(1, 0)) == t p1 = Polygon(Point(0, 0), Point(3, -1), Point(6, 0), Point(4, 5), Point(2, 3), Point(0, 3)) p2 = Polygon(Point(6, 0), Point(3, -1), Point(0, 0), Point(0, 3), Point(2, 3), Point(4, 5)) p3 = Polygon(Point(0, 0), Point(3, 0), Point(5, 2), Point(4, 4)) p4 = Polygon(Point(0, 0), Point(4, 4), Point(5, 2), Point(3, 0)) p5 = Polygon(Point(0, 0), Point(4, 4), Point(0, 4)) # # General polygon # assert p1 == p2 assert len(p1.args) == 6 assert len(p1.sides) == 6 assert p1.perimeter == 5 + 2 * sqrt(10) + sqrt(29) + sqrt(8) assert p1.area == 22 assert not p1.is_convex() # ensure convex for both CW and CCW point specification assert p3.is_convex() assert p4.is_convex() dict5 = p5.angles assert dict5[Point(0, 0)] == pi / 4 assert dict5[Point(0, 4)] == pi / 2 assert p5.encloses_point(Point(x, y)) is None assert p5.encloses_point(Point(1, 3)) assert p5.encloses_point(Point(0, 0)) is False assert p5.encloses_point(Point(4, 0)) is False p5.plot_interval('x') == [x, 0, 1] assert p5.distance(Polygon(Point(10, 10), Point(14, 14), Point(10, 14))) == 6 * sqrt(2) assert p5.distance( Polygon(Point(1, 8), Point(5, 8), Point(8, 12), Point(1, 12))) == 4 warnings.filterwarnings( "error", message="Polygons may intersect producing erroneous output") raises( UserWarning, lambda: Polygon(Point(0, 0), Point(1, 0), Point(1, 1)).distance( Polygon(Point(0, 0), Point(0, 1), Point(1, 1)))) warnings.filterwarnings( "ignore", message="Polygons may intersect producing erroneous output") assert hash(p5) == hash(Polygon(Point(0, 0), Point(4, 4), Point(0, 4))) assert p5 == Polygon(Point(4, 4), Point(0, 4), Point(0, 0)) assert Polygon(Point(4, 4), Point(0, 4), Point(0, 0)) in p5 assert p5 != Point(0, 4) assert Point(0, 1) in p5 assert p5.arbitrary_point('t').subs(Symbol('t', real=True), 0) == \ Point(0, 0) raises( ValueError, lambda: Polygon(Point(x, 0), Point(0, y), Point(x, y)). arbitrary_point('x')) # # Regular polygon # p1 = RegularPolygon(Point(0, 0), 10, 5) p2 = RegularPolygon(Point(0, 0), 5, 5) raises(GeometryError, lambda: RegularPolygon(Point(0, 0), Point(0, 1), Point(1, 1))) raises(GeometryError, lambda: RegularPolygon(Point(0, 0), 1, 2)) raises(ValueError, lambda: RegularPolygon(Point(0, 0), 1, 2.5)) assert p1 != p2 assert p1.interior_angle == 3 * pi / 5 assert p1.exterior_angle == 2 * pi / 5 assert p2.apothem == 5 * cos(pi / 5) assert p2.circumcenter == p1.circumcenter == Point(0, 0) assert p1.circumradius == p1.radius == 10 assert p2.circumcircle == Circle(Point(0, 0), 5) assert p2.incircle == Circle(Point(0, 0), p2.apothem) assert p2.inradius == p2.apothem == (5 * (1 + sqrt(5)) / 4) p2.spin(pi / 10) dict1 = p2.angles assert dict1[Point(0, 5)] == 3 * pi / 5 assert p1.is_convex() assert p1.rotation == 0 assert p1.encloses_point(Point(0, 0)) assert p1.encloses_point(Point(11, 0)) is False assert p2.encloses_point(Point(0, 4.9)) p1.spin(pi / 3) assert p1.rotation == pi / 3 assert p1.vertices[0] == Point(5, 5 * sqrt(3)) for var in p1.args: if isinstance(var, Point): assert var == Point(0, 0) else: assert var == 5 or var == 10 or var == pi / 3 assert p1 != Point(0, 0) assert p1 != p5 # while spin works in place (notice that rotation is 2pi/3 below) # rotate returns a new object p1_old = p1 assert p1.rotate(pi / 3) == RegularPolygon(Point(0, 0), 10, 5, 2 * pi / 3) assert p1 == p1_old assert p1.area == (-250 * sqrt(5) + 1250) / (4 * tan(pi / 5)) assert p1.length == 20 * sqrt(-sqrt(5) / 8 + S(5) / 8) assert p1.scale(2, 2) == \ RegularPolygon(p1.center, p1.radius*2, p1._n, p1.rotation) assert RegularPolygon((0, 0), 1, 4).scale(2, 3) == \ Polygon(Point(2, 0), Point(0, 3), Point(-2, 0), Point(0, -3)) assert repr(p1) == str(p1) # # Angles # angles = p4.angles assert feq(angles[Point(0, 0)].evalf(), Float("0.7853981633974483")) assert feq(angles[Point(4, 4)].evalf(), Float("1.2490457723982544")) assert feq(angles[Point(5, 2)].evalf(), Float("1.8925468811915388")) assert feq(angles[Point(3, 0)].evalf(), Float("2.3561944901923449")) angles = p3.angles assert feq(angles[Point(0, 0)].evalf(), Float("0.7853981633974483")) assert feq(angles[Point(4, 4)].evalf(), Float("1.2490457723982544")) assert feq(angles[Point(5, 2)].evalf(), Float("1.8925468811915388")) assert feq(angles[Point(3, 0)].evalf(), Float("2.3561944901923449")) # # Triangle # p1 = Point(0, 0) p2 = Point(5, 0) p3 = Point(0, 5) t1 = Triangle(p1, p2, p3) t2 = Triangle(p1, p2, Point(Rational(5, 2), sqrt(Rational(75, 4)))) t3 = Triangle(p1, Point(x1, 0), Point(0, x1)) s1 = t1.sides assert Triangle(p1, p2, p1) == Polygon(p1, p2, p1) == Segment(p1, p2) raises(GeometryError, lambda: Triangle(Point(0, 0))) # Basic stuff assert Triangle(p1, p1, p1) == p1 assert Triangle(p2, p2 * 2, p2 * 3) == Segment(p2, p2 * 3) assert t1.area == Rational(25, 2) assert t1.is_right() assert t2.is_right() is False assert t3.is_right() assert p1 in t1 assert t1.sides[0] in t1 assert Segment((0, 0), (1, 0)) in t1 assert Point(5, 5) not in t2 assert t1.is_convex() assert feq(t1.angles[p1].evalf(), pi.evalf() / 2) assert t1.is_equilateral() is False assert t2.is_equilateral() assert t3.is_equilateral() is False assert are_similar(t1, t2) is False assert are_similar(t1, t3) assert are_similar(t2, t3) is False assert t1.is_similar(Point(0, 0)) is False # Bisectors bisectors = t1.bisectors() assert bisectors[p1] == Segment(p1, Point(Rational(5, 2), Rational(5, 2))) ic = (250 - 125 * sqrt(2)) / 50 assert t1.incenter == Point(ic, ic) # Inradius assert t1.inradius == t1.incircle.radius == 5 - 5 * sqrt(2) / 2 assert t2.inradius == t2.incircle.radius == 5 * sqrt(3) / 6 assert t3.inradius == t3.incircle.radius == x1**2 / ( (2 + sqrt(2)) * Abs(x1)) # Circumcircle assert t1.circumcircle.center == Point(2.5, 2.5) # Medians + Centroid m = t1.medians assert t1.centroid == Point(Rational(5, 3), Rational(5, 3)) assert m[p1] == Segment(p1, Point(Rational(5, 2), Rational(5, 2))) assert t3.medians[p1] == Segment(p1, Point(x1 / 2, x1 / 2)) assert intersection(m[p1], m[p2], m[p3]) == [t1.centroid] assert t1.medial == Triangle(Point(2.5, 0), Point(0, 2.5), Point(2.5, 2.5)) # Perpendicular altitudes = t1.altitudes assert altitudes[p1] == Segment(p1, Point(Rational(5, 2), Rational(5, 2))) assert altitudes[p2] == s1[0] assert altitudes[p3] == s1[2] assert t1.orthocenter == p1 t = S('''Triangle( Point(100080156402737/5000000000000, 79782624633431/500000000000), Point(39223884078253/2000000000000, 156345163124289/1000000000000), Point(31241359188437/1250000000000, 338338270939941/1000000000000000))''') assert t.orthocenter == S( '''Point(-780660869050599840216997''' '''79471538701955848721853/80368430960602242240789074233100000000000000,''' '''20151573611150265741278060334545897615974257/16073686192120448448157''' '''8148466200000000000)''') # Ensure assert len(intersection(*bisectors.values())) == 1 assert len(intersection(*altitudes.values())) == 1 assert len(intersection(*m.values())) == 1 # Distance p1 = Polygon(Point(0, 0), Point(1, 0), Point(1, 1), Point(0, 1)) p2 = Polygon(Point(0, Rational(5) / 4), Point(1, Rational(5) / 4), Point(1, Rational(9) / 4), Point(0, Rational(9) / 4)) p3 = Polygon(Point(1, 2), Point(2, 2), Point(2, 1)) p4 = Polygon(Point(1, 1), Point(Rational(6) / 5, 1), Point(1, Rational(6) / 5)) pt1 = Point(half, half) pt2 = Point(1, 1) '''Polygon to Point''' assert p1.distance(pt1) == half assert p1.distance(pt2) == 0 assert p2.distance(pt1) == Rational(3) / 4 assert p3.distance(pt2) == sqrt(2) / 2 '''Polygon to Polygon''' # p1.distance(p2) emits a warning # First, test the warning warnings.filterwarnings( "error", message="Polygons may intersect producing erroneous output") raises(UserWarning, lambda: p1.distance(p2)) # now test the actual output warnings.filterwarnings( "ignore", message="Polygons may intersect producing erroneous output") assert p1.distance(p2) == half / 2 assert p1.distance(p3) == sqrt(2) / 2 assert p3.distance(p4) == (sqrt(2) / 2 - sqrt(Rational(2) / 25) / 2)
def test_polygon(): x = Symbol('x', real=True) y = Symbol('y', real=True) q = Symbol('q', real=True) u = Symbol('u', real=True) v = Symbol('v', real=True) w = Symbol('w', real=True) x1 = Symbol('x1', real=True) half = S.Half a, b, c = Point(0, 0), Point(2, 0), Point(3, 3) t = Triangle(a, b, c) assert Polygon(Point(0, 0)) == Point(0, 0) assert Polygon(a, Point(1, 0), b, c) == t assert Polygon(Point(1, 0), b, c, a) == t assert Polygon(b, c, a, Point(1, 0)) == t # 2 "remove folded" tests assert Polygon(a, Point(3, 0), b, c) == t assert Polygon(a, b, Point(3, -1), b, c) == t # remove multiple collinear points assert Polygon(Point(-4, 15), Point(-11, 15), Point(-15, 15), Point(-15, 33/5), Point(-15, -87/10), Point(-15, -15), Point(-42/5, -15), Point(-2, -15), Point(7, -15), Point(15, -15), Point(15, -3), Point(15, 10), Point(15, 15)) == \ Polygon(Point(-15, -15), Point(15, -15), Point(15, 15), Point(-15, 15)) p1 = Polygon( Point(0, 0), Point(3, -1), Point(6, 0), Point(4, 5), Point(2, 3), Point(0, 3)) p2 = Polygon( Point(6, 0), Point(3, -1), Point(0, 0), Point(0, 3), Point(2, 3), Point(4, 5)) p3 = Polygon( Point(0, 0), Point(3, 0), Point(5, 2), Point(4, 4)) p4 = Polygon( Point(0, 0), Point(4, 4), Point(5, 2), Point(3, 0)) p5 = Polygon( Point(0, 0), Point(4, 4), Point(0, 4)) p6 = Polygon( Point(-11, 1), Point(-9, 6.6), Point(-4, -3), Point(-8.4, -8.7)) p7 = Polygon( Point(x, y), Point(q, u), Point(v, w)) p8 = Polygon( Point(x, y), Point(v, w), Point(q, u)) p9 = Polygon( Point(0, 0), Point(4, 4), Point(3, 0), Point(5, 2)) p10 = Polygon( Point(0, 2), Point(2, 2), Point(0, 0), Point(2, 0)) p11 = Polygon(Point(0, 0), 1, n=3) p12 = Polygon(Point(0, 0), 1, 0, n=3) r = Ray(Point(-9, 6.6), Point(-9, 5.5)) # # General polygon # assert p1 == p2 assert len(p1.args) == 6 assert len(p1.sides) == 6 assert p1.perimeter == 5 + 2*sqrt(10) + sqrt(29) + sqrt(8) assert p1.area == 22 assert not p1.is_convex() assert Polygon((-1, 1), (2, -1), (2, 1), (-1, -1), (3, 0) ).is_convex() is False # ensure convex for both CW and CCW point specification assert p3.is_convex() assert p4.is_convex() dict5 = p5.angles assert dict5[Point(0, 0)] == pi / 4 assert dict5[Point(0, 4)] == pi / 2 assert p5.encloses_point(Point(x, y)) is None assert p5.encloses_point(Point(1, 3)) assert p5.encloses_point(Point(0, 0)) is False assert p5.encloses_point(Point(4, 0)) is False assert p1.encloses(Circle(Point(2.5, 2.5), 5)) is False assert p1.encloses(Ellipse(Point(2.5, 2), 5, 6)) is False p5.plot_interval('x') == [x, 0, 1] assert p5.distance( Polygon(Point(10, 10), Point(14, 14), Point(10, 14))) == 6 * sqrt(2) assert p5.distance( Polygon(Point(1, 8), Point(5, 8), Point(8, 12), Point(1, 12))) == 4 with warns(UserWarning, \ match="Polygons may intersect producing erroneous output"): Polygon(Point(0, 0), Point(1, 0), Point(1, 1)).distance( Polygon(Point(0, 0), Point(0, 1), Point(1, 1))) assert hash(p5) == hash(Polygon(Point(0, 0), Point(4, 4), Point(0, 4))) assert hash(p1) == hash(p2) assert hash(p7) == hash(p8) assert hash(p3) != hash(p9) assert p5 == Polygon(Point(4, 4), Point(0, 4), Point(0, 0)) assert Polygon(Point(4, 4), Point(0, 4), Point(0, 0)) in p5 assert p5 != Point(0, 4) assert Point(0, 1) in p5 assert p5.arbitrary_point('t').subs(Symbol('t', real=True), 0) == \ Point(0, 0) raises(ValueError, lambda: Polygon( Point(x, 0), Point(0, y), Point(x, y)).arbitrary_point('x')) assert p6.intersection(r) == [Point(-9, Rational(-84, 13)), Point(-9, Rational(33, 5))] assert p10.area == 0 assert p11 == RegularPolygon(Point(0, 0), 1, 3, 0) assert p11 == p12 assert p11.vertices[0] == Point(1, 0) assert p11.args[0] == Point(0, 0) p11.spin(pi/2) assert p11.vertices[0] == Point(0, 1) # # Regular polygon # p1 = RegularPolygon(Point(0, 0), 10, 5) p2 = RegularPolygon(Point(0, 0), 5, 5) raises(GeometryError, lambda: RegularPolygon(Point(0, 0), Point(0, 1), Point(1, 1))) raises(GeometryError, lambda: RegularPolygon(Point(0, 0), 1, 2)) raises(ValueError, lambda: RegularPolygon(Point(0, 0), 1, 2.5)) assert p1 != p2 assert p1.interior_angle == pi*Rational(3, 5) assert p1.exterior_angle == pi*Rational(2, 5) assert p2.apothem == 5*cos(pi/5) assert p2.circumcenter == p1.circumcenter == Point(0, 0) assert p1.circumradius == p1.radius == 10 assert p2.circumcircle == Circle(Point(0, 0), 5) assert p2.incircle == Circle(Point(0, 0), p2.apothem) assert p2.inradius == p2.apothem == (5 * (1 + sqrt(5)) / 4) p2.spin(pi / 10) dict1 = p2.angles assert dict1[Point(0, 5)] == 3 * pi / 5 assert p1.is_convex() assert p1.rotation == 0 assert p1.encloses_point(Point(0, 0)) assert p1.encloses_point(Point(11, 0)) is False assert p2.encloses_point(Point(0, 4.9)) p1.spin(pi/3) assert p1.rotation == pi/3 assert p1.vertices[0] == Point(5, 5*sqrt(3)) for var in p1.args: if isinstance(var, Point): assert var == Point(0, 0) else: assert var == 5 or var == 10 or var == pi / 3 assert p1 != Point(0, 0) assert p1 != p5 # while spin works in place (notice that rotation is 2pi/3 below) # rotate returns a new object p1_old = p1 assert p1.rotate(pi/3) == RegularPolygon(Point(0, 0), 10, 5, pi*Rational(2, 3)) assert p1 == p1_old assert p1.area == (-250*sqrt(5) + 1250)/(4*tan(pi/5)) assert p1.length == 20*sqrt(-sqrt(5)/8 + Rational(5, 8)) assert p1.scale(2, 2) == \ RegularPolygon(p1.center, p1.radius*2, p1._n, p1.rotation) assert RegularPolygon((0, 0), 1, 4).scale(2, 3) == \ Polygon(Point(2, 0), Point(0, 3), Point(-2, 0), Point(0, -3)) assert repr(p1) == str(p1) # # Angles # angles = p4.angles assert feq(angles[Point(0, 0)].evalf(), Float("0.7853981633974483")) assert feq(angles[Point(4, 4)].evalf(), Float("1.2490457723982544")) assert feq(angles[Point(5, 2)].evalf(), Float("1.8925468811915388")) assert feq(angles[Point(3, 0)].evalf(), Float("2.3561944901923449")) angles = p3.angles assert feq(angles[Point(0, 0)].evalf(), Float("0.7853981633974483")) assert feq(angles[Point(4, 4)].evalf(), Float("1.2490457723982544")) assert feq(angles[Point(5, 2)].evalf(), Float("1.8925468811915388")) assert feq(angles[Point(3, 0)].evalf(), Float("2.3561944901923449")) # # Triangle # p1 = Point(0, 0) p2 = Point(5, 0) p3 = Point(0, 5) t1 = Triangle(p1, p2, p3) t2 = Triangle(p1, p2, Point(Rational(5, 2), sqrt(Rational(75, 4)))) t3 = Triangle(p1, Point(x1, 0), Point(0, x1)) s1 = t1.sides assert Triangle(p1, p2, p1) == Polygon(p1, p2, p1) == Segment(p1, p2) raises(GeometryError, lambda: Triangle(Point(0, 0))) # Basic stuff assert Triangle(p1, p1, p1) == p1 assert Triangle(p2, p2*2, p2*3) == Segment(p2, p2*3) assert t1.area == Rational(25, 2) assert t1.is_right() assert t2.is_right() is False assert t3.is_right() assert p1 in t1 assert t1.sides[0] in t1 assert Segment((0, 0), (1, 0)) in t1 assert Point(5, 5) not in t2 assert t1.is_convex() assert feq(t1.angles[p1].evalf(), pi.evalf()/2) assert t1.is_equilateral() is False assert t2.is_equilateral() assert t3.is_equilateral() is False assert are_similar(t1, t2) is False assert are_similar(t1, t3) assert are_similar(t2, t3) is False assert t1.is_similar(Point(0, 0)) is False assert t1.is_similar(t2) is False # Bisectors bisectors = t1.bisectors() assert bisectors[p1] == Segment( p1, Point(Rational(5, 2), Rational(5, 2))) assert t2.bisectors()[p2] == Segment( Point(5, 0), Point(Rational(5, 4), 5*sqrt(3)/4)) p4 = Point(0, x1) assert t3.bisectors()[p4] == Segment(p4, Point(x1*(sqrt(2) - 1), 0)) ic = (250 - 125*sqrt(2))/50 assert t1.incenter == Point(ic, ic) # Inradius assert t1.inradius == t1.incircle.radius == 5 - 5*sqrt(2)/2 assert t2.inradius == t2.incircle.radius == 5*sqrt(3)/6 assert t3.inradius == t3.incircle.radius == x1**2/((2 + sqrt(2))*Abs(x1)) # Exradius assert t1.exradii[t1.sides[2]] == 5*sqrt(2)/2 # Excenters assert t1.excenters[t1.sides[2]] == Point2D(25*sqrt(2), -5*sqrt(2)/2) # Circumcircle assert t1.circumcircle.center == Point(2.5, 2.5) # Medians + Centroid m = t1.medians assert t1.centroid == Point(Rational(5, 3), Rational(5, 3)) assert m[p1] == Segment(p1, Point(Rational(5, 2), Rational(5, 2))) assert t3.medians[p1] == Segment(p1, Point(x1/2, x1/2)) assert intersection(m[p1], m[p2], m[p3]) == [t1.centroid] assert t1.medial == Triangle(Point(2.5, 0), Point(0, 2.5), Point(2.5, 2.5)) # Nine-point circle assert t1.nine_point_circle == Circle(Point(2.5, 0), Point(0, 2.5), Point(2.5, 2.5)) assert t1.nine_point_circle == Circle(Point(0, 0), Point(0, 2.5), Point(2.5, 2.5)) # Perpendicular altitudes = t1.altitudes assert altitudes[p1] == Segment(p1, Point(Rational(5, 2), Rational(5, 2))) assert altitudes[p2].equals(s1[0]) assert altitudes[p3] == s1[2] assert t1.orthocenter == p1 t = S('''Triangle( Point(100080156402737/5000000000000, 79782624633431/500000000000), Point(39223884078253/2000000000000, 156345163124289/1000000000000), Point(31241359188437/1250000000000, 338338270939941/1000000000000000))''') assert t.orthocenter == S('''Point(-780660869050599840216997''' '''79471538701955848721853/80368430960602242240789074233100000000000000,''' '''20151573611150265741278060334545897615974257/16073686192120448448157''' '''8148466200000000000)''') # Ensure assert len(intersection(*bisectors.values())) == 1 assert len(intersection(*altitudes.values())) == 1 assert len(intersection(*m.values())) == 1 # Distance p1 = Polygon( Point(0, 0), Point(1, 0), Point(1, 1), Point(0, 1)) p2 = Polygon( Point(0, Rational(5)/4), Point(1, Rational(5)/4), Point(1, Rational(9)/4), Point(0, Rational(9)/4)) p3 = Polygon( Point(1, 2), Point(2, 2), Point(2, 1)) p4 = Polygon( Point(1, 1), Point(Rational(6)/5, 1), Point(1, Rational(6)/5)) pt1 = Point(half, half) pt2 = Point(1, 1) '''Polygon to Point''' assert p1.distance(pt1) == half assert p1.distance(pt2) == 0 assert p2.distance(pt1) == Rational(3)/4 assert p3.distance(pt2) == sqrt(2)/2 '''Polygon to Polygon''' # p1.distance(p2) emits a warning with warns(UserWarning, \ match="Polygons may intersect producing erroneous output"): assert p1.distance(p2) == half/2 assert p1.distance(p3) == sqrt(2)/2 # p3.distance(p4) emits a warning with warns(UserWarning, \ match="Polygons may intersect producing erroneous output"): assert p3.distance(p4) == (sqrt(2)/2 - sqrt(Rational(2)/25)/2)
def test_polygon(): t = Triangle(Point(0, 0), Point(2, 0), Point(3, 3)) assert Polygon(Point(0, 0), Point(1, 0), Point(2, 0), Point(3, 3)) == t assert Polygon(Point(1, 0), Point(2, 0), Point(3, 3), Point(0, 0)) == t assert Polygon(Point(2, 0), Point(3, 3), Point(0, 0), Point(1, 0)) == t p1 = Polygon(Point(0, 0), Point(3, -1), Point(6, 0), Point(4, 5), Point(2, 3), Point(0, 3)) p2 = Polygon(Point(6, 0), Point(3, -1), Point(0, 0), Point(0, 3), Point(2, 3), Point(4, 5)) p3 = Polygon(Point(0, 0), Point(3, 0), Point(5, 2), Point(4, 4)) p4 = Polygon(Point(0, 0), Point(4, 4), Point(5, 2), Point(3, 0)) p5 = Polygon(Point(0, 0), Point(4, 4), Point(0, 4)) # # General polygon # assert p1 == p2 assert len(p1) == 6 assert len(p1.sides) == 6 assert p1.perimeter == 5 + 2 * sqrt(10) + sqrt(29) + sqrt(8) assert p1.area == 22 assert not p1.is_convex() assert p3.is_convex() assert p4.is_convex( ) # ensure convex for both CW and CCW point specification dict5 = p5.angles assert dict5[Point(0, 0)] == pi / 4 assert dict5[Point(0, 4)] == pi / 2 assert p5.encloses_point(Point(x, y)) == None assert p5.encloses_point(Point(1, 3)) assert p5.encloses_point(Point(0, 0)) == False assert p5.encloses_point(Point(4, 0)) == False p5.plot_interval('x') == [x, 0, 1] assert p5.distance(Polygon(Point(10, 10), Point(14, 14), Point(10, 14))) == 6 * sqrt(2) assert p5.distance( Polygon(Point(1, 8), Point(5, 8), Point(8, 12), Point(1, 12))) == 4 raises( UserWarning, 'Polygon(Point(0, 0), Point(1, 0), Point(1,1)).distance(Polygon(Point(0, 0), Point(0, 1), Point(1, 1)))' ) assert hash(p5) == hash(Polygon(Point(0, 0), Point(4, 4), Point(0, 4))) assert p5 == Polygon(Point(4, 4), Point(0, 4), Point(0, 0)) assert Polygon(Point(4, 4), Point(0, 4), Point(0, 0)) in p5 assert p5 != Point(0, 4) assert Point(0, 1) in p5 assert p5.arbitrary_point('t').subs(Symbol('t', real=True), 0) == Point(0, 0) raises( ValueError, "Polygon(Point(x, 0), Point(0, y), Point(x, y)).arbitrary_point('x')") # # Regular polygon # p1 = RegularPolygon(Point(0, 0), 10, 5) p2 = RegularPolygon(Point(0, 0), 5, 5) raises(GeometryError, 'RegularPolygon(Point(0, 0), Point(0, 1), Point(1, 1))') raises(GeometryError, 'RegularPolygon(Point(0, 0), 1, 2)') assert p1 != p2 assert p1.interior_angle == 3 * pi / 5 assert p1.exterior_angle == 2 * pi / 5 assert p2.apothem == 5 * cos(pi / 5) assert p2.circumcenter == p1.circumcenter == Point(0, 0) assert p1.circumradius == p1.radius == 10 assert p2.circumcircle == Circle(Point(0, 0), 5) assert p2.incircle == Circle(Point(0, 0), p2.apothem) assert p2.inradius == p2.apothem == (5 * (1 + sqrt(5)) / 4) p2.spin(pi / 10) dict1 = p2.angles assert dict1[Point(0, 5)] == 3 * pi / 5 assert p1.is_convex() assert p1.rotation == 0 assert p1.encloses_point(Point(0, 0)) assert p1.encloses_point(Point(11, 0)) == False assert p2.encloses_point(Point(0, 4.9)) p1.spin(pi / 3) assert p1.rotation == pi / 3 assert p1[0] == Point(5, 5 * sqrt(3)) for var in p1: if isinstance(var, Point): assert var == Point(0, 0) else: assert var == 5 or var == 10 or var == pi / 3 assert p1 != Point(0, 0) assert p1 != p5 raises(IndexError, 'RegularPolygon(Point(0, 0), 1, 3)[4]') # while spin works in place (notice that rotation is 2pi/3 below) # rotate returns a new object p1_old = p1 assert p1.rotate(pi / 3) == RegularPolygon(Point(0, 0), 10, 5, 2 * pi / 3) assert p1 == p1_old assert ` p1 ` == str(p1) # # Angles # angles = p4.angles assert feq(angles[Point(0, 0)].evalf(), Float("0.7853981633974483")) assert feq(angles[Point(4, 4)].evalf(), Float("1.2490457723982544")) assert feq(angles[Point(5, 2)].evalf(), Float("1.8925468811915388")) assert feq(angles[Point(3, 0)].evalf(), Float("2.3561944901923449")) angles = p3.angles assert feq(angles[Point(0, 0)].evalf(), Float("0.7853981633974483")) assert feq(angles[Point(4, 4)].evalf(), Float("1.2490457723982544")) assert feq(angles[Point(5, 2)].evalf(), Float("1.8925468811915388")) assert feq(angles[Point(3, 0)].evalf(), Float("2.3561944901923449")) # # Triangle # p1 = Point(0, 0) p2 = Point(5, 0) p3 = Point(0, 5) t1 = Triangle(p1, p2, p3) t2 = Triangle(p1, p2, Point(Rational(5, 2), sqrt(Rational(75, 4)))) t3 = Triangle(p1, Point(x1, 0), Point(0, x1)) s1 = t1.sides assert Triangle(p1, p2, p1) == Polygon(p1, p2, p1) == Segment(p1, p2) raises(GeometryError, 'Triangle(Point(0, 0))') # Basic stuff assert Triangle(p1, p1, p1) == p1 assert Triangle(p2, p2 * 2, p2 * 3) == Segment(p2, p2 * 3) assert t1.area == Rational(25, 2) assert t1.is_right() assert t2.is_right() == False assert t3.is_right() assert p1 in t1 assert t1.sides[0] in t1 assert Segment((0, 0), (1, 0)) in t1 assert Point(5, 5) not in t2 assert t1.is_convex() assert feq(t1.angles[p1].evalf(), pi.evalf() / 2) assert t1.is_equilateral() == False assert t2.is_equilateral() assert t3.is_equilateral() == False assert are_similar(t1, t2) == False assert are_similar(t1, t3) assert are_similar(t2, t3) == False assert t1.is_similar(Point(0, 0)) == False # Bisectors bisectors = t1.bisectors() assert bisectors[p1] == Segment(p1, Point(Rational(5, 2), Rational(5, 2))) ic = (250 - 125 * sqrt(2)) / 50 assert t1.incenter == Point(ic, ic) # Inradius assert t1.inradius == t1.incircle.radius == 5 - 5 * sqrt(2) / 2 assert t2.inradius == t2.incircle.radius == 5 * sqrt(3) / 6 assert t3.inradius == t3.incircle.radius == x1**2 / ( (2 + sqrt(2)) * Abs(x1)) # Circumcircle assert t1.circumcircle.center == Point(2.5, 2.5) # Medians + Centroid m = t1.medians assert t1.centroid == Point(Rational(5, 3), Rational(5, 3)) assert m[p1] == Segment(p1, Point(Rational(5, 2), Rational(5, 2))) assert t3.medians[p1] == Segment(p1, Point(x1 / 2, x1 / 2)) assert intersection(m[p1], m[p2], m[p3]) == [t1.centroid] assert t1.medial == Triangle(Point(2.5, 0), Point(0, 2.5), Point(2.5, 2.5)) # Perpendicular altitudes = t1.altitudes assert altitudes[p1] == Segment(p1, Point(Rational(5, 2), Rational(5, 2))) assert altitudes[p2] == s1[0] assert altitudes[p3] == s1[2] assert t1.orthocenter == p1 # Ensure assert len(intersection(*bisectors.values())) == 1 assert len(intersection(*altitudes.values())) == 1 assert len(intersection(*m.values())) == 1 # Distance p1 = Polygon(Point(0, 0), Point(1, 0), Point(1, 1), Point(0, 1)) p2 = Polygon(Point(0, Rational(5) / 4), Point(1, Rational(5) / 4), Point(1, Rational(9) / 4), Point(0, Rational(9) / 4)) p3 = Polygon(Point(1, 2), Point(2, 2), Point(2, 1)) p4 = Polygon(Point(1, 1), Point(Rational(6) / 5, 1), Point(1, Rational(6) / 5)) pt1 = Point(half, half) pt2 = Point(1, 1) '''Polygon to Point''' assert p1.distance(pt1) == half assert p1.distance(pt2) == 0 assert p2.distance(pt1) == Rational(3) / 4 assert p3.distance(pt2) == sqrt(2) / 2
def test_polygon(): t = Triangle(Point(0, 0), Point(2, 0), Point(3, 3)) assert Polygon(Point(0, 0), Point(1, 0), Point(2, 0), Point(3, 3)) == t assert Polygon(Point(1, 0), Point(2, 0), Point(3, 3), Point(0, 0)) == t assert Polygon(Point(2, 0), Point(3, 3), Point(0, 0), Point(1, 0)) == t p1 = Polygon(Point(0, 0), Point(3, -1), Point(6, 0), Point(4, 5), Point(2, 3), Point(0, 3)) p2 = Polygon(Point(6, 0), Point(3, -1), Point(0, 0), Point(0, 3), Point(2, 3), Point(4, 5)) p3 = Polygon(Point(0, 0), Point(3, 0), Point(5, 2), Point(4, 4)) p4 = Polygon(Point(0, 0), Point(4, 4), Point(5, 2), Point(3, 0)) # # General polygon # assert p1 == p2 assert len(p1) == 6 assert len(p1.sides) == 6 assert p1.perimeter == 5 + 2 * sqrt(10) + sqrt(29) + sqrt(8) assert p1.area == 22 assert not p1.is_convex() assert p3.is_convex() assert p4.is_convex( ) # ensure convex for both CW and CCW point specification # # Regular polygon # p1 = RegularPolygon(Point(0, 0), 10, 5) p2 = RegularPolygon(Point(0, 0), 5, 5) assert p1 != p2 assert p1.interior_angle == 3 * pi / 5 assert p1.exterior_angle == 2 * pi / 5 assert p2.apothem == 5 * cos(pi / 5) assert p2.circumcircle == Circle(Point(0, 0), 5) assert p2.incircle == Circle(Point(0, 0), p2.apothem) assert p1.is_convex() assert p1.rotation == 0 p1.spin(pi / 3) assert p1.rotation == pi / 3 assert p1[0] == Point(5, 5 * sqrt(3)) # while spin works in place (notice that rotation is 2pi/3 below) # rotate returns a new object p1_old = p1 assert p1.rotate(pi / 3) == RegularPolygon(Point(0, 0), 10, 5, 2 * pi / 3) assert p1 == p1_old # # Angles # angles = p4.angles assert feq(angles[Point(0, 0)].evalf(), Float("0.7853981633974483")) assert feq(angles[Point(4, 4)].evalf(), Float("1.2490457723982544")) assert feq(angles[Point(5, 2)].evalf(), Float("1.8925468811915388")) assert feq(angles[Point(3, 0)].evalf(), Float("2.3561944901923449")) angles = p3.angles assert feq(angles[Point(0, 0)].evalf(), Float("0.7853981633974483")) assert feq(angles[Point(4, 4)].evalf(), Float("1.2490457723982544")) assert feq(angles[Point(5, 2)].evalf(), Float("1.8925468811915388")) assert feq(angles[Point(3, 0)].evalf(), Float("2.3561944901923449")) # # Triangle # p1 = Point(0, 0) p2 = Point(5, 0) p3 = Point(0, 5) t1 = Triangle(p1, p2, p3) t2 = Triangle(p1, p2, Point(Rational(5, 2), sqrt(Rational(75, 4)))) t3 = Triangle(p1, Point(x1, 0), Point(0, x1)) s1 = t1.sides s2 = t2.sides s3 = t3.sides # Basic stuff assert Triangle(p1, p1, p1) == p1 assert Triangle(p2, p2 * 2, p2 * 3) == Segment(p2, p2 * 3) assert t1.area == Rational(25, 2) assert t1.is_right() assert t2.is_right() == False assert t3.is_right() assert p1 in t1 assert Point(5, 5) not in t2 assert t1.is_convex() assert feq(t1.angles[p1].evalf(), pi.evalf() / 2) assert t1.is_equilateral() == False assert t2.is_equilateral() assert t3.is_equilateral() == False assert are_similar(t1, t2) == False assert are_similar(t1, t3) assert are_similar(t2, t3) == False # Bisectors bisectors = t1.bisectors() assert bisectors[p1] == Segment(p1, Point(Rational(5, 2), Rational(5, 2))) ic = (250 - 125 * sqrt(2)) / 50 assert t1.incenter == Point(ic, ic) # Inradius assert t1.inradius == 5 - 5 * sqrt(2) / 2 assert t2.inradius == 5 * sqrt(3) / 6 assert t3.inradius == x1**2 / ((2 + sqrt(2)) * Abs(x1)) # Medians + Centroid m = t1.medians assert t1.centroid == Point(Rational(5, 3), Rational(5, 3)) assert m[p1] == Segment(p1, Point(Rational(5, 2), Rational(5, 2))) assert t3.medians[p1] == Segment(p1, Point(x1 / 2, x1 / 2)) assert intersection(m[p1], m[p2], m[p3]) == [t1.centroid] # Perpendicular altitudes = t1.altitudes assert altitudes[p1] == Segment(p1, Point(Rational(5, 2), Rational(5, 2))) assert altitudes[p2] == s1[0] assert altitudes[p3] == s1[2] # Ensure assert len(intersection(*bisectors.values())) == 1 assert len(intersection(*altitudes.values())) == 1 assert len(intersection(*m.values())) == 1 # Distance p1 = Polygon(Point(0, 0), Point(1, 0), Point(1, 1), Point(0, 1)) p2 = Polygon(Point(0, Rational(5) / 4), Point(1, Rational(5) / 4), Point(1, Rational(9) / 4), Point(0, Rational(9) / 4)) p3 = Polygon(Point(1, 2), Point(2, 2), Point(2, 1)) p4 = Polygon(Point(1, 1), Point(Rational(6) / 5, 1), Point(1, Rational(6) / 5)) p5 = Polygon(Point(half, 3**(half) / 2), Point(-half, 3**(half) / 2), Point(-1, 0), Point(-half, -(3)**(half) / 2), Point(half, -(3)**(half) / 2), Point(1, 0)) p6 = Polygon(Point(2, Rational(3) / 10), Point(Rational(17) / 10, 0), Point(2, -Rational(3) / 10), Point(Rational(23) / 10, 0)) pt1 = Point(half, half) pt2 = Point(1, 1) '''Polygon to Point''' assert p1.distance(pt1) == half assert p1.distance(pt2) == 0 assert p2.distance(pt1) == Rational(3) / 4 assert p3.distance(pt2) == sqrt(2) / 2 '''Polygon to Polygon''' import warnings # p1.distance(p2) emits a warning # First, test the warning warnings.filterwarnings( "error", "Polygons may intersect producing erroneous output") raises(UserWarning, "p1.distance(p2)") # now test the actual output warnings.filterwarnings( "ignore", "Polygons may intersect producing erroneous output") assert p1.distance(p2) == half / 2 # Keep testing reasonably thread safe, so reset the warning warnings.filterwarnings( "default", "Polygons may intersect producing erroneous output") # Note, in Python 2.6+, this can be done more nicely using the # warnings.catch_warnings context manager. # See http://docs.python.org/library/warnings#testing-warnings. assert p1.distance(p3) == sqrt(2) / 2 assert p3.distance(p4) == (sqrt(2) / 2 - sqrt(Rational(2) / 25) / 2) assert p5.distance(p6) == Rational(7) / 10
def test_transform(): pts = [Point(0, 0), Point(S(1)/2, S(1)/4), Point(1, 1)] pts_out = [Point(-4, -10), Point(-3, -S(37)/4), Point(-2, -7)] assert Triangle(*pts).scale(2, 3, (4, 5)) == Triangle(*pts_out) assert RegularPolygon((0, 0), 1, 4).scale(2, 3, (4, 5)) == \ Polygon(Point(-2, -10), Point(-4, -7), Point(-6, -10), Point(-4, -13))
def test_ellipse_geom(): x = Symbol('x', real=True) y = Symbol('y', real=True) t = Symbol('t', real=True) y1 = Symbol('y1', real=True) half = Rational(1, 2) p1 = Point(0, 0) p2 = Point(1, 1) p4 = Point(0, 1) e1 = Ellipse(p1, 1, 1) e2 = Ellipse(p2, half, 1) e3 = Ellipse(p1, y1, y1) c1 = Circle(p1, 1) c2 = Circle(p2, 1) c3 = Circle(Point(sqrt(2), sqrt(2)), 1) l1 = Line(p1, p2) # Test creation with three points cen, rad = Point(3*half, 2), 5*half assert Circle(Point(0, 0), Point(3, 0), Point(0, 4)) == Circle(cen, rad) assert Circle(Point(0, 0), Point(1, 1), Point(2, 2)) == Segment2D(Point2D(0, 0), Point2D(2, 2)) raises(ValueError, lambda: Ellipse(None, None, None, 1)) raises(GeometryError, lambda: Circle(Point(0, 0))) # Basic Stuff assert Ellipse(None, 1, 1).center == Point(0, 0) assert e1 == c1 assert e1 != e2 assert e1 != l1 assert p4 in e1 assert p2 not in e2 assert e1.area == pi assert e2.area == pi/2 assert e3.area == pi*y1*abs(y1) assert c1.area == e1.area assert c1.circumference == e1.circumference assert e3.circumference == 2*pi*y1 assert e1.plot_interval() == e2.plot_interval() == [t, -pi, pi] assert e1.plot_interval(x) == e2.plot_interval(x) == [x, -pi, pi] assert c1.minor == 1 assert c1.major == 1 assert c1.hradius == 1 assert c1.vradius == 1 assert Ellipse((1, 1), 0, 0) == Point(1, 1) assert Ellipse((1, 1), 1, 0) == Segment(Point(0, 1), Point(2, 1)) assert Ellipse((1, 1), 0, 1) == Segment(Point(1, 0), Point(1, 2)) # Private Functions assert hash(c1) == hash(Circle(Point(1, 0), Point(0, 1), Point(0, -1))) assert c1 in e1 assert (Line(p1, p2) in e1) is False assert e1.__cmp__(e1) == 0 assert e1.__cmp__(Point(0, 0)) > 0 # Encloses assert e1.encloses(Segment(Point(-0.5, -0.5), Point(0.5, 0.5))) is True assert e1.encloses(Line(p1, p2)) is False assert e1.encloses(Ray(p1, p2)) is False assert e1.encloses(e1) is False assert e1.encloses( Polygon(Point(-0.5, -0.5), Point(-0.5, 0.5), Point(0.5, 0.5))) is True assert e1.encloses(RegularPolygon(p1, 0.5, 3)) is True assert e1.encloses(RegularPolygon(p1, 5, 3)) is False assert e1.encloses(RegularPolygon(p2, 5, 3)) is False assert e2.arbitrary_point() in e2 # Foci f1, f2 = Point(sqrt(12), 0), Point(-sqrt(12), 0) ef = Ellipse(Point(0, 0), 4, 2) assert ef.foci in [(f1, f2), (f2, f1)] # Tangents v = sqrt(2) / 2 p1_1 = Point(v, v) p1_2 = p2 + Point(half, 0) p1_3 = p2 + Point(0, 1) assert e1.tangent_lines(p4) == c1.tangent_lines(p4) assert e2.tangent_lines(p1_2) == [Line(Point(S(3)/2, 1), Point(S(3)/2, S(1)/2))] assert e2.tangent_lines(p1_3) == [Line(Point(1, 2), Point(S(5)/4, 2))] assert c1.tangent_lines(p1_1) != [Line(p1_1, Point(0, sqrt(2)))] assert c1.tangent_lines(p1) == [] assert e2.is_tangent(Line(p1_2, p2 + Point(half, 1))) assert e2.is_tangent(Line(p1_3, p2 + Point(half, 1))) assert c1.is_tangent(Line(p1_1, Point(0, sqrt(2)))) assert e1.is_tangent(Line(Point(0, 0), Point(1, 1))) is False assert c1.is_tangent(e1) is True assert c1.is_tangent(Ellipse(Point(2, 0), 1, 1)) is True assert c1.is_tangent( Polygon(Point(1, 1), Point(1, -1), Point(2, 0))) is True assert c1.is_tangent( Polygon(Point(1, 1), Point(1, 0), Point(2, 0))) is False assert Circle(Point(5, 5), 3).is_tangent(Circle(Point(0, 5), 1)) is False assert Ellipse(Point(5, 5), 2, 1).tangent_lines(Point(0, 0)) == \ [Line(Point(0, 0), Point(S(77)/25, S(132)/25)), Line(Point(0, 0), Point(S(33)/5, S(22)/5))] assert Ellipse(Point(5, 5), 2, 1).tangent_lines(Point(3, 4)) == \ [Line(Point(3, 4), Point(4, 4)), Line(Point(3, 4), Point(3, 5))] assert Circle(Point(5, 5), 2).tangent_lines(Point(3, 3)) == \ [Line(Point(3, 3), Point(4, 3)), Line(Point(3, 3), Point(3, 4))] assert Circle(Point(5, 5), 2).tangent_lines(Point(5 - 2*sqrt(2), 5)) == \ [Line(Point(5 - 2*sqrt(2), 5), Point(5 - sqrt(2), 5 - sqrt(2))), Line(Point(5 - 2*sqrt(2), 5), Point(5 - sqrt(2), 5 + sqrt(2))), ] # for numerical calculations, we shouldn't demand exact equality, # so only test up to the desired precision def lines_close(l1, l2, prec): """ tests whether l1 and 12 are within 10**(-prec) of each other """ return abs(l1.p1 - l2.p1) < 10**(-prec) and abs(l1.p2 - l2.p2) < 10**(-prec) def line_list_close(ll1, ll2, prec): return all(lines_close(l1, l2, prec) for l1, l2 in zip(ll1, ll2)) e = Ellipse(Point(0, 0), 2, 1) assert e.normal_lines(Point(0, 0)) == \ [Line(Point(0, 0), Point(0, 1)), Line(Point(0, 0), Point(1, 0))] assert e.normal_lines(Point(1, 0)) == \ [Line(Point(0, 0), Point(1, 0))] assert e.normal_lines((0, 1)) == \ [Line(Point(0, 0), Point(0, 1))] assert line_list_close(e.normal_lines(Point(1, 1), 2), [ Line(Point(-S(51)/26, -S(1)/5), Point(-S(25)/26, S(17)/83)), Line(Point(S(28)/29, -S(7)/8), Point(S(57)/29, -S(9)/2))], 2) # test the failure of Poly.intervals and checks a point on the boundary p = Point(sqrt(3), S.Half) assert p in e assert line_list_close(e.normal_lines(p, 2), [ Line(Point(-S(341)/171, -S(1)/13), Point(-S(170)/171, S(5)/64)), Line(Point(S(26)/15, -S(1)/2), Point(S(41)/15, -S(43)/26))], 2) # be sure to use the slope that isn't undefined on boundary e = Ellipse((0, 0), 2, 2*sqrt(3)/3) assert line_list_close(e.normal_lines((1, 1), 2), [ Line(Point(-S(64)/33, -S(20)/71), Point(-S(31)/33, S(2)/13)), Line(Point(1, -1), Point(2, -4))], 2) # general ellipse fails except under certain conditions e = Ellipse((0, 0), x, 1) assert e.normal_lines((x + 1, 0)) == [Line(Point(0, 0), Point(1, 0))] raises(NotImplementedError, lambda: e.normal_lines((x + 1, 1))) # Properties major = 3 minor = 1 e4 = Ellipse(p2, minor, major) assert e4.focus_distance == sqrt(major**2 - minor**2) ecc = e4.focus_distance / major assert e4.eccentricity == ecc assert e4.periapsis == major*(1 - ecc) assert e4.apoapsis == major*(1 + ecc) assert e4.semilatus_rectum == major*(1 - ecc ** 2) # independent of orientation e4 = Ellipse(p2, major, minor) assert e4.focus_distance == sqrt(major**2 - minor**2) ecc = e4.focus_distance / major assert e4.eccentricity == ecc assert e4.periapsis == major*(1 - ecc) assert e4.apoapsis == major*(1 + ecc) # Intersection l1 = Line(Point(1, -5), Point(1, 5)) l2 = Line(Point(-5, -1), Point(5, -1)) l3 = Line(Point(-1, -1), Point(1, 1)) l4 = Line(Point(-10, 0), Point(0, 10)) pts_c1_l3 = [Point(sqrt(2)/2, sqrt(2)/2), Point(-sqrt(2)/2, -sqrt(2)/2)] assert intersection(e2, l4) == [] assert intersection(c1, Point(1, 0)) == [Point(1, 0)] assert intersection(c1, l1) == [Point(1, 0)] assert intersection(c1, l2) == [Point(0, -1)] assert intersection(c1, l3) in [pts_c1_l3, [pts_c1_l3[1], pts_c1_l3[0]]] assert intersection(c1, c2) == [Point(0, 1), Point(1, 0)] assert intersection(c1, c3) == [Point(sqrt(2)/2, sqrt(2)/2)] assert e1.intersection(l1) == [Point(1, 0)] assert e2.intersection(l4) == [] assert e1.intersection(Circle(Point(0, 2), 1)) == [Point(0, 1)] assert e1.intersection(Circle(Point(5, 0), 1)) == [] assert e1.intersection(Ellipse(Point(2, 0), 1, 1)) == [Point(1, 0)] assert e1.intersection(Ellipse(Point(5, 0), 1, 1)) == [] assert e1.intersection(Point(2, 0)) == [] assert e1.intersection(e1) == e1 assert intersection(Ellipse(Point(0, 0), 2, 1), Ellipse(Point(3, 0), 1, 2)) == [Point(2, 0)] assert intersection(Circle(Point(0, 0), 2), Circle(Point(3, 0), 1)) == [Point(2, 0)] assert intersection(Circle(Point(0, 0), 2), Circle(Point(7, 0), 1)) == [] assert intersection(Ellipse(Point(0, 0), 5, 17), Ellipse(Point(4, 0), 1, 0.2)) == [Point(5, 0)] assert intersection(Ellipse(Point(0, 0), 5, 17), Ellipse(Point(4, 0), 0.999, 0.2)) == [] assert Circle((0, 0), S(1)/2).intersection( Triangle((-1, 0), (1, 0), (0, 1))) == [ Point(-S(1)/2, 0), Point(S(1)/2, 0)] raises(TypeError, lambda: intersection(e2, Line((0, 0, 0), (0, 0, 1)))) raises(TypeError, lambda: intersection(e2, Rational(12))) # some special case intersections csmall = Circle(p1, 3) cbig = Circle(p1, 5) cout = Circle(Point(5, 5), 1) # one circle inside of another assert csmall.intersection(cbig) == [] # separate circles assert csmall.intersection(cout) == [] # coincident circles assert csmall.intersection(csmall) == csmall v = sqrt(2) t1 = Triangle(Point(0, v), Point(0, -v), Point(v, 0)) points = intersection(t1, c1) assert len(points) == 4 assert Point(0, 1) in points assert Point(0, -1) in points assert Point(v/2, v/2) in points assert Point(v/2, -v/2) in points circ = Circle(Point(0, 0), 5) elip = Ellipse(Point(0, 0), 5, 20) assert intersection(circ, elip) in \ [[Point(5, 0), Point(-5, 0)], [Point(-5, 0), Point(5, 0)]] assert elip.tangent_lines(Point(0, 0)) == [] elip = Ellipse(Point(0, 0), 3, 2) assert elip.tangent_lines(Point(3, 0)) == \ [Line(Point(3, 0), Point(3, -12))] e1 = Ellipse(Point(0, 0), 5, 10) e2 = Ellipse(Point(2, 1), 4, 8) a = S(53)/17 c = 2*sqrt(3991)/17 ans = [Point(a - c/8, a/2 + c), Point(a + c/8, a/2 - c)] assert e1.intersection(e2) == ans e2 = Ellipse(Point(x, y), 4, 8) c = sqrt(3991) ans = [Point(-c/68 + a, 2*c/17 + a/2), Point(c/68 + a, -2*c/17 + a/2)] assert [p.subs({x: 2, y:1}) for p in e1.intersection(e2)] == ans # Combinations of above assert e3.is_tangent(e3.tangent_lines(p1 + Point(y1, 0))[0]) e = Ellipse((1, 2), 3, 2) assert e.tangent_lines(Point(10, 0)) == \ [Line(Point(10, 0), Point(1, 0)), Line(Point(10, 0), Point(S(14)/5, S(18)/5))] # encloses_point e = Ellipse((0, 0), 1, 2) assert e.encloses_point(e.center) assert e.encloses_point(e.center + Point(0, e.vradius - Rational(1, 10))) assert e.encloses_point(e.center + Point(e.hradius - Rational(1, 10), 0)) assert e.encloses_point(e.center + Point(e.hradius, 0)) is False assert e.encloses_point( e.center + Point(e.hradius + Rational(1, 10), 0)) is False e = Ellipse((0, 0), 2, 1) assert e.encloses_point(e.center) assert e.encloses_point(e.center + Point(0, e.vradius - Rational(1, 10))) assert e.encloses_point(e.center + Point(e.hradius - Rational(1, 10), 0)) assert e.encloses_point(e.center + Point(e.hradius, 0)) is False assert e.encloses_point( e.center + Point(e.hradius + Rational(1, 10), 0)) is False assert c1.encloses_point(Point(1, 0)) is False assert c1.encloses_point(Point(0.3, 0.4)) is True assert e.scale(2, 3) == Ellipse((0, 0), 4, 3) assert e.scale(3, 6) == Ellipse((0, 0), 6, 6) assert e.rotate(pi) == e assert e.rotate(pi, (1, 2)) == Ellipse(Point(2, 4), 2, 1) raises(NotImplementedError, lambda: e.rotate(pi/3)) # Circle rotation tests (Issue #11743) # Link - https://github.com/sympy/sympy/issues/11743 cir = Circle(Point(1, 0), 1) assert cir.rotate(pi/2) == Circle(Point(0, 1), 1) assert cir.rotate(pi/3) == Circle(Point(S(1)/2, sqrt(3)/2), 1) assert cir.rotate(pi/3, Point(1, 0)) == Circle(Point(1, 0), 1) assert cir.rotate(pi/3, Point(0, 1)) == Circle(Point(S(1)/2 + sqrt(3)/2, S(1)/2 + sqrt(3)/2), 1)
def test_ellipse_geom(): p1 = Point(0, 0) p2 = Point(1, 1) p4 = Point(0, 1) e1 = Ellipse(p1, 1, 1) e2 = Ellipse(p2, half, 1) e3 = Ellipse(p1, y1, y1) c1 = Circle(p1, 1) c2 = Circle(p2, 1) c3 = Circle(Point(sqrt(2), sqrt(2)), 1) # Test creation with three points cen, rad = Point(3*half, 2), 5*half assert Circle(Point(0, 0), Point(3, 0), Point(0, 4)) == Circle(cen, rad) raises( GeometryError, lambda: Circle(Point(0, 0), Point(1, 1), Point(2, 2))) raises(ValueError, lambda: Ellipse(None, None, None, 1)) raises(GeometryError, lambda: Circle(Point(0, 0))) # Basic Stuff assert Ellipse(None, 1, 1).center == Point(0, 0) assert e1 == c1 assert e1 != e2 assert p4 in e1 assert p2 not in e2 assert e1.area == pi assert e2.area == pi/2 assert e3.area == pi*y1*abs(y1) assert c1.area == e1.area assert c1.circumference == e1.circumference assert e3.circumference == 2*pi*y1 assert e1.plot_interval() == e2.plot_interval() == [t, -pi, pi] assert e1.plot_interval(x) == e2.plot_interval(x) == [x, -pi, pi] assert Ellipse(None, 1, None, 1).circumference == 2*pi assert c1.minor == 1 assert c1.major == 1 assert c1.hradius == 1 assert c1.vradius == 1 # Private Functions assert hash(c1) == hash(Circle(Point(1, 0), Point(0, 1), Point(0, -1))) assert c1 in e1 assert (Line(p1, p2) in e1) is False assert e1.__cmp__(e1) == 0 assert e1.__cmp__(Point(0, 0)) > 0 # Encloses assert e1.encloses(Segment(Point(-0.5, -0.5), Point(0.5, 0.5))) is True assert e1.encloses(Line(p1, p2)) is False assert e1.encloses(Ray(p1, p2)) is False assert e1.encloses(e1) is False assert e1.encloses( Polygon(Point(-0.5, -0.5), Point(-0.5, 0.5), Point(0.5, 0.5))) is True assert e1.encloses(RegularPolygon(p1, 0.5, 3)) is True assert e1.encloses(RegularPolygon(p1, 5, 3)) is False assert e1.encloses(RegularPolygon(p2, 5, 3)) is False # with generic symbols, the hradius is assumed to contain the major radius M = Symbol('M') m = Symbol('m') c = Ellipse(p1, M, m).circumference _x = c.atoms(Dummy).pop() assert c == 4*M*Integral( sqrt((1 - _x**2*(M**2 - m**2)/M**2)/(1 - _x**2)), (_x, 0, 1)) assert e2.arbitrary_point() in e2 # Foci f1, f2 = Point(sqrt(12), 0), Point(-sqrt(12), 0) ef = Ellipse(Point(0, 0), 4, 2) assert ef.foci in [(f1, f2), (f2, f1)] # Tangents v = sqrt(2) / 2 p1_1 = Point(v, v) p1_2 = p2 + Point(half, 0) p1_3 = p2 + Point(0, 1) assert e1.tangent_lines(p4) == c1.tangent_lines(p4) assert e2.tangent_lines(p1_2) == [Line(Point(3/2, 1), Point(3/2, 1/2))] assert e2.tangent_lines(p1_3) == [Line(Point(1, 2), Point(5/4, 2))] assert c1.tangent_lines(p1_1) != [Line(p1_1, Point(0, sqrt(2)))] assert c1.tangent_lines(p1) == [] assert e2.is_tangent(Line(p1_2, p2 + Point(half, 1))) assert e2.is_tangent(Line(p1_3, p2 + Point(half, 1))) assert c1.is_tangent(Line(p1_1, Point(0, sqrt(2)))) assert e1.is_tangent(Line(Point(0, 0), Point(1, 1))) is False assert c1.is_tangent(e1) is False assert c1.is_tangent(Ellipse(Point(2, 0), 1, 1)) is True assert c1.is_tangent( Polygon(Point(1, 1), Point(1, -1), Point(2, 0))) is True assert c1.is_tangent( Polygon(Point(1, 1), Point(1, 0), Point(2, 0))) is False assert Circle(Point(5, 5), 3).is_tangent(Circle(Point(0, 5), 1)) is False assert Ellipse(Point(5, 5), 2, 1).tangent_lines(Point(0, 0)) == \ [Line(Point(0, 0), Point(77/25, 132/25)), Line(Point(0, 0), Point(33/5, 22/5))] assert Ellipse(Point(5, 5), 2, 1).tangent_lines(Point(3, 4)) == \ [Line(Point(3, 4), Point(4, 4)), Line(Point(3, 4), Point(3, 5))] assert Circle(Point(5, 5), 2).tangent_lines(Point(3, 3)) == \ [Line(Point(3, 3), Point(4, 3)), Line(Point(3, 3), Point(3, 4))] assert Circle(Point(5, 5), 2).tangent_lines(Point(5 - 2*sqrt(2), 5)) == \ [Line(Point(5 - 2*sqrt(2), 5), Point(5 - sqrt(2), 5 - sqrt(2))), Line(Point(5 - 2*sqrt(2), 5), Point(5 - sqrt(2), 5 + sqrt(2))), ] e = Ellipse(Point(0, 0), 2, 1) assert e.normal_lines(Point(0, 0)) == \ [Line(Point(0, 0), Point(0, 1)), Line(Point(0, 0), Point(1, 0))] assert e.normal_lines(Point(1, 0)) == \ [Line(Point(0, 0), Point(1, 0))] assert e.normal_lines((0, 1)) == \ [Line(Point(0, 0), Point(0, 1))] assert e.normal_lines(Point(1, 1), 2) == [ Line(Point(-51/26, -1/5), Point(-25/26, 17/83)), Line(Point(28/29, -7/8), Point(57/29, -9/2))] # test the failure of Poly.intervals and checks a point on the boundary p = Point(sqrt(3), S.Half) assert p in e assert e.normal_lines(p, 2) == [ Line(Point(-341/171, -1/13), Point(-170/171, 5/64)), Line(Point(26/15, -1/2), Point(41/15, -43/26))] # be sure to use the slope that isn't undefined on boundary e = Ellipse((0, 0), 2, 2*sqrt(3)/3) assert e.normal_lines((1, 1), 2) == [ Line(Point(-64/33, -20/71), Point(-31/33, 2/13)), Line(Point(1, -1), Point(2, -4))] # general ellipse fails except under certain conditions e = Ellipse((0, 0), x, 1) assert e.normal_lines((x + 1, 0)) == [Line(Point(0, 0), Point(1, 0))] raises(NotImplementedError, lambda: e.normal_lines((x + 1, 1))) # Properties major = 3 minor = 1 e4 = Ellipse(p2, minor, major) assert e4.focus_distance == sqrt(major**2 - minor**2) ecc = e4.focus_distance / major assert e4.eccentricity == ecc assert e4.periapsis == major*(1 - ecc) assert e4.apoapsis == major*(1 + ecc) # independent of orientation e4 = Ellipse(p2, major, minor) assert e4.focus_distance == sqrt(major**2 - minor**2) ecc = e4.focus_distance / major assert e4.eccentricity == ecc assert e4.periapsis == major*(1 - ecc) assert e4.apoapsis == major*(1 + ecc) # Intersection l1 = Line(Point(1, -5), Point(1, 5)) l2 = Line(Point(-5, -1), Point(5, -1)) l3 = Line(Point(-1, -1), Point(1, 1)) l4 = Line(Point(-10, 0), Point(0, 10)) pts_c1_l3 = [Point(sqrt(2)/2, sqrt(2)/2), Point(-sqrt(2)/2, -sqrt(2)/2)] assert intersection(e2, l4) == [] assert intersection(c1, Point(1, 0)) == [Point(1, 0)] assert intersection(c1, l1) == [Point(1, 0)] assert intersection(c1, l2) == [Point(0, -1)] assert intersection(c1, l3) in [pts_c1_l3, [pts_c1_l3[1], pts_c1_l3[0]]] assert intersection(c1, c2) == [Point(0, 1), Point(1, 0)] assert intersection(c1, c3) == [Point(sqrt(2)/2, sqrt(2)/2)] assert e1.intersection(l1) == [Point(1, 0)] assert e2.intersection(l4) == [] assert e1.intersection(Circle(Point(0, 2), 1)) == [Point(0, 1)] assert e1.intersection(Circle(Point(5, 0), 1)) == [] assert e1.intersection(Ellipse(Point(2, 0), 1, 1)) == [Point(1, 0)] assert e1.intersection(Ellipse(Point(5, 0), 1, 1,)) == [] assert e1.intersection(Point(2, 0)) == [] assert e1.intersection(e1) == e1 # some special case intersections csmall = Circle(p1, 3) cbig = Circle(p1, 5) cout = Circle(Point(5, 5), 1) # one circle inside of another assert csmall.intersection(cbig) == [] # separate circles assert csmall.intersection(cout) == [] # coincident circles assert csmall.intersection(csmall) == csmall v = sqrt(2) t1 = Triangle(Point(0, v), Point(0, -v), Point(v, 0)) points = intersection(t1, c1) assert len(points) == 4 assert Point(0, 1) in points assert Point(0, -1) in points assert Point(v/2, v/2) in points assert Point(v/2, -v/2) in points circ = Circle(Point(0, 0), 5) elip = Ellipse(Point(0, 0), 5, 20) assert intersection(circ, elip) in \ [[Point(5, 0), Point(-5, 0)], [Point(-5, 0), Point(5, 0)]] assert elip.tangent_lines(Point(0, 0)) == [] elip = Ellipse(Point(0, 0), 3, 2) assert elip.tangent_lines(Point(3, 0)) == \ [Line(Point(3, 0), Point(3, -12))] e1 = Ellipse(Point(0, 0), 5, 10) e2 = Ellipse(Point(2, 1), 4, 8) a = 53/17 c = 2*sqrt(3991)/17 ans = [Point(a - c/8, a/2 + c), Point(a + c/8, a/2 - c)] assert e1.intersection(e2) == ans e2 = Ellipse(Point(x, y), 4, 8) c = sqrt(3991) ans = [Point(-c/68 + a, 2*c/17 + a/2), Point(c/68 + a, -2*c/17 + a/2)] assert [p.subs({x: 2, y:1}) for p in e1.intersection(e2)] == ans # Combinations of above assert e3.is_tangent(e3.tangent_lines(p1 + Point(y1, 0))[0]) e = Ellipse((1, 2), 3, 2) assert e.tangent_lines(Point(10, 0)) == \ [Line(Point(10, 0), Point(1, 0)), Line(Point(10, 0), Point(14/5, 18/5))] # encloses_point e = Ellipse((0, 0), 1, 2) assert e.encloses_point(e.center) assert e.encloses_point(e.center + Point(0, e.vradius - Rational(1, 10))) assert e.encloses_point(e.center + Point(e.hradius - Rational(1, 10), 0)) assert e.encloses_point(e.center + Point(e.hradius, 0)) is False assert e.encloses_point( e.center + Point(e.hradius + Rational(1, 10), 0)) is False e = Ellipse((0, 0), 2, 1) assert e.encloses_point(e.center) assert e.encloses_point(e.center + Point(0, e.vradius - Rational(1, 10))) assert e.encloses_point(e.center + Point(e.hradius - Rational(1, 10), 0)) assert e.encloses_point(e.center + Point(e.hradius, 0)) is False assert e.encloses_point( e.center + Point(e.hradius + Rational(1, 10), 0)) is False assert c1.encloses_point(Point(1, 0)) is False assert c1.encloses_point(Point(0.3, 0.4)) is True assert e.scale(2, 3) == Ellipse((0, 0), 4, 3) assert e.scale(3, 6) == Ellipse((0, 0), 6, 6) assert e.rotate(pi) == e assert e.rotate(pi, (1, 2)) == Ellipse(Point(2, 4), 2, 1) raises(NotImplementedError, lambda: e.rotate(pi/3)) # transformations c = Circle((1, 1), 2) assert c.scale(-1) == Circle((-1, 1), 2) assert c.scale(y=-1) == Circle((1, -1), 2) assert c.scale(2) == Ellipse((2, 1), 4, 2)