surface

Generic mutable and immutable surfaces

This module provides base classes and implementations of surfaces. Most surfaces in sage-flatsurf inherit from some of the classes in this module.

The most important class in this module is MutableOrientedSimilaritySurface which allows you to create a surface by gluing polygons with similarities.

EXAMPLES:

We build a translation surface by gluing two hexagons, labeled 0 and 1:

sage: from flatsurf import MutableOrientedSimilaritySurface, polygons
sage: S = MutableOrientedSimilaritySurface(QuadraticField(3))

sage: S.add_polygon(polygons.regular_ngon(6))
0
sage: S.add_polygon(polygons.regular_ngon(6))
1

sage: S.glue((0, 0), (1, 3))
sage: S.glue((0, 1), (1, 4))
sage: S.glue((0, 2), (1, 5))
sage: S.glue((0, 3), (1, 0))
sage: S.glue((0, 4), (1, 1))
sage: S.glue((0, 5), (1, 2))

sage: S
Translation Surface built from 2 regular hexagons

We signal that the construction is complete. This refines the category of the surface and makes more functionality available:

sage: S.set_immutable()
sage: S
Translation Surface in H_2(1^2) built from 2 regular hexagons
class flatsurf.geometry.surface.BaseRingChangedSurface(surface, ring, category=None)[source]

Changes the ring over which a surface is defined.

EXAMPLES:

This class is used in the implementation of flatsurf.geometry.categories.similarity_surfaces.SimilaritySurfaces.Oriented.ParentMethods.change_ring():

sage: from flatsurf import translation_surfaces
sage: T = translation_surfaces.square_torus()
sage: S = T.change_ring(AA)
__annotations__ = {}
__eq__(other)[source]

Return whether this surface is indistinguishable from other.

See _test_eq_surface() for details on this notion of equality.

EXAMPLES:

sage: from flatsurf import translation_surfaces
sage: T = translation_surfaces.square_torus()
sage: T.change_ring(AA) == T.change_ring(AA)
True
__hash__()[source]

Return a hash value for this surface that is compatible with __eq__().

EXAMPLES:

sage: from flatsurf import translation_surfaces
sage: T = translation_surfaces.square_torus()
sage: hash(T.change_ring(AA)) == hash(T.change_ring(AA))
True
__init__(surface, ring, category=None)[source]
__module__ = 'flatsurf.geometry.surface'
change_ring(ring)[source]

Return a copy of this surface whose polygons are defined over ring.

This overrides flatsurf.geometry.categories.similarity_surfaces.SimilaritySurfaces.Oriented.ParentMethods.change_ring().

EXAMPLES:

sage: from flatsurf import EuclideanPolygonsWithAngles, similarity_surfaces
sage: P = EuclideanPolygonsWithAngles(1, 3, 5).an_element()
sage: S = similarity_surfaces.billiard(P).change_ring(AA)
sage: T = S.change_ring(AA)

sage: S
Genus 0 Rational Cone Surface built from 2 triangles over Algebraic Real Field
sage: T
Genus 0 Rational Cone Surface built from 2 triangles over Algebraic Real Field

This method creates a copy of the surface even if the base ring is unchanged:

sage: S is T
False
is_mutable()[source]

Return whether this surface can be modified, i.e., return False.

This implements flatsurf.geometry.categories.topological_surfaces.TopologicalSurfaces.ParentMethods.is_mutable().

EXAMPLES:

sage: from flatsurf import translation_surfaces
sage: T = translation_surfaces.square_torus()
sage: S = T.change_ring(AA)

sage: S.is_mutable()
False
labels()[source]

Return the labels of the polygons of this surface.

EXAMPLES:

sage: from flatsurf import translation_surfaces
sage: T = translation_surfaces.square_torus()
sage: S = T.change_ring(AA)
sage: S.labels()
(0,)
opposite_edge(label, edge)[source]

Return the edge that edge of label is glued to or None if this edge is unglued.

This implements flatsurf.geometry.categories.polygonal_surfaces.PolygonalSurfaces.ParentMethods.opposite_edge().

EXAMPLES:

sage: from flatsurf import translation_surfaces
sage: T = translation_surfaces.square_torus()
sage: S = T.change_ring(AA)

sage: S.opposite_edge(0, 0)
(0, 2)
polygon(label)[source]

Return the polygon with label.

This implements flatsurf.geometry.categories.polygonal_surfaces.PolygonalSurfaces.ParentMethods.polygon().

EXAMPLES:

sage: from flatsurf import translation_surfaces
sage: T = translation_surfaces.square_torus()
sage: S = T.change_ring(AA)

sage: p = S.polygon(0)
sage: p.base_ring()
Algebraic Real Field
roots()[source]

Return a label for each connected component on this surface.

This implements flatsurf.geometry.categories.polygonal_surfaces.PolygonalSurfaces.ParentMethods.roots().

EXAMPLES:

sage: from flatsurf import translation_surfaces
sage: T = translation_surfaces.square_torus()
sage: S = T.change_ring(AA)

sage: S.roots()
(0,)
class flatsurf.geometry.surface.ComponentLabels(surface, root, finite=None)[source]

The labels of a connected component.

INPUT:

  • surface – a polygonal surface

  • root – a label of the connected component from which enumeration of the component starts.

  • finite – a boolean or None (default: None); whether this is a finite component; if None, it is not known whether the component is finite (some operations might not be supported in that case or not terminate if the component is actually infinite).

EXAMPLES:

sage: from flatsurf import translation_surfaces
sage: S = translation_surfaces.t_fractal()
sage: component = S.component(0)

sage: from flatsurf.geometry.surface import ComponentLabels
sage: isinstance(component, ComponentLabels)
True
__abstractmethods__ = frozenset({})
__annotations__ = {}
__init__(surface, root, finite=None)[source]
__iter__()[source]

Return an iterator of this component that enumerates labels starting from the root label in a breadth-first-search.

EXAMPLES:

