def test_encloses(): # square with a dimpled left side s = Polygon(Point(0, 0), Point(1, 0), Point(1, 1), Point(0, 1), Point(Rational(1, 2), Rational(1, 2))) # the following is True if the polygon isn't treated as closing on itself assert s.encloses(Point(0, Rational(1, 2))) is False assert s.encloses(Point(Rational(1, 2), Rational( 1, 2))) is False # it's a vertex assert s.encloses(Point(Rational(3, 4), Rational(1, 2))) is True l2 = Line(Point(0, 0), Point(0, 1)) assert s.reflect(l2).encloses(Point(0, Rational(1, 2)).reflect(l2)) is False
def test_polygon(): a, b, c = Point(0, 0), Point(2, 0), Point(3, 3) t = Triangle(a, b, c) assert Polygon(a) == a assert Polygon(a, a) == a assert Polygon(a, b, b, c) == Polygon(a, b, c) assert Polygon(a, 1, 1, n=4) == RegularPolygon(a, 1, 4, 1) 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 pytest.raises(GeometryError, lambda: Polygon((0, 0), (1, 0), (0, 1), (1, 1))) # 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)) 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 p1.contains(Segment((0, 0), (1, 2))) is False assert p1.contains(Ray((0, 0), angle=pi / 3)) 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 assert 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 p7 = Polygon(Point(1, 2), Point(3, 7), Point(0, 1)) assert p5.distance(p7) == 9 * sqrt(29) / 29 l1 = Line(Point(0, 0), Point(1, 0)) assert p5.reflect(l1).distance(p7.reflect(l1)) == 9 * sqrt(29) / 29 warnings.filterwarnings( 'error', message='Polygons may intersect producing erroneous output') pytest.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', extended_real=True): 0}) == \ Point(0, 0) pytest.raises( ValueError, lambda: Polygon(Point(x, 0), Point(0, y), Point(x, y)). arbitrary_point('x')) assert p6.intersection(r) == [Point(-9, 33 / 5), Point(-9, -84 / 13)] # # Regular polygon # p1 = RegularPolygon(Point(0, 0), 10, 5) p2 = RegularPolygon(Point(0, 0), 5, 5) pytest.raises( GeometryError, lambda: RegularPolygon(Point(0, 0), Point(0, 1), Point(1, 1))) pytest.raises(GeometryError, lambda: RegularPolygon(Point(0, 0), 1, 2)) pytest.raises(ValueError, lambda: RegularPolygon(Point(0, 0), 1, 2.5)) assert Polygon(Point(0, 0), 10, 5, pi, n=5) == RegularPolygon(Point(0, 0), 10, 5, pi) 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 in (5, 10, 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 + 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')) assert (Polygon((0, 0), (10, 0), (2, 1), (0, 3)).angles == { Point(0, 0): pi / 2, Point(0, 3): pi / 4, Point(2, 1): -acos(-9 * sqrt(130) / 130) + 2 * pi, Point(10, 0): acos(8 * sqrt(65) / 65) }) # # 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) pytest.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 = Triangle( Point(Rational(100080156402737, 5000000000000), Rational(79782624633431, 500000000000)), Point(Rational(39223884078253, 2000000000000), Rational(156345163124289, 1000000000000)), Point(Rational(31241359188437, 1250000000000), Rational(338338270939941, 1000000000000000))) assert t.orthocenter == \ Point(Rational(-78066086905059984021699779471538701955848721853, 80368430960602242240789074233100000000000000), Rational(20151573611150265741278060334545897615974257, 160736861921204484481578148466200000000000)) # 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(0.5, 0.5) pt2 = Point(1, 1) # Polygon to Point assert p1.distance(pt1) == Rational(1, 2) 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') pytest.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) == Rational(1, 4) assert p1.distance(p3) == sqrt(2) / 2 assert p3.distance(p4) == 2 * sqrt(2) / 5 r = Polygon(Point(0, 0), 1, n=3) assert r.vertices[0] == Point(1, 0) mid = Point(1, 1) assert Polygon((0, 2), (2, 2), mid, (0, 0), (2, 0), mid).area == 0 t1 = Triangle(Point(0, 0), Point(4, 0), Point(2, 4)) assert t1.is_isosceles() is True t1 = Triangle(Point(0, 0), Point(4, 0), Point(1, 4)) assert t1.is_scalene() is True assert t1.is_isosceles() is False p1 = Polygon((1, 0), (2, 0), (2, 2), (-4, 3)) p2 = Polygon((1, 0), (2, 0), (3, 2), (-4, 3)) assert (p1 == p2) is False