euclidean_polygons_with_angles

The category of polygons in the real plane with fixed rational angles.

This module provides a common structure for all polygons with certain fixed angles.

See flatsurf.geometry.categories for a general description of the category framework in sage-flatsurf.

Normally, you won’t create this (or any other) category directly. The correct category is automatically determined for polygons.

EXAMPLES:

The category of rectangles:

sage: from flatsurf.geometry.categories import EuclideanPolygons
sage: C = EuclideanPolygons(QQ).WithAngles([1, 1, 1, 1])

It is often tedious to create this category manually, since you need to determine a base ring that can describe the coordinates of polygons with such angles:

sage: C = EuclideanPolygons(QQ).WithAngles([1, 1, 1])
sage: C.slopes()
Traceback (most recent call last):
...
TypeError: Unable to coerce c to a rational

sage: C = EuclideanPolygons(AA).WithAngles([1, 1, 1])
sage: C.slopes()
[(1, 0), (-0.5773502691896258?, 1), (-0.5773502691896258?, -1)]

Instead, we can use EuclideanPolygonsWithAngles() to create this category over a minimal number field:

sage: from flatsurf import EuclideanPolygonsWithAngles
sage: C = EuclideanPolygonsWithAngles([1, 1, 1])
sage: C.slopes()
[(1, 0), (-c, 3), (-c, -3)]

The category of polygons is automatically determined when using Polygon():

sage: from flatsurf import Polygon
sage: p = Polygon(angles=(1, 1, 1))
sage: p.category()
Category of convex simple euclidean equilateral triangles over Number Field in c with defining polynomial x^2 - 3 with c = 1.732050807568878?

However, it can be very costly to determine that a polygon is rational and what its actual angles are (the “equilateral” in the previous example). Therefore, the category might get refined once these aspects have been determined:

sage: p = Polygon(edges=[(1, 0), (0, 1), (-1, 0), (0, -1)])
sage: p.category()
Category of convex simple euclidean polygons over Rational Field
sage: p.is_rational()
True
sage: p.category()
Category of rational convex simple euclidean polygons over Rational Field
sage: p.angles()
(1/4, 1/4, 1/4, 1/4)
sage: p.category()
Category of convex simple euclidean rectangles over Rational Field

Note that SageMath applies the same strategy when determining whether the integers modulo N are a field:

sage: K = Zmod(1361)
sage: K.category()
Join of Category of finite commutative rings and Category of subquotients of monoids and Category of quotients of semigroups and Category of finite enumerated sets
sage: K.is_field()
True
sage: K.category()
Join of Category of finite enumerated fields and Category of subquotients of monoids and Category of quotients of semigroups
class flatsurf.geometry.categories.euclidean_polygons_with_angles.EuclideanPolygonsWithAngles(base_ring, angles)[source]

The category of euclidean polygons with fixed rational angles.

EXAMPLES:

sage: from flatsurf.geometry.categories import EuclideanPolygons
sage: C = EuclideanPolygons(QQ).WithAngles([1, 1, 1, 1])
class ParentMethods[source]

Provides methods available to all polygons with known angles.

If you want to add functionality to all such polygons, you probably want to put it here.

angle(e, numerical=None, assume_rational=None)[source]

Return the angle at the beginning of the start point of the edge e.

EXAMPLES:

sage: from flatsurf.geometry.polygon import polygons
sage: polygons.square().angle(0)
1/4
sage: polygons.regular_ngon(8).angle(0)
3/8

sage: from flatsurf import Polygon
sage: T = Polygon(vertices=[(0,0), (3,1), (1,5)])
sage: [T.angle(i, numerical=True) for i in range(3)]  # abs tol 1e-13
[0.16737532973071603, 0.22741638234956674, 0.10520828791971722]
sage: sum(T.angle(i, numerical=True) for i in range(3))   # abs tol 1e-13
0.5
is_convex(strict=False)[source]

Return whether this is a convex polygon.

INPUT:

  • strict – whether to check for strict convexity, i.e., a polygon with a π angle is not considered convex.

EXAMPLES:

sage: from flatsurf import polygons
sage: S = polygons.square()
sage: S.is_convex()
True
sage: S.is_convex(strict=True)
True
class Simple(base_category)[source]

The subcategory of simple Euclidean polygons with prescribed angles.

EXAMPLES:

sage: from flatsurf.geometry.categories import EuclideanPolygons
sage: EuclideanPolygons(QQ).WithAngles([1, 1, 1, 1]).Simple()
Category of simple euclidean rectangles over Rational Field
class SubcategoryMethods[source]
an_element()[source]