sage: from flatsurf import translation_surfaces
sage: C = translation_surfaces.cathedral(1, 2)
sage: component = C.component(0)
sage: list(component)
[0, 1, 3, 2]
__module__ = 'flatsurf.geometry.surface'
class flatsurf.geometry.surface.Edges(surface, finite=None)[source]

The set of edges of a surface.

The set of edges contains of pairs (label, index) with the labels of the polygons and the actual edges indexed from 0 in the second component.

EXAMPLES:

sage: from flatsurf import translation_surfaces
sage: C = translation_surfaces.cathedral(1, 2)
sage: edges = C.edges()
sage: edges
((0, 0), (0, 1), (0, 2), (0, 3), (1, 0), (1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (1, 6), (1, 7), (1, 8), (1, 9), (3, 0), (3, 1), (3, 2), (3, 3), (3, 4), (3, 5), (3, 6), (3, 7), (2, 0), (2, 1), (2, 2), (2, 3))
__abstractmethods__ = frozenset({})
__annotations__ = {}
__contains__(x)[source]
__iter__()[source]
__module__ = 'flatsurf.geometry.surface'
class flatsurf.geometry.surface.Gluings(surface, finite=None)[source]

The set of gluings of the surface.

Each gluing consists of two pairs (label, index) that describe the edges being glued.

Note that each gluing (that is not a self-gluing) is reported twice.

EXAMPLES:

sage: from flatsurf import translation_surfaces
sage: S = translation_surfaces.square_torus()
sage: gluings = S.gluings()
sage: gluings
(((0, 0), (0, 2)), ((0, 1), (0, 3)), ((0, 2), (0, 0)), ((0, 3), (0, 1)))
__abstractmethods__ = frozenset({})
__annotations__ = {}
__contains__(x)[source]
__iter__()[source]
__module__ = 'flatsurf.geometry.surface'
class flatsurf.geometry.surface.LabeledCollection(surface, finite=None)[source]

Abstract base class for collection of labels as returned by labels() methods of surfaces.

This also serves as a base clas for things such as polygons() that are tied to labels.

INPUT:

  • surface – a polygonal surface, the labels are taken from that surface; subclasses might change this to only represent a subset of the labels of this surface

  • finite – a boolean or None (default: None); whether this is a finite set; if None, it is not known whether the set is finite (some operations might not be supported in that case or not terminate if the set is actually infinite).

EXAMPLES:

sage: from flatsurf import translation_surfaces
sage: S = translation_surfaces.square_torus()
sage: labels = S.labels()

sage: from flatsurf.geometry.surface import LabeledCollection
sage: isinstance(labels, LabeledCollection)
True
__abstractmethods__ = frozenset({'__iter__'})
__annotations__ = {}
__contains__(x)[source]

Return whether x is contained in this set.

EXAMPLES:

sage: from flatsurf import translation_surfaces
sage: S = translation_surfaces.square_torus()
sage: labels = S.labels()
sage: 0 in labels
True
sage: 1 in labels
False
__dict__ = mappingproxy({'__module__': 'flatsurf.geometry.surface', '__doc__': '\n    Abstract base class for collection of labels as returned by ``labels()``\n    methods of surfaces.\n\n    This also serves as a base clas for things such as ``polygons()`` that are\n    tied to labels.\n\n    INPUT:\n\n    - ``surface`` -- a polygonal surface, the labels are taken from that\n      surface; subclasses might change this to only represent a subset of the\n      labels of this surface\n\n    - ``finite`` -- a boolean or ``None`` (default: ``None``); whether this is\n      a finite set; if ``None``, it is not known whether the set is finite\n      (some operations might not be supported in that case or not terminate if\n      the set is actually infinite).\n\n    EXAMPLES::\n\n        sage: from flatsurf import translation_surfaces\n        sage: S = translation_surfaces.square_torus()\n        sage: labels = S.labels()\n\n        sage: from flatsurf.geometry.surface import LabeledCollection\n        sage: isinstance(labels, LabeledCollection)\n        True\n\n    ', '__init__': <function LabeledCollection.__init__>, '__repr__': <function LabeledCollection.__repr__>, '__len__': <function LabeledCollection.__len__>, '__contains__': <function LabeledCollection.__contains__>, '__dict__': <attribute '__dict__' of 'LabeledCollection' objects>, '__weakref__': <attribute '__weakref__' of 'LabeledCollection' objects>, '__abstractmethods__': frozenset({'__iter__'}), '_abc_impl': <_abc._abc_data object>, '__annotations__': {}})
__init__(surface, finite=None)[source]
__len__()[source]

Return the size of this set.

EXAMPLES:

sage: from flatsurf import translation_surfaces
sage: S = translation_surfaces.square_torus()
sage: len(S.labels())
1

Python does not allow __len__ to return anything but an integer, so we cannot return infinity:

sage: S = translation_surfaces.infinite_staircase()
sage: len(S.labels())
Traceback (most recent call last):
...
NotImplementedError: len() of an infinite set
__module__ = 'flatsurf.geometry.surface'
__repr__()[source]

Return a printable representation of this set.

EXAMPLES:

sage: from flatsurf import translation_surfaces
sage: S = translation_surfaces.square_torus()
sage: S.labels()
(0,)

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, …)
__weakref__

list of weak references to the object

class flatsurf.geometry.surface.LabeledSet(surface, finite=None)[source]

Abstract base class for sets of labels or related objects, such as the set of gluings of a surface.

EXAMPLES:

sage: from flatsurf import translation_surfaces
sage: S = translation_surfaces.square_torus()
sage: gluings = S.gluings()

sage: from flatsurf.geometry.surface import LabeledSet
sage: isinstance(gluings, LabeledSet)
True
__abstractmethods__ = frozenset({'__iter__'})
__annotations__ = {}
__module__ = 'flatsurf.geometry.surface'
class flatsurf.geometry.surface.LabeledView(surface, view, finite=None)[source]

A set of labels (or something resembling labels such as polygons()) backed by another collection view.

