Ticket #6098: trac6098_bezier3d.patch

File trac6098_bezier3d.patch, 9.7 KB (added by rlm, 14 years ago)

Referee edit

  • sage/graphs/graph_plot.py

    # HG changeset patch
    # User Emily Kirkman <>
    # Date 1242874073 25200
    # Node ID f49d216fe07bb1d352f380f77d4225c1e970bc2d
    # Parent  54cc8d2ba3ffdc64f99805b63edc5171844a0de6
    3d bezier path implementation
    
    diff -r 54cc8d2ba3ff -r f49d216fe07b sage/graphs/graph_plot.py
    a b  
    443443            dist = self._options['dist']*2
    444444            loop_size = self._options['loop_size']
    445445            max_dist = self._options['max_dist']
    446             from sage.calculus.calculus import SymbolicVariable
     446                   
    447447            from sage.calculus.calculus import sqrt as Sqrt
    448448            for (a,b) in tmp:
    449449                if a == b:
  • sage/plot/bezier_path.py

    diff -r 54cc8d2ba3ff -r f49d216fe07b 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, to_mpl_color, rename_keyword
    2020
    21 class BezierPath(GraphicPrimitive):
     21class BezierPath(GraphicPrimitive_xydata):
    2222    """
    2323    Path of Bezier Curves graphics primitive.
    2424    """
     
    4040            codes += (len(curve))*[len(curve)+1]
    4141        self.codes = codes
    4242        self.vertices = np.array(vertices, np.float)
    43         GraphicPrimitive.__init__(self, options)
     43        GraphicPrimitive_xydata.__init__(self, options)
    4444       
    4545    def _allowed_options(self):
    4646        """
     
    6262                'thickness':'How thick the border of the polygon is.',
    6363                'rgbcolor':'The color as an rgb tuple.',
    6464                'zorder':'The layer level in which to draw',
    65                                 'linestyle':"The style of the line, which is one of 'dashed', 'dotted', 'solid', 'dashdot'."}
    66                
     65                'linestyle':"The style of the line, which is one of 'dashed', 'dotted', 'solid', 'dashdot'."}
     66   
     67    def _plot3d_options(self, options=None):
     68        """
     69        Updates BezierPath options to those allowed by 3d implementation.
     70       
     71        EXAMPLES:
     72       
     73            sage: from sage.plot.bezier_path import BezierPath
     74            sage: B = BezierPath([[(0,0),(.5,.5),(1,0)],[(.5,1),(0,0)]],{'linestyle':'dashed'})
     75            sage: B._plot3d_options()
     76            Traceback (most recent call last):
     77            ...
     78            NotImplementedError: Invalid 3d line style: dashed
     79            sage: B = BezierPath([[(0,0),(.5,.5),(1,0)],[(.5,1),(0,0)]],{'fill':False, 'thickness':2})
     80            sage: B._plot3d_options()
     81            {'thickness': 2}
     82        """
     83        if options == None:
     84            options = dict(self.options())
     85        options_3d = {}
     86        if 'thickness' in options:
     87            options_3d['thickness'] = options['thickness']
     88            del options['thickness']
     89        if 'fill' in options:
     90            if options['fill']:
     91                raise NotImplementedError, "Invalid 3d fill style.  Must set fill to False."
     92            del options['fill']
     93        if 'linestyle' in options:
     94            if options['linestyle'] != 'solid':
     95                raise NotImplementedError, "Invalid 3d line style: %s" % options['linestyle']
     96            del options['linestyle']
     97        options_3d.update(GraphicPrimitive_xydata._plot3d_options(self, options))
     98        return options_3d
     99
     100    def plot3d(self, **kwds):
     101        """
     102        Returns a 3d plot (Jmol) of the bezier path.  Since a BezierPath primitive contains
     103        only x,y coordinates, the path will be drawn in the z=0 plane.  To create a bezier path
     104        with nonzero z coordinates in the path and control points, use the constructor bezier3d
     105        instead of bezier_path.
     106       
     107        EXAMPLES:
     108            sage: b = bezier_path([[(0,0),(0,1),(1,0)]])
     109            sage: b.plot3d()
     110            sage: bezier3d([[(0,0,0),(1,0,0),(0,1,0),(0,1,1)]])
     111        """
     112        from sage.plot.plot3d.shapes2 import bezier3d
     113        options = self._plot3d_options()
     114        options.update(kwds)
     115        return bezier3d([[(x,y,0) for x,y in self.path[i]] for i in range(len(self.path))], **options)
     116                                       
    67117    def _repr_(self):
    68118        return "Bezier path from %s to %s"%(self.path[0][0],self.path[-1][-1])
    69119       
  • sage/plot/plot3d/all.py

    diff -r 54cc8d2ba3ff -r f49d216fe07b 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 54cc8d2ba3ff -r f49d216fe07b 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 SymbolicVariable
     169   
     170    p0 = vector(path[0][-1])
     171    t = SymbolicVariable('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 54cc8d2ba3ff -r f49d216fe07b sage/plot/primitive.py
    a b  
    103103        if 'alpha' in options:
    104104            options_3d['opacity'] = options['alpha']
    105105            del options['alpha']
     106        if 'zorder' in options:
     107            del options['zorder']
    106108        if len(options) != 0:
    107109            raise NotImplementedError, "Unknown plot3d equivalent for %s" % ", ".join(options.keys())
    108110        return options_3d