similarity_surfaces
¶
The category of similarity surfaces.
This module provides shared functionality for all surfaces in sage-flatsurf that are built from Euclidean polygons that are glued by similarities, i.e., identified edges can be transformed into each other by application of rotation and homothety (dilation) and translation.
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 immutable surfaces.
EXAMPLES:
sage: from flatsurf import MutableOrientedSimilaritySurface
sage: C = MutableOrientedSimilaritySurface(QQ).category()
sage: from flatsurf.geometry.categories import SimilaritySurfaces
sage: C.is_subcategory(SimilaritySurfaces())
True
The easiest way to construct a similarity surface is to use the constructions
from
flatsurf.geometry.similarity_surface_generators.SimilaritySurfaceGenerators
:
sage: from flatsurf import Polygon, similarity_surfaces
sage: P = Polygon(vertices=[(0,0), (2,0), (1,4), (0,5)])
sage: similarity_surfaces.self_glued_polygon(P)
Half-Translation Surface in Q_0(0, -1^4) built from a quadrilateral
Another way is to build a surface from scratch (using e.g.
flatsurf.geometry.surface.MutableOrientedSimilaritySurface
):
sage: P = Polygon(vertices=[(0,0), (1,0), (1,1), (0,1)])
sage: S = MutableOrientedSimilaritySurface(QQ)
sage: S.add_polygon(P)
0
sage: S.add_polygon(2*P)
1
sage: S.add_polygon(3*P)
2
sage: S.glue((0, 1), (1, 3))
sage: S.glue((0, 0), (2, 2))
sage: S.glue((0, 2), (2, 0))
sage: S.glue((0, 3), (1, 1))
sage: S.glue((1, 2), (2, 1))
sage: S.glue((1, 0), (2, 3))
sage: S
Surface built from 3 squares
To perform a sanity check on the obtained surface, you can run its test suite:
sage: TestSuite(S).run()
If there are no errors reported, no consistency problems could be detected in your surface.
Once you mark the surface as immutable, it gets more functionality, e.g., coming from its structure as a translation surface. This also adds more tests to its test suite:
sage: S.category()
Category of finite type oriented similarity surfaces
sage: S.set_immutable()
sage: S.category()
Category of connected without boundary finite type oriented rational similarity surfaces
sage: TestSuite(S).run()
In the following example, we attempt to build a broken surface by gluing more than two edges to each other; however, edges get unglued automatically:
sage: S = MutableOrientedSimilaritySurface.from_surface(S)
sage: S.glue((0, 0), (0, 3))
sage: S.glue((0, 1), (0, 3))
sage: S.glue((0, 2), (0, 3))
sage: S.gluings()
(((0, 2), (0, 3)), ((0, 3), (0, 2)), ((1, 0), (2, 3)), ((1, 2), (2, 1)), ((2, 1), (1, 2)), ((2, 3), (1, 0)))
sage: S.set_immutable()
sage: S.category()
Category of with boundary finite type oriented rational similarity surfaces
sage: TestSuite(S).run()
If we don’t glue all the edges, we get a surface with boundary:
sage: P = Polygon(vertices=[(0,0), (1,0), (1,1), (0,1)])
sage: S = MutableOrientedSimilaritySurface(QQ)
sage: S.add_polygon(P)
0
sage: TestSuite(S).run()
- class flatsurf.geometry.categories.similarity_surfaces.SimilaritySurfaces[source]¶
The category of surfaces built from polygons with edges identified by similarities.
EXAMPLES:
sage: from flatsurf.geometry.categories import SimilaritySurfaces sage: SimilaritySurfaces() Category of similarity surfaces
- class FiniteType(base_category)[source]¶
The category of surfaces built by gluing a finite number of Euclidean polygons with similarities.
EXAMPLES:
sage: from flatsurf import Polygon, similarity_surfaces sage: P = Polygon(vertices=[(0,0), (1,0), (1,1), (0,1)]) sage: S = similarity_surfaces.self_glued_polygon(P) sage: "FiniteType" in S.category().axioms() True
- class Oriented(base_category)[source]¶
The category of surfaces built from finitely many Euclidean polygons glued with singularities with an orientation that is compatible with the embedding that the polygons inherit from the real plane.
EXAMPLES:
sage: from flatsurf import Polygon, similarity_surfaces sage: P = Polygon(vertices=[(0,0), (1,0), (1,1), (0,1)]) sage: S = similarity_surfaces.self_glued_polygon(P) sage: "Oriented" in S.category().axioms() True
- class ParentMethods[source]¶
Provides methods available to all surfaces that are built from finitely many Euclidean polygons that are glued by similarities and are oriented with the natural orientation of the polygons in the real plane.
If you want to add functionality for such surfaces you most likely want to put it here.
- reposition_polygons(in_place=False, relabel=None)[source]¶
We choose a maximal tree in the dual graph of the decomposition into polygons, and ensure that the gluings between two polygons joined by an edge in this tree is by translation.
This guarantees that the group generated by the edge identifications is minimal among representations of the surface. In particular, if for instance you have a translation surface which is anot representable as a translation surface (because polygons are presented with rotations) then after this change it will be representable as a translation surface.
- standardize_polygons(in_place=False)[source]¶
Return a surface with each polygon replaced with a new polygon which differs by translation and reindexing. The new polygon will have the property that vertex zero is the origin, and all vertices lie either in the upper half plane, or on the x-axis with non-negative x-coordinate.
EXAMPLES:
sage: from flatsurf import translation_surfaces sage: s=translation_surfaces.veech_double_n_gon(4) sage: s.polygon(1) Polygon(vertices=[(0, 0), (-1, 0), (-1, -1), (0, -1)]) sage: [s.opposite_edge(0,i) for i in range(4)] [(1, 0), (1, 1), (1, 2), (1, 3)] sage: ss=s.standardize_polygons() sage: ss.polygon(1) Polygon(vertices=[(0, 0), (1, 0), (1, 1), (0, 1)]) sage: [ss.opposite_edge(0,i) for i in range(4)] [(1, 2), (1, 3), (1, 0), (1, 1)] sage: TestSuite(ss).run()
- class ParentMethods[source]¶
Provides methods available to all surfaces that are built from finitely many polygons in the real plane glued with similarities.
If you want to add functionality for such surfaces you most likely want to put it here.
- _test_eq_surface(**options)[source]¶
Verify that this surface follows our standards for equality of surfaces.
We want two surfaces to compare equal (\(S == T\)) iff they are virtually indistinguishable; so without a lot of non-Pythonic effort, you should not be able to tell them apart. They have (virtually) the same type, are made from equally labeled polygons with indistinguishable coordinates and equal gluings. Any other data that was used when creating them should be indistinguishable. They might of course live at different memory addresses have differences in their internal caches and representation but everything user-facing should be the same.
People often want \(==\) to mean that the two surfaces are isomorphic in some more-or-less strong sense. Such a notion for \(==\) always leads to trouble down the road. The operator \(==\) is used to identify surfaces in caches and identify surfaces in sets. Sometimes “are isomorphic” is a good notion in such cases but most of the time “are indistinguishable” is the much safer default. Also, “are isomorphic” is often costly or, e.g. in the case of infinite surfaces, not even decidable.
Currently, we do treat two surfaces as equal even if they differ by category because categories can presently be changed for immutable surfaces (as more properties of the surface are found.)
EXAMPLES:
sage: from flatsurf import Polygon, similarity_surfaces sage: P = Polygon(vertices=[(0,0), (1,0), (1,1), (0,1)]) sage: S = similarity_surfaces.self_glued_polygon(P) sage: S._test_eq_surface()
- num_singularities()[source]¶
EXAMPLES:
sage: from flatsurf import translation_surfaces sage: translation_surfaces.regular_octagon().num_singularities() doctest:warning ... UserWarning: num_singularities() has been deprecated and will be removed in a future version of sage-flatsurf; use len(vertices()) instead 1 sage: S = SymmetricGroup(4) sage: r = S('(1,2)(3,4)') sage: u = S('(2,3)') sage: translation_surfaces.origami(r,u).num_singularities() 2 sage: S = SymmetricGroup(8) sage: r = S('(1,2,3,4,5,6,7,8)') sage: u = S('(1,8,5,4)(2,3)(6,7)') sage: translation_surfaces.origami(r,u).num_singularities() 4
- class Oriented(base_category)[source]¶
The category of oriented surfaces built from Euclidean polygons that are glued by similarities with the orientation compatible with the orientation of the real plane that polygons are defined in.
EXAMPLES:
sage: from flatsurf.geometry.categories import SimilaritySurfaces sage: SimilaritySurfaces().Oriented() Category of oriented similarity surfaces
- class ElementMethods[source]¶
Provides methods available to all points of oriented similarity surfaces.
If you want to add functionality for such surfaces, you most likely want to put it here.
- angle(numerical=False)[source]¶
Return the total angle at this point as a multiple of 2π.
INPUT:
numerical
– a boolean (default:False
); whether to return a floating point approximation of the angle or its exact value.
EXAMPLES:
sage: from flatsurf import Polygon, similarity_surfaces sage: P = Polygon(vertices=[(0, 0), (2, 0), (1, 4), (0, 5)]) sage: S = similarity_surfaces.self_glued_polygon(P) sage: S(0, 0).angle() 1 sage: S(0, (1, 0)).angle() 1/2 sage: S(0, (1, 0)).angle(numerical=True) 0.500000000000000
See also
turns()
for the number of full 2π turns at a point.
- edges()[source]¶
Return the edges of the polygons that contain this point.
Implements
polygonal_surfaces.PolygonalSurfaces.ElementMethods.edges()
for similarity surfaces.
- edges_ccw(start_edge=None, start_holonomy=None)[source]¶
Return the edges of the polygons that are crossed when walking around this point in counterclockwise direction.
Each edge is reported together with its holonomy vector in the coordinate system of the
start_edge
.Each edge is reported “twice”, once when leaving a polygon, and once when entering a polygon.
INPUT:
start_edge
– an edge orNone
(default:None
); a particular outgoing edge at which to start the walk.start_holonomy
– a vector orNone
(default:None
); the holonomy that the first edge reported should use. IfNone
, then use the holonomy that the polygon edge reports normally.
EXAMPLES:
sage: from flatsurf import Polygon, similarity_surfaces sage: P = Polygon(vertices=[(0, 0), (2, 0), (1, 4), (0, 5)]) sage: S = similarity_surfaces.self_glued_polygon(P) sage: S(0, 0).edges_ccw() [((0, 2), (-1, 1)), ((0, 1), (1, -4)), ((0, 1), (1, -4)), ((0, 0), (2, 0)), ((0, 0), (2, 0)), ((0, 3), (0, 5)), ((0, 3), (0, 5)), ((0, 2), (-1, 1))] sage: S(0, 0).edges_ccw(start_edge=(0, 0)) [((0, 0), (2, 0)), ((0, 3), (0, 5)), ((0, 3), (0, 5)), ((0, 2), (-1, 1)), ((0, 2), (-1, 1)), ((0, 1), (1, -4)), ((0, 1), (1, -4)), ((0, 0), (2, 0))] sage: S(0, 0).edges_ccw(start_holonomy=(1, 0)) [((0, 2), (1, 0)), ((0, 1), (-5/2, 3/2)), ((0, 1), (-5/2, 3/2)), ((0, 0), (-1, -1)), ((0, 0), (-1, -1)), ((0, 3), (5/2, -5/2)), ((0, 3), (5/2, -5/2)), ((0, 2), (1, 0))]
See also
edges()
for the edges containing this point in no particular order.
- turns(start_edge=None, start_holonomy=None)[source]¶
Return the number of total 2π turns at this vertex.
Returns a triple
(turns, start, end)
whereturns
is an integer, andstart
andend
are vectors such that start is the vector at which we begin counting the turns, andend
is the vector at which we stop counting the turns.If the total angle at this point is a multiple of 2π, then
start
andend
are parallel.If the surface has no boundary, then
start
andend
are holonomy vectors of the same edge of the surface.INPUT:
start_edge
– an edge orNone
(default:None
); a particular outgoing edge at which to start counting the turns.start_holonomy
– a vector orNone
(default:None
); the holonomy that the first edge reported should use. IfNone
, then use the holonomy that the polygon edge reports normally.
ALGORITHM:
We count the half turns of angle π by walking around the vertex and counting how often the outgoing edges go between being clockwise and being counterclockwise from the
start_edge
.EXAMPLES:
sage: from flatsurf import translation_surfaces sage: S = translation_surfaces.square_torus() sage: S(0, 0).turns() (1, (0, -1), (0, -1)) sage: from flatsurf import Polygon, similarity_surfaces sage: P = Polygon(vertices=[(0, 0), (2, 0), (1, 4), (0, 5)]) sage: S = similarity_surfaces.self_glued_polygon(P) sage: S(0, 0).turns() (1, (-1, 1), (-1, 1)) sage: S(0, (1, 0)).turns() Traceback (most recent call last): ... ValueError: point must be a vertex
See also
angle()
for the possibly non-integral number of turns at this point.
- class ParentMethods[source]¶
Provides methods available to all oriented surfaces that are built from Euclidean polygons that are glued by similarities.
If you want to add functionality for such surfaces you most likely want to put it here.
- angles(numerical=False, return_adjacent_edges=None)[source]¶
Return the angles around the vertices of the surface as multiples of 2π.
INPUT:
numerical
– a boolean (default:False
); whether the angles are returned as floating point numbers or as exact algebraic numbers.
EXAMPLES:
sage: from flatsurf import polygons, similarity_surfaces, translation_surfaces sage: T = polygons.triangle(3, 4, 5) sage: S = similarity_surfaces.billiard(T) sage: S.angles() [1/4, 5/12, 1/3] sage: S.angles(numerical=True) # abs tol 1e-14 [0.25, 0.4166666666666667, 0.33333333333333337] sage: S.angles(return_adjacent_edges=True) doctest:warning ... UserWarning: return_adjacent_edges has been deprecated as a keyword argument to angles() and will be removed in a future version of sage-flatsurf; use angle() and edges_ccw()[::2] on each vertex instead. [(1/4, [(0, 0), (1, 0)]), (5/12, [(0, 2), (1, 1)]), (1/3, [(0, 1), (1, 2)])]
sage: translation_surfaces.regular_octagon().angles() [3] sage: S = translation_surfaces.veech_2n_gon(5) sage: S.angles() [2, 2] sage: S.angles(numerical=True) [2.0, 2.0] sage: S.angles(return_adjacent_edges=True) # random output [(2, [(0, 1), (0, 5), (0, 9), (0, 3), (0, 7)]), (2, [(0, 0), (0, 4), (0, 8), (0, 2), (0, 6)])] sage: S.angles(numerical=True, return_adjacent_edges=True) # random output [(2.0, [(0, 1), (0, 5), (0, 9), (0, 3), (0, 7)]), (2.0, [(0, 0), (0, 4), (0, 8), (0, 2), (0, 6)])] sage: translation_surfaces.veech_2n_gon(6).angles() [5] sage: translation_surfaces.veech_double_n_gon(5).angles() [3] sage: translation_surfaces.cathedral(1, 1).angles() [3, 3, 3] sage: from flatsurf import polygons, similarity_surfaces sage: B = similarity_surfaces.billiard(polygons.triangle(1, 2, 5)) sage: H = B.minimal_cover(cover_type="half-translation") sage: S = B.minimal_cover(cover_type="translation") sage: H.angles() [1/2, 1/2, 1/2, 5/2] sage: S.angles() [1, 1, 5, 1] sage: H.angles(return_adjacent_edges=True) [(1/2, [...]), (1/2, [...]), (1/2, [...]), (5/2, [...])] sage: S.angles(return_adjacent_edges=True) [(1, [...]), (1, [...]), (5, [...]), (1, [...])]
For self-glued edges, no angle is reported for the “vertex” at the midpoint of the edge:
sage: from flatsurf import Polygon, similarity_surfaces sage: P = Polygon(vertices=[(0,0), (2,0), (1,4), (0,5)]) sage: S = similarity_surfaces.self_glued_polygon(P) sage: S.angles() [1]
Non-convex examples:
sage: from flatsurf import Polygon, MutableOrientedSimilaritySurface sage: S = MutableOrientedSimilaritySurface(QQ) sage: L = Polygon(vertices=[(0,0),(1,0),(2,0),(2,1),(1,1),(1,2),(0,2),(0,1)]) sage: S.add_polygon(L) 0 sage: S.glue((0, 0), (0, 5)) sage: S.glue((0, 1), (0, 3)) sage: S.glue((0, 2), (0, 7)) sage: S.glue((0, 4), (0, 6)) sage: S.set_immutable() sage: S.angles() [3] sage: S = MutableOrientedSimilaritySurface(QQ) sage: P = Polygon(vertices=[(0,0),(1,0),(2,0),(2,1),(3,1),(3,2),(2,2),(1,2),(1,1),(0,1)]) sage: S.add_polygon(P) 0 sage: S.glue((0, 0), (0, 8)) sage: S.glue((0, 1), (0, 6)) sage: S.glue((0, 2), (0, 9)) sage: S.glue((0, 3), (0, 5)) sage: S.glue((0, 4), (0, 7)) sage: S.set_immutable() sage: S.angles() [2, 2]
Angles can also be determined for surfaces with boundary:
sage: from flatsurf import MutableOrientedSimilaritySurface sage: P = Polygon(vertices=[(0, 0), (1, 0), (1, 1), (0, 2)]) sage: S = MutableOrientedSimilaritySurface(QQ) sage: S.add_polygon(P) 0 sage: S.set_immutable() sage: S.angles() [1/4, 1/4, 3/8, 1/8]
- change_ring(ring)[source]¶
Return a copy of this surface whose polygons are defined over
ring
.EXAMPLES:
sage: from flatsurf import translation_surfaces sage: S = translation_surfaces.veech_2n_gon(4) sage: T = S.change_ring(AA) sage: T.base_ring() Algebraic Real Field
This method creates a copy even if the base ring is unchanged:
sage: S.change_ring(S.base_ring()) is S False
Note that the resulting surface might not be functional if the polygon cannot be represented in the ring:
sage: S.change_ring(QQ).polygon(0) Traceback (most recent call last): ... TypeError: Unable to coerce 1/2*a + 1 to a rational
- copy(relabel=False, mutable=False, lazy=None, new_field=None, optimal_number_field=False)[source]¶
Returns a copy of this surface. The method takes several flags to modify how the copy is taken.
If relabel is True, then instead of returning an exact copy, it returns a copy indexed by the non-negative integers. This uses the Surface_list implementation. If relabel is False (default), then we return an exact copy. The returned surface uses the Surface_dict implementation.
The mutability flag returns if the resulting surface should be mutable or not. By default, the resulting surface will not be mutable.
If lazy is True, then the surface is copied by reference. This is the only type of copy possible for infinite surfaces. The parameter defaults to False for finite surfaces, and defaults to True for infinite surfaces.
The new_field parameter can be used to place the vertices in a larger field than the basefield for the original surface.
The optimal_number_field option can be used to find a best NumberField containing the (necessarily finite) surface.
EXAMPLES:
sage: from flatsurf import translation_surfaces sage: ss=translation_surfaces.ward(3) sage: ss.is_mutable() False sage: s=ss.copy(mutable=True) doctest:warning ... UserWarning: copy() has been deprecated and will be removed from a future version of sage-flatsurf; for surfaces of finite type use MutableOrientedSimilaritySurface.from_surface() instead. sage: s.is_mutable() True sage: TestSuite(s).run() sage: s == ss False
Changing the base field:
sage: s=translation_surfaces.veech_double_n_gon(5) sage: ss=s.copy(mutable=False,new_field=AA) doctest:warning ... UserWarning: copy() has been deprecated and will be removed from a future version of sage-flatsurf; for surfaces of finite type use MutableOrientedSimilaritySurface.from_surface() instead. Use set_immutable() to make the resulting surface immutable. Use change_ring() to change the field over which the surface is defined. sage: TestSuite(ss).run() sage: ss.base_ring() Algebraic Real Field
Optimization of number field:
sage: s = translation_surfaces.arnoux_yoccoz(3) sage: ss = s.copy(new_field=AA).copy(optimal_number_field=True) doctest:warning ... UserWarning: copy() has been deprecated and will be removed from a future version of sage-flatsurf; for surfaces of finite type use MutableOrientedSimilaritySurface.from_surface() instead. Use set_immutable() to make the resulting surface immutable. Use change_ring() to change the field over which the surface is defined. doctest:warning ... UserWarning: copy() has been deprecated and will be removed from a future version of sage-flatsurf; for surfaces of finite type use MutableOrientedSimilaritySurface.from_surface() instead. Use set_immutable() to make the resulting surface immutable. There is currently no replacement for optimal number field. If you are relying on this features, let the authors of sage-flatsurf know and we will try to make it available again. sage: TestSuite(ss).run() sage: ss.base_ring().discriminant() -44
- delaunay_decompose(codomain=None)[source]¶
Return a Delaunay decomposition of this surface, i.e., a representation of this surface such that the circumscribed disk of each polygon contains exactly the vertices of that polygon.
ALGORITHM:
The Delaunay decomposition is obtained by removing ambiguous edges from a Delaunay triangulation. An edge is ambiguous if after its removal the circumscribed disk of each polygon (still) contains no vertices in its interior.
INPUT:
codomain
– a Delaunay decomposed surface orNone
(default:None
); if present, the morphism returned goes from this surface tocodomain
.
EXAMPLES:
sage: from flatsurf import translation_surfaces sage: S = translation_surfaces.octagon_and_squares() sage: a = S.base_ring().gens()[0] sage: M = Matrix([[1, 2 + a], [0, 1]]) sage: S = M * S sage: S = S.triangulate().codomain() sage: S = S.delaunay_decompose().codomain() sage: S.is_delaunay_decomposed() True sage: S Delaunay cell decomposition of Triangulation of Translation Surface in H_3(4) built from 2 quadrilaterals and an octagon
sage: from flatsurf import Polygon, similarity_surfaces sage: P = Polygon(edges=[(4, 0), (-2, 1), (-2, -1)]) sage: T = similarity_surfaces.self_glued_polygon(P) sage: T = T.delaunay_decompose().codomain() sage: T.is_delaunay_decomposed() True sage: T Delaunay cell decomposition of Half-Translation Surface in Q_0(-1^4) built from an isosceles triangle
sage: M = matrix([[2, 1], [1, 1]]) sage: U = M * translation_surfaces.infinite_staircase() sage: U = U.delaunay_decompose().codomain() sage: U.is_delaunay_decomposed() True sage: U.root() (0, 0) sage: U.polygon((0, 0)) Polygon(vertices=[(0, 0), (-1, 0), (-1, -1), (0, -1)])
- delaunay_decomposition(triangulated=None, delaunay_triangulated=None, in_place=False, direction=None, relabel=None)[source]¶
Return the Delaunay Decomposition of this surface.
INPUT:
triangulated
-None
; ignoreddelaunay_triangulated
-None
; ignoredin_place
- boolean (default:False
); whether this surface is modified and returned or just a copy of the surfacedirection
-None
; ignoredrelabel
-None
; ignored
EXAMPLES:
sage: from flatsurf import translation_surfaces, Polygon, similarity_surfaces sage: s0 = translation_surfaces.octagon_and_squares() sage: a = s0.base_ring().gens()[0] sage: m = Matrix([[1,2+a],[0,1]]) sage: s = m*s0 sage: s = s.triangulate().codomain() sage: ss = s.delaunay_decomposition() doctest:warning ... UserWarning: delaunay_decomposition() has been deprecated and will be removed in a future version of sage-flatsurf; use delaunay_decompose().codomain() instead sage: len(ss.polygons()) 3 sage: p = Polygon(edges=[(4,0),(-2,1),(-2,-1)]) sage: s0 = similarity_surfaces.self_glued_polygon(p) sage: s = s0.delaunay_decomposition() sage: TestSuite(s).run() sage: m = matrix([[2,1],[1,1]]) sage: s = m*translation_surfaces.infinite_staircase() sage: ss = s.delaunay_decomposition() doctest:warning ... UserWarning: delaunay_decomposition() has been deprecated and will be removed in a future version of sage-flatsurf; use delaunay_decompose().codomain() instead sage: ss.root() (0, 0) sage: ss.polygon(ss.root()) Polygon(vertices=[(0, 0), (-1, 0), (-1, -1), (0, -1)]) sage: TestSuite(ss).run() sage: ss.is_delaunay_decomposed() True
- delaunay_triangulate()[source]¶
Return a Delaunay triangulation of this surface.
EXAMPLES:
sage: from flatsurf import translation_surfaces sage: M = matrix([[2, 1], [1, 1]]) sage: S = M * translation_surfaces.infinite_staircase() sage: S = S.delaunay_triangulate().codomain() sage: S.root() (0, 0) sage: S.polygon((0, 0)) Polygon(vertices=[(0, 0), (-1, 0), (-1, -1)]) sage: S.is_delaunay_triangulated() True
- delaunay_triangulation(triangulated=None, in_place=False, direction=None, relabel=None)[source]¶
Return a Delaunay triangulation of this surface.
INPUT:
triangulated
-None
; ignoredin_place
- boolean (default:False
); whether this ssurface is modified and returned or just a copy of the surfacedirection
-None
; ignoredrelabel
-None
; ignored
EXAMPLES:
sage: from flatsurf import translation_surfaces sage: m = matrix([[2, 1], [1, 1]]) sage: s = m * translation_surfaces.infinite_staircase() sage: ss = s.delaunay_triangulation() doctest:warning ... UserWarning: delaunay_triangulation() is deprecated and will be removed in a future version of sage-flatsurf; use delaunay_triangulate().codomain() instead sage: ss.root() (0, 0) sage: ss.polygon((0, 0)) Polygon(vertices=[(0, 0), (-1, 0), (-1, -1)]) sage: TestSuite(ss).run() sage: ss.is_delaunay_triangulated() True
- edge_matrix(p, e=None)[source]¶
Returns the 2x2 matrix representing a similarity which when applied to the polygon with label \(p\) makes it so the edge \(e\) can be glued to its opposite edge by translation.
If \(e\) is not provided, then \(p\) should be a pair consisting of a polygon label and an edge.
EXAMPLES:
sage: from flatsurf.geometry.similarity_surface_generators import SimilaritySurfaceGenerators sage: s = SimilaritySurfaceGenerators.example() sage: s.polygon(0) Polygon(vertices=[(0, 0), (2, -2), (2, 0)]) sage: s.polygon(1) Polygon(vertices=[(0, 0), (2, 0), (1, 3)]) sage: s.opposite_edge(0,0) (1, 1) sage: m = s.edge_matrix(0, 0) sage: m [ 1 1/2] [-1/2 1] sage: m * vector((2,-2)) == -vector((-1, 3)) True
- edge_transformation(p, e)[source]¶
Return the similarity bringing the provided edge to the opposite edge.
EXAMPLES:
sage: from flatsurf.geometry.similarity_surface_generators import SimilaritySurfaceGenerators sage: s = SimilaritySurfaceGenerators.example() sage: s.polygon(0) Polygon(vertices=[(0, 0), (2, -2), (2, 0)]) sage: s.polygon(1) Polygon(vertices=[(0, 0), (2, 0), (1, 3)]) sage: s.opposite_edge(0,0) (1, 1) sage: g = s.edge_transformation(0,0) sage: g((0,0)) (1, 3) sage: g((2,-2)) (2, 0)
- is_convex(label, edge, strict=False)[source]¶
Return whether the polygon with
label
is convex after it has been glued with the polygon across itsedge
.INPUT:
label
– a label of a polygon in this surfaceedge
– the index of an edge of the polygon withlabel
strict
– a boolean (default:False
); whether to determine that the polygon is strictly convex, i.e., none of its inner angles greater or equal than π.
EXAMPLES:
sage: from flatsurf import translation_surfaces sage: S = translation_surfaces.mcmullen_L(1, 1, 1, 1) sage: S.is_convex(0, 0) True sage: S.is_convex(0, 0, strict=True) False sage: S.is_convex(2, 0) True
- is_delaunay_decomposed(limit=None)[source]¶
Return if the decomposition of the surface into polygons is Delaunay.
INPUT:
limit
– an integer orNone
(default:None
); check onlylimit
many polygons if set
- is_delaunay_triangulated(limit=None)[source]¶
Return whether the surface is triangulated and the triangulation is Delaunay.
INPUT:
limit
– an integer orNone
(default:None
); check onlylimit
many edges if set
- join_polygons(p1, e1, test=False, in_place=False)[source]¶
Join polygons across the provided edge (p1,e1). By default, it returns the surface obtained by joining the two polygons together. It raises a ValueError if gluing the two polygons together results in a non-convex polygon. This is done to the current surface if in_place is True, and otherwise a mutable copy is made and then modified.
If test is True then instead of changing the surface, it just checks to see if the change would be successful and returns True if successful or False if not.
EXAMPLES:
sage: from flatsurf import translation_surfaces, MutableOrientedSimilaritySurface sage: ss = translation_surfaces.ward(3) sage: s = MutableOrientedSimilaritySurface.from_surface(ss) sage: s.join_polygons(0,0, in_place=True) Translation Surface built from an equilateral triangle and a pentagon with 2 marked vertices sage: s.polygon(0) Polygon(vertices=[(0, 0), (1, -a), (2, 0), (3, a), (2, 2*a), (0, 2*a), (-1, a)]) sage: s.join_polygons(0,4, in_place=True) Translation Surface built from a rhombus sage: s.polygon(0) Polygon(vertices=[(0, 0), (1, -a), (2, 0), (3, a), (2, 2*a), (1, 3*a), (0, 2*a), (-1, a)])
- minimal_cover(cover_type='translation')[source]¶
Return the minimal translation or half-translation cover of the surface.
Cover type may be either “translation”, “half-translation” or “planar”.
The minimal planar cover of a surface S is the smallest cover C so that the developing map from the universal cover U to the plane induces a well defined map from C to the plane. This is an infinite translation surface that is naturally a branched cover of the plane.
EXAMPLES:
sage: from flatsurf import polygons, MutableOrientedSimilaritySurface sage: s = MutableOrientedSimilaritySurface(QQ) sage: square = polygons.square(base_ring=QQ) sage: s.add_polygon(square) 0 sage: s.glue((0,0), (0,1)) sage: s.glue((0,2) ,(0,3)) sage: cs = s sage: ts = cs.minimal_cover(cover_type="translation") sage: ts Minimal Translation Cover of Rational Cone Surface built from a square sage: from flatsurf.geometry.categories import TranslationSurfaces sage: ts in TranslationSurfaces() True sage: hts = cs.minimal_cover(cover_type="half-translation") sage: hts Minimal Half-Translation Cover of Genus 0 Rational Cone Surface built from a square sage: from flatsurf.geometry.categories import HalfTranslationSurfaces sage: hts in HalfTranslationSurfaces() True sage: TestSuite(hts).run() sage: ps = cs.minimal_cover(cover_type="planar") sage: ps Minimal Planar Cover of Genus 0 Rational Cone Surface built from a square sage: ps in TranslationSurfaces() True sage: TestSuite(ps).run() sage: from flatsurf import similarity_surfaces sage: S = similarity_surfaces.example() sage: T = S.minimal_cover(cover_type="translation") sage: T Minimal Translation Cover of Genus 1 Surface built from 2 isosceles triangles sage: T in TranslationSurfaces() True sage: T.polygon(T.root()) Polygon(vertices=[(0, 0), (2, -2), (2, 0)])
- point(label, point, ring=None, limit=None)[source]¶
Return a point in this surface.
INPUT:
label
- label of the polygonpoint
- coordinates of the point inside the polygon or the index of the vertex of the polygon.ring
(optional) - a ring for the coordinateslimit
(optional) - undocumented (only relevant if the point corresponds to a singularity in an infinite surface)
EXAMPLES:
sage: from flatsurf import translation_surfaces sage: s = translation_surfaces.square_torus() sage: pc = s.minimal_cover(cover_type="planar") sage: pc.point(pc.root(), (0, 0)) Vertex 0 of polygon (0, (x, y) |-> (x, y)) sage: pc.point(pc.root(), 0) Vertex 0 of polygon (0, (x, y) |-> (x, y)) sage: pc.point(pc.root(), 1) Vertex 0 of polygon (0, (x, y) |-> (x + 1, y)) sage: pc.point(pc.root(), (1, 1)) Vertex 0 of polygon (0, (x, y) |-> (x + 1, y + 1)) sage: z = pc.point(pc.root(),(sqrt(2)-1,sqrt(3)-1),ring=AA) doctest:warning ... UserWarning: the ring parameter is deprecated and will be removed in a future version of sage-flatsurf; define the surface over a larger ring instead so that this points' coordinates live in the base ring sage: next(iter(z.coordinates(next(iter(z.labels()))))).parent() Vector space of dimension 2 over Algebraic Real Field
sage: s = translation_surfaces.cathedral(2, 3) sage: s.point(0, 0) Vertex 0 of polygon 0 sage: s.point(0, (0, 0)) Vertex 0 of polygon 0 sage: s.point(0, (1, 1)) Point (1, 0) of polygon 0 sage: s.point(0, 1) Vertex 0 of polygon 1
- ramified_cover(d, data)[source]¶
Return a ramified cover of this surface.
INPUT:
d
- integer (the degree of the cover)data
- a dictionary which to a pair(label, edge_num)
associates a permutation of {1,…,d}
EXAMPLES:
The L-shape origami:
sage: import flatsurf sage: T = flatsurf.translation_surfaces.square_torus() sage: T.ramified_cover(3, {(0,0): '(1,2)', (0,1): '(1,3)'}) Translation Surface in H_2(2) built from 3 squares sage: O = T.ramified_cover(3, {(0,0): '(1,2)', (0,1): '(1,3)'}) sage: O.stratum() H_2(2)
- random_flip(repeat=1, in_place=False)[source]¶
Perform random edge flip on a triangulated surface.
INPUT:
repeat
– integer (default1
). The number of edge flip to perform.in_place
– whether the transformation is done in place.
EXAMPLES:
sage: from flatsurf import translation_surfaces sage: ss = translation_surfaces.ward(3).triangulate() sage: ss.random_flip(15) # random Translation Surface in H_1(0^3) built from 6 triangles
- relabel(relabeling=None, in_place=False)[source]¶
Return a surface whose polygons have been relabeled according to
relabeling
.INPUT:
relabeling
– a dict, a callable, orNone
(default:None
); the mapping from labels of this surface to labels of the relabeled surface. IfNone
, then relabel to the non-negative integers.in_place
– a boolean (default:False
); whether to modify this surface or return a relabeled copy instead.
EXAMPLES:
sage: from flatsurf import translation_surfaces sage: S = translation_surfaces.veech_double_n_gon(5) sage: SS = S.relabel({0: 1, 1: 2}) sage: SS Translation Surface in H_2(2) built from 2 regular pentagons sage: SS.root() 1 sage: SS.opposite_edge(1, 0) (2, 0) sage: TestSuite(SS).run()
The relabeling can also be a callable:
sage: SSS = SS.relabel(lambda label: label -1) sage: SSS == S True
However, this is only supported on finite-type surfaces:
sage: S = translation_surfaces.infinite_staircase() sage: S.labels() (0, 1, -1, 2, -2, 3, -3, 4, -4, 5, -5, 6, -6, 7, -7, 8, …) sage: S.relabel(lambda label: -label) Traceback (most recent call last): ... NotImplementedError: cannot relabel a surface with an infinite number of polygons with a callable relabeling yet
sage: S.relabel({1: 'X'}) Traceback (most recent call last): ... NotImplementedError: cannot relabel a surface with an infinite number of polygons with a dict relabeling yet
For infinite surfaces, we only support relabeling to the non-negative integers:
sage: S.relabel().labels() (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, …)
- saddle_connections(squared_length_bound, initial_label=None, initial_vertex=None, sc_list=None, check=False)[source]¶
Returns a list of saddle connections on the surface whose length squared is less than or equal to squared_length_bound. The length of a saddle connection is measured using holonomy from polygon in which the trajectory starts.
If initial_label and initial_vertex are not provided, we return all saddle connections satisfying the bound condition.
If initial_label and initial_vertex are provided, it only provides saddle connections emanating from the corresponding vertex of a polygon. If only initial_label is provided, the added saddle connections will only emanate from the corresponding polygon.
If sc_list is provided the found saddle connections are appended to this list and the resulting list is returned.
If check==True it uses the checks in the SaddleConnection class to sanity check our results.
EXAMPLES:
sage: from flatsurf import translation_surfaces sage: s = translation_surfaces.square_torus() sage: sc_list = s.saddle_connections(13, check=True) sage: len(sc_list) 32
- set_vertex_zero(label, v, in_place=False)[source]¶
Applies a combinatorial rotation to the polygon with the provided label.
This makes what is currently vertex v of this polygon vertex 0. In other words, what is currently vertex (or edge) e will now become vertex (e-v)%n where n is the number of sides of the polygon.
For the updated polygons, the polygons will be translated so that vertex 0 is the origin.
EXAMPLES:
Example with polygon glued to another polygon:
sage: from flatsurf import translation_surfaces sage: s = translation_surfaces.veech_double_n_gon(4) sage: s.polygon(0) Polygon(vertices=[(0, 0), (1, 0), (1, 1), (0, 1)]) sage: [s.opposite_edge(0,i) for i in range(4)] [(1, 0), (1, 1), (1, 2), (1, 3)] sage: ss = s.set_vertex_zero(0,1) sage: ss.polygon(0) Polygon(vertices=[(0, 0), (0, 1), (-1, 1), (-1, 0)]) sage: [ss.opposite_edge(0,i) for i in range(4)] [(1, 1), (1, 2), (1, 3), (1, 0)] sage: TestSuite(ss).run()
Example with polygon glued to self:
sage: s = translation_surfaces.veech_2n_gon(2) sage: s.polygon(0) Polygon(vertices=[(0, 0), (1, 0), (1, 1), (0, 1)]) sage: [s.opposite_edge(0,i) for i in range(4)] [(0, 2), (0, 3), (0, 0), (0, 1)] sage: ss = s.set_vertex_zero(0,3) sage: ss.polygon(0) Polygon(vertices=[(0, 0), (0, -1), (1, -1), (1, 0)]) sage: [ss.opposite_edge(0,i) for i in range(4)] [(0, 2), (0, 3), (0, 0), (0, 1)] sage: TestSuite(ss).run()
- singularity(label, v, limit=None)[source]¶
Represents the Singularity associated to the v-th vertex of the polygon with label
label
.If the surface is infinite, the limit can be set. In this case the construction of the singularity is successful if the sequence of vertices hit by passing through edges closes up in limit or less steps.
EXAMPLES:
sage: from flatsurf import translation_surfaces sage: s = translation_surfaces.square_torus() sage: pc = s.minimal_cover(cover_type="planar") sage: pc.singularity(pc.root(), 0) doctest:warning ... UserWarning: Singularity() is deprecated and will be removed in a future version of sage-flatsurf. Use surface.point() instead. Vertex 0 of polygon (0, (x, y) |-> (x, y)) sage: pc.singularity(pc.root(), 0, limit=1) Traceback (most recent call last): ... ValueError: number of edges at singularity exceeds limit
- some_elements()[source]¶
Return some typical points of this surface (for testing).
EXAMPLES:
sage: from flatsurf import translation_surfaces sage: S = translation_surfaces.square_torus() sage: list(S.some_elements()) [Point (1/2, 1/2) of polygon 0, Vertex 0 of polygon 0]
- subdivide()[source]¶
Return a copy of this surface whose polygons have been partitioned into smaller triangles with
subdivide()
.EXAMPLES:
A surface consisting of a single triangle:
sage: from flatsurf import MutableOrientedSimilaritySurface, Polygon sage: S = MutableOrientedSimilaritySurface(QQ) sage: S.add_polygon(Polygon(edges=[(1, 0), (0, 1), (-1, -1)]), label="Δ") 'Δ'
Subdivision of this surface yields a surface with three triangles:
sage: T = S.subdivide() sage: T.labels() (('Δ', 0), ('Δ', 1), ('Δ', 2))
Note that the new labels are old labels plus an index. We verify that the triangles are glued correctly:
sage: list(T.gluings()) [((('Δ', 0), 1), (('Δ', 1), 2)), ((('Δ', 0), 2), (('Δ', 2), 1)), ((('Δ', 1), 1), (('Δ', 2), 2)), ((('Δ', 1), 2), (('Δ', 0), 1)), ((('Δ', 2), 1), (('Δ', 0), 2)), ((('Δ', 2), 2), (('Δ', 1), 1))]
If we add another polygon to the original surface and glue things, we can see how existing gluings are preserved when subdividing:
sage: S.add_polygon(Polygon(edges=[(1, 0), (0, 1), (-1, 0), (0, -1)]), label='□') '□' sage: S.glue(("Δ", 0), ("□", 2)) sage: S.glue(("□", 1), ("□", 3)) sage: T = S.subdivide() sage: T.labels() (('Δ', 0), ('□', 2), ('Δ', 1), ('Δ', 2), ('□', 3), ('□', 1), ('□', 0)) sage: list(sorted(T.gluings())) [((('Δ', 0), 0), (('□', 2), 0)), ((('Δ', 0), 1), (('Δ', 1), 2)), ((('Δ', 0), 2), (('Δ', 2), 1)), ((('Δ', 1), 1), (('Δ', 2), 2)), ((('Δ', 1), 2), (('Δ', 0), 1)), ((('Δ', 2), 1), (('Δ', 0), 2)), ((('Δ', 2), 2), (('Δ', 1), 1)), ((('□', 0), 1), (('□', 1), 2)), ((('□', 0), 2), (('□', 3), 1)), ((('□', 1), 0), (('□', 3), 0)), ((('□', 1), 1), (('□', 2), 2)), ((('□', 1), 2), (('□', 0), 1)), ((('□', 2), 0), (('Δ', 0), 0)), ((('□', 2), 1), (('□', 3), 2)), ((('□', 2), 2), (('□', 1), 1)), ((('□', 3), 0), (('□', 1), 0)), ((('□', 3), 1), (('□', 0), 2)), ((('□', 3), 2), (('□', 2), 1))]
- subdivide_edges(parts=2)[source]¶
Return a copy of this surface whose edges have been split into
parts
equal pieces each.INPUT:
parts
– a positive integer (default: 2)
EXAMPLES:
A surface consisting of a single triangle:
sage: from flatsurf import MutableOrientedSimilaritySurface sage: from flatsurf.geometry.polygon import Polygon sage: S = MutableOrientedSimilaritySurface(QQ) sage: S.add_polygon(Polygon(edges=[(1, 0), (0, 1), (-1, -1)]), label="Δ") 'Δ'
Subdividing this triangle yields a triangle with marked points along the edges:
sage: T = S.subdivide_edges()
If we add another polygon to the original surface and glue them, we can see how existing gluings are preserved when subdividing:
sage: S.add_polygon(Polygon(edges=[(1, 0), (0, 1), (-1, 0), (0, -1)]), label='□') '□' sage: S.glue(("Δ", 0), ("□", 2)) sage: S.glue(("□", 1), ("□", 3)) sage: T = S.subdivide_edges().codomain() sage: list(sorted(T.gluings())) [(('Δ', 0), ('□', 5)), (('Δ', 1), ('□', 4)), (('□', 2), ('□', 7)), (('□', 3), ('□', 6)), (('□', 4), ('Δ', 1)), (('□', 5), ('Δ', 0)), (('□', 6), ('□', 3)), (('□', 7), ('□', 2))]
- subdivide_polygon(p, v1, v2, test=False, new_label=None)[source]¶
Cut the polygon with label p along the diagonal joining vertex v1 to vertex v2. This cuts p into two polygons, one will keep the same label. The other will get a new label, which can be provided via new_label. Otherwise a default new label will be provided. If test=False, then the surface will be changed (in place). If test=True, then it just checks to see if the change would be successful
The convention is that the resulting subdivided polygon which has an oriented edge going from the original vertex v1 to vertex v2 will keep the label p. The other polygon will get a new label.
The change will be done in place.
- surface_point(*args, **kwargs)[source]¶
Return a point in this surface.
This is an alias for
point()
.
- tangent_bundle(ring=None)[source]¶
Return the tangent bundle
INPUT:
ring
– an optional field (defaults to the coordinate field of the surface)
- tangent_vector(lab, p, v, ring=None)[source]¶
Return a tangent vector.
INPUT:
lab
– label of a polygonp
– coordinates of a point in the polygonv
– coordinates of a vector in R^2
EXAMPLES:
sage: from flatsurf.geometry.chamanara import chamanara_surface sage: S = chamanara_surface(1/2) sage: S.tangent_vector(S.root(), (1/2,1/2), (1,1)) SimilaritySurfaceTangentVector in polygon 1 based at (1/2, -3/2) with vector (1, 1) sage: K.<sqrt2> = QuadraticField(2) sage: S.tangent_vector(S.root(), (1/2,1/2), (1,sqrt2), ring=K) SimilaritySurfaceTangentVector in polygon 1 based at (1/2, -3/2) with vector (1, sqrt2)
- triangle_flip(label, edge, in_place=False, test=None, direction=None)[source]¶
Flips the diagonal of the quadrilateral formed by two triangles glued together along the provided
edge
of the polygon withlabel
.The diagonal is flipped by turning it counterclockwise (from the point of view of the polygon with
label
.) Thelabel
is given to the triangle which has the edge that was previously the edge precedingedge
in the polygon. The diagonal does not change its index in the triangles.In other words,
+<----------+ +<----------+ |\ ^ | /^ | \ L' | | L' / | | \e' | | / | | \| | | /e | |e+1 \ | | /- | | \ | | / | | \ | | -/ | | \ | | e'/ L | | L |\ | | / | | e\ | | / e-1| v e-1 \| v/ e+1 | +---------->+ +---------->+
where
L
islabel
,L'
is the label of the opposite polygon,e
isedge
ande'
is the edge index of the diagonal inL'
.INPUT:
label
– a polygon labeledge
– an int; the index of an edge of the triangle withlabel
in_place
– a bool (default:False
) - whether this surface is modified or a modified copy is produced instead.test
– a bool (default:False
) - whether not to perform the flip but return whether the flip is possible.direction
– ignored
EXAMPLES:
sage: from flatsurf import similarity_surfaces, MutableOrientedSimilaritySurface sage: S = similarity_surfaces.right_angle_triangle(1, 1) sage: S.triangle_flip(0, 0) Traceback (most recent call last): ... ValueError: cannot flip this edge because the surrounding quadrilateral is not strictly convex sage: S.triangle_flip(0, 1) Genus 0 Rational Cone Surface built from 2 isosceles triangles sage: S.triangle_flip(0, 2) Traceback (most recent call last): ... ValueError: cannot flip this edge because the surrounding quadrilateral is not strictly convex
We can flip edges of self-glued polygons:
sage: from flatsurf import Polygon, MutableOrientedSimilaritySurface, similarity_surfaces sage: P = Polygon(edges=[(2, 0), (-1, 3), (-1, -3)]) sage: T = MutableOrientedSimilaritySurface.from_surface(similarity_surfaces.self_glued_polygon(P)) sage: T.triangle_flip(0, 1, in_place=True) Half-Translation Surface built from a triangle sage: T.set_immutable() sage: from flatsurf.geometry.categories import DilationSurfaces sage: T in DilationSurfaces() True sage: T.labels() (0,) sage: T.polygons() (Polygon(vertices=[(0, 0), (-1, -3), (2, 0)]),) sage: T.gluings() (((0, 0), (0, 0)), ((0, 1), (0, 1)), ((0, 2), (0, 2)))
- triangulate(in_place=False, label=None, relabel=None)[source]¶
Return a triangulated version of this surface. (This may be mutable or not depending on the input.)
INPUT:
in_place
– a boolean (default:False
); whether to modify this surface or return a triangulated copy instead.label
– a label orNone
(default:None
); if set, then only the polygon with that label is triangulated and all other polygons are unchanged. Otherwise, all polygons are triangulated.
EXAMPLES:
sage: from flatsurf import translation_surfaces sage: S = translation_surfaces.mcmullen_L(1, 1, 1, 1) sage: S.triangulate() Triangulation morphism: From: Translation Surface in H_2(2) built from 3 squares To: Triangulation of Translation Surface in H_2(2) built from 3 squares
A non-strictly convex example that caused trouble at some point:
sage: from flatsurf import similarity_surfaces, Polygon sage: P = Polygon(edges=[(1, 1), (-3, -1), (1, 0), (1, 0)]) sage: S = similarity_surfaces.self_glued_polygon(P) sage: S Half-Translation Surface in Q_0(0, -1^4) built from a triangle
sage: T = S.triangulate().codomain() sage: len(T.polygon((0, 0)).vertices()) 3
The surface returned is explicitly a triangulation of the original surface. Use
flatsurf.geometry.surface.MutableOrientedSimilaritySurface.from_surface()
orrelabel()
to get a primitive surface:sage: T Triangulation of Half-Translation Surface in Q_0(0, -1^4) built from a triangle sage: T.relabel() Half-Translation Surface in Q_0(0, -1^4) built from 2 triangles
sage: from flatsurf import MutableOrientedSimilaritySurface sage: T = MutableOrientedSimilaritySurface.from_surface(T) sage: T.set_immutable() sage: T Half-Translation Surface in Q_0(0, -1^4) built from 2 triangles
We can also only triangulate part of a surface, namely a single polygon:
sage: from flatsurf import translation_surfaces sage: S = translation_surfaces.cathedral(1, 1) sage: S Translation Surface in H_4(2^3) built from 2 squares, a hexagon with 4 marked vertices and an octagon sage: S.triangulate(label=1).codomain().relabel() Translation Surface in H_4(2^3) built from 2 isosceles triangles, 5 triangles, a right triangle, 2 squares and an octagon
- triangulation_mapping()[source]¶
Return a
SurfaceMapping
triangulating the surface orNone
if the surface is already triangulated.
- underlying_surface()[source]¶
Return this surface.
EXAMPLES:
sage: from flatsurf import MutableOrientedSimilaritySurface sage: S = MutableOrientedSimilaritySurface(QQ) sage: S.underlying_surface() is S doctest:warning ... UserWarning: underlying_surface() has been deprecated and will be removed in a future version of sage-flatsurf; this function has no effect anymore since there is no distinction between a surface and its underlying surface anymore True
- vector_space()[source]¶
Return the vector space in which self naturally embeds.
EXAMPLES:
sage: from flatsurf import translation_surfaces sage: S = translation_surfaces.square_torus() sage: S.vector_space() doctest:warning ... UserWarning: vector_space() has been deprecated and will be removed in a future version of sage-flatsurf; use base_ring()**2 or base_ring().fraction_field()**2 instead Vector space of dimension 2 over Rational Field sage: S.base_ring()**2 Vector space of dimension 2 over Rational Field
- class ParentMethods[source]¶
Provides methods available to all surfaces that are built from Euclidean polygons that are glued by similarities.
If you want to add functionality for such surfaces you most likely want to put it here.
- apply_matrix(m, in_place=None)[source]¶
Apply the 2×2 matrix
m
to the polygons of this surface and return a morphism from this surface to the deformed surface.INPUT:
m
– a 2×2 matrixin_place
– a boolean (default:True
); whether to modify this surface itself or return a modified copy of this surface instead.
EXAMPLES:
sage: from flatsurf import translation_surfaces sage: S = translation_surfaces.square_torus() sage: morphism = S.apply_matrix(matrix([[2, 0], [0, 1]]), in_place=False) sage: morphism.domain() Translation Surface in H_1(0) built from a square sage: morphism.codomain() Translation Surface in H_1(0) built from a rectangle sage: morphism.codomain().polygon(0) Polygon(vertices=[(0, 0), (2, 0), (2, 1), (0, 1)])
- cohomology(k=1, coefficients=None, relative=None, implementation='dual', category=None)[source]¶
Return the
k
-th simplicial cohomology group of this surface.INPUT:
k
– an integer (default:1
)coefficients
– a ring (default: the reals); consider cohomology with coefficients in this ringrelative
– a set (default: the empty set); if non-empty, then relative cohomology with respect to this set is constructed.implementation
– a string (default:"dual"
); the algorithm used to compute the cohomology groups. Currently only"dual"
is supported, i.e., the groups are computed as duals of the generic homology groups from SageMath.category
– a category; if not specified, a category for the cohomology group is chosen automatically depending oncoefficients
.
EXAMPLES:
sage: from flatsurf import dilation_surfaces sage: S = dilation_surfaces.genus_two_square(1/2, 1/3, 1/4, 1/5) sage: S.cohomology() H¹(Genus 2 Positive Dilation Surface built from 2 right triangles and a hexagon)
sage: S.cohomology(0) H⁰(Genus 2 Positive Dilation Surface built from 2 right triangles and a hexagon)
- homology(k=1, coefficients=None, relative=None, implementation='generic', category=None)[source]¶
Return the
k
-th simplicial homology group of this surface.INPUT:
k
– an integer (default:1
)coefficients
– a ring (default: the integer ring); consider the homology with coefficients in this ringrelative
– a set (default: the empty set); if non-empty, then relative homology with respect to this set is constructed.implementation
– a string (default:"generic"
); the algorithm used to compute the homology groups. Currently only"generic"
is supported, i.e., the groups are computed with the generic homology machinery from SageMath.category
– a category; if not specified, a category for the homology group is chosen automatically depending oncoefficients
.
EXAMPLES:
sage: from flatsurf import dilation_surfaces sage: S = dilation_surfaces.genus_two_square(1/2, 1/3, 1/4, 1/5) sage: S.homology() H₁(Genus 2 Positive Dilation Surface built from 2 right triangles and a hexagon) sage: S.homology(0) H₀(Genus 2 Positive Dilation Surface built from 2 right triangles and a hexagon)
- is_cone_surface()[source]¶
Return whether this surface is a cone surface, i.e., glued edges can be transformed into each other with isometries.
Note
This is a stronger requirement than the usual definition of a cone surface, see
cone_surfaces
for details.Note
This method is used to determine whether this surface is in the category of
ConeSurfaces
. Surfaces can override this method to perform specialized logic, see the note inflatsurf.geometry.categories
for performance considerations.EXAMPLES:
sage: from flatsurf import Polygon, similarity_surfaces sage: P = Polygon(vertices=[(0,0), (1,0), (1,1), (0,1)]) sage: S = similarity_surfaces.self_glued_polygon(P) sage: S.is_cone_surface() True
- is_dilation_surface(positive=False)[source]¶
Return whether this surface is a dilation surface, i.e., whether glued edges can be transformed into each other by translation followed by a dilation (multiplication by a diagonal matrix).
Note
This method is used to determine whether this surface is in the category of
DilationSurfaces
orPositive
. Surfaces can override this method to perform specialized logic, see the note incategories
for performance considerations.INPUT:
positive
– a boolean (default:False
); whether the entries of the diagonal matrix must be positive or are allowed to be negative.
EXAMPLES:
sage: from flatsurf import Polygon, similarity_surfaces sage: P = Polygon(vertices=[(0,0), (2,0), (1,4), (0,5)]) sage: S = similarity_surfaces.self_glued_polygon(P) sage: S.is_dilation_surface() True sage: S.is_dilation_surface(positive=True) False
- is_rational_surface()[source]¶
Return whether this surface is a rational surface, i.e., the rotational part of all gluings is a rational multiple of π.
Note
This method is used to determine whether this surface satisfies the
Rational
axiom. Surfaces can override this method to perform specialized logic, see the note inflatsurf.geometry.categories
for performance considerations.EXAMPLES:
sage: from flatsurf import Polygon, similarity_surfaces sage: P = Polygon(vertices=[(0,0), (1,0), (1,1), (0,1)]) sage: S = similarity_surfaces.self_glued_polygon(P) sage: S.is_rational_surface() True
- is_translation_surface(positive=True)[source]¶
Return whether this surface is a translation surface, i.e., glued edges can be transformed into each other by translations.
This method must be implemented if this surface is a dilation surface.
Note
This method is used to determine whether this surface is in the category of
HalfTranslationSurfaces
orTranslationSurfaces
. Surfaces can override this method to perform specialized logic, see the note incategories
for performance considerations.INPUT:
positive
– a boolean (default:True
); whether the transformation must be a translation or is allowed to be a half-translation, i.e., a reflection about a point (equivalently, a rotation by π).
EXAMPLES:
sage: from flatsurf import Polygon, similarity_surfaces sage: P = Polygon(vertices=[(0,0), (1,0), (1,1), (0,1)]) sage: S = similarity_surfaces.self_glued_polygon(P) sage: S.is_translation_surface() False sage: S.is_translation_surface(False) True
sage: from flatsurf import translation_surfaces sage: S = translation_surfaces.square_torus() sage: S.is_translation_surface() True
- refined_category()[source]¶
Return the smallest subcategory that this surface is in by consulting how its edges are glued.
The result of this method can be fed to
_refine_category_
to change the category of the surface (and enable functionality specific to the smaller classes of surfaces).Note
If a surface cannot implement the various
is_
methods used in the implementation of this method (i.e., if any of them throws aNotImplementedError
,) then this methodrefined_category
must be overridden to skip that check. We don’t want to actively catch aNotImplementedError
and instead encourage authors to explicitly select the category their surfaces lives in.EXAMPLES:
sage: from flatsurf import MutableOrientedSimilaritySurface sage: S = MutableOrientedSimilaritySurface(QQ) sage: from flatsurf import polygons sage: S.add_polygon(polygons.square(), label=0) 0 sage: S.refined_category() Category of connected with boundary finite type translation surfaces sage: S.glue((0, 0), (0, 2)) sage: S.glue((0, 1), (0, 3)) sage: S.refined_category() Category of connected without boundary finite type translation surfaces
- class Rational(base_category)[source]¶
The axiom satisfied by similarity surfaces where all similarities that describe how edges are glued only use rational rotations, i.e., rotations by a rational multiple of π.
Note that this differs slightly from the usual definition of “rational”. Normally, a surface would be rational if it can be described using only such similarities. Here we require that the similarities used are actually of that kind.
EXAMPLES:
sage: from flatsurf import translation_surfaces sage: S = translation_surfaces.infinite_staircase() sage: "Rational" in S.category().axioms() True
- class ParentMethods[source]¶
Provides methods available to all surfaces built from Euclidean polygons glued by similarities that have rational monodromy, i.e., monodromy gives similarities whose rotational part has finite order.
If you want to add functionality for such surfaces you most likely want to put it here.
- is_rational_surface()[source]¶
Return whether all edges of this surface are glued with similarities whose rotational part is by a rational multiple of π, i.e., return
True
since this is a rational surface.EXAMPLES:
sage: from flatsurf import translation_surfaces sage: S = translation_surfaces.infinite_staircase() sage: S.is_rational_surface() True
- super_categories()[source]¶
Return the categories that a similarity surface is also a member of, namely the surfaces formed by Euclidean polygons.
EXAMPLES:
sage: from flatsurf.geometry.categories import SimilaritySurfaces sage: SimilaritySurfaces().super_categories() [Category of euclidean polygonal surfaces]