INPUT:

  • surface – a polygonal surface, the labels in view are labels of that surface

  • view – a collection that all queries are going to be redirected to. Note that labels() guarantees that iteration over labels happens in a breadth-first-search so iteration over view must follow that same order. However, subclasses can remove this requirement by overriding __iter__().

  • finite – a boolean or None (default: None); whether this is a finite set; if None, it is not known whether the set is finite (some operations might not be supported in that case or not terminate if the set is actually infinite).

EXAMPLES:

sage: from flatsurf import translation_surfaces
sage: S = translation_surfaces.t_fractal()
sage: labels = S.labels()

sage: from flatsurf.geometry.surface import LabeledView
sage: isinstance(labels, LabeledView)
True
__abstractmethods__ = frozenset({})
__annotations__ = {}
__contains__(x)[source]
__init__(surface, view, finite=None)[source]
__iter__()[source]
__len__()[source]
__module__ = 'flatsurf.geometry.surface'
min()[source]

Return a minimal item in this set.

If the items can be compared, this is just the actual min of the items.

Otherwise, we take the one with minimal repr.

Note

If the items cannot be compared, and there are clashes in the repr, this method will fail.

Also, if comparison of items is not consistent, then this can produce somewhat random output.

Finally, note with this approach the min of a set is not the always the min of the mins of a each partition of that set.

EXAMPLES:

sage: from flatsurf import translation_surfaces
sage: S = translation_surfaces.t_fractal()
sage: S.labels().min()
Traceback (most recent call last):
...
NotImplementedError: cannot determine minimum of an infinite set
sage: from flatsurf import translation_surfaces
sage: C = translation_surfaces.cathedral(1,2)
sage: C.labels().min()
0
sage: labels = list(C.labels())[:3]
sage: from flatsurf.geometry.surface import LabeledView
sage: LabeledView(C, labels).min()
0
class flatsurf.geometry.surface.Labels(surface, finite=None)[source]

The labels of a surface.

Note

This is a generic implementation that represents the set of labels of a surface in a breadth-first iteration starting from the root labels of the connected components.

This implementation makes no assumption on the surface and can be very slow to answer, e.g., containment or compute the number of labels in the surface (because it needs to iterate over the entire surface).

When possible, a faster implementation should be used such as LabelsFromView.

EXAMPLES:

sage: from flatsurf import polygons, similarity_surfaces
sage: T = polygons.triangle(1, 2, 5)
sage: S = similarity_surfaces.billiard(T)
sage: S = S.minimal_cover("translation")

sage: labels = S.labels()
sage: labels
((0, 1, 0), (1, 1, 0), (1, 0, -1), (1, 1/2*c0, 1/2*c0), (0, 1/2*c0, -1/2*c0), (0, 0, 1), (0, -1/2*c0, -1/2*c0), (0, 0, -1), (0, -1/2*c0, 1/2*c0), (0, 1/2*c0, 1/2*c0),
 (1, 1/2*c0, -1/2*c0), (1, -1/2*c0, -1/2*c0), (1, 0, 1), (1, -1/2*c0, 1/2*c0), (1, -1, 0), (0, -1, 0))
__abstractmethods__ = frozenset({})
__annotations__ = {}
__getitem__(key)[source]

Return the labels at position key.

EXAMPLES:

sage: from flatsurf import translation_surfaces
sage: C = translation_surfaces.cathedral(1, 2)
sage: labels = C.labels()
sage: labels[0]
0
sage: labels[-1]
2
sage: labels[::-1]
[2, 3, 1, 0]
__iter__()[source]
__module__ = 'flatsurf.geometry.surface'
class flatsurf.geometry.surface.LabelsFromView(surface, view, finite=None)[source]

The labels of a surface backed by another set that can quickly compute the length of the labels and decide containment in the set.

Note

Iteration of the view collection does not have to be in breadth-first search order in the surface since this class is picking up the generic Labels.__iter__().

EXAMPLES:

sage: from flatsurf import translation_surfaces
sage: C = translation_surfaces.cathedral(1, 2)
sage: labels = C.labels()

sage: from flatsurf.geometry.surface import LabelsFromView
sage: type(labels) == LabelsFromView
True
__abstractmethods__ = frozenset({})
__annotations__ = {}
__module__ = 'flatsurf.geometry.surface'
class flatsurf.geometry.surface.MutableOrientedSimilaritySurface(base, category=None)[source]

A surface built from Euclidean polyogns glued by orientation preserving similarities.

This is the main tool to create new surfaces of finite type in sage-flatsurf.

EXAMPLES:

sage: from flatsurf import MutableOrientedSimilaritySurface
sage: S = MutableOrientedSimilaritySurface(QQ)

sage: from flatsurf import polygons
sage: S.add_polygon(polygons.square())
0

sage: S.glue((0, 0), (0, 2))
sage: S.glue((0, 1), (0, 3))

sage: S.set_immutable()

sage: S
Translation Surface in H_1(0) built from a square
__annotations__ = {}
__eq__(other)[source]

Return whether this surface is indistinguishable from other.

See _test_eq_surface() for details on this notion of equality.

EXAMPLES:

sage: from flatsurf import MutableOrientedSimilaritySurface

sage: S = MutableOrientedSimilaritySurface(QQ)
sage: T = MutableOrientedSimilaritySurface(AA)

sage: S == T
False

sage: S == S
True
__hash__()[source]

Return a hash value for this surface that is compatible with __eq__().

EXAMPLES:

sage: from flatsurf import MutableOrientedSimilaritySurface

sage: S = MutableOrientedSimilaritySurface(QQ)
sage: T = MutableOrientedSimilaritySurface(QQ)

sage: hash(S) == hash(T)
Traceback (most recent call last):
...
TypeError: cannot hash a mutable surface

sage: S.set_immutable()
sage: T.set_immutable()
sage: hash(S) == hash(T)
True
__init__(base, category=None)[source]
__module__ = 'flatsurf.geometry.surface'
add_polygon(polygon, label)[source]
change_edge_gluing(label0, edge0, label1, edge1)[source]
change_polygon(label, polygon, gluing_list=None)[source]
change_polygon_gluings(label, gluings)[source]
cmp(s2, limit=None)[source]

