Ticket #6098: trac_6098-rebased.patch

File trac_6098-rebased.patch, 9.1 KB (added by rlm, 8 months ago)

Apply only this patch

  • sage/plot/bezier_path.py

    # HG changeset patch
    # User Emily Kirkman <>
    # Date 1242874073 25200
    # Node ID ef8c792c47412e9cd9e3c328790bfebf94d0c4c5
    # Parent  ca1f31d6f6bf7b1f8da0cb8973c838ab19921c29
    3d bezier path implementation
    
    diff -r ca1f31d6f6bf -r ef8c792c4741 sage/plot/bezier_path.py
    a b  
    1515# 
    1616#                  http://www.gnu.org/licenses/ 
    1717#***************************************************************************** 
    18 from sage.plot.primitive import GraphicPrimitive 
     18from sage.plot.primitive import GraphicPrimitive_xydata 
    1919from sage.plot.misc import options, rename_keyword 
    2020from sage.plot.colors import to_mpl_color 
    2121 
    22 class BezierPath(GraphicPrimitive): 
     22class BezierPath(GraphicPrimitive_xydata): 
    2323    """ 
    2424    Path of Bezier Curves graphics primitive. 
    2525    """ 
     
    4141            codes += (len(curve))*[len(curve)+1] 
    4242        self.codes = codes 
    4343        self.vertices = np.array(vertices, np.float) 
    44         GraphicPrimitive.__init__(self, options) 
     44        GraphicPrimitive_xydata.__init__(self, options) 
    4545         
    4646    def _allowed_options(self): 
    4747        """ 
     
    6363                'thickness':'How thick the border of the polygon is.', 
    6464                'rgbcolor':'The color as an rgb tuple.', 
    6565                'zorder':'The layer level in which to draw', 
    66                                 'linestyle':"The style of the line, which is one of 'dashed', 'dotted', 'solid', 'dashdot'."} 
    67                  
     66                'linestyle':"The style of the line, which is one of 'dashed', 'dotted', 'solid', 'dashdot'."} 
     67     
     68    def _plot3d_options(self, options=None): 
     69        """ 
     70        Updates BezierPath options to those allowed by 3d implementation. 
     71         
     72        EXAMPLES: 
     73         
     74            sage: from sage.plot.bezier_path import BezierPath 
     75            sage: B = BezierPath([[(0,0),(.5,.5),(1,0)],[(.5,1),(0,0)]],{'linestyle':'dashed'}) 
     76            sage: B._plot3d_options() 
     77            Traceback (most recent call last): 
     78            ... 
     79            NotImplementedError: Invalid 3d line style: dashed 
     80            sage: B = BezierPath([[(0,0),(.5,.5),(1,0)],[(.5,1),(0,0)]],{'fill':False, 'thickness':2}) 
     81            sage: B._plot3d_options() 
     82            {'thickness': 2} 
     83        """ 
     84        if options == None: 
     85            options = dict(self.options()) 
     86        options_3d = {} 
     87        if 'thickness' in options: 
     88            options_3d['thickness'] = options['thickness'] 
     89            del options['thickness'] 
     90        if 'fill' in options: 
     91            if options['fill']: 
     92                raise NotImplementedError, "Invalid 3d fill style.  Must set fill to False." 
     93            del options['fill'] 
     94        if 'linestyle' in options: 
     95            if options['linestyle'] != 'solid': 
     96                raise NotImplementedError, "Invalid 3d line style: %s" % options['linestyle'] 
     97            del options['linestyle'] 
     98        options_3d.update(GraphicPrimitive_xydata._plot3d_options(self, options)) 
     99        return options_3d 
     100 
     101    def plot3d(self, **kwds): 
     102        """ 
     103        Returns a 3d plot (Jmol) of the bezier path.  Since a BezierPath primitive contains 
     104        only x,y coordinates, the path will be drawn in the z=0 plane.  To create a bezier path 
     105        with nonzero z coordinates in the path and control points, use the constructor bezier3d 
     106        instead of bezier_path. 
     107         
     108        EXAMPLES: 
     109            sage: b = bezier_path([[(0,0),(0,1),(1,0)]]) 
     110            sage: b.plot3d() 
     111            sage: bezier3d([[(0,0,0),(1,0,0),(0,1,0),(0,1,1)]]) 
     112        """ 
     113        from sage.plot.plot3d.shapes2 import bezier3d 
     114        options = self._plot3d_options() 
     115        options.update(kwds) 
     116        return bezier3d([[(x,y,0) for x,y in self.path[i]] for i in range(len(self.path))], **options) 
     117                                         
    68118    def _repr_(self): 
    69119        return "Bezier path from %s to %s"%(self.path[0][0],self.path[-1][-1]) 
    70120         
  • sage/plot/plot3d/all.py

    diff -r ca1f31d6f6bf -r ef8c792c4741 sage/plot/plot3d/all.py
    a b  
    66 
    77from platonic          import tetrahedron, cube, octahedron, dodecahedron, icosahedron 
    88 
    9 from shapes2           import sphere, line3d, polygon3d, point3d, text3d 
     9from shapes2           import sphere, line3d, polygon3d, point3d, text3d, bezier3d 
    1010 
    1111from shapes            import arrow3d 
    1212 
  • sage/plot/plot3d/shapes2.py

    diff -r ca1f31d6f6bf -r ef8c792c4741 sage/plot/plot3d/shapes2.py
    a b  
    104104        w._set_extra_kwds(kwds) 
    105105        return w 
    106106 
     107@options(opacity=1, color="red", aspect_ratio=[1,1,1], thickness=2) 
     108def bezier3d(path, **options): 
     109    """ 
     110    Draws a 3-dimensional bezier path.  Input is similar to bezier_path, but each 
     111    point in the path and each control point is required to have 3 coordinates. 
     112     
     113    INPUT: 
     114     
     115    -  ``path`` - a list of curves, which each is a list of points. See further  
     116        detail below. 
     117     
     118    -  ``thickness`` - (default: 2) 
     119     
     120    -  ``color`` - a word that describes a color 
     121 
     122    -  ``opacity`` - (default: 1) if less than 1 then is 
     123       transparent 
     124        
     125    -  ``aspect_ratio`` - (default:[1,1,1]) 
     126     
     127    The path is a list of curves, and each curve is a list of points.   
     128    Each point is a tuple (x,y,z). 
     129     
     130    The first curve contains the endpoints as the first and last point  
     131    in the list.  All other curves assume a starting point given by the 
     132    last entry in the preceding list, and take the last point in the list 
     133    as their opposite endpoint.  A curve can have 0, 1 or 2 control points 
     134    listed between the endpoints.  In the input example for path below,  
     135    the first and second curves have 2 control points, the third has one, 
     136    and the fourth has no control points:     
     137     
     138    path = [[p1, c1, c2, p2], [c3, c4, p3], [c5, p4], [p5], ...] 
     139     
     140    In the case of no control points, a striaght line will be drawn 
     141    between the two endpoints.  If one control point is supplied, then  
     142    the curve at each of the endpoints will be tangent to the line from 
     143    that endpoint to the control point.  Similarly, in the case of two  
     144    control points, at each endpoint the curve will be tangent to the line 
     145    connecting that endpoint with the control point immediately after or 
     146    immediately preceding it in the list. 
     147     
     148    So in our example above, the curve between p1 and p2 is tangent to the 
     149    line through p1 and c1 at p1, and tangent to the line through p2 and c2 
     150    at p2.  Similarly, the curve between p2 and p3 is tangent to line(p2,c3) 
     151    at p2 and tangent to line(p3,c4) at p3.  Curve(p3,p4) is tangent to  
     152    line(p3,c5) at p3 and tangent to line(p4,c5) at p4.  Curve(p4,p5) is a 
     153    straight line. 
     154 
     155    EXAMPLES: 
     156        sage: path = [[(0,0,0),(.5,.1,.2),(.75,3,-1),(1,1,0)],[(.5,1,.2),(1,.5,0)],[(.7,.2,.5)]] 
     157        sage: b = bezier3d(path, color='green') 
     158        sage: b 
     159 
     160    To construct a simple curve, create a list containing a single list: 
     161         
     162        sage: path = [[(0,0,0),(1,0,0),(0,1,0),(0,1,1)]] 
     163        sage: curve = bezier3d(path, thickness=5, color='blue') 
     164        sage: curve 
     165    """ 
     166    import parametric_plot3d as P3D 
     167    from sage.modules.free_module_element import vector 
     168    from sage.calculus.calculus import var 
     169     
     170    p0 = vector(path[0][-1]) 
     171    t = var('t') 
     172    if len(path[0]) > 2: 
     173        B = (1-t)**3*vector(path[0][0])+3*t*(1-t)**2*vector(path[0][1])+3*t**2*(1-t)*vector(path[0][-2])+t**3*p0 
     174        G = P3D.parametric_plot3d(list(B), (0, 1), color=options['color'], aspect_ratio=options['aspect_ratio'], thickness=options['thickness'], opacity=options['opacity']) 
     175    else: 
     176        G = line3d([path[0][0], p0], color=options['color'], thickness=options['thickness'], opacity=options['opacity']) 
     177     
     178    for curve in path[1:]: 
     179        if len(curve) > 1: 
     180            p1 = vector(curve[0]) 
     181            p2 = vector(curve[-2]) 
     182            p3 = vector(curve[-1]) 
     183            B = (1-t)**3*p0+3*t*(1-t)**2*p1+3*t**2*(1-t)*p2+t**3*p3 
     184            G += P3D.parametric_plot3d(list(B), (0, 1), color=options['color'], aspect_ratio=options['aspect_ratio'], thickness=options['thickness'], opacity=options['opacity']) 
     185        else: 
     186            G += line3d([p0,curve[0]], color=options['color'], thickness=options['thickness'], opacity=options['opacity']) 
     187        p0 = curve[-1] 
     188    return G 
     189     
    107190@rename_keyword(alpha='opacity') 
    108191@options(opacity=1, color=(0,0,1)) 
    109192def polygon3d(points, **options): 
  • sage/plot/primitive.py

    diff -r ca1f31d6f6bf -r ef8c792c4741 sage/plot/primitive.py
    a b  
    106106        if 'alpha' in options: 
    107107            options_3d['opacity'] = options['alpha'] 
    108108            del options['alpha'] 
     109        if 'zorder' in options: 
     110            del options['zorder'] 
    109111        if len(options) != 0: 
    110112            raise NotImplementedError, "Unknown plot3d equivalent for %s" % ", ".join(options.keys()) 
    111113        return options_3d