コード例 #1
0
ファイル: revolution_plot3d.py プロジェクト: ipozdnyakov/sage
def revolution_plot3d(curve,
                      trange,
                      phirange=None,
                      parallel_axis='z',
                      axis=(0, 0),
                      print_vector=False,
                      show_curve=False,
                      **kwds):
    """
    Return a plot of a revolved curve.

    There are three ways to call this function:

    - ``revolution_plot3d(f,trange)`` where `f` is a function located in the `x z` plane.

    - ``revolution_plot3d((f_x,f_z),trange)`` where `(f_x,f_z)` is a parametric curve on the `x z` plane.

    - ``revolution_plot3d((f_x,f_y,f_z),trange)`` where `(f_x,f_y,f_z)` can be any parametric curve.

    INPUT:

    - ``curve`` - A curve to be revolved, specified as a function, a 2-tuple or a 3-tuple.

    - ``trange`` - A 3-tuple `(t,t_{\min},t_{\max})` where t is the independent variable of the curve.

    - ``phirange`` - A 2-tuple of the form `(\phi_{\min},\phi_{\max})`, (default `(0,\pi)`) that specifies the angle in which the curve is to be revolved.

    - ``parallel_axis`` - A string (Either 'x', 'y', or 'z') that specifies the coordinate axis parallel to the revolution axis.

    - ``axis`` - A 2-tuple that specifies the position of the revolution axis. If parallel is:

        - 'z' - then axis is the point in which the revolution axis intersects the  `x y` plane.

        - 'x' - then axis is the point in which the revolution axis intersects the  `y z` plane.

        - 'y' - then axis is the point in which the revolution axis intersects the `x z` plane.

    - ``print_vector`` - If True, the parametrization of the surface of revolution will be printed.

    - ``show_curve`` - If True, the curve will be displayed.


    EXAMPLES:

    Let's revolve a simple function around different axes::

        sage: u = var('u')
        sage: f=u^2
        sage: revolution_plot3d(f,(u,0,2),show_curve=True,opacity=0.7).show(aspect_ratio=(1,1,1))

    If we move slightly the axis, we get a goblet-like surface::

        sage: revolution_plot3d(f,(u,0,2),axis=(1,0.2),show_curve=True,opacity=0.5).show(aspect_ratio=(1,1,1))

    A common problem in calculus books, find the volume within the following revolution solid::

        sage: line=u
        sage: parabola=u^2
        sage: sur1=revolution_plot3d(line,(u,0,1),opacity=0.5,rgbcolor=(1,0.5,0),show_curve=True,parallel_axis='x')
        sage: sur2=revolution_plot3d(parabola,(u,0,1),opacity=0.5,rgbcolor=(0,1,0),show_curve=True,parallel_axis='x')
        sage: (sur1+sur2).show()


    Now let's revolve a parametrically defined circle. We can play with the topology of the surface by changing the axis, an axis in `(0,0)` (as the previous one) will produce a sphere-like surface::

        sage: u = var('u')
        sage: circle=(cos(u),sin(u))
        sage: revolution_plot3d(circle,(u,0,2*pi),axis=(0,0),show_curve=True,opacity=0.5).show(aspect_ratio=(1,1,1))

    An axis on `(0,y)` will produce a cylinder-like surface::

        sage: revolution_plot3d(circle,(u,0,2*pi),axis=(0,2),show_curve=True,opacity=0.5).show(aspect_ratio=(1,1,1))

    And any other axis will produce a torus-like surface::

        sage: revolution_plot3d(circle,(u,0,2*pi),axis=(2,0),show_curve=True,opacity=0.5).show(aspect_ratio=(1,1,1))

    Now, we can get another goblet-like surface by revolving a curve in 3d::

        sage: u = var('u')
        sage: curve=(u,cos(4*u),u^2)
        sage: revolution_plot3d(curve,(u,0,2),show_curve=True,parallel_axis='z',axis=(1,.2),opacity=0.5).show(aspect_ratio=(1,1,1))

    A curvy curve with only a quarter turn::

        sage: u = var('u')
        sage: curve=(sin(3*u),.8*cos(4*u),cos(u))
        sage: revolution_plot3d(curve,(u,0,pi),(0,pi/2),show_curve=True,parallel_axis='z',opacity=0.5).show(aspect_ratio=(1,1,1),frame=False)
    """
    from sage.symbolic.ring import SR
    from sage.symbolic.constants import pi
    from sage.functions.other import sqrt
    from sage.functions.trig import sin
    from sage.functions.trig import cos
    from sage.functions.trig import atan2

    if parallel_axis not in ['x', 'y', 'z']:
        raise ValueError("parallel_axis must be either 'x', 'y', or 'z'.")

    vart = trange[0]

    if str(vart) == 'phi':
        phi = SR.var('fi')
    else:
        phi = SR.var('phi')

    if phirange is None:  #this if-else provides a phirange
        phirange = (phi, 0, 2 * pi)
    elif len(phirange) == 3:
        phi = phirange[0]
        pass
    else:
        phirange = (phi, phirange[0], phirange[1])

    if isinstance(curve, tuple) or isinstance(curve, list):
        #this if-else provides a vector v to be plotted
        #if curve is a tuple or a list of length 2, it is interpreted as a parametric curve
        #in the x-z plane.
        #if it is of length 3 it is interpreted as a parametric curve in 3d space

        if len(curve) == 2:
            x = curve[0]
            y = 0
            z = curve[1]
        elif len(curve) == 3:
            x = curve[0]
            y = curve[1]
            z = curve[2]
    else:
        x = vart
        y = 0
        z = curve

    if parallel_axis == 'z':
        x0 = axis[0]
        y0 = axis[1]
        # (0,0) must be handled separately for the phase value
        phase = 0
        if x0 != 0 or y0 != 0:
            phase = atan2((y - y0), (x - x0))
        R = sqrt((x - x0)**2 + (y - y0)**2)
        v = (R * cos(phi + phase) + x0, R * sin(phi + phase) + y0, z)
    elif parallel_axis == 'x':
        y0 = axis[0]
        z0 = axis[1]
        # (0,0) must be handled separately for the phase value
        phase = 0
        if z0 != 0 or y0 != 0:
            phase = atan2((z - z0), (y - y0))
        R = sqrt((y - y0)**2 + (z - z0)**2)
        v = (x, R * cos(phi + phase) + y0, R * sin(phi + phase) + z0)
    elif parallel_axis == 'y':
        x0 = axis[0]
        z0 = axis[1]
        # (0,0) must be handled separately for the phase value
        phase = 0
        if z0 != 0 or x0 != 0:
            phase = atan2((z - z0), (x - x0))
        R = sqrt((x - x0)**2 + (z - z0)**2)
        v = (R * cos(phi + phase) + x0, y, R * sin(phi + phase) + z0)

    if print_vector:
        print(v)
    if show_curve:
        curveplot = parametric_plot3d((x, y, z),
                                      trange,
                                      thickness=2,
                                      rgbcolor=(1, 0, 0))
        return parametric_plot3d(v, trange, phirange, **kwds) + curveplot
    return parametric_plot3d(v, trange, phirange, **kwds)