Compare two surfaces. This is an ordering returning -1, 0, or 1.

The surfaces will be considered equal if and only if there is a translation automorphism respecting the polygons and the root labels.

If the two surfaces are infinite, we just examine the first limit polygons.

delaunay_single_flip()[source]

Perform a single in place flip of a triangulated mutable surface in-place.

classmethod from_surface(surface, labels=None, category=None)[source]

Return a mutable copy of surface.

INPUT:

  • labels – a set of labels or None (default: None); if None, the entire surface is copied, otherwise only these labels are copied and glued like in the original surface.

EXAMPLES:

sage: from flatsurf import translation_surfaces, MutableOrientedSimilaritySurface, polygons

sage: T = translation_surfaces.square_torus()

We build a surface that is made from two tori:

sage: S = MutableOrientedSimilaritySurface.from_surface(T) sage: S.add_polygon(polygons.square()) 1 sage: S.glue((1, 0), (1, 2)) sage: S.glue((1, 1), (1, 3))

sage: S.set_immutable()

sage: S Disconnected Surface built from 2 squares

We can build partial copies of an infinite surface:

sage: S = translation_surfaces.infinite_staircase()
sage: T = MutableOrientedSimilaritySurface.from_surface(S)
Traceback (most recent call last):
...
TypeError: cannot create a full copy of an infinite surface

sage: T = MutableOrientedSimilaritySurface.from_surface(S, labels=S.labels()[:10])
sage: T.components()
((0, 1, -1, 2, -2, 3, -3, 4, -4, 5),)

sage: T = MutableOrientedSimilaritySurface.from_surface(S, labels=S.labels()[:30:3])
sage: T.components()
((0,), (-12,), (-9,), (-6,), (-3,), (2,), (5,), (8,), (11,), (14,))
glue(x, y)[source]

Glue x and y with an (orientation preserving) similarity.

INPUT:

  • x – a pair consisting of a polygon label and an edge index for that polygon

  • y – a pair consisting of a polygon label and an edge index for that polygon

EXAMPLES:

sage: from flatsurf import MutableOrientedSimilaritySurface, polygons

sage: S = MutableOrientedSimilaritySurface(QQ)
sage: S.add_polygon(polygons.square())
0

Glue two opposite sides of the square to each other:

sage: S.glue((0, 1), (0, 3))

Glue the other sides of the square to themselves:

sage: S.glue((0, 0), (0, 0))
sage: S.glue((0, 2), (0, 2))

Note that existing gluings are removed when gluing already glued sides:

sage: S.glue((0, 0), (0, 2))
sage: S.set_immutable()

sage: S
Translation Surface in H_1(0) built from a square
join_polygons(p1, e1, test=False, in_place=False)[source]

Overrides flatsurf.geometry.categories.similarity_surfaces.SimilaritySurfaces.Oriented.ParentMethods.join_polygons() to allow joining in-place.

opposite_edge(label, edge=None)[source]

Return the edge that edge of label is glued to or None if this edge is unglued.

This implements flatsurf.geometry.categories.polygonal_surfaces.PolygonalSurfaces.ParentMethods.opposite_edge().

INPUT:

  • label – one of the labels included in labels()

  • edge – a non-negative integer to specify an edge (the edges of a polygon are numbered starting from zero).

EXAMPLES:

sage: from flatsurf import Polygon, MutableOrientedSimilaritySurface
sage: S = MutableOrientedSimilaritySurface(QQ)
sage: S.add_polygon(Polygon(vertices=[(0, 0), (1, 0), (1, 1), (0, 1)]))
0

sage: S.glue((0, 0), (0, 1))
sage: S.glue((0, 2), (0, 2))

sage: S.opposite_edge(0, 0)
(0, 1)
sage: S.opposite_edge(0, 1)
(0, 0)
sage: S.opposite_edge(0, 2)
(0, 2)
sage: S.opposite_edge(0, 3)

sage: S.opposite_edge((0, 0))
doctest:warning
...
UserWarning: calling opposite_edge() with a single argument has been deprecated and will be removed in a future version of sage-flatsurf; use opposite_edge(label, edge) instead
(0, 1)
refine_polygon(label, surface, gluings)[source]
relabel(relabeling=None, in_place=False)[source]

Overrides flatsurf.geometry.categories.similarity_surfaces.SimilaritySurfaces.Oriented.ParentMethods.relabel() to allow relabeling in-place.

remove_polygon(label)[source]
replace_polygon(label, polygon)[source]

Replace the polygon label with polygon while keeping its gluings intact.

INPUT:

  • label – an element of labels()

  • polygon – a Euclidean polygon

EXAMPLES:

sage: from flatsurf import Polygon, MutableOrientedSimilaritySurface
sage: S = MutableOrientedSimilaritySurface(QQ)
sage: S.add_polygon(Polygon(vertices=[(0, 0), (1, 0), (1, 1), (0, 1)]))
0
sage: S.glue((0, 0), (0, 2))
sage: S.glue((0, 1), (0, 3))

sage: S.replace_polygon(0, Polygon(vertices=[(0, 0), (2, 0), (2, 2), (0, 2)]))

The replacement of a polygon must have the same number of sides:

sage: S.replace_polygon(0, Polygon(vertices=[(0, 0), (2, 0), (2, 2)]))
Traceback (most recent call last):
...
ValueError: polygon must be a quadrilateral

To replace the polygon without keeping its glueings, remove the polygon first and then add a new one:

sage: S.remove_polygon(0)
sage: S.add_polygon(Polygon(vertices=[(0, 0), (2, 0), (2, 2)]), label=0)
0
reposition_polygons(in_place=False, relabel=None)[source]

Overrides flatsurf.geometry.categories.similarity_surfaces.SimilaritySurfaces.FiniteType.Oriented.ParentMethods.reposition_polygons() to allow normalizing in-place.

set_edge_pairing(label0, edge0, label1, edge1)[source]
set_vertex_zero(label, v, in_place=False)[source]

