Beispiel #1
0
    def ward(n):
        r"""
        Return the surface formed by gluing a regular 2n-gon to two regular n-gons.
        These surfaces have Veech's lattice property due to work of Ward.
        
        EXAMPLES::

            sage: from flatsurf import *
            sage: s=translation_surfaces.ward(3)
            sage: TestSuite(s).run()
            sage: s=translation_surfaces.ward(7)
            sage: TestSuite(s).run()
        """
        assert n>=3
        from .polygon import polygons
        from .surface import Surface_list
        from .translation_surface import TranslationSurface
        o = ZZ_2*polygons.regular_ngon(2*n)
        p1 = polygons(*[o.edge((2*i+n)%(2*n)) for i in xrange(n)])
        p2 = polygons(*[o.edge((2*i+n+1)%(2*n)) for i in xrange(n)])
        s = Surface_list(base_ring=o.parent().field())
        s.add_polygon(o)
        s.add_polygon(p1)
        s.add_polygon(p2)
        s.change_polygon_gluings(1, [(0,2*i) for i in xrange(n)])
        s.change_polygon_gluings(2, [(0,2*i+1) for i in xrange(n)])
        s.make_immutable()
        return TranslationSurface(s)
Beispiel #2
0
    def mcmullen_L(l1,l2,l3,l4):
        r"""
        Return McMullen's L shaped surface with parameters l1, l2, l3, l4.

        Polygon labels and lengths are marked below.
        
        +-----+
        |     |
        |  1  |l1
        |     |
        |     |    l4
        +-----+---------+
        |               |
        |       0       |l2
        |               |
        +-----+---------+
          l3        

        Note that this surface may not work correctly yet due to a non-strictly 
        convex polygon in the representation.

        EXAMPLES::

            sage: from flatsurf import *
            sage: s = translation_surfaces.mcmullen_L(1,1,1,1)
            sage: TestSuite(s).run()
        """
        from .polygon import polygons
        from .surface import Surface_list
        from .translation_surface import TranslationSurface
        from sage.structure.sequence import Sequence
        
        field = Sequence([l1,l2,l3,l4]).universe()
        if not field.is_field():
            field = field.fraction_field()

        s=Surface_list(base_ring=field)
        s.add_polygon(polygons((l3,0),(l4,0),(0,l2),(-l4,0),(-l3,0),(0,-l2), ring=field))
        s.add_polygon(polygons((l3,0),(0,l1),(-l3,0),(0,-l1), ring=field))
        s.change_edge_gluing(0,0,1,2)
        s.change_edge_gluing(0,1,0,3)
        s.change_edge_gluing(0,2,0,5)
        s.change_edge_gluing(0,4,1,0)
        s.change_edge_gluing(1,1,1,3)
        s.make_immutable()
        return TranslationSurface(s)
Beispiel #3
0
    def example():
        r"""
        Construct a SimilaritySurface from a pair of triangles.

        TESTS::

            sage: from flatsurf import *
            sage: ex = similarity_surfaces.example()
            sage: ex
            SimilaritySurface built from 2 polygons
            sage: TestSuite(ex).run()
        """
        from .similarity_surface import SimilaritySurface
        from .surface import Surface_list
        from .polygon import polygons
        from sage.rings.rational_field import QQ
        s=Surface_list(base_ring=QQ)
        s.add_polygon(polygons(vertices=[(0,0), (2,-2), (2,0)],ring=QQ)) # gets label 0
        s.add_polygon(polygons(vertices=[(0,0), (2,0), (1,3)],ring=QQ)) # gets label 1
        s.change_polygon_gluings(0, [(1,1), (1,2), (1,0)])
        s.make_immutable()
        return SimilaritySurface(s)
Beispiel #4
0
    def polygon_double(P):
        r"""
        Return the ConeSurface associated to the billiard in the polygon ``P``.
        Differs from billiard(P) only in the graphical display. Here, we display
        the polygons separately.
        """
        from .polygon import polygons
        from .cone_surface import ConeSurface
        from sage.matrix.constructor import matrix

        n = P.num_edges()
        r = matrix(2, [-1,0,0,1])
        Q = polygons(edges=[r*v for v in reversed(P.edges())])

        surface = Surface_list(base_ring = P.base_ring())
        surface.add_polygon(P) # gets label 0)
        surface.add_polygon(Q) # gets label 1
        surface.change_polygon_gluings(0,[(1,n-i-1) for i in xrange(n)])
        surface.make_immutable()
        return ConeSurface(surface)
