Ticket #11379: trac_11379_2d_boundary-sl.patch

File trac_11379_2d_boundary-sl.patch, 11.8 KB (added by slabbe, 10 years ago)

Applies over the precedent patches.

  • sage/combinat/tiling.py

    # HG changeset patch
    # User Sebastien Labbe <slabqc at gmail.com>
    # Date 1311356485 14400
    # Node ID d630c934cb58da41a47885d9bc9d30d6f6c49c54
    # Parent  2aa9585e1c3c73c9ac2e88093b49499e19c6cdff
    #11379: Improving the drawing of 2d polyomino using its boundary.
    
    diff --git a/sage/combinat/tiling.py b/sage/combinat/tiling.py
    a b The following is a puzzle owned by Flore 
    8181
    8282    sage: from sage.combinat.tiling import Polyomino, TilingSolver
    8383    sage: L = []
    84     sage: L.append(Polyomino([(0,0),(0,1),(0,2),(0,3),(1,0),(1,1),(1,2),(1,3)]))
    85     sage: L.append(Polyomino([(0,0),(0,1),(0,2),(0,3),(1,0),(1,1),(1,2)]))
    86     sage: L.append(Polyomino([(0,0),(0,1),(0,2),(0,3),(1,0),(1,1),(1,3)]))
    87     sage: L.append(Polyomino([(0,0),(0,1),(0,2),(0,3),(1,0),(1,3)]))
    88     sage: L.append(Polyomino([(0,0),(0,1),(0,2),(0,3),(1,0),(1,1)]))
    89     sage: L.append(Polyomino([(0,0),(0,1),(0,2),(0,3),(1,1),(1,2)]))
    90     sage: L.append(Polyomino([(0,0),(0,1),(0,2),(0,3),(1,1),(1,3)]))
    91     sage: L.append(Polyomino([(0,1),(0,2),(0,3),(1,0),(1,1),(1,3)]))
    92     sage: L.append(Polyomino([(0,1),(0,2),(0,3),(1,0),(1,1),(1,2)]))
    93     sage: L.append(Polyomino([(0,0),(0,1),(0,2),(1,0),(1,1),(1,2)]))
     84    sage: L.append(Polyomino([(0,0),(0,1),(0,2),(0,3),(1,0),(1,1),(1,2),(1,3)], 'yellow'))
     85    sage: L.append(Polyomino([(0,0),(0,1),(0,2),(0,3),(1,0),(1,1),(1,2)], "black"))
     86    sage: L.append(Polyomino([(0,0),(0,1),(0,2),(0,3),(1,0),(1,1),(1,3)], "gray"))
     87    sage: L.append(Polyomino([(0,0),(0,1),(0,2),(0,3),(1,0),(1,3)],"cyan"))
     88    sage: L.append(Polyomino([(0,0),(0,1),(0,2),(0,3),(1,0),(1,1)],"red"))
     89    sage: L.append(Polyomino([(0,0),(0,1),(0,2),(0,3),(1,1),(1,2)],"blue"))
     90    sage: L.append(Polyomino([(0,0),(0,1),(0,2),(0,3),(1,1),(1,3)],"green"))
     91    sage: L.append(Polyomino([(0,1),(0,2),(0,3),(1,0),(1,1),(1,3)],"magenta"))
     92    sage: L.append(Polyomino([(0,1),(0,2),(0,3),(1,0),(1,1),(1,2)],"orange"))
     93    sage: L.append(Polyomino([(0,0),(0,1),(0,2),(1,0),(1,1),(1,2)],"pink"))
    9494
    9595By default, rotations are allowed and reflections are not. In this case,
    9696there are no solution::
    one solution:: 
    104104
    105105    sage: T = TilingSolver(L, (8,8), reflection=True)
    106106    sage: solution = T.solve().next()
    107     sage: G = sum([piece.show2d(size=0.85) for piece in solution], Graphics())
    108     sage: G.show(aspect_ratio=1)
     107    sage: G = sum([piece.show2d() for piece in solution], Graphics())
     108    sage: G.show(aspect_ratio=1, axes=False)
    109109
    110110Compute the number of solutions::
    111111
    112112    sage: T.number_of_solutions()                              # long time (2.6s)
    113113    328
    114114
     115Create a animation of all the solutions::
     116
     117    sage: a = T.animate()                            # not tested
     118    sage: a                                          # not tested
     119    Animation with 328 frames
     120
    1151213d Puzzle
    116122---------
    117123
    from sage.misc.misc import prod 
    220226from sage.combinat.all import WeylGroup
    221227from sage.plot.plot import Graphics
    222228from sage.plot.polygon import polygon
     229from sage.plot.line import line
     230from sage.plot.circle import circle
    223231from sage.modules.free_module_element import vector
    224232from sage.plot.plot3d.platonic import cube
    225233from sage.plot.animate import Animation
    class Polyomino(SageObject): 
    334342        assert isinstance(color, str)
    335343        self._color = color
    336344        self._blocs = frozenset(tuple(c) for c in coords)
     345        assert len(self._blocs) != 0, "Polyomino must be non empty"
    337346        dimension_set = set(len(a) for a in self._blocs)
    338347        assert len(dimension_set) <= 1, "coord must be all of the same dimension"
    339348        self._dimension = dimension_set.pop()
    class Polyomino(SageObject): 
    759768                yield t
    760769
    761770
    762     def middle_of_neighbor_coords(self):
     771    def neighbor_edges(self):
    763772        r"""
    764         Return the list of middle of neighbor coords.
     773        Return an iterator over the pairs of neighbor coordinates of the
     774        polyomino.
    765775
    766         This is use to draw cube in between two neighbor cubes.
     776        Two points `P` and `Q` are neighbor if `P - Q` has one coordinate
     777        equal to `+1` or `-1` and zero everywhere else.
    767778
    768779        EXAMPLES::
    769780
    770781            sage: from sage.combinat.tiling import Polyomino
    771782            sage: p = Polyomino([(0,0,0),(0,0,1)])
    772             sage: list(p.middle_of_neighbor_coords())
    773             [(0.0, 0.0, 0.5)]
     783            sage: list(sorted(edge) for edge in p.neighbor_edges())
     784            [[(0, 0, 0), (0, 0, 1)]]
    774785
    775786        In 3d::
    776787
    777788            sage: p = Polyomino([(0,0,0),(1,0,0),(1,1,0),(1,1,1),(1,2,0)], color='deeppink')
    778             sage: L = sorted(p.middle_of_neighbor_coords())
     789            sage: L = sorted(sorted(edge) for edge in p.neighbor_edges())
    779790            sage: for a in L: a
    780             (0.5, 0.0, 0.0)
    781             (1.0, 0.5, 0.0)
    782             (1.0, 1.0, 0.5)
    783             (1.0, 1.5, 0.0)
     791            [(0, 0, 0), (1, 0, 0)]
     792            [(1, 0, 0), (1, 1, 0)]
     793            [(1, 1, 0), (1, 1, 1)]
     794            [(1, 1, 0), (1, 2, 0)]
    784795
    785796        In 2d::
    786797
    787798            sage: p = Polyomino([(0,0),(1,0),(1,1),(1,2)])
    788             sage: L = sorted(p.middle_of_neighbor_coords())
     799            sage: L = sorted(sorted(edge) for edge in p.neighbor_edges())
    789800            sage: for a in L: a
    790             (0.5, 0.0)
    791             (1.0, 0.5)
    792             (1.0, 1.5)
     801            [(0, 0), (1, 0)]
     802            [(1, 0), (1, 1)]
     803            [(1, 1), (1, 2)]
    793804        """
    794805        for P, Q in itertools.combinations(self, 2):
    795806            P, Q = vector(P), vector(Q)
    class Polyomino(SageObject): 
    797808            firsts = s[:-1]
    798809            last = s[-1]
    799810            if last == 1 and all(f == 0 for f in firsts):
    800                 yield (P + Q) / 2.0
     811                yield P, Q
     812
    801813    def center(self):
    802814        r"""
    803815        Return the center of the polyomino.
    class Polyomino(SageObject): 
    823835        """
    824836        return sum(vector(t) for t in self) / len(self)
    825837
     838    def boundary(self):
     839        r"""
     840        Return the boundary of a 2D polyomino.
     841
     842        INPUT:
     843
     844        - ``self`` - a 2D polyomino
     845
     846        OUTPUT:
     847
     848        - list of edges (an edge is a pair of adjacent 2D coordinates)
     849
     850        EXAMPLES::
     851
     852            sage: from sage.combinat.tiling import Polyomino
     853            sage: p = Polyomino([(0,0), (1,0), (0,1), (1,1)])
     854            sage: p.boundary()
     855            [((0.5, 1.5), (1.5, 1.5)), ((-0.5, -0.5), (0.5, -0.5)), ((0.5, -0.5), (1.5, -0.5)), ((-0.5, 1.5), (0.5, 1.5)), ((-0.5, 0.5), (-0.5, 1.5)), ((-0.5, -0.5), (-0.5, 0.5)), ((1.5, 0.5), (1.5, 1.5)), ((1.5, -0.5), (1.5, 0.5))]
     856            sage: len(_)
     857            8
     858            sage: p = Polyomino([(5,5)])
     859            sage: p.boundary()
     860            [((4.5, 5.5), (5.5, 5.5)), ((4.5, 4.5), (5.5, 4.5)), ((4.5, 4.5), (4.5, 5.5)), ((5.5, 4.5), (5.5, 5.5))]
     861        """
     862        if self._dimension != 2:
     863            raise NotImplementedError("The method boundary is currently implemented "
     864                                      "only for dimension 2")
     865        from collections import defaultdict
     866        horizontal = defaultdict(int)
     867        vertical = defaultdict(int)
     868        for a in self:
     869            x,y = a = tuple(a)
     870            horizontal[a] += 1
     871            vertical[a] += 1
     872            horizontal[(x,y+1)] -= 1
     873            vertical[(x+1,y)] -= 1
     874        edges = []
     875        h = 0.5
     876        for (x,y), coeff in horizontal.iteritems():
     877            if coeff != 0:
     878                edges.append(((x-h,y-h),(x+h,y-h)))
     879        for (x,y), coeff in vertical.iteritems():
     880            if coeff != 0:
     881                edges.append(((x-h,y-h),(x-h,y+h)))
     882        return edges
     883
     884
    826885    def show3d(self, size=1):
    827886        r"""
    828887        Returns a 3d Graphic object representing the polyomino.
    class Polyomino(SageObject): 
    840899            sage: p = Polyomino([(0,0,0), (0,1,0), (1,1,0), (1,1,1)], color='blue')
    841900            sage: p.show3d()
    842901        """
    843         assert self._dimension == 3, "To show a polyomino in 3d, its dimension must be 3."
     902        assert self._dimension == 3, "Dimension of the polyomino must be 3."
    844903        G = Graphics()
    845904        for p in self:
    846905            G += cube(p, color=self._color)
    class Polyomino(SageObject): 
    850909        G = G.translate(center)
    851910        return G
    852911
    853     def show2d(self, size=1):
     912    def show2d(self, size=0.7, color='black', thickness=1):
    854913        r"""
    855914        Returns a 2d Graphic object representing the polyomino.
    856915
    857916        INPUT:
    858917
    859918        - ``self`` - a polyomino of dimension 2
    860         - ``size`` - number (optional, default: ``1``), the size of each
    861           ``1 \times 1`` square. This does a homothety with respect
    862           to the center of the polyomino.
     919        - ``size`` - number (optional, default: ``0.7``), the size of each
     920          square.
     921        - ``color`` - color (optional, default: ``'black'``), color of
     922          the boundary line.
     923        - ``thickness`` - number (optional, default: ``1``), how thick the
     924          boundary line is.
    863925
    864926        EXAMPLES::
    865927
    class Polyomino(SageObject): 
    867929            sage: p = Polyomino([(0,0),(1,0),(1,1),(1,2)], color='deeppink')
    868930            sage: p.show2d()              # long time (0.5s)
    869931        """
    870         assert self._dimension == 2, "To show a polyomino in 2d, its dimension must be 2."
    871         center = self.center()
    872         transformed = [size * (vector(t) - center) + center for t in self]
     932        assert self._dimension == 2, "Dimension of the polyomino must be 2."
    873933        h = size / 2.0
    874934        G = Graphics()
    875         for a,b in transformed:
    876             G += polygon([(a-h,b-h), (a+h,b-h), (a+h,b+h), (a-h,b+h), (a-h,b-h)], color=self._color)
     935        for a,b in self:
     936            G += circle((a,b), h, fill=True, color=self._color)
     937        k = h / 2.0
     938        for P,Q in self.neighbor_edges():
     939            a,b = (P + Q) / 2.0
     940            G += polygon([(a-k,b-k), (a+k,b-k), (a+k,b+k), (a-k,b+k), (a-k,b-k)], color=self._color)
     941        for edge in self.boundary():
     942            G += line(edge, color=color, thickness=thickness)
    877943        return G
    878944
    879945#######################
    class TilingSolver(SageObject): 
    15331599            N += 1
    15341600        return N
    15351601
    1536     def animate(self, partial=None, stop=None, size=0.9):
     1602    def animate(self, partial=None, stop=None, size=0.75, axes=False):
    15371603        r"""
    15381604        Return an animation of evolving solutions.
    15391605
    class TilingSolver(SageObject): 
    15491615
    15501616        - ``stop`` - integer (optional, default:``None``), number of frames
    15511617
    1552         - ``size`` - number (optional, default: ``0.9``), the size of each
     1618        - ``size`` - number (optional, default: ``0.75``), the size of each
    15531619          ``1 \times 1`` square. This does a homothety with respect
    15541620          to the center of each polyomino.
     1621
     1622        - ``axes`` - bool (optional, default:``False``), whether the x and
     1623          y axes are shown.
    15551624       
    15561625        EXAMPLES::
    15571626
    class TilingSolver(SageObject): 
    15981667            it = itertools.islice(it, stop)
    15991668            L = [sum([piece.show2d(size) for piece in solution], Graphics()) for solution in it]
    16001669            xmax, ymax = self._box
    1601             a = Animation(L, xmin=0, ymin=0, xmax=xmax, ymax=ymax, aspect_ratio=1)
     1670            xmax = xmax-0.5
     1671            ymax = ymax-0.5
     1672            a = Animation(L, xmin=-0.5, ymin=-0.5, xmax=xmax, ymax=ymax, aspect_ratio=1, axes=axes)
    16021673            return a
    16031674        elif dimension == 3:
    16041675            raise NotImplementedError("3d Animation must be implemented in Jmol first")
  • sage/games/quantumino.py

    diff --git a/sage/games/quantumino.py b/sage/games/quantumino.py
    a b class QuantuminoState(SageObject): 
    331331        """
    332332        return list(self)
    333333
    334     def show3d(self, size=0.75):
     334    def show3d(self, size=0.85):
    335335        r"""
    336336        Return the solution as a 3D Graphic object.
    337337