コード例 #2
0
def revolution_plot3d(curve,
                      trange,
                      phirange=None,
                      parallel_axis='z',
                      axis=(0, 0),
                      print_vector=False,
                      show_curve=False,
                      **kwds):
    r"""
    Return a plot of a revolved curve.

    There are three ways to call this function:

    - ``revolution_plot3d(f,trange)`` where `f` is a function located in the `x z` plane.

    - ``revolution_plot3d((f_x,f_z),trange)`` where `(f_x,f_z)` is a parametric curve on the `x z` plane.

    - ``revolution_plot3d((f_x,f_y,f_z),trange)`` where `(f_x,f_y,f_z)` can be any parametric curve.

    INPUT:

    - ``curve`` - A curve to be revolved, specified as a function, a 2-tuple or a 3-tuple.

    - ``trange`` - A 3-tuple `(t,t_{\min},t_{\max})` where t is the independent variable of the curve.

    - ``phirange`` - A 2-tuple of the form `(\phi_{\min},\phi_{\max})`, (default `(0,\pi)`) that specifies the angle in which the curve is to be revolved.

    - ``parallel_axis`` - A string (Either 'x', 'y', or 'z') that specifies the coordinate axis parallel to the revolution axis.

    - ``axis`` - A 2-tuple that specifies the position of the revolution axis. If parallel is:

        - 'z' - then axis is the point in which the revolution axis intersects the  `x y` plane.

        - 'x' - then axis is the point in which the revolution axis intersects the  `y z` plane.

        - 'y' - then axis is the point in which the revolution axis intersects the `x z` plane.

    - ``print_vector`` - If True, the parametrization of the surface of revolution will be printed.

    - ``show_curve`` - If True, the curve will be displayed.


    EXAMPLES:

    Let's revolve a simple function around different axes::

        sage: u = var('u')
        sage: f = u^2
        sage: revolution_plot3d(f, (u,0,2), show_curve=True, opacity=0.7).show(aspect_ratio=(1,1,1))

    .. PLOT::

        u = var('u')
        f = u**2
        P = revolution_plot3d(f, (u,0,2), show_curve=True, opacity=0.7).plot()
        sphinx_plot(P)

    If we move slightly the axis, we get a goblet-like surface::

        sage: revolution_plot3d(f, (u,0,2), axis=(1,0.2), show_curve=True, opacity=0.5).show(aspect_ratio=(1,1,1))

    .. PLOT::

        u = var('u')
        f = u**2
        P = revolution_plot3d(f, (u,0,2), axis=(1,0.2), show_curve=True, opacity=0.5).plot()
        sphinx_plot(P)

    A common problem in calculus books, find the volume within the following revolution solid::

        sage: line = u
        sage: parabola = u^2
        sage: sur1 = revolution_plot3d(line, (u,0,1), opacity=0.5, rgbcolor=(1,0.5,0), show_curve=True, parallel_axis='x')
        sage: sur2 = revolution_plot3d(parabola, (u,0,1), opacity=0.5, rgbcolor=(0,1,0), show_curve=True, parallel_axis='x')
        sage: (sur1+sur2).show()

    .. PLOT::

        u = var('u')
        line = u
        parabola = u**2
        sur1 = revolution_plot3d(line, (u,0,1), opacity=0.5, rgbcolor=(1,0.5,0), show_curve=True, parallel_axis='x')
        sur2 = revolution_plot3d(parabola, (u,0,1), opacity=0.5, rgbcolor=(0,1,0), show_curve=True, parallel_axis='x')
        P = sur1 + sur2
        sphinx_plot(P)

    Now let's revolve a parametrically defined circle. We can play with the topology of the surface by changing the axis,
    an axis in `(0,0)` (as the previous one) will produce a sphere-like surface::

        sage: u = var('u')
        sage: circle = (cos(u), sin(u))
        sage: revolution_plot3d(circle, (u,0,2*pi), axis=(0,0), show_curve=True, opacity=0.5).show(aspect_ratio=(1,1,1))

    .. PLOT::

        u = var('u')
        circle = (cos(u), sin(u))
        P = revolution_plot3d(circle, (u,0,2*pi), axis=(0,0), show_curve=True, opacity=0.5)
        sphinx_plot(P)

    An axis on `(0,y)` will produce a cylinder-like surface::

        sage: revolution_plot3d(circle, (u,0,2*pi), axis=(0,2), show_curve=True, opacity=0.5).show(aspect_ratio=(1,1,1))

    .. PLOT::

        u = var('u')
        circle = (cos(u), sin(u))
        P = revolution_plot3d(circle, (u,0,2*pi), axis=(0,2), show_curve=True, opacity=0.5)
        sphinx_plot(P)

    And any other axis will produce a torus-like surface::

        sage: revolution_plot3d(circle, (u,0,2*pi), axis=(2,0), show_curve=True, opacity=0.5).show(aspect_ratio=(1,1,1))

    .. PLOT::

        u = var('u')
        circle = (cos(u), sin(u))
        P = revolution_plot3d(circle, (u,0,2*pi), axis=(2,0), show_curve=True, opacity=0.5)
        sphinx_plot(P)

    Now, we can get another goblet-like surface by revolving a curve in 3d::

        sage: u = var('u')
        sage: curve = (u, cos(4*u), u^2)
        sage: P = revolution_plot3d(curve, (u,0,2), show_curve=True, parallel_axis='z',axis=(1,.2), opacity=0.5)
        sage: P.show(aspect_ratio=(1,1,1))

    .. PLOT::

        u = var('u')
        curve = (u, cos(4*u), u**2)
        P = revolution_plot3d(curve, (u,0,2), show_curve=True, parallel_axis='z', axis=(1,.2), opacity=0.5)
        sphinx_plot(P)

    A curvy curve with only a quarter turn::

        sage: u = var('u')
        sage: curve = (sin(3*u), .8*cos(4*u), cos(u))
        sage: revolution_plot3d(curve, (u,0,pi), (0,pi/2), show_curve=True, parallel_axis='z', opacity=0.5).show(aspect_ratio=(1,1,1),frame=False)

    .. PLOT::

        u = var('u')
        curve = (sin(3*u), .8*cos(4*u), cos(u))
        P = revolution_plot3d(curve, (u,0,pi), (0,pi/2), show_curve=True, parallel_axis='z', opacity=0.5)
        sphinx_plot(P)

    One can also color the surface using a coloring function of two
    parameters and a colormap as follows. Note that the coloring
    function must take values in the interval [0,1]. ::

        sage: u, phi = var('u,phi')
        sage: def cf(u,phi): return sin(phi+u) ^ 2
        sage: curve = (1+u^2/4, 0, u)
        sage: revolution_plot3d(curve, (u,-2,2), (0,2*pi), parallel_axis='z', color=(cf, colormaps.PiYG)).show(aspect_ratio=(1,1,1))

    .. PLOT::

        u, phi = var('u,phi')
        def cf(u, phi): return sin(phi+u) ** 2
        curve = (1+u**2/4, 0, u)
        P = revolution_plot3d(curve, (u,-2,2), (0,2*pi), parallel_axis='z', color=(cf, colormaps.PiYG))
        sphinx_plot(P)

    The first parameter of the coloring function will be identified with the
    parameter of the curve, and the second with the angle parameter.

    .. WARNING::

        This kind of coloring using a colormap can be visualized using
        Jmol, Tachyon (option ``viewer='tachyon'``) and Canvas3D
        (option ``viewer='canvas3d'`` in the notebook).

    Another colored example, illustrating that one can use (colormap, color function) instead of (color function, colormap)::

        sage: u, phi = var('u,phi')
        sage: def cf(u, phi): return float(2 * u / pi) % 1
        sage: curve = (sin(u), 0, u)
        sage: revolution_plot3d(curve, (u,0,pi), (0,2*pi), parallel_axis
        ....: ='z', color=(colormaps.brg, cf)).show(aspect_ratio=1)

    .. PLOT::

        u, phi = var('u,phi')
        def cf(u, phi): return float(2 * u / pi) % 1
        curve = (sin(u), 0, u)
        P = revolution_plot3d(curve, (u,0,pi), (0,2*pi), parallel_axis='z', color=(colormaps.brg, cf))
        sphinx_plot(P)
    """
    from sage.symbolic.ring import SR
    from sage.symbolic.constants import pi
    from sage.misc.functional import sqrt
    from sage.functions.trig import sin
    from sage.functions.trig import cos
    from sage.functions.trig import atan2

    if parallel_axis not in ['x', 'y', 'z']:
        raise ValueError("parallel_axis must be either 'x', 'y', or 'z'.")

    vart = trange[0]

    if str(vart) == 'phi':
        phi = SR.var('fi')
    else:
        phi = SR.var('phi')

    if phirange is None:  # this if-else provides a phirange
        phirange = (phi, 0, 2 * pi)
    elif len(phirange) == 3:
        phi = phirange[0]
    else:
        phirange = (phi, phirange[0], phirange[1])

    if isinstance(curve, (tuple, list)):
        #this if-else provides a vector v to be plotted
        #if curve is a tuple or a list of length 2, it is interpreted as a parametric curve
        #in the x-z plane.
        #if it is of length 3 it is interpreted as a parametric curve in 3d space

        if len(curve) == 2:
            x = curve[0]
            y = 0
            z = curve[1]
        elif len(curve) == 3:
            x = curve[0]
            y = curve[1]
            z = curve[2]
    else:
        x = vart
        y = 0
        z = curve

    phase = 0
    if parallel_axis == 'z':
        x0 = axis[0]
        y0 = axis[1]
        # (0,0) must be handled separately for the phase value
        if x0 != 0 or y0 != 0:
            phase = atan2(y - y0, x - x0)
        R = sqrt((x - x0)**2 + (y - y0)**2)
        v = (R * cos(phi + phase) + x0, R * sin(phi + phase) + y0, z)
    elif parallel_axis == 'x':
        y0 = axis[0]
        z0 = axis[1]
        # (0,0) must be handled separately for the phase value
        if z0 != 0 or y0 != 0:
            phase = atan2(z - z0, y - y0)
        R = sqrt((y - y0)**2 + (z - z0)**2)
        v = (x, R * cos(phi + phase) + y0, R * sin(phi + phase) + z0)
    elif parallel_axis == 'y':
        x0 = axis[0]
        z0 = axis[1]
        # (0,0) must be handled separately for the phase value
        if z0 != 0 or x0 != 0:
            phase = atan2(z - z0, x - x0)
        R = sqrt((x - x0)**2 + (z - z0)**2)
        v = (R * cos(phi + phase) + x0, y, R * sin(phi + phase) + z0)

    if print_vector:
        print(v)

    if show_curve:
        curveplot = parametric_plot3d((x, y, z),
                                      trange,
                                      thickness=2,
                                      rgbcolor=(1, 0, 0))
        return parametric_plot3d(v, trange, phirange, **kwds) + curveplot

    return parametric_plot3d(v, trange, phirange, **kwds)