Return a polygon in this category.

Since currently polygons must not be self-intersecting, the construction used might fail.

EXAMPLES:

sage: from flatsurf import EuclideanPolygonsWithAngles
sage: EuclideanPolygonsWithAngles(4, 3, 4, 4, 3, 4).an_element()
Polygon(vertices=[(0, 0),
                  (1/22*c + 1, 0),
                  (9*c^9 + 1/2*c^8 - 88*c^7 - 9/2*c^6 + 297*c^5 + 27/2*c^4 - 396*c^3 - 15*c^2 + 3631/22*c + 11/2, 1/2*c + 11),
                  (16*c^9 + c^8 - 154*c^7 - 9*c^6 + 506*c^5 + 27*c^4 - 638*c^3 - 30*c^2 + 4841/22*c + 9, c + 22),
                  (16*c^9 + c^8 - 154*c^7 - 9*c^6 + 506*c^5 + 27*c^4 - 638*c^3 - 30*c^2 + 220*c + 8, c + 22),
                  (7*c^9 + 1/2*c^8 - 66*c^7 - 9/2*c^6 + 209*c^5 + 27/2*c^4 - 242*c^3 - 15*c^2 + 55*c + 7/2, 1/2*c + 11)])
angles(integral=False)[source]

Return the interior angles of this polygon as multiples of 2π.

INPUT:

  • integral – a boolean (default: False); whether to return the angles not as multiples of 2π but rescaled so that they have no denominators.

EXAMPLES:

sage: from flatsurf import EuclideanPolygonsWithAngles
sage: E = EuclideanPolygonsWithAngles(1, 1, 1, 2, 6)
sage: E.angles()
(3/22, 3/22, 3/22, 3/11, 9/11)

When integral is set, the output is scaled to eliminate denominators:

sage: E.angles(integral=True)
(1, 1, 1, 2, 6)
billiard_unfolding_angles(cover_type='translation')[source]

Return the angles of the unfolding rational, half-translation or translation surface.

INPUT:

  • cover_type (optional, default "translation") - either "rational", "half-translation" or "translation"

EXAMPLES:

sage: from flatsurf import EuclideanPolygonsWithAngles

sage: E = EuclideanPolygonsWithAngles(1, 2, 5)
sage: E.billiard_unfolding_angles(cover_type="rational")
{1/8: 1, 1/4: 1, 5/8: 1}
sage: (1/8 - 1) + (1/4 - 1) + (5/8 - 1)  # Euler characteristic (of the sphere)
-2
sage: E.billiard_unfolding_angles(cover_type="half-translation")
{1/2: 3, 5/2: 1}
sage: E.billiard_unfolding_angles(cover_type="translation")
{1: 3, 5: 1}

sage: E = EuclideanPolygonsWithAngles(1, 3, 1, 7)
sage: E.billiard_unfolding_angles(cover_type="rational")
{1/6: 2, 1/2: 1, 7/6: 1}
sage: 2 * (1/6 - 1) + (1/2 - 1) + (7/6 - 1) # Euler characteristic
-2
sage: E.billiard_unfolding_angles(cover_type="half-translation")
{1/2: 5, 7/2: 1}
sage: E.billiard_unfolding_angles(cover_type="translation")
{1: 5, 7: 1}

sage: E = EuclideanPolygonsWithAngles(1, 3, 5, 7)
sage: E.billiard_unfolding_angles(cover_type="rational")
{1/8: 1, 3/8: 1, 5/8: 1, 7/8: 1}
sage: (1/8 - 1) + (3/8 - 1) + (5/8 - 1) + (7/8 - 1) # Euler characteristic
-2
sage: E.billiard_unfolding_angles(cover_type="half-translation")
{1/2: 1, 3/2: 1, 5/2: 1, 7/2: 1}
sage: E.billiard_unfolding_angles(cover_type="translation")
{1: 1, 3: 1, 5: 1, 7: 1}

sage: E = EuclideanPolygonsWithAngles(1, 2, 8)
sage: E.billiard_unfolding_angles(cover_type="rational")
{1/11: 1, 2/11: 1, 8/11: 1}
sage: (1/11 - 1) + (2/11 - 1) + (8/11 - 1) # Euler characteristic
-2
sage: E.billiard_unfolding_angles(cover_type="half-translation")
{1: 1, 2: 1, 8: 1}
sage: E.billiard_unfolding_angles(cover_type="translation")
{1: 1, 2: 1, 8: 1}
billiard_unfolding_stratum(cover_type='translation', marked_points=False)[source]

