Source code for flatsurf.geometry.origami

# ********************************************************************
#  This file is part of sage-flatsurf.
#
#        Copyright (C) 2016 W. Patrick Hooper
#                      2022 Vincent Delecroix
#                      2023 Julian Rüth
#
#  sage-flatsurf is free software: you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation, either version 2 of the License, or
#  (at your option) any later version.
#
#  sage-flatsurf is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with sage-flatsurf. If not, see <https://www.gnu.org/licenses/>.
# ********************************************************************
from sage.rings.rational_field import QQ
from flatsurf.geometry.surface import OrientedSimilaritySurface


[docs] class AbstractOrigami(OrientedSimilaritySurface): r""" Abstract base class for (connected) origamis. """ def __init__(self, domain, root=None, base_label=None, category=None): self._domain = domain if base_label is not None: import warnings warnings.warn( "base_label has been deprecated as a keyword argument for AbstractOrigami and will be removed in a future version of sage-flatsurf; use root instead" ) root = base_label base_label = None if root is None: root = domain.an_element() self._root = root from flatsurf.geometry.categories import TranslationSurfaces if category is None: category = TranslationSurfaces() category &= TranslationSurfaces().WithoutBoundary().Connected() finite = domain.is_finite() if finite: category &= category.FiniteType() else: category &= category.InfiniteType() from flatsurf.geometry.polygon import polygons self._square = polygons.square() super().__init__(QQ, category=category)
[docs] def roots(self): return (self._root,)
[docs] def labels(self): from flatsurf.geometry.surface import LabelsFromView return LabelsFromView(self, self._domain)
[docs] def is_mutable(self): return False
[docs] def up(self, label): raise NotImplementedError
[docs] def down(self, label): raise NotImplementedError
[docs] def right(self, label): raise NotImplementedError
[docs] def left(self, label): raise NotImplementedError
def _repr_(self): return "Some AbstractOrigami"
[docs] def polygon_labels(self): return self._domain
[docs] def polygon(self, lab): if lab not in self._domain: # Updated to print a possibly useful error message raise ValueError("Label " + str(lab) + " is not in the domain") return self._square
[docs] def opposite_edge(self, p, e): if p not in self._domain: raise ValueError if e == 0: return self.down(p), 2 if e == 1: return self.right(p), 3 if e == 2: return self.up(p), 0 if e == 3: return self.left(p), 1 raise ValueError
[docs] class Origami(AbstractOrigami): def __init__( self, r, u, rr=None, uu=None, domain=None, root=None, base_label=None, category=None, ): if domain is None: domain = r.parent().domain() self._r = r self._u = u if rr is None: rr = ~r else: for a in domain.some_elements(): if r(rr(a)) != a: raise ValueError(f"r o rr is not identity on {a}") if rr(r(a)) != a: raise ValueError(f"rr o r is not identity on {a}") if uu is None: uu = ~u else: for a in domain.some_elements(): if u(uu(a)) != a: raise ValueError(f"u o uu is not identity on {a}") if uu(u(a)) != a: raise ValueError(f"uu o u is not identity on {a}") self._perms = [uu, r, u, rr] # down,right,up,left AbstractOrigami.__init__( self, domain, root=root, base_label=base_label, category=category )
[docs] def opposite_edge(self, p, e): if p not in self._domain: raise ValueError( "Polygon label p=" + str(p) + " is not in domain=" + str(self._domain) ) if e < 0 or e > 3: raise ValueError("Edge value e=" + str(e) + " does not satisfy 0<=e<4.") return self._perms[e](p), (e + 2) % 4
[docs] def up(self, label): return self.opposite_edge(label, 2)[0]
[docs] def down(self, label): return self.opposite_edge(label, 0)[0]
[docs] def right(self, label): return self.opposite_edge(label, 1)[0]
[docs] def left(self, label): return self.opposite_edge(label, 3)[0]
def _repr_(self): return "Origami defined by r={} and u={}".format(self._r, self._u) def __eq__(self, other): if not isinstance(other, Origami): return False return ( self._perms == other._perms and self._domain is other._domain and self.roots() == other.roots() ) def __hash__(self): return hash((Origami, tuple(self._perms), self._domain, self.roots()))