コード例 #3
0
ファイル: sphere.py プロジェクト: sagemath/sagetrac-mirror
    def _transition_spher_stereo(self):
        r"""
        Initialize the transition map between spherical and stereographic
        coordinates.

        TESTS::

            sage: S1 = manifolds.Sphere(1)
            sage: spher = S1.spherical_coordinates(); spher
            Chart (A, (phi,))
            sage: A = spher.domain()
            sage: stereoN = S1.stereographic_coordinates(pole='north'); stereoN
            Chart (S^1-{NP}, (y1,))
            sage: S1.coord_change(spher, stereoN.restrict(A))
            Change of coordinates from Chart (A, (phi,)) to Chart (A, (y1,))

        """
        # speed-up via simplification method...
        self.set_simplify_function(lambda expr: expr.simplify())

        # configure preexisting charts...
        W = self._stereoN_dom.intersection(self._stereoS_dom)
        A = self._spher_dom
        stereoN, stereoS = self._coordinates['stereographic'][:]
        coordN = stereoN[:]
        coordS = stereoS[:]
        rstN = (coordN[0] != 0, )
        rstS = (coordS[0] != 0, )
        if self._dim > 1:
            rstN += (coordN[0] > 0, )
            rstS += (coordS[0] > 0, )
        stereoN_A = stereoN.restrict(A, rstN)
        stereoS_A = stereoS.restrict(A, rstS)
        self._coord_changes[(stereoN.restrict(W),
                             stereoS.restrict(W))].restrict(A)
        self._coord_changes[(stereoS.restrict(W),
                             stereoN.restrict(W))].restrict(A)
        spher = self._coordinates['spherical'][0]

        R = self._radius
        n = self._dim

        # transition: spher to stereoN...
        imm = self.embedding()
        cart = self._ambient.cartesian_coordinates()
        # get ambient coordinates and shift to coordinate origin:
        x = self._shift_coords(imm.expr(spher, cart), s='-')
        coordfunc = [(R * x[i]) / (R - x[-1]) for i in range(n)]
        # define transition map:
        spher_to_stereoN = spher.transition_map(stereoN_A, coordfunc)

        # transition: stereoN to spher...
        from sage.functions.trig import acos, atan2
        from sage.misc.functional import sqrt
        # get ambient coordinates and shift to coordinate origin:
        x = self._shift_coords(imm.expr(stereoN, cart), s='-')
        coordfunc = [atan2(x[1], x[0])]
        for k in range(2, n + 1):
            c = acos(x[k] / sqrt(sum(x[i]**2 for i in range(k + 1))))
            coordfunc.append(c)
        coordfunc = reversed(coordfunc)
        spher_to_stereoN.set_inverse(*coordfunc, check=False)

        # transition spher <-> stereoS...
        stereoN_to_S_A = self.coord_change(stereoN_A, stereoS_A)
        stereoN_to_S_A * spher_to_stereoN  # generates spher_to_stereoS
        stereoS_to_N_A = self.coord_change(stereoS_A, stereoN_A)
        spher_to_stereoN.inverse(
        ) * stereoS_to_N_A  # generates stereoS_to_spher