Return the stratum of quadratic or Abelian differential obtained by unfolding a billiard in a polygon of this equiangular family.

INPUT:

  • cover_type (optional, default "translation") - either "rational", "half-translation" or "translation"

  • marked_poins (optional, default False) - whether the stratum should have regular marked points

EXAMPLES:

sage: from flatsurf import EuclideanPolygonsWithAngles, similarity_surfaces

sage: E = EuclideanPolygonsWithAngles(1, 2, 5)
sage: E.billiard_unfolding_stratum("half-translation")
Q_1(3, -1^3)
sage: E.billiard_unfolding_stratum("translation")
H_3(4)
sage: E.billiard_unfolding_stratum("half-translation", True)
Q_1(3, -1^3)
sage: E.billiard_unfolding_stratum("translation", True)
H_3(4, 0^3)

sage: E = EuclideanPolygonsWithAngles(1, 3, 1, 7)
sage: E.billiard_unfolding_stratum("half-translation")
Q_1(5, -1^5)
sage: E.billiard_unfolding_stratum("translation")
H_4(6)
sage: E.billiard_unfolding_stratum("half-translation", True)
Q_1(5, -1^5)
sage: E.billiard_unfolding_stratum("translation", True)
H_4(6, 0^5)

sage: P = E.an_element()
sage: S = similarity_surfaces.billiard(P)
sage: S.minimal_cover("half-translation").stratum()
Q_1(5, -1^5)
sage: S.minimal_cover("translation").stratum()
H_4(6, 0^5)

sage: E = EuclideanPolygonsWithAngles(1, 3, 5, 7)
sage: E.billiard_unfolding_stratum("half-translation")
Q_3(5, 3, 1, -1)
sage: E.billiard_unfolding_stratum("translation")
H_7(6, 4, 2)

sage: P = E.an_element()
sage: S = similarity_surfaces.billiard(P)
sage: S.minimal_cover("half-translation").stratum()
Q_3(5, 3, 1, -1)
sage: S.minimal_cover("translation").stratum()
H_7(6, 4, 2, 0)

sage: E = EuclideanPolygonsWithAngles(1, 2, 8)
sage: E.billiard_unfolding_stratum("half-translation")
H_5(7, 1)
sage: E.billiard_unfolding_stratum("translation")
H_5(7, 1)

sage: E.billiard_unfolding_stratum("half-translation", True)
H_5(7, 1, 0)
sage: E.billiard_unfolding_stratum("translation", True)
H_5(7, 1, 0)

sage: E = EuclideanPolygonsWithAngles(9, 6, 3, 2)
sage: p = E.an_element()
sage: B = similarity_surfaces.billiard(p)
sage: B.minimal_cover("half-translation").stratum()
Q_4(7, 4, 1, 0)
sage: E.billiard_unfolding_stratum("half-translation", True)
Q_4(7, 4, 1, 0)
sage: B.minimal_cover("translation").stratum()
H_8(8, 2^3, 0^2)
sage: E.billiard_unfolding_stratum("translation", True)
H_8(8, 2^3, 0^2)
billiard_unfolding_stratum_dimension(cover_type='translation', marked_points=False)[source]

Return the dimension of the stratum of quadratic or Abelian differential obtained by unfolding a billiard in a polygon of this equiangular family.

INPUT:

  • cover_type (optional, default "translation") - either "rational", "half-translation" or "translation"

  • marked_poins (optional, default False) - whether the stratum should have marked regular points

EXAMPLES:

sage: from flatsurf import EuclideanPolygonsWithAngles

sage: E = EuclideanPolygonsWithAngles(1, 1, 1)
sage: E.billiard_unfolding_stratum_dimension("half-translation")
2
sage: E.billiard_unfolding_stratum_dimension("translation")
2
sage: E.billiard_unfolding_stratum_dimension("half-translation", True)
4
sage: E.billiard_unfolding_stratum_dimension("translation", True)
4

sage: E = EuclideanPolygonsWithAngles(1, 2, 5)
sage: E.billiard_unfolding_stratum_dimension("half-translation")
4
sage: E.billiard_unfolding_stratum("half-translation").dimension()
4
sage: E.billiard_unfolding_stratum_dimension(cover_type="translation")
6
sage: E.billiard_unfolding_stratum("translation").dimension()
6
sage: E.billiard_unfolding_stratum_dimension("translation", True)
9
sage: E.billiard_unfolding_stratum("translation", True).dimension()
9