Overrides flatsurf.geometry.categories.similarity_surfaces.SimilaritySurfaces.Oriented.ParentMethods.set_vertex_zero() to make it possible to set the zero vertex in-place.

subdivide_polygon(p, v1, v2, test=False, new_label=None)[source]

Overrides flatsurf.geometry.categories.similarity_surfaces.SimilaritySurfaces.Oriented.ParentMethods.subdivide_polygon() to allow subdividing in-place.

triangulate(in_place=False, label=None, relabel=None)[source]

Overrides flatsurf.geometry.categories.similarity_surfaces.SimilaritySurfaces.Oriented.ParentMethods.triangulate() to allow triangulating in-place.

unglue(label, edge)[source]

Unglue the side edge of the polygon label if it is glued.

EXAMPLES:

sage: from flatsurf import MutableOrientedSimilaritySurface, translation_surfaces

sage: T = translation_surfaces.square_torus()

sage: S = MutableOrientedSimilaritySurface.from_surface(T)

sage: S.unglue(0, 0)

sage: S.gluings()
(((0, 1), (0, 3)), ((0, 3), (0, 1)))

sage: S.set_immutable()
sage: S
Translation Surface with boundary built from a square
class flatsurf.geometry.surface.MutableOrientedSimilaritySurface_base(base, category=None)[source]

Base class for surface built from Euclidean polyogns glued by orientation preserving similarities.

This provides the features of MutableOrientedSimilaritySurface without making a choice about how data is stored internally; it is a generic base class for other implementations of mutable surfaces.

EXAMPLES:

sage: from flatsurf import MutableOrientedSimilaritySurface
sage: S = MutableOrientedSimilaritySurface(QQ)

sage: from flatsurf.geometry.surface import MutableOrientedSimilaritySurface_base
sage: isinstance(S, MutableOrientedSimilaritySurface_base)
True
__annotations__ = {}
__module__ = 'flatsurf.geometry.surface'
standardize_polygons(in_place=False)[source]

Replace each polygon 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.

This is done to the current surface if in_place=True. A mutable copy is created and returned if in_place=False (as default).

This overrides flatsurf.geometry.categories.similarity_surfaces.SimilaritySurfaces.FiniteType.Oriented.ParentMethods.standardize_polygons() to provide in-place standardizing of surfaces.

EXAMPLES:

sage: from flatsurf import MutableOrientedSimilaritySurface, Polygon
sage: p = Polygon(vertices = ([(1,1),(2,1),(2,2),(1,2)]))
sage: s = MutableOrientedSimilaritySurface(QQ)
sage: s.add_polygon(p)
0
sage: s.glue((0, 0), (0, 2))
sage: s.glue((0, 1), (0, 3))
sage: s.set_root(0)
sage: s.set_immutable()

sage: s.standardize_polygons().polygon(0)
Polygon(vertices=[(0, 0), (1, 0), (1, 1), (0, 1)])
triangle_flip(label, edge, in_place=False, test=None, direction=None)[source]

Overrides categories.similarity_surfaces.SimilaritySurfaces.Oriented.ParentMethods.triangle_flip() to provide in-place flipping of triangles.

See that method for details.

class flatsurf.geometry.surface.MutablePolygonalSurface(base, category=None)[source]

A base class for mutable surfaces that are built by gluing polygons.

EXAMPLES:

sage: from flatsurf import MutableOrientedSimilaritySurface
sage: S = MutableOrientedSimilaritySurface(QQ)

sage: from flatsurf.geometry.surface import MutablePolygonalSurface
sage: isinstance(S, MutablePolygonalSurface)
True
__annotations__ = {}
__eq__(other)[source]

Return whether this surface is indistinguishable from other.

See _test_eq_surface() for details on this notion of equality.

EXAMPLES:

sage: from flatsurf import MutableOrientedSimilaritySurface
sage: S = MutableOrientedSimilaritySurface(QQ)
sage: T = MutableOrientedSimilaritySurface(QQ)

sage: S == T
True

sage: from flatsurf import polygons
sage: S.add_polygon(polygons.square())
0

sage: S == T
False
__hash__()[source]

Return a hash value for this surface that is compatible with __eq__().

EXAMPLES:

sage: from flatsurf import MutableOrientedSimilaritySurface
sage: S = MutableOrientedSimilaritySurface(QQ)
sage: T = MutableOrientedSimilaritySurface(QQ)
sage: hash(S) == hash(T)
Traceback (most recent call last):
...
TypeError: cannot hash a mutable surface

sage: S.set_immutable()
sage: T.set_immutable()
sage: hash(S) == hash(T)
True
__init__(base, category=None)[source]
__module__ = 'flatsurf.geometry.surface'
add_polygon(polygon, label)[source]

Add an unglued polygon to this surface and return its label.

INPUT:

  • polygon – a simple Euclidean polygon

  • label – a hashable identifier or None (default: None); if None an integer identifier is automatically selected

EXAMPLES:

sage: from flatsurf import MutableOrientedSimilaritySurface
sage: S = MutableOrientedSimilaritySurface(QQ)

sage: from flatsurf import polygons
sage: S.add_polygon(polygons.square())
0

sage: S.add_polygon(polygons.square(), label=0)
Traceback (most recent call last):
...
ValueError: polygon label already present in this surface

sage: S.add_polygon(polygons.square(), label='X')
'X'
add_polygons(polygons)[source]

Add several polygons with automatically assigned labels at once.

EXAMPLES:

sage: from flatsurf import MutableOrientedSimilaritySurface
sage: S = MutableOrientedSimilaritySurface(QQ)

sage: from flatsurf import polygons
sage: S.add_polygons([polygons.square(), polygons.square()])
doctest:warning
...
UserWarning: add_polygons() has been deprecated and will be removed in a future version of sage-flatsurf; use labels = [add_polygon(p) for p in polygons] instead
[0, 1]
change_base_label(label)[source]

This is a deprecated alias for set_root().

EXAMPLES:

sage: from flatsurf import MutableOrientedSimilaritySurface
sage: S = MutableOrientedSimilaritySurface(QQ)