コード例 #4
0
ファイル: revolution_plot3d.py プロジェクト: CETHop/sage
def revolution_plot3d(curve,trange,phirange=None,parallel_axis='z',axis=(0,0),print_vector=False,show_curve=False,**kwds):
    """
    Return a plot of a revolved curve.

    There are three ways to call this function:

    - ``revolution_plot3d(f,trange)`` where `f` is a function located in the `x z` plane.

    - ``revolution_plot3d((f_x,f_z),trange)`` where `(f_x,f_z)` is a parametric curve on the `x z` plane.

    - ``revolution_plot3d((f_x,f_y,f_z),trange)`` where `(f_x,f_y,f_z)` can be any parametric curve.

    INPUT:

    - ``curve`` - A curve to be revolved, specified as a function, a 2-tuple or a 3-tuple.

    - ``trange`` - A 3-tuple `(t,t_{\min},t_{\max})` where t is the independent variable of the curve.

    - ``phirange`` - A 2-tuple of the form `(\phi_{\min},\phi_{\max})`, (default `(0,\pi)`) that specifies the angle in which the curve is to be revolved.

    - ``parallel_axis`` - A string (Either 'x', 'y', or 'z') that specifies the coordinate axis parallel to the revolution axis.

    - ``axis`` - A 2-tuple that specifies the position of the revolution axis. If parallel is:

        - 'z' - then axis is the point in which the revolution axis intersects the  `x y` plane.

        - 'x' - then axis is the point in which the revolution axis intersects the  `y z` plane.

        - 'y' - then axis is the point in which the revolution axis intersects the `x z` plane.

    - ``print_vector`` - If True, the parametrization of the surface of revolution will be printed.

    - ``show_curve`` - If True, the curve will be displayed.


    EXAMPLES:

    Let's revolve a simple function around different axes::

        sage: u = var('u')
        sage: f=u^2
        sage: revolution_plot3d(f,(u,0,2),show_curve=True,opacity=0.7).show(aspect_ratio=(1,1,1))

    If we move slightly the axis, we get a goblet-like surface::

        sage: revolution_plot3d(f,(u,0,2),axis=(1,0.2),show_curve=True,opacity=0.5).show(aspect_ratio=(1,1,1))

    A common problem in calculus books, find the volume within the following revolution solid::

        sage: line=u
        sage: parabola=u^2
        sage: sur1=revolution_plot3d(line,(u,0,1),opacity=0.5,rgbcolor=(1,0.5,0),show_curve=True,parallel_axis='x')
        sage: sur2=revolution_plot3d(parabola,(u,0,1),opacity=0.5,rgbcolor=(0,1,0),show_curve=True,parallel_axis='x')
        sage: (sur1+sur2).show()


    Now let's revolve a parametrically defined circle. We can play with the topology of the surface by changing the axis, an axis in `(0,0)` (as the previous one) will produce a sphere-like surface::

        sage: u = var('u')
        sage: circle=(cos(u),sin(u))
        sage: revolution_plot3d(circle,(u,0,2*pi),axis=(0,0),show_curve=True,opacity=0.5).show(aspect_ratio=(1,1,1))

    An axis on `(0,y)` will produce a cylinder-like surface::

        sage: revolution_plot3d(circle,(u,0,2*pi),axis=(0,2),show_curve=True,opacity=0.5).show(aspect_ratio=(1,1,1))

    And any other axis will produce a torus-like surface::

        sage: revolution_plot3d(circle,(u,0,2*pi),axis=(2,0),show_curve=True,opacity=0.5).show(aspect_ratio=(1,1,1))

    Now, we can get another goblet-like surface by revolving a curve in 3d::

        sage: u = var('u')
        sage: curve=(u,cos(4*u),u^2)
        sage: revolution_plot3d(curve,(u,0,2),show_curve=True,parallel_axis='z',axis=(1,.2),opacity=0.5).show(aspect_ratio=(1,1,1))

    A curvy curve with only a quarter turn::

        sage: u = var('u')
        sage: curve=(sin(3*u),.8*cos(4*u),cos(u))
        sage: revolution_plot3d(curve,(u,0,pi),(0,pi/2),show_curve=True,parallel_axis='z',opacity=0.5).show(aspect_ratio=(1,1,1),frame=False)
    """
    from sage.symbolic.ring import var
    from sage.symbolic.constants import pi
    from sage.functions.other import sqrt
    from sage.functions.trig import sin
    from sage.functions.trig import cos
    from sage.functions.trig import atan2


    if parallel_axis not in ['x','y','z']:
        raise ValueError, "parallel_axis must be either 'x', 'y', or 'z'."

    vart=trange[0]


    if str(vart)=='phi':
        phi=var('fi')
    else:
        phi=var('phi')


    if phirange is None:#this if-else provides a phirange
        phirange=(phi,0,2*pi)
    elif len(phirange)==3:
        phi=phirange[0]
        pass
    else:
        phirange=(phi,phirange[0],phirange[1])

    if isinstance(curve,tuple) or isinstance(curve,list):
        #this if-else provides a vector v to be plotted
        #if curve is a tuple or a list of length 2, it is interpreted as a parametric curve
        #in the x-z plane.
        #if it is of length 3 it is interpreted as a parametric curve in 3d space

        if len(curve) ==2:
            x=curve[0]
            y=0
            z=curve[1]
        elif len(curve)==3:
            x=curve[0]
            y=curve[1]
            z=curve[2]
    else:
        x=vart
        y=0
        z=curve

    if parallel_axis=='z':
        x0=axis[0]
        y0=axis[1]
        # (0,0) must be handled separately for the phase value
        phase=0
        if x0!=0 or y0!=0:
            phase=atan2((y-y0),(x-x0))
        R=sqrt((x-x0)**2+(y-y0)**2)
        v=(R*cos(phi+phase)+x0,R*sin(phi+phase)+y0,z)
    elif parallel_axis=='x':
        y0=axis[0]
        z0=axis[1]
        # (0,0) must be handled separately for the phase value
        phase=0
        if z0!=0 or y0!=0:
            phase=atan2((z-z0),(y-y0))
        R=sqrt((y-y0)**2+(z-z0)**2)
        v=(x,R*cos(phi+phase)+y0,R*sin(phi+phase)+z0)
    elif parallel_axis=='y':
        x0=axis[0]
        z0=axis[1]
        # (0,0) must be handled separately for the phase value
        phase=0
        if z0!=0 or x0!=0:
            phase=atan2((z-z0),(x-x0))
        R=sqrt((x-x0)**2+(z-z0)**2)
        v=(R*cos(phi+phase)+x0,y,R*sin(phi+phase)+z0)

    if print_vector:
        print v
    if show_curve:
        curveplot=parametric_plot3d((x,y,z),trange,thickness=2,rgbcolor=(1,0,0))
        return parametric_plot3d(v,trange,phirange,**kwds)+curveplot
    return parametric_plot3d(v,trange,phirange,**kwds)