Beispiel #5
0
    def billiard(P):
        r"""
        Return the ConeSurface associated to the billiard in the polygon ``P``.

        EXAMPLES::

            sage: from flatsurf import *
            sage: P = polygons(vertices=[(0,0), (1,0), (0,1)])
            sage: from flatsurf.geometry.rational_cone_surface import RationalConeSurface
            sage: Q = RationalConeSurface(similarity_surfaces.billiard(P))
            sage: Q
            RationalConeSurface built from 2 polygons
            sage: Q.underlying_surface()
            <class 'flatsurf.geometry.surface.Surface_list'>
            sage: M = Q.minimal_translation_cover()
            sage: M
            TranslationSurface built from 8 polygons
            sage: TestSuite(M).run()
        """
        from .polygon import polygons
        from .surface import Surface_list
        from .cone_surface import ConeSurface
        from sage.matrix.constructor import matrix

        n = P.num_edges()
        r = matrix(2, [-1,0,0,1])
        Q = polygons(edges=[r*v for v in reversed(P.edges())])

        surface = Surface_list(base_ring = P.base_ring())
        surface.add_polygon(P) # gets label 0)
        surface.add_polygon(Q) # gets label 1
        surface.change_polygon_gluings(0,[(1,n-i-1) for i in xrange(n)])
        
        surface.make_immutable()
        s=ConeSurface(surface)
        gs = s.graphical_surface(edge_labels=False, polygon_labels=False)
        gs.make_adjacent(0,0,reverse=True)
        return s
    def triangle_flip(self, l1, e1, in_place=False, test=False):
        r"""
        Flips the diagonal of the quadrilateral formed by two triangles
        glued together along the provided edge (l1,e1). This can be broken 
        into two steps: join along the edge to form a convex quadilateral,
        then cut along the other diagonal. Raises a ValueError if this 
        quadrilateral would be non-convex.
        
        Parameters
        ----------
        l1
            label of polygon
        e1 : integer
            edge of the polygon
        in_place : boolean
            if True do the flip to the current surface which must be mutable. 
            In this case the updated surface will be returned.
            Otherwise a mutable copy is made and then an edge is flipped, which is then returned.
        test : boolean
            if True we don't actually flip, and we return True or False depending
            on whether or not the flip would be successful.
        
        EXAMPLES::

            sage: from flatsurf import *
            sage: s=similarity_surfaces.right_angle_triangle(ZZ(1),ZZ(1))
            sage: print(s.polygon(0))
            Polygon: (0, 0), (1, 0), (0, 1)
            sage: print s.triangle_flip(0, 0, test=True)
            False
            sage: print s.triangle_flip(0, 1, test=True)
            True
            sage: print s.triangle_flip(0, 2, test=True)
            False

            sage: from flatsurf import *
            sage: s=similarity_surfaces.right_angle_triangle(ZZ(1),ZZ(1))
            sage: from flatsurf.geometry.surface import Surface_fast
            sage: s=s.__class__(Surface_fast(s, mutable=True))
            sage: try:
            ....:     s.triangle_flip(0,0,in_place=True)
            ....: except ValueError as e:
            ....:     print e
            Gluing triangles along this edge yields a non-convex quadrilateral.
            sage: print s.triangle_flip(0,1,in_place=True)
            ConeSurface built from 2 polygons
            sage: print s.polygon(0)
            Polygon: (0, 0), (1, 1), (0, 1)
            sage: print s.polygon(1)
            Polygon: (0, 0), (-1, -1), (0, -1)
            sage: for p in s.edge_iterator(gluings=True):
            ....:     print p
            ((0, 0), (1, 0))
            ((0, 1), (0, 2))
            ((0, 2), (0, 1))
            ((1, 0), (0, 0))
            ((1, 1), (1, 2))
            ((1, 2), (1, 1))
            sage: try:
            ....:     s.triangle_flip(0,2,in_place=True)
            ....: except ValueError as e:
            ....:     print e
            ....: 
            Gluing triangles along this edge yields a non-convex quadrilateral.

            sage: from flatsurf import *
            sage: p=polygons((2,0),(-1,3),(-1,-3))
            sage: s=similarity_surfaces.self_glued_polygon(p)
            sage: from flatsurf.geometry.surface import Surface_fast
            sage: s=s.__class__(Surface_fast(s,mutable=True))
            sage: s.triangle_flip(0,1,in_place=True)
            HalfTranslationSurface built from 1 polygon
            sage: for x in s.label_iterator(polygons=True):
            ....:     print x
            (0, Polygon: (0, 0), (3, 3), (1, 3))
            sage: for x in s.edge_iterator(gluings=True):
            ....:     print x
            ((0, 0), (0, 0))
            ((0, 1), (0, 1))
            ((0, 2), (0, 2))
            sage: TestSuite(s).run()
        """
        if test:
            # Just test if the flip would be successful
            p1=self.polygon(l1)
            if not p1.num_edges()==3:
                return false
            l2,e2 = self.opposite_edge(l1,e1)
            p2 = self.polygon(l2)
            if not p2.num_edges()==3:
                return false
            sim = self.edge_transformation(l2,e2)
            hol = sim( p2.vertex( (e2+2)%3 ) - p1.vertex((e1+2)%3) )
            from flatsurf.geometry.polygon import wedge_product
            return wedge_product(p1.edge((e1+2)%3), hol) > 0 and \
                wedge_product(p1.edge((e1+1)%3), hol) > 0
        if in_place:
            s=self.underlying_surface()
        else:
            from flatsurf.geometry.surface import Surface_fast
            s=Surface_fast(surface=self.underlying_surface(), \
                mutable=True, dictionary=True)
        p1=self.polygon(l1)
        if not p1.num_edges()==3:
            raise ValueError("The polygon with the provided label is not a triangle.")
        l2,e2 = self.opposite_edge(l1,e1)
        p2 = self.polygon(l2)
        if not p2.num_edges()==3:
            raise ValueError("The polygon opposite the provided edge is not a triangle.")
        sim = self.edge_transformation(l2,e2)
        m = sim.derivative()
        hol = sim( p2.vertex( (e2+2)%3 ) ) - p1.vertex((e1+2)%3)

        from flatsurf import polygons

        try:
            np1 = polygons(edges=[hol, m * p2.edge((e2+2)%3), p1.edge((e1+1)%3)])
            np2 = polygons(edges=[-hol, p1.edge((e1+2)%3), m * p2.edge((e2+1)%3)])
        except (ValueError, TypeError):
            raise ValueError("Gluing triangles along this edge yields a non-convex quadrilateral.")
        # Old gluings:
        pairs = [self.opposite_edge(l2,(e2+2)%3), \
            self.opposite_edge(l1,(e1+1)%3), \
            self.opposite_edge(l1,(e1+2)%3), \
            self.opposite_edge(l2,(e2+1)%3)]
        for i, (l,e) in enumerate(pairs):
            if l==l1:
                if e==(e1+1)%3:
                    pairs[i]=(l1,2)
                elif e==(e1+2)%3:
                    pairs[i]=(l2,1)
                else:
                    raise ValueError("Surfaced passed has errors in polygon gluings.")
            elif l==l2:
                if e==(e2+1)%3:
                    pairs[i]=(l2,2)
                elif e==(e2+2)%3:
                    pairs[i]=(l1,1)
                else:
                    raise ValueError("Surfaced passed has errors in polygon gluings.")
        if l1==l2:
            s.change_polygon(l1,np1)
            s.change_edge_gluing(l1,0,l1,0)
            s.change_edge_gluing(l1,1,pairs[0][0],pairs[0][1])
            s.change_edge_gluing(l1,2,pairs[1][0],pairs[1][1])
        else:
            s.change_polygon(l1,np1)
            s.change_polygon(l2,np2)
            s.change_edge_gluing(l1,0,l2,0)
            s.change_edge_gluing(l1,1,pairs[0][0],pairs[0][1])
            s.change_edge_gluing(l1,2,pairs[1][0],pairs[1][1])
            s.change_edge_gluing(l2,1,pairs[2][0],pairs[2][1])
            s.change_edge_gluing(l2,2,pairs[3][0],pairs[3][1])
        if in_place:
            return self
        else:
            return self.__class__(s)