--- 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