コード例 #5
0
ファイル: catalog.py プロジェクト: swewers/mein_sage
def Sphere(dim=None, radius=1, names=None, stereo2d=False, stereo_lim=None):
    """
    Generate a sphere embedded in Euclidean space.

    The shortcut operator ``.<,>`` can be used to specify the coordinates.

    INPUT:

    - ``dim`` -- (optional) the dimension of the sphere; if not specified,
      equals to the number of coordinate names
    - ``radius`` -- (default: ``1``) radius of the sphere
    - ``names`` -- (default: ``None``) name of the coordinates,
      automatically set by the shortcut operator
    - ``stereo2d`` -- (default: ``False``) if ``True``, defines only the
      stereographic charts, only implemented in 2d
    - ``stereo_lim`` -- (default: ``None``) parameter used to restrict the
      span of the stereographic charts, so that they don't cover the whole
      sphere; valid domain will be ``x**2 + y**2 < stereo_lim**2``

    OUTPUT:

    - Riemannian manifold

    EXAMPLES::

        sage: S.<th, ph> = manifolds.Sphere()
        sage: S
        2-dimensional Riemannian submanifold S embedded in the Euclidean
         space E^3
        sage: S.atlas()
        [Chart (S, (th, ph))]
        sage: S.metric().display()
        gamma = dth*dth + sin(th)^2 dph*dph

        sage: S = manifolds.Sphere(2, stereo2d=True)  # long time
        sage: S  # long time
        2-dimensional Riemannian submanifold S embedded in the Euclidean
         space E^3
        sage: S.metric().display()  # long time
        gamma = 4/(x^4 + y^4 + 2*(x^2 + 1)*y^2 + 2*x^2 + 1) dx*dx
         + 4/(x^4 + y^4 + 2*(x^2 + 1)*y^2 + 2*x^2 + 1) dy*dy
    """
    from sage.functions.trig import cos, sin, atan, atan2
    from sage.functions.other import sqrt
    from sage.symbolic.constants import pi
    from sage.misc.misc_c import prod
    from sage.manifolds.manifold import Manifold
    from sage.manifolds.differentiable.euclidean import EuclideanSpace

    if dim is None:
        if names is None:
            raise ValueError("either the names or the dimension must be specified")
        dim = len(names)
    else:
        if names is not None and dim != len(names):
            raise ValueError("the number of coordinates does not match the dimension")

    if stereo2d:
        if dim != 2:
            raise NotImplementedError("stereographic charts only "
                                      "implemented for 2d spheres")
        E = EuclideanSpace(3, names=("X", "Y", "Z"))
        S2 = Manifold(dim, 'S', ambient=E, structure='Riemannian')
        U = S2.open_subset('U')
        V = S2.open_subset('V')
        stereoN = U.chart(names=("x", "y"))
        x, y = stereoN[:]
        stereoS = V.chart(names=("xp", "yp"))
        xp, yp = stereoS[:]
        if stereo_lim is not None:
            stereoN.add_restrictions(x**2+y**2 < stereo_lim**2)
            stereoS.add_restrictions(xp**2+yp**2 < stereo_lim**2)

        stereoN_to_S = stereoN.transition_map(stereoS,
          (x / (x**2 + y**2), y / (x**2 + y**2)), intersection_name='W',
          restrictions1=x**2 + y**2 != 0, restrictions2=xp**2+yp**2!=0)
        stereoN_to_S.set_inverse(xp / (xp**2 + yp**2), yp / (xp**2 + yp**2),
                                 check=False)
        W = U.intersection(V)
        stereoN_W = stereoN.restrict(W)
        stereoS_W = stereoS.restrict(W)
        A = W.open_subset('A', coord_def={stereoN_W: (y != 0, x < 0),
                                          stereoS_W: (yp != 0, xp < 0)})
        stereoN_A = stereoN_W.restrict(A)
        if names is None:
            names = tuple(["phi_{}:(0,pi)".format(i) for i in range(dim - 1)] +
                          ["phi_{}:(-pi,pi):periodic".format(dim - 1)])
        else:
            names = tuple([names[i] + ":(0,pi)" for i in range(dim - 1)] +
                          [names[dim - 1] + ":(-pi,pi):periodic"])
        spher = A.chart(names=names)
        th, ph = spher[:]
        spher_to_stereoN = spher.transition_map(stereoN_A, (sin(th)*cos(ph) / (1-cos(th)),
                                                            sin(th)*sin(ph) / (1-cos(th))))
        spher_to_stereoN.set_inverse(2*atan(1/sqrt(x**2+y**2)), atan2(-y, -x)+pi,
                                     check=False)
        stereoN_to_S_A = stereoN_to_S.restrict(A)
        stereoN_to_S_A * spher_to_stereoN # generates spher_to_stereoS
        stereoS_to_N_A = stereoN_to_S.inverse().restrict(A)
        spher_to_stereoN.inverse() * stereoS_to_N_A  # generates stereoS_to_spher

        coordfunc1 = [sin(th)*cos(ph), sin(th)*sin(ph), cos(th)]
        coordfunc2 = [2*x/(1+x**2+y**2), 2*y/(1+x**2+y**2), (x**2+y**2-1)/(1+x**2+y**2)]
        coordfunc3 = [2*xp/(1+xp**2+yp**2), 2*yp/(1+xp**2+yp**2),(1-xp**2-yp**2)/(1+xp**2+yp**2)]
        imm = S2.diff_map(E, {(spher, E.default_chart()): coordfunc1,
                              (stereoN, E.default_chart()): coordfunc2,
                              (stereoS, E.default_chart()): coordfunc3})
        S2.set_embedding(imm)
        S2.induced_metric()

        return S2

    if dim != 2:
        raise NotImplementedError("only implemented for 2 dimensional spheres")

    E = EuclideanSpace(3, symbols='X Y Z')
    M = Manifold(dim, 'S', ambient=E, structure='Riemannian')
    if names is None:
        names = tuple(["phi_{}:(0,pi)".format(i) for i in range(dim-1)] +
                      ["phi_{}:(-pi,pi):periodic".format(dim-1)])
    else:
        names = tuple([names[i]+":(0,pi)"for i in range(dim - 1)] +
                      [names[dim-1]+":(-pi,pi):periodic"])
    C = M.chart(names=names)
    M._first_ngens = C._first_ngens
    phi = M._first_ngens(dim)[:]
    coordfunc = ([radius * prod(sin(phi[j]) for j in range(dim))] +
                 [radius * cos(phi[i]) * prod(sin(phi[j]) for j in range(i))
                  for i in range(dim)])
    imm = M.diff_map(E, coordfunc)
    M.set_embedding(imm)
    M.induced_metric()
    return M