---
tags: flatsurf
---
# Hyperbolic tessellations
```python=3
class flatsurf.geometry.HyperbolicPlaneTessellation:
r"""
A hyperbolic tessellation
It consists of
- ``base_ring`` -- ring that contains coordinates
of endpoints of supporting geodesics
- collection of vertices, edges and polygons
(with symmetry group attached to them)
- symmetry group (= discrete subgroup of SL(2,ℝ))
"""
class flatsurf.geometry.IsoDelaunayTessellation:
r"""
A dynamical HyperbolicPlaneTessellation + more data
Correspondence between SO(2) \ GL(2,ℝ) and ℍ²
``SO(2) * m * translation_surface`` versus point in ℍ²:
- `x + iy` -> `[1 x; 0 y] \in SO(2) \ GL(2,ℝ)`
- `m \in SO(2) \ GL(2,ℝ)` -> `σ(~m) * I`
where `σ([a b; c d]) = [a -b; -c d]`
Data attached to the tessellation:
- polygon -> triangulation of the translation surface (that could be set
into Delaunay form by applying some matrix + a canonical representative)
- unoriented edge -> triangul-quadrangul-ation of the base surface
- vertex -> triangul-quadrangul-and-more-ation of the base surface
(When there are symmetries, a region could be a polygon modulo
a finite group of rotations.)
"""
def __init__(self, translation_surface):
r"""
Compute all elements of the tessellation that touch ``translation_surface``
(generically a single polygon)
"""
def plot(self):
r"""
Plot what we have so far.
"""
def face(self, edge):
r"""
Return the face on the right of the oriented ``edge``.
The data structure is updated accordingly if necessary;
including discovering symmetries.
"""
# Probably cached.
# Lookup degenerated hinges for this edge (hinges = edges in the triangulation that can be flipped while still being a Delaunay triangulation) from the local data stored in this object.
# Flip these hinges.
# Determine the iso-Delaunay region (IDR).
# Determine if this region is equivalent to something we've seen before. (i.e., run some kind of FlatTriangulation::isomorphism()).
# Determine self-equivalences. (i.e., run FlatTriangulation::isomorphism() on itself.)
def iso_delaunay_region(self, surface):
r"""
Return the polygon describing the Iso-Delaunay region containing ``surface``.
"""
# Build half planes from equations given by hinges and intersect them.
def explore(self, limit=None, edge=None):
r"""
Several strategies
- combinatorial distance (in the dual graph)
- hyperbolic distance
Starts the search crossing ``edge`` if specified.
Explores a combinatorial distance of ``limit`` polygons from the ``edge`` or until it finds a fundamental domain. (Note that the latter might not terminate.)
"""
# Perform a BFS calling face()
def fundamental_domain(self):
r"""
Return the fundamental domain as a polygon with edge pairings
The result would be a fundamental domain of the group generated by the
symmetries discovered so far.
We possibly want the flat bundle (triangle flip).
"""
def surface(self, point):
r"""
Return a translation surface corresponding to this ``point``.
"""
# This should be shared with the IDR code.
# Should we follow the SageMath arithmetic subgroup naming conventions?
# Name: DiscreteSubgroup? HyperbolicPlaneIsometryGroup?
class flatsurf.geometry.DiscreteSubgroup:
r"""
A discrete finitely generated group of isometries of ℍ².
Also used for the quotient of ℍ² by that group.
"""
def __init__(self, hyperbolic_polygon, edge_pairing):
r"""
Initialize this discrete subgroup.
"""
def euler_characteristic(self):
r"""
Return the Euler characteristic of the quotient of ℍ²
by this discrete subgroup.
"""
def volume(self):
r"""
Return the volume of the quotient of ℍ²
by this discrete subgroup.
"""
def cusps(self):
r"""
Return the cusps of the quotient of ℍ²
by this discrete subgroup.
"""
def orbifold_points(self):
r"""
Return the orbifold points of the quotient of ℍ²
by this discrete subgroup.
"""
def systole(self):
r"""
Return the systole of the quotient of ℍ²
by this discrete subgroup.
"""
def fenchel_nielsen_coordinates(self):
r"""
Return Fenchel-Nielsen coordinates for the quotient of ℍ²
by this discrete subgroup.
"""
class flatsurf.geometry.SpineTessellation:
r"""
A HyperbolicPlaneTessellation + more data
"""
def __init__(self, translation_surface):
r"""
"""
# Move to a vertex canonically.
# We'll explore the spine tree from there.
def explore(self, limit=None, translation_surface=None):
r"""
Explore the spine tree up to the combinatorial ``limit`` starting from
``translation_surface`` (moving it as in :meth:`__init__`).
"""
def is_vertex(self, translation_surface):
r"""
Return whether this is a vertex.
"""
def root(self):
r"""
Return the vertex from which we started to build the spine tree.
"""
def edge(self, translation_surface):
r"""
Return the spine edge this translation surface is on.
The edge is oriented such that it points from the :meth:`root`.
"""
def face(self, translation_surface/edge):
r"""
Return the spine face this translation surface is in.
Return the face this oriented edge bounds.
"""
def shortest_periods(self, translation_surface):
r"""
Return the shortest periods for the vertex ``translation_surface``.
"""
def standard_form_surface(self, edge):
r"""
Return the standard form surface determined by the ``edge``
as a point on the underlying geodesic.
"""
def surface(self, point):
r"""
Return a translation surface corresponding to this ``point``.
"""
# This should be shared with the IDR code.
def fundamental_domain(self):
r"""
Return the fundamental domain as a polygon with edge pairings
The result would be a fundamental domain of the group generated by the
symmetries discovered so far.
"""
def plot(self):
r"""
Return a plot.
"""
def polygon(self, vertex/edge):
r"""
Return the polygon obtained as the union of the
triangles bounded by this edge and its reverse /
by the edges adjacent to this vertex.
"""
def other_endpoint(self, vertex, edge_initial):
r"""
Return the new vertex of the enriched spine that is connected to ``vertex``
in the direction of ``edge_initial``.
"""
# Compute half-planes for when hinges in ``vertex`` will flip, and for when two vectors in ``vertex`` become same length
# Compute the geodesic that begins flowing along the edge
# If a half-plane flips first, change the triangulation (and compute new halfplanes?)
# If an edge ties first, change the set of systoles
```