sage: E = EuclideanPolygonsWithAngles(1, 3, 5)
sage: E.billiard_unfolding_stratum_dimension("half-translation")
6
sage: E.billiard_unfolding_stratum("half-translation").dimension()
6
sage: E.billiard_unfolding_stratum_dimension("translation")
6
sage: E.billiard_unfolding_stratum("translation").dimension()
6

sage: E = EuclideanPolygonsWithAngles(1, 3, 1, 7)
sage: E.billiard_unfolding_stratum_dimension("half-translation")
6

sage: E = EuclideanPolygonsWithAngles(1, 3, 5, 7)
sage: E.billiard_unfolding_stratum_dimension("half-translation")
8

sage: E = EuclideanPolygonsWithAngles(1, 2, 8)
sage: E.billiard_unfolding_stratum_dimension()
11
sage: E.billiard_unfolding_stratum().dimension()
11
sage: E.billiard_unfolding_stratum_dimension(marked_points=True)
12
sage: E.billiard_unfolding_stratum(marked_points=True).dimension()
12
convexity()[source]

EXAMPLES:

sage: from flatsurf import EuclideanPolygonsWithAngles
sage: EuclideanPolygonsWithAngles(1, 2, 5).convexity()
doctest:warning
...
UserWarning: convexity() has been deprecated and will be removed in a future version of sage-flatsurf; use is_convex() instead
True
sage: EuclideanPolygonsWithAngles(2, 2, 3, 13).convexity()
False
is_convex(strict=False)[source]

Return whether the polygons in this category are convex.

INPUT:

  • strict – a boolean (default: False); whether only to consider polygons convex if all angles are <π.

EXAMPLES:

sage: from flatsurf import EuclideanPolygonsWithAngles
sage: EuclideanPolygonsWithAngles(1, 2, 5).is_convex()
True
sage: EuclideanPolygonsWithAngles(2, 2, 3, 13).is_convex()
False
sage: E = EuclideanPolygonsWithAngles([1, 1, 1, 1, 2])
sage: E.angles()
(1/4, 1/4, 1/4, 1/4, 1/2)
sage: E.is_convex(strict=False)
True
sage: E.is_convex(strict=True)
False
lengths_polytope()[source]

Return the polytope parametrizing the admissible vectors data.

This polytope parametrizes the tangent space to the set of these equiangular polygons. Be careful that even though the lengths are admissible, they may not define a polygon without intersection.

EXAMPLES:

sage: from flatsurf import EuclideanPolygonsWithAngles
sage: EuclideanPolygonsWithAngles(1, 2, 1, 2).lengths_polytope()
A 2-dimensional polyhedron in (Number Field in c with defining polynomial x^2 - 3 with c = 1.732050807568878?)^4 defined as the convex hull of 1 vertex and 2 rays
random_element(ring=None, **kwds)[source]

Return a random polygon in this category.

EXAMPLES:

sage: from flatsurf import EuclideanPolygonsWithAngles
sage: EuclideanPolygonsWithAngles(1, 1, 1, 2, 5).random_element()
Polygon(vertices=[(0, 0), ...])
sage: EuclideanPolygonsWithAngles(1,1,1,15,15,15).random_element()
Polygon(vertices=[(0, 0), ...])
sage: EuclideanPolygonsWithAngles(1,15,1,15,1,15).random_element()
Polygon(vertices=[(0, 0), ...])
slopes(e0=(1, 0))[source]

Return the slopes of the edges as a list of vectors.

INPUT:

  • e0 – the first slope returned (default: (1, 0))

EXAMPLES:

sage: from flatsurf import EuclideanPolygonsWithAngles
sage: EuclideanPolygonsWithAngles(1, 2, 1, 2).slopes()
[(1, 0), (c, 3), (-1, 0), (-c, -3)]
strict_convexity()[source]

EXAMPLES:

sage: from flatsurf import EuclideanPolygonsWithAngles
sage: E = EuclideanPolygonsWithAngles([1, 1, 1, 1, 2])
sage: E.angles()
(1/4, 1/4, 1/4, 1/4, 1/2)
sage: E.convexity()
True
sage: E.strict_convexity()
doctest:warning
...
UserWarning: strict_convexity() has been deprecated and will be removed in a future version of sage-flatsurf; use is_convex(strict=True) instead
False
super_categories()[source]

Return the other categories such polygons are automatically members of, namely, the category of rational euclidean polygons polygons.

EXAMPLES:

sage: from flatsurf.geometry.categories import EuclideanPolygons
sage: C = EuclideanPolygons(QQ).WithAngles([1, 1, 1, 1])
sage: C.super_categories()
[Category of rational euclidean polygons over Rational Field]