sage: from flatsurf import polygons
sage: S.add_polygon(polygons.square())
0

sage: S.change_base_label(0)
doctest:warning
...
UserWarning: change_base_label() has been deprecated and will be removed in a future version of sage-flatsurf; use set_root() instead
components()[source]

Return the connected components as the sequence of their respective polygon labels.

EXAMPLES:

sage: from flatsurf import MutableOrientedSimilaritySurface
sage: S = MutableOrientedSimilaritySurface(QQ)

sage: S.components()
()

sage: from flatsurf import polygons
sage: S.add_polygon(polygons.square())
0

sage: S.components()
((0,),)

sage: from flatsurf import polygons
sage: S.add_polygon(polygons.square())
1

sage: S.components()
((0,), (1,))

sage: S.glue((0, 0), (1, 0))
sage: S.components()
((0, 1),)
is_mutable()[source]

Return whether this surface can be modified.

This implements flatsurf.geometry.categories.topological_surfaces.TopologicalSurfaces.ParentMethods.is_mutable().

EXAMPLES:

sage: from flatsurf import MutableOrientedSimilaritySurface
sage: S = MutableOrientedSimilaritySurface(QQ)

sage: S.is_mutable()
True

sage: S.set_immutable()
sage: S.is_mutable()
False
labels()[source]

Return the polygon labels in this surface.

This replaces the generic flatsurf.geometry.categories.polygonal_surfaces.PolygonalSurfaces.ParentMethods.labels() method with a more efficient implementation.

EXAMPLES:

sage: from flatsurf import MutableOrientedSimilaritySurface
sage: S = MutableOrientedSimilaritySurface(QQ)

sage: S.labels()
()

sage: from flatsurf import polygons
sage: S.add_polygon(polygons.square())
0

sage: S.labels()
(0,)

See also

polygon() to translate polygon labels to the corresponding polygons

polygons() for the corresponding sequence of polygons

polygon(label)[source]

Return the polygon with label label in this surface.

This implements flatsurf.geometry.categories.polygonal_surfaces.PolygonalSurfaces.ParentMethods.polygon().

EXAMPLES:

sage: from flatsurf import MutableOrientedSimilaritySurface
sage: S = MutableOrientedSimilaritySurface(QQ)

sage: S.polygon(0)
Traceback (most recent call last):
...
KeyError: 0

sage: from flatsurf import polygons
sage: S.add_polygon(polygons.square())
0

sage: S.polygon(0)
Polygon(vertices=[(0, 0), (1, 0), (1, 1), (0, 1)])
polygons()[source]

Return the polygons that make up this surface.

The order the polygons are returned is guaranteed to be compatible with the order of the labels in labels().

This replaces the generic flatsurf.geometry.categories.polygonal_surfaces.PolygonalSurfaces.ParentMethods.polygons() with a more efficient implementation.

EXAMPLES:

sage: from flatsurf import MutableOrientedSimilaritySurface
sage: S = MutableOrientedSimilaritySurface(QQ)

sage: S.polygons()
()

sage: from flatsurf import polygons
sage: S.add_polygon(polygons.square())
0
sage: S.add_polygon(polygons.square())
1
sage: S.add_polygon(polygons.square())
2

sage: S.polygons()
(Polygon(vertices=[(0, 0), (1, 0), (1, 1), (0, 1)]), Polygon(vertices=[(0, 0), (1, 0), (1, 1), (0, 1)]), Polygon(vertices=[(0, 0), (1, 0), (1, 1), (0, 1)]))

See also

polygon() to get a single polygon

remove_polygon(label)[source]

Remove the polygon with label label from this surface (and all data associated to it).

EXAMPLES:

sage: from flatsurf import MutableOrientedSimilaritySurface
sage: S = MutableOrientedSimilaritySurface(QQ)

sage: from flatsurf import polygons
sage: S.add_polygon(polygons.square())
0

sage: S.remove_polygon(0)

sage: S.add_polygon(polygons.square())
0
roots()[source]

Return a label for each connected component on this surface.

This implements flatsurf.geometry.categories.polygonal_surfaces.PolygonalSurfaces.ParentMethods.roots().

EXAMPLES:

sage: from flatsurf import MutableOrientedSimilaritySurface
sage: S = MutableOrientedSimilaritySurface(QQ)

sage: S.roots()
()

sage: from flatsurf import polygons
sage: S.add_polygon(polygons.square())
0

sage: S.roots()
(0,)

sage: from flatsurf import polygons
sage: S.add_polygon(polygons.square())
1

sage: S.roots()
(0, 1)

sage: S.glue((0, 0), (1, 0))
sage: S.roots()
(0,)

See also

components()

set_default_graphical_surface(graphical_surface)[source]

EXAMPLES:

This has been disabled because it tends to break caching:

sage: from flatsurf import MutableOrientedSimilaritySurface
sage: S = MutableOrientedSimilaritySurface(QQ)
sage: S.set_default_graphical_surface(S.graphical_surface())
Traceback (most recent call last):
...
NotImplementedError: set_default_graphical_surface() has been removed from this version of sage-flatsurf. If you want to change the default plotting of a surface, create a subclass and override graphical_surface() instead
set_immutable()[source]

Make this surface immutable.

Any mutation attempts from now on will be an error.

EXAMPLES:

sage: from flatsurf import MutableOrientedSimilaritySurface
sage: S = MutableOrientedSimilaritySurface(QQ)

sage: from flatsurf import polygons
sage: S.add_polygon(polygons.square())
0

sage: S.glue((0, 0), (0, 2))
sage: S.glue((0, 1), (0, 3))

Note that declaring a surface immutable refines its category and thereby unlocks more methods that are available to such a surface:

sage: S.category()
Category of finite type oriented similarity surfaces
sage: old_methods = set(method for method in dir(S) if not method.startswith('_'))

sage: S.set_immutable()
sage: S.category()
Category of connected without boundary finite type translation surfaces
sage: new_methods = set(method for method in dir(S) if not method.startswith('_'))
sage: new_methods - old_methods
{'affine_automorphism_group',
 'area',
 'canonicalize',
 'canonicalize_mapping',
 'erase_marked_points',
 'holonomy_field',
 'is_veering_triangulated',
 'j_invariant',
 'l_infinity_delaunay_triangulation',
 'minimal_translation_cover',
 'normalized_coordinates',
 'pyflatsurf',
 'rel_deformation',
 'stratum',
 'veech_group',
 'veering_triangulation'}

An immutable surface cannot be mutated anymore:

sage: S.remove_polygon(0)
Traceback (most recent call last):
...
Exception: cannot modify an immutable surface

However, the category of an immutable might be further refined as (expensive to determine) features of the surface are deduced.

set_root(root)[source]

Set root as the label at which exploration of a connected component starts.

This method can be called for connected and disconnected surfaces. In either case, it establishes root as the new label from which enumeration of the connected component containing it starts. If another label for this component had been set earlier, it is replaced.

Note

After roots have been declared explicitly, gluing operations come at an additional cost since the root labels have to be updated sometimes. It is therefore good practice to declare the root labels after all the gluings have been established when creating a surface.

INPUT:

  • root – a polygon label in this surface

EXAMPLES:

sage: from flatsurf import MutableOrientedSimilaritySurface
sage: S = MutableOrientedSimilaritySurface(QQ)

sage: S.set_root(0)
Traceback (most recent call last):
...
ValueError: root must be a label in the surface

sage: from flatsurf import polygons
sage: S.add_polygon(polygons.square())
0
sage: S.add_polygon(polygons.square())
1

sage: S.set_root(0)
sage: S.set_root(1)

sage: S.roots()
(0, 1)

Note that the roots get updated automatically when merging components:

sage: S.glue((0, 0), (1, 0))
sage: S.roots()
(0,)

The purpose of changing the root label is to modify the order of exploration, e.g., in labels():

sage: S.labels()
(0, 1)

sage: S.set_root(1)
sage: S.labels()
(1, 0)

See also

set_roots() to replace all the root labels

set_roots(roots)[source]

Declare that the labels in roots are the labels from which their corresponding connected components should be enumerated.

There must be at most one label for each connected component in roots. Components that have no label set explicitly will have their label chosen automatically.

INPUT:

  • roots – a sequence of polygon labels in this surface

EXAMPLES:

sage: from flatsurf import MutableOrientedSimilaritySurface
sage: S = MutableOrientedSimilaritySurface(QQ)

sage: from flatsurf import polygons
sage: S.add_polygon(polygons.square())
0
sage: S.add_polygon(polygons.square())
1
sage: S.add_polygon(polygons.square())
2

sage: S.glue((0, 0), (1, 0))

sage: S.set_roots([1])
sage: S.roots()
(1, 2)

Setting the roots of connected components affects their enumeration in labels():

sage: S.labels()
(1, 0, 2)

sage: S.set_roots([0, 2])
sage: S.labels()
(0, 1, 2)

There must be at most one root per component:

sage: S.set_roots([0, 1, 2])
Traceback (most recent call last):
...
ValueError: there must be at most one root label for each connected component
class flatsurf.geometry.surface.OrientedSimilaritySurface(base, category=None)[source]

Base class for surfaces built from Euclidean polygons that are glued with orientation preserving similarities.

EXAMPLES:

sage: from flatsurf import MutableOrientedSimilaritySurface
sage: S = MutableOrientedSimilaritySurface(QQ)

sage: from flatsurf.geometry.surface import OrientedSimilaritySurface
sage: isinstance(S, OrientedSimilaritySurface)
True
Element

alias of SurfacePoint

__annotations__ = {}
__init__(base, category=None)[source]
__module__ = 'flatsurf.geometry.surface'
class flatsurf.geometry.surface.Polygons(surface, finite=None)[source]

The collection of polygons of a surface.

The polygons are returned in the same order as labels of the surface are returned by Labels.

EXAMPLES:

sage: from flatsurf import translation_surfaces
sage: C = translation_surfaces.cathedral(1, 2)
sage: polygons = C.polygons()

sage: from flatsurf.geometry.surface import Polygons
sage: isinstance(polygons, Polygons)
True
__abstractmethods__ = frozenset({})
__annotations__ = {}
__iter__()[source]

Iterate over the polygons in the same order as labels() does.

EXAMPLES:

sage: from flatsurf import translation_surfaces
sage: C = translation_surfaces.cathedral(1, 2)
sage: labels = C.labels()
sage: polygons = C.polygons()

sage: for entry in zip(labels, polygons):
....:     print(entry)
(0, Polygon(vertices=[(0, 0), (1, 0), (1, 1), (0, 1)]))
(1, Polygon(vertices=[(1, 0), (1, -2), (3/2, -5/2), (2, -2), (2, 0), (2, 1), (2, 3), (3/2, 7/2), (1, 3), (1, 1)]))
(3, Polygon(vertices=[(3, 0), (7/2, -1/2), (11/2, -1/2), (6, 0), (6, 1), (11/2, 3/2), (7/2, 3/2), (3, 1)]))
(2, Polygon(vertices=[(2, 0), (3, 0), (3, 1), (2, 1)]))
__len__()[source]

Return the number of polygons in this surface.

EXAMPLES:

sage: from flatsurf import translation_surfaces
sage: C = translation_surfaces.cathedral(1, 2)
sage: polygons = C.polygons()
sage: len(polygons)
4
__module__ = 'flatsurf.geometry.surface'
class flatsurf.geometry.surface.Polygons_MutableOrientedSimilaritySurface(surface)[source]

The collection of polygons of a MutableOrientedSimilaritySurface.

This is a faster version of Polygons.

EXAMPLES:

sage: from flatsurf import translation_surfaces
sage: C = translation_surfaces.cathedral(1, 2)
sage: polygons = C.polygons()

sage: from flatsurf.geometry.surface import Polygons_MutableOrientedSimilaritySurface
sage: isinstance(polygons, Polygons_MutableOrientedSimilaritySurface)
True
__abstractmethods__ = frozenset({})
__annotations__ = {}
__init__(surface)[source]
__len__()[source]
__module__ = 'flatsurf.geometry.surface'
class flatsurf.geometry.surface.RootedComponents_MutablePolygonalSurface(surface)[source]

Connected components of a MutablePolygonalSurface.

The components are represented as a mapping that maps the root labels to the labels of the corresponding component.

This is a helper method for MutablePolygonalSurface.components() and MutablePolygonalSurface.roots().

EXAMPLES:

sage: from flatsurf import MutableOrientedSimilaritySurface
sage: S = MutableOrientedSimilaritySurface(QQ)

sage: from flatsurf import polygons
sage: S.add_polygon(polygons.square())
0
sage: S.add_polygon(polygons.square())
1

sage: from flatsurf.geometry.surface import RootedComponents_MutablePolygonalSurface
sage: components = RootedComponents_MutablePolygonalSurface(S)
__abstractmethods__ = frozenset({})
__annotations__ = {}
__dict__ = mappingproxy({'__module__': 'flatsurf.geometry.surface', '__doc__': '\n    Connected components of a :class:`MutablePolygonalSurface`.\n\n    The components are represented as a mapping that maps the root labels to\n    the labels of the corresponding component.\n\n    This is a helper method for :meth:`MutablePolygonalSurface.components` and\n    :meth:`MutablePolygonalSurface.roots`.\n\n    EXAMPLES::\n\n        sage: from flatsurf import MutableOrientedSimilaritySurface\n        sage: S = MutableOrientedSimilaritySurface(QQ)\n\n        sage: from flatsurf import polygons\n        sage: S.add_polygon(polygons.square())\n        0\n        sage: S.add_polygon(polygons.square())\n        1\n\n        sage: from flatsurf.geometry.surface import RootedComponents_MutablePolygonalSurface\n        sage: components = RootedComponents_MutablePolygonalSurface(S)\n\n    ', '__init__': <function RootedComponents_MutablePolygonalSurface.__init__>, '__getitem__': <function RootedComponents_MutablePolygonalSurface.__getitem__>, '__iter__': <function RootedComponents_MutablePolygonalSurface.__iter__>, '__len__': <function RootedComponents_MutablePolygonalSurface.__len__>, '__dict__': <attribute '__dict__' of 'RootedComponents_MutablePolygonalSurface' objects>, '__weakref__': <attribute '__weakref__' of 'RootedComponents_MutablePolygonalSurface' objects>, '__abstractmethods__': frozenset(), '_abc_impl': <_abc._abc_data object>, '__annotations__': {}})
__getitem__(root)[source]

Return the labels of the connected component rooted at the label root.

EXAMPLES:

sage: from flatsurf import MutableOrientedSimilaritySurface
sage: S = MutableOrientedSimilaritySurface(QQ)

sage: from flatsurf import polygons
sage: S.add_polygon(polygons.square())
0
sage: S.add_polygon(polygons.square())
1
sage: S.glue((0, 0), (1, 0))

sage: from flatsurf.geometry.surface import RootedComponents_MutablePolygonalSurface
sage: components = RootedComponents_MutablePolygonalSurface(S)
sage: components[0]
(0, 1)
__init__(surface)[source]
__iter__()[source]

Iterate over the keys of this mapping, i.e., the root labels of the connected components.

EXAMPLES:

sage: from flatsurf import MutableOrientedSimilaritySurface
sage: S = MutableOrientedSimilaritySurface(QQ)

sage: from flatsurf import polygons
sage: S.add_polygon(polygons.square())
0
sage: S.add_polygon(polygons.square())
1
sage: S.glue((0, 0), (1, 0))

sage: from flatsurf.geometry.surface import RootedComponents_MutablePolygonalSurface
sage: components = RootedComponents_MutablePolygonalSurface(S)
sage: list(components)
[0]
__len__()[source]

Return the number of connected components of this surface.

EXAMPLES:

sage: from flatsurf import MutableOrientedSimilaritySurface
sage: S = MutableOrientedSimilaritySurface(QQ)

sage: from flatsurf import polygons
sage: S.add_polygon(polygons.square())
0
sage: S.add_polygon(polygons.square())
1
sage: S.glue((0, 0), (1, 0))

sage: from flatsurf.geometry.surface import RootedComponents_MutablePolygonalSurface
sage: components = RootedComponents_MutablePolygonalSurface(S)
sage: len(components)
1
__module__ = 'flatsurf.geometry.surface'
__weakref__

list of weak references to the object

class flatsurf.geometry.surface.Surface_base[source]

A base class for all surfaces in sage-flatsurf.

This class patches bits of the category framework in SageMath that assume that all parent structures are immutable.

EXAMPLES:

sage: from flatsurf import translation_surfaces
sage: S = translation_surfaces.square_torus()

sage: from flatsurf.geometry.surface import Surface_base
sage: isinstance(S, Surface_base)
True
__annotations__ = {}
__dict__ = mappingproxy({'__module__': 'flatsurf.geometry.surface', '__doc__': '\n    A base class for all surfaces in sage-flatsurf.\n\n    This class patches bits of the category framework in SageMath that assume\n    that all parent structures are immutable.\n\n    EXAMPLES::\n\n        sage: from flatsurf import translation_surfaces\n        sage: S = translation_surfaces.square_torus()\n\n        sage: from flatsurf.geometry.surface import Surface_base\n        sage: isinstance(S, Surface_base)\n        True\n\n    ', '_refine_category_': <function Surface_base._refine_category_>, 'an_element': <function Surface_base.an_element>, '__dict__': <attribute '__dict__' of 'Surface_base' objects>, '__annotations__': {}})
__module__ = 'flatsurf.geometry.surface'
an_element()[source]

Return a point of this surface.

EXAMPLES:

sage: from flatsurf import translation_surfaces
sage: S = translation_surfaces.square_torus()
sage: S.an_element()
Point (1/2, 1/2) of polygon 0