Пример #1
0
def set_axes_labels(graph, xlabel, ylabel, zlabel, **kwds):
    r"""
    Set axes labels for a 3D graphics object ``graph``.

    This is a workaround for the lack of axes labels in 3D plots.
    This sets the labels as :func:`~sage.plot.plot3d.shapes2.text3d`
    objects at locations determined from the bounding box of the
    graphic object ``graph``.

    INPUT:

    - ``graph`` -- :class:`~sage.plot.plot3d.base.Graphics3d`;
      a 3D graphic object
    - ``xlabel`` -- string for the x-axis label
    - ``ylabel`` -- string for the y-axis label
    - ``zlabel`` -- string for the z-axis label
    - ``**kwds`` -- options (e.g. color) for text3d

    OUTPUT:

    - the 3D graphic object with text3d labels added

    EXAMPLES::

        sage: g = sphere()
        sage: g.all
        [Graphics3d Object]
        sage: from sage.manifolds.utilities import set_axes_labels
        sage: ga = set_axes_labels(g, 'X', 'Y', 'Z', color='red')
        sage: ga.all  # the 3D frame has now axes labels
        [Graphics3d Object, Graphics3d Object,
         Graphics3d Object, Graphics3d Object]

    """
    from sage.plot.plot3d.shapes2 import text3d
    xmin, ymin, zmin = graph.bounding_box()[0]
    xmax, ymax, zmax = graph.bounding_box()[1]
    dx = xmax - xmin
    dy = ymax - ymin
    dz = zmax - zmin
    x1 = xmin + dx / 2
    y1 = ymin + dy / 2
    z1 = zmin + dz / 2
    xmin1 = xmin - dx / 20
    xmax1 = xmax + dx / 20
    ymin1 = ymin - dy / 20
    zmin1 = zmin - dz / 20
    graph += text3d('  ' + xlabel, (x1, ymin1, zmin1), **kwds)
    graph += text3d('  ' + ylabel, (xmax1, y1, zmin1), **kwds)
    graph += text3d('  ' + zlabel, (xmin1, ymin1, z1), **kwds)
    return graph
Пример #2
0
def set_axes_labels(graph, xlabel, ylabel, zlabel, **kwds):
    r"""
    Set axes labels for a 3D graphics object ``graph``.

    This is a workaround for the lack of axes labels in 3D plots.
    This sets the labels as :func:`~sage.plot.plot3d.shapes2.text3d`
    objects at locations determined from the bounding box of the
    graphic object ``graph``.

    INPUT:

    - ``graph`` -- :class:`~sage.plot.plot3d.base.Graphics3d`;
      a 3D graphic object
    - ``xlabel`` -- string for the x-axis label
    - ``ylabel`` -- string for the y-axis label
    - ``zlabel`` -- string for the z-axis label
    - ``**kwds`` -- options (e.g. color) for text3d

    OUTPUT:

    - the 3D graphic object with text3d labels added

    EXAMPLES::

        sage: g = sphere()
        sage: g.all
        [Graphics3d Object]
        sage: from sage.manifolds.utilities import set_axes_labels
        sage: ga = set_axes_labels(g, 'X', 'Y', 'Z', color='red')
        sage: ga.all  # the 3D frame has now axes labels
        [Graphics3d Object, Graphics3d Object,
         Graphics3d Object, Graphics3d Object]

    """
    from sage.plot.plot3d.shapes2 import text3d
    xmin, ymin, zmin = graph.bounding_box()[0]
    xmax, ymax, zmax = graph.bounding_box()[1]
    dx = xmax - xmin
    dy = ymax - ymin
    dz = zmax - zmin
    x1 = xmin + dx / 2
    y1 = ymin + dy / 2
    z1 = zmin + dz / 2
    xmin1 = xmin - dx / 20
    xmax1 = xmax + dx / 20
    ymin1 = ymin - dy / 20
    zmin1 = zmin - dz / 20
    graph += text3d('  ' + xlabel, (x1, ymin1, zmin1), **kwds)
    graph += text3d('  ' + ylabel, (xmax1, y1, zmin1), **kwds)
    graph += text3d('  ' + zlabel, (xmin1, ymin1, z1), **kwds)
    return graph
Пример #3
0
def set_axes_labels(graph, xlabel, ylabel, zlabel, **kwds):
    r"""
    Set axes labels for a 3D graphics object.

    This is a workaround for the lack of axes labels in Sage 3D plots; it
    sets the labels as text3d objects at locations determined from the
    bounding box of the graphic object ``graph``.

    INPUT:

    - ``graph`` -- a 3D graphic object, as an instance of
      :class:`~sage.plot.plot3d.base.Graphics3d`
    - ``xlabel`` -- string for the x-axis label
    - ``ylabel`` -- string for the y-axis label
    - ``zlabel`` -- string for the z-axis label
    - ``**kwds`` -- options (e.g. color) for text3d

    OUTPUT:

    - the 3D graphic object with text3d labels added.

    """
    from sage.plot.plot3d.shapes2 import text3d
    xmin, ymin, zmin = graph.bounding_box()[0]
    xmax, ymax, zmax = graph.bounding_box()[1]
    dx = xmax - xmin
    dy = ymax - ymin
    dz = zmax - zmin
    x1 = xmin + dx / 2
    y1 = ymin + dy / 2
    z1 = zmin + dz / 2
    xmin1 = xmin - dx / 20
    xmax1 = xmax + dx / 20
    ymin1 = ymin - dy / 20
    zmin1 = zmin - dz / 20
    graph += text3d('  ' + xlabel, (x1, ymin1, zmin1), **kwds)
    graph += text3d('  ' + ylabel, (xmax1, y1, zmin1), **kwds)
    graph += text3d('  ' + zlabel, (xmin1, ymin1, z1), **kwds)
    return graph
Пример #4
0
def set_axes_labels(graph, xlabel, ylabel, zlabel, **kwds):
    r"""
    Set axes labels for a 3D graphics object.

    This is a workaround for the lack of axes labels in Sage 3D plots; it
    sets the labels as text3d objects at locations determined from the
    bounding box of the graphic object ``graph``.

    INPUT:

    - ``graph`` -- a 3D graphic object, as an instance of
      :class:`~sage.plot.plot3d.base.Graphics3d`
    - ``xlabel`` -- string for the x-axis label
    - ``ylabel`` -- string for the y-axis label
    - ``zlabel`` -- string for the z-axis label
    - ``**kwds`` -- options (e.g. color) for text3d

    OUTPUT:

    - the 3D graphic object with text3d labels added.

    """
    from sage.plot.plot3d.shapes2 import text3d
    xmin, ymin, zmin = graph.bounding_box()[0]
    xmax, ymax, zmax = graph.bounding_box()[1]
    dx = xmax - xmin
    dy = ymax - ymin
    dz = zmax - zmin
    x1 = xmin + dx / 2
    y1 = ymin + dy / 2
    z1 = zmin + dz / 2
    xmin1 = xmin - dx / 20
    xmax1 = xmax + dx / 20
    ymin1 = ymin - dy / 20
    zmin1 = zmin - dz / 20
    graph += text3d('  ' + xlabel, (x1, ymin1, zmin1), **kwds)
    graph += text3d('  ' + ylabel, (xmax1, y1, zmin1), **kwds)
    graph += text3d('  ' + zlabel, (xmin1, ymin1, z1), **kwds)
    return graph
Пример #5
0
    def text(self, label, position):
        r"""
        Return text widget with label ``label`` at position ``position``

        INPUT:

        - ``label`` -- a string, or a Sage object upon which latex will
          be called

        - ``position`` -- a position

        EXAMPLES::

            sage: L = RootSystem(["A",2]).root_lattice()
            sage: options = L.plot_parse_options()
            sage: list(options.text("coucou", [0,1]))
            [Text 'coucou' at the point (0.0,1.0)]
            sage: list(options.text(L.simple_root(1), [0,1]))
            [Text '$\alpha_{1}$' at the point (0.0,1.0)]

            sage: options = RootSystem(["A",2]).root_lattice().plot_parse_options(labels=False)
            sage: options.text("coucou", [0,1])
            0

            sage: options = RootSystem(["B",3]).root_lattice().plot_parse_options()
            sage: print options.text("coucou", [0,1,2]).x3d_str()
            <Transform translation='0 1 2'>
            <Shape><Text string='coucou' solid='true'/><Appearance><Material diffuseColor='0.0 0.0 0.0' shininess='1' specularColor='0.0 0.0 0.0'/></Appearance></Shape>
            <BLANKLINE>
            </Transform>
        """
        if self.labels:
            if self.dimension <= 2:
                if not isinstance(label, basestring):
                    label = "$" + str(latex(label)) + "$"
                from sage.plot.text import text

                return text(label, position, fontsize=15)
            elif self.dimension == 3:
                # LaTeX labels not yet supported in 3D
                if isinstance(label, basestring):
                    label = label.replace("{", "").replace("}", "").replace("$", "").replace("_", "")
                else:
                    label = str(label)
                from sage.plot.plot3d.shapes2 import text3d

                return text3d(label, position)
            else:
                raise NotImplementedError("Plots in dimension > 3")
        else:
            return self.empty()
Пример #6
0
    def text(self, label, position):
        r"""
        Return text widget with label ``label`` at position ``position``

        INPUT:

        - ``label`` -- a string, or a Sage object upon which latex will
          be called

        - ``position`` -- a position

        EXAMPLES::

            sage: L = RootSystem(["A",2]).root_lattice()
            sage: options = L.plot_parse_options()
            sage: list(options.text("coucou", [0,1]))
            [Text 'coucou' at the point (0.0,1.0)]
            sage: list(options.text(L.simple_root(1), [0,1]))
            [Text '$\alpha_{1}$' at the point (0.0,1.0)]

            sage: options = RootSystem(["A",2]).root_lattice().plot_parse_options(labels=False)
            sage: options.text("coucou", [0,1])
            0

            sage: options = RootSystem(["B",3]).root_lattice().plot_parse_options()
            sage: print options.text("coucou", [0,1,2]).x3d_str()
            <Transform translation='0 1 2'>
            <Shape><Text string='coucou' solid='true'/><Appearance><Material diffuseColor='0.0 0.0 0.0' shininess='1' specularColor='0.0 0.0 0.0'/></Appearance></Shape>
            <BLANKLINE>
            </Transform>
        """
        if self.labels:
            if self.dimension <= 2:
                if not isinstance(label, basestring):
                    label = "$" + str(latex(label)) + "$"
                from sage.plot.text import text
                return text(label, position, fontsize=15)
            elif self.dimension == 3:
                # LaTeX labels not yet supported in 3D
                if isinstance(label, basestring):
                    label = label.replace("{", "").replace("}", "").replace(
                        "$", "").replace("_", "")
                else:
                    label = str(label)
                from sage.plot.plot3d.shapes2 import text3d
                return text3d(label, position)
            else:
                raise NotImplementedError("Plots in dimension > 3")
        else:
            return self.empty()
Пример #7
0
    def plot3d(self, **kwds):
        """
        Plots 2D text in 3D.

        EXAMPLES::

            sage: T = text("ABC",(1,1))
            sage: t = T[0]
            sage: s=t.plot3d()
            sage: s.jmol_repr(s.testing_render_params())[0][2]
            'label "ABC"'
            sage: s._trans
            (1.0, 1.0, 0)
        """
        from sage.plot.plot3d.shapes2 import text3d
        options = self._plot3d_options()
        options.update(kwds)
        return text3d(self.string, (self.x, self.y, 0), **options)
Пример #8
0
    def plot3d(self, **kwds):
        """
        Plots 2D text in 3D.

        EXAMPLES::

            sage: T = text("ABC",(1,1))
            sage: t = T[0]
            sage: s=t.plot3d()
            sage: s.jmol_repr(s.testing_render_params())[0][2]
            'label "ABC"'
            sage: s._trans
            (1.0, 1.0, 0)
        """
        from sage.plot.plot3d.shapes2 import text3d
        options = self._plot3d_options()
        options.update(kwds)
        return text3d(self.string, (self.x, self.y, 0), **options)
Пример #9
0
def show_pentaminos(box=(5, 8, 2)):
    r"""
    Show the 17 3-D pentaminos included in the game and the `5 \times 8
    \times 2` box where 16 of them must fit.

    INPUT:

    - ``box`` - tuple of size three (optional, default: ``(5,8,2)``),
      size of the box

    OUTPUT:

        3D Graphic object

    EXAMPLES::

        sage: from sage.games.quantumino import show_pentaminos
        sage: show_pentaminos()    # not tested (1s)

    To remove the frame do::

        sage: show_pentaminos().show(frame=False)  # not tested (1s)
    """
    G = Graphics()
    for i, p in enumerate(pentaminos):
        x = 4 * (i % 4)
        y = 4 * (i / 4)
        q = p + (x, y, 0)
        G += q.show3d()
        G += text3d(str(i), (x, y, 2))
    G += cube(color='gray', opacity=0.5).scale(box).translate((17, 6, 0))

    # hack to set the aspect ratio to 1
    a, b = G.bounding_box()
    a, b = map(vector, (a, b))
    G.frame_aspect_ratio(tuple(b - a))

    return G
Пример #10
0
def show_pentaminos(box=(5,8,2)):
    r"""
    Show the 17 3-D pentaminos included in the game and the `5 \times 8
    \times 2` box where 16 of them must fit.

    INPUT:

    - ``box`` -- tuple of size three (optional, default: ``(5,8,2)``),
      size of the box

    OUTPUT:

    3D Graphic object

    EXAMPLES::

        sage: from sage.games.quantumino import show_pentaminos
        sage: show_pentaminos()    # not tested (1s)

    To remove the frame do::

        sage: show_pentaminos().show(frame=False)  # not tested (1s)
    """
    G = Graphics()
    for i, p in enumerate(pentaminos):
        x = 4 * (i % 4)
        y = 4 * (i // 4)
        q = p + (x, y, 0)
        G += q.show3d()
        G += text3d(str(i), (x, y, 2))
    G += cube(color='gray',opacity=0.5).scale(box).translate((17, 6, 0))

    # hack to set the aspect ratio to 1
    a, b = G.bounding_box()
    a, b = map(vector, (a, b))
    G.frame_aspect_ratio(tuple(b - a))

    return G
Пример #11
0
    def plot(self, chart=None, ambient_coords=None, mapping=None, label=None, parameters=None, **kwds):
        r"""
        For real manifolds, plot ``self`` in a Cartesian graph based
        on the coordinates of some ambient chart.

        The point is drawn in terms of two (2D graphics) or three (3D graphics)
        coordinates of a given chart, called hereafter the *ambient chart*.
        The domain of the ambient chart must contain the point, or its image
        by a continuous manifold map `\Phi`.

        INPUT:

        - ``chart`` -- (default: ``None``) the ambient chart (see above); if
          ``None``, the ambient chart is set the default chart of
          ``self.parent()``
        - ``ambient_coords`` -- (default: ``None``) tuple containing the 2
          or 3 coordinates of the ambient chart in terms of which the plot
          is performed; if ``None``, all the coordinates of the ambient
          chart are considered
        - ``mapping`` -- (default: ``None``)
          :class:`~sage.manifolds.continuous_map.ContinuousMap`; continuous
          manifold map `\Phi` providing the link between the current point
          `p` and the ambient chart ``chart``: the domain of ``chart`` must
          contain `\Phi(p)`; if ``None``, the identity map is assumed
        - ``label`` -- (default: ``None``) label printed next to the point;
          if ``None``, the point's name is used
        - ``parameters`` -- (default: ``None``) dictionary giving the numerical
          values of the parameters that may appear in the point coordinates
        - ``size`` -- (default: 10) size of the point once drawn as a small
          disk or sphere
        - ``color`` -- (default: ``'black'``) color of the point
        - ``label_color`` -- (default: ``None``) color to print the label;
          if ``None``, the value of ``color`` is used
        - ``fontsize`` -- (default: 10) size of the font used to print the
          label
        - ``label_offset`` -- (default: 0.1) determines the separation between
          the point and its label

        OUTPUT:

        - a graphic object, either an instance of
          :class:`~sage.plot.graphics.Graphics` for a 2D plot (i.e. based on
          2 coordinates of the ambient chart) or an instance of
          :class:`~sage.plot.plot3d.base.Graphics3d` for a 3D plot (i.e.
          based on 3 coordinates of the ambient chart)

        EXAMPLES:

        Drawing a point on a 2-dimensional manifold::

            sage: M = Manifold(2, 'M', structure='topological')
            sage: X.<x,y> = M.chart()
            sage: p = M.point((1,3), name='p')
            sage: g = p.plot(X)
            sage: print(g)
            Graphics object consisting of 2 graphics primitives
            sage: gX = X.plot(max_range=4) # plot of the coordinate grid
            sage: g + gX # display of the point atop the coordinate grid
            Graphics object consisting of 20 graphics primitives

        .. PLOT::

            M = Manifold(2, 'M', structure='topological')
            X = M.chart('x y'); x,y = X[:]
            p = M.point((1,3), name='p')
            g = p.plot(X)
            gX = X.plot(max_range=4)
            sphinx_plot(g+gX)

        Actually, since ``X`` is the default chart of the open set in which
        ``p`` has been defined, it can be skipped in the arguments of
        ``plot``::

            sage: g = p.plot()
            sage: g + gX
            Graphics object consisting of 20 graphics primitives

        Call with some options::

            sage: g = p.plot(chart=X, size=40, color='green', label='$P$',
            ....:            label_color='blue', fontsize=20, label_offset=0.3)
            sage: g + gX
            Graphics object consisting of 20 graphics primitives

        .. PLOT::

            M = Manifold(2, 'M', structure='topological')
            X = M.chart('x y'); x,y = X[:]
            p = M.point((1,3), name='p')
            g = p.plot(chart=X, size=40, color='green', label='$P$', \
                       label_color='blue', fontsize=20, label_offset=0.3)
            gX = X.plot(max_range=4)
            sphinx_plot(g+gX)

        Use of the ``parameters`` option to set a numerical value of some
        symbolic variable::

            sage: a = var('a')
            sage: q = M.point((a,2*a), name='q')
            sage: gq = q.plot(parameters={a:-2}, label_offset=0.2)
            sage: g + gX + gq
            Graphics object consisting of 22 graphics primitives

        .. PLOT::

            M = Manifold(2, 'M', structure='topological')
            X = M.chart('x y'); x,y = X[:]
            p = M.point((1,3), name='p')
            g = p.plot(chart=X, size=40, color='green', label='$P$', \
                       label_color='blue', fontsize=20, label_offset=0.3)
            var('a')
            q = M.point((a,2*a), name='q')
            gq = q.plot(parameters={a:-2}, label_offset=0.2)
            gX = X.plot(max_range=4)
            sphinx_plot(g+gX+gq)

        The numerical value is used only for the plot::

            sage: q.coord()
            (a, 2*a)

        Drawing a point on a 3-dimensional manifold::

            sage: M = Manifold(3, 'M', structure='topological')
            sage: X.<x,y,z> = M.chart()
            sage: p = M.point((2,1,3), name='p')
            sage: g = p.plot()
            sage: print(g)
            Graphics3d Object
            sage: gX = X.plot(nb_values=5) # coordinate mesh cube
            sage: g + gX # display of the point atop the coordinate mesh
            Graphics3d Object

        Call with some options::

            sage: g = p.plot(chart=X, size=40, color='green', label='P_1',
            ....:            label_color='blue', fontsize=20, label_offset=0.3)
            sage: g + gX
            Graphics3d Object

        An example of plot via a mapping: plot of a point on a 2-sphere viewed
        in the 3-dimensional space ``M``::

            sage: S2 = Manifold(2, 'S^2', structure='topological')
            sage: U = S2.open_subset('U') # the open set covered by spherical coord.
            sage: XS.<th,ph> = U.chart(r'th:(0,pi):\theta ph:(0,2*pi):\phi')
            sage: p = U.point((pi/4, pi/8), name='p')
            sage: F = S2.continuous_map(M, {(XS, X): [sin(th)*cos(ph),
            ....:                           sin(th)*sin(ph), cos(th)]}, name='F')
            sage: F.display()
            F: S^2 --> M
            on U: (th, ph) |--> (x, y, z) = (cos(ph)*sin(th), sin(ph)*sin(th), cos(th))
            sage: g = p.plot(chart=X, mapping=F)
            sage: gS2 = XS.plot(chart=X, mapping=F, nb_values=9)
            sage: g + gS2
            Graphics3d Object

        Use of the option ``ambient_coords`` for plots on a 4-dimensional
        manifold::

            sage: M = Manifold(4, 'M', structure='topological')
            sage: X.<t,x,y,z> = M.chart()
            sage: p = M.point((1,2,3,4), name='p')
            sage: g = p.plot(X, ambient_coords=(t,x,y), label_offset=0.4)  # the coordinate z is skipped
            sage: gX = X.plot(X, ambient_coords=(t,x,y), nb_values=5)  # long time
            sage: g + gX # 3D plot  # long time
            Graphics3d Object
            sage: g = p.plot(X, ambient_coords=(t,y,z), label_offset=0.4)  # the coordinate x is skipped
            sage: gX = X.plot(X, ambient_coords=(t,y,z), nb_values=5)  # long time
            sage: g + gX # 3D plot  # long time
            Graphics3d Object
            sage: g = p.plot(X, ambient_coords=(y,z), label_offset=0.4)  # the coordinates t and x are skipped
            sage: gX = X.plot(X, ambient_coords=(y,z))
            sage: g + gX # 2D plot
            Graphics object consisting of 20 graphics primitives

        .. PLOT::

            M = Manifold(4, 'M', structure='topological')
            X = M.chart('t x y z'); t,x,y,z = X[:]
            p = M.point((1,2,3,4), name='p')
            g = p.plot(X, ambient_coords=(y,z), label_offset=0.4)
            gX = X.plot(X, ambient_coords=(y,z))
            sphinx_plot(g+gX)

        """
        from sage.plot.point import point2d
        from sage.plot.text import text
        from sage.plot.graphics import Graphics
        from sage.plot.plot3d.shapes2 import point3d, text3d
        from sage.manifolds.chart import Chart

        if self._manifold.base_field_type() != "real":
            raise NotImplementedError(
                "plot of points on manifolds over fields different" " from the real field is not implemented"
            )
        # The ambient chart:
        if chart is None:
            chart = self.parent().default_chart()
        elif not isinstance(chart, Chart):
            raise TypeError("the argument 'chart' must be a coordinate chart")
        # The effective point to be plotted:
        if mapping is None:
            eff_point = self
        else:
            eff_point = mapping(self)
        # The coordinates of the ambient chart used for the plot:
        if ambient_coords is None:
            ambient_coords = chart[:]
        elif not isinstance(ambient_coords, tuple):
            ambient_coords = tuple(ambient_coords)
        nca = len(ambient_coords)
        if nca != 2 and nca != 3:
            raise TypeError("invalid number of ambient coordinates: {}".format(nca))

        # Extract the kwds options
        size = kwds["size"]
        color = kwds["color"]
        label_color = kwds["label_color"]
        fontsize = kwds["fontsize"]
        label_offset = kwds["label_offset"]

        # The point coordinates:
        coords = eff_point.coord(chart)
        xx = chart[:]
        xp = [coords[xx.index(c)] for c in ambient_coords]
        if parameters is not None:
            xps = [coord.substitute(parameters) for coord in xp]
            xp = xps
        xlab = [coord + label_offset for coord in xp]
        if label_color is None:
            label_color = color
        resu = Graphics()
        if nca == 2:
            if label is None:
                label = r"$" + self._latex_name + r"$"
            resu += point2d(xp, color=color, size=size) + text(label, xlab, fontsize=fontsize, color=label_color)
        else:
            if label is None:
                label = self._name
            resu += point3d(xp, color=color, size=size) + text3d(label, xlab, fontsize=fontsize, color=label_color)
        return resu
Пример #12
0
    def plot(self, chart=None, ambient_coords=None, mapping=None, size=10,
             color='black', label=None, label_color=None, fontsize=10,
             label_offset=0.1, parameters=None):
        r"""
        Plot the current point (``self``) in a Cartesian graph based on the
        coordinates of some ambient chart.

        The point is drawn in terms of two (2D graphics) or three (3D graphics)
        coordinates of a given chart, called hereafter the *ambient chart*.
        The domain of the ambient chart must contain the point, or its image
        by a differentiable mapping `\Phi`.

        INPUT:

        - ``chart`` -- (default: ``None``) the ambient chart (see above); if
          ``None``, the ambient chart is set the default chart of
          ``self.containing_set()``
        - ``ambient_coords`` -- (default: ``None``) tuple containing the 2 or 3
          coordinates of the ambient chart in terms of which the plot is
          performed; if ``None``, all the coordinates of the ambient chart are
          considered
        - ``mapping`` -- (default: ``None``) differentiable mapping `\Phi`
          (instance of
          :class:`~sage.geometry.manifolds.diffmapping.DiffMapping`)
          providing the link between the point `p` represented by ``self``
          and the ambient chart ``chart``: the domain of ``chart`` must
          contain `\Phi(p)`; if ``None``, the identity mapping is assumed
        - ``size`` -- (default: 10) size of the point once drawn as a small
          disk or sphere
        - ``color`` -- (default: 'black') color of the point
        - ``label`` -- (default: ``None``) label printed next to the point;
          if ``None``, the point's name is used.
        - ``label_color`` -- (default: ``None``) color to print the label;
          if ``None``, the value of ``color`` is used
        - ``fontsize`` -- (default: 10) size of the font used to print the
          label
        - ``label_offset`` -- (default: 0.1) determines the separation between
          the point and its label
        - ``parameters`` -- (default: ``None``) dictionary giving the numerical
          values of the parameters that may appear in the point coordinates

        OUTPUT:

        - a graphic object, either an instance of
          :class:`~sage.plot.graphics.Graphics` for a 2D plot (i.e. based on
          2 coordinates of the ambient chart) or an instance of
          :class:`~sage.plot.plot3d.base.Graphics3d` for a 3D plot (i.e.
          based on 3 coordinates of the ambient chart)

        EXAMPLES:

        Drawing a point on a 2-dimensional manifold::

            sage: M = Manifold(2, 'M')
            sage: X.<x,y> = M.chart()
            sage: p = M.point((1,3), name='p')
            sage: g = p.plot(X)
            sage: print g
            Graphics object consisting of 2 graphics primitives
            sage: gX = X.plot() # plot of the coordinate grid
            sage: show(g+gX) # display of the point atop the coordinate grid

        Actually, since ``X`` is the default chart of the open set in which
        ``p`` has been defined, it can be skipped in the arguments of
        ``plot``::

            sage: g = p.plot()
            sage: show(g+gX)

        Call with some options::

            sage: g = p.plot(chart=X, size=40, color='green', label='$P$',
            ....:            label_color='blue', fontsize=20, label_offset=0.3)
            sage: show(g+gX)

        Use of the ``parameters`` option to set a numerical value of some
        symbolic variable::

            sage: a = var('a')
            sage: q = M.point((a,2*a), name='q')
            sage: gq = q.plot(parameters={a:-2})
            sage: show(g+gX+gq)

        The numerical value is used only for the plot::

            sage: q.coord()
            (a, 2*a)

        Drawing a point on a 3-dimensional manifold::

            sage: M = Manifold(3, 'M')
            sage: X.<x,y,z> = M.chart()
            sage: p = M.point((2,1,3), name='p')
            sage: g = p.plot()
            sage: print g
            Graphics3d Object
            sage: gX = X.plot(nb_values=5) # coordinate mesh cube
            sage: show(g+gX) # display of the point atop the coordinate mesh

        Call with some options::

            sage: g = p.plot(chart=X, size=40, color='green', label='P_1',
            ....:            label_color='blue', fontsize=20, label_offset=0.3)
            sage: show(g+gX)

        An example of plot via a differential mapping: plot of a point on a
        2-sphere viewed in the 3-dimensional space ``M``::

            sage: S2 = Manifold(2, 'S^2')
            sage: U = S2.open_subset('U') # the open set covered by spherical coord.
            sage: XS.<th,ph> = U.chart(r'th:(0,pi):\theta ph:(0,2*pi):\phi')
            sage: p = U.point((pi/4, pi/8), name='p')
            sage: F = S2.diff_mapping(M, {(XS, X): [sin(th)*cos(ph),
            ....:                         sin(th)*sin(ph), cos(th)]}, name='F')
            sage: F.display()
            F: S^2 --> M
            on U: (th, ph) |--> (x, y, z) = (cos(ph)*sin(th), sin(ph)*sin(th), cos(th))
            sage: g = p.plot(chart=X, mapping=F)
            sage: gS2 = XS.plot(chart=X, mapping=F, nb_values=9)
            sage: show(g+gS2)

        Use of the option ``ambient_coords`` for plots on a 4-dimensional
        manifold::

            sage: M = Manifold(4, 'M')
            sage: X.<t,x,y,z> = M.chart()
            sage: p = M.point((1,2,3,4), name='p')
            sage: g = p.plot(X, ambient_coords=(t,x,y))  # the coordinate z is skipped
            sage: gX = X.plot(X, ambient_coords=(t,x,y), nb_values=5)
            sage: show(g+gX) # 3D plot
            sage: g = p.plot(X, ambient_coords=(t,y,z))  # the coordinate x is skipped
            sage: gX = X.plot(X, ambient_coords=(t,y,z), nb_values=5)
            sage: show(g+gX) # 3D plot
            sage: g = p.plot(X, ambient_coords=(y,z))  # the coordinates t and x are skipped
            sage: gX = X.plot(X, ambient_coords=(y,z))
            sage: show(g+gX) # 2D plot

        """
        from sage.plot.point import point2d
        from sage.plot.text import text
        from sage.plot.graphics import Graphics
        from sage.plot.plot3d.shapes2 import point3d, text3d
        from sage.geometry.manifolds.chart import Chart
        # The ambient chart:
        if chart is None:
            chart = self.containing_set().default_chart()
        elif not isinstance(chart, Chart):
            raise TypeError("the argument 'chart' must be a coordinate chart")
        # The effective point to be plotted:
        if mapping is None:
            eff_point = self
        else:
            eff_point = mapping(self)
        # The coordinates of the ambient chart used for the plot:
        if ambient_coords is None:
            ambient_coords = chart._xx
        elif not isinstance(ambient_coords, tuple):
            ambient_coords = tuple(ambient_coords)
        nca = len(ambient_coords)
        if nca != 2 and nca !=3:
            raise TypeError("Bad number of ambient coordinates: " + str(nca))
        # The point coordinates:
        coords = eff_point.coord(chart)
        xx = chart[:]
        xp = [coords[xx.index(c)] for c in ambient_coords]
        if parameters is not None:
            xps = [coord.substitute(parameters) for coord in xp]
            xp = xps
        xlab = [coord + label_offset for coord in xp]
        if label_color is None:
            label_color = color
        resu = Graphics()
        if nca == 2:
            if label is None:
                label = r'$' + self._latex_name + r'$'
            resu += point2d(xp, color=color, size=size) + \
                    text(label, xlab, fontsize=fontsize, color=label_color)
        else:
            if label is None:
                label = self._name
            resu += point3d(xp, color=color, size=size) + \
                    text3d(label, xlab, fontsize=fontsize, color=label_color)
        return resu
Пример #13
0
    def plot(self,
             chart=None,
             ambient_coords=None,
             mapping=None,
             color='blue',
             print_label=True,
             label=None,
             label_color=None,
             fontsize=10,
             label_offset=0.1,
             parameters=None,
             **extra_options):
        r"""
        Plot the vector in a Cartesian graph based on the coordinates of some
        ambient chart.

        The vector is drawn in terms of two (2D graphics) or three (3D graphics)
        coordinates of a given chart, called hereafter the *ambient chart*.
        The vector's base point `p` (or its image `\Phi(p)` by some
        differentiable mapping `\Phi`) must lie in the ambient chart's domain.
        If `\Phi` is different from the identity mapping, the vector
        actually depicted is `\mathrm{d}\Phi_p(v)`, where `v` is the current
        vector (``self``) (see the example of a vector tangent to the
        2-sphere below, where `\Phi: S^2 \to \RR^3`).

        INPUT:

        - ``chart`` -- (default: ``None``) the ambient chart (see above); if
          ``None``, it is set to the default chart of the open set containing
          the point at which the vector (or the vector image via the
          differential `\mathrm{d}\Phi_p` of ``mapping``) is defined

        - ``ambient_coords`` -- (default: ``None``) tuple containing the 2
          or 3 coordinates of the ambient chart in terms of which the plot
          is performed; if ``None``, all the coordinates of the ambient
          chart are considered

        - ``mapping`` -- (default: ``None``)
          :class:`~sage.manifolds.differentiable.diff_map.DiffMap`;
          differentiable mapping `\Phi` providing the link between the
          point `p` at which the vector is defined and the ambient chart
          ``chart``: the domain of ``chart`` must contain `\Phi(p)`;
          if ``None``, the identity mapping is assumed

        - ``scale`` -- (default: 1) value by which the length of the arrow
          representing the vector is multiplied

        - ``color`` -- (default: 'blue') color of the arrow representing the
          vector

        - ``print_label`` -- (boolean; default: ``True``) determines whether a
          label is printed next to the arrow representing the vector

        - ``label`` -- (string; default: ``None``) label printed next to the
          arrow representing the vector; if ``None``, the vector's symbol is
          used, if any

        - ``label_color`` -- (default: ``None``) color to print the label;
          if ``None``, the value of ``color`` is used

        - ``fontsize`` -- (default: 10) size of the font used to print the
          label

        - ``label_offset`` -- (default: 0.1) determines the separation between
          the vector arrow and the label

        - ``parameters`` -- (default: ``None``) dictionary giving the numerical
          values of the parameters that may appear in the coordinate expression
          of ``self`` (see example below)

        - ``**extra_options`` -- extra options for the arrow plot, like
          ``linestyle``, ``width`` or ``arrowsize`` (see
          :func:`~sage.plot.arrow.arrow2d` and
          :func:`~sage.plot.plot3d.shapes.arrow3d` for details)

        OUTPUT:

        - a graphic object, either an instance of
          :class:`~sage.plot.graphics.Graphics` for a 2D plot (i.e. based on
          2 coordinates of ``chart``) or an instance of
          :class:`~sage.plot.plot3d.base.Graphics3d` for a 3D plot (i.e.
          based on 3 coordinates of ``chart``)

        EXAMPLES:

        Vector tangent to a 2-dimensional manifold::

            sage: M = Manifold(2, 'M')
            sage: X.<x,y> = M.chart()
            sage: p = M((2,2), name='p')
            sage: Tp = M.tangent_space(p)
            sage: v = Tp((2, 1), name='v') ; v
            Tangent vector v at Point p on the 2-dimensional differentiable
             manifold M

        Plot of the vector alone (arrow + label)::

            sage: v.plot()
            Graphics object consisting of 2 graphics primitives

        Plot atop of the chart grid::

            sage: X.plot() + v.plot()
            Graphics object consisting of 20 graphics primitives

        .. PLOT::

            M = Manifold(2, 'M')
            X = M.chart('x y'); x, y = X[:]
            p = M((2,2), name='p'); Tp = M.tangent_space(p)
            v = Tp((2, 1), name='v')
            g = X.plot() + v.plot()
            sphinx_plot(g)

        Plots with various options::

            sage: X.plot() + v.plot(color='green', scale=2, label='V')
            Graphics object consisting of 20 graphics primitives

        .. PLOT::

            M = Manifold(2, 'M')
            X = M.chart('x y'); x, y = X[:]
            p = M((2,2), name='p'); Tp = M.tangent_space(p)
            v = Tp((2, 1), name='v')
            g = X.plot() + v.plot(color='green', scale=2, label='V')
            sphinx_plot(g)

        ::

            sage: X.plot() + v.plot(print_label=False)
            Graphics object consisting of 19 graphics primitives

        .. PLOT::

            M = Manifold(2, 'M')
            X = M.chart('x y'); x, y = X[:]
            p = M((2,2), name='p'); Tp = M.tangent_space(p)
            v = Tp((2, 1), name='v')
            g = X.plot() + v.plot(print_label=False)
            sphinx_plot(g)

        ::

            sage: X.plot() + v.plot(color='green', label_color='black',
            ....:                   fontsize=20, label_offset=0.2)
            Graphics object consisting of 20 graphics primitives

        .. PLOT::

            M = Manifold(2, 'M')
            X = M.chart('x y'); x, y = X[:]
            p = M((2,2), name='p'); Tp = M.tangent_space(p)
            v = Tp((2, 1), name='v')
            g = X.plot() + v.plot(color='green', label_color='black', fontsize=20, label_offset=0.2)
            sphinx_plot(g)

        ::

            sage: X.plot() + v.plot(linestyle=':', width=4, arrowsize=8,
            ....:                   fontsize=20)
            Graphics object consisting of 20 graphics primitives

        .. PLOT::

            M = Manifold(2, 'M')
            X = M.chart('x y'); x, y = X[:]
            p = M((2,2), name='p'); Tp = M.tangent_space(p)
            v = Tp((2, 1), name='v')
            g = X.plot() + v.plot(linestyle=':', width=4, arrowsize=8, fontsize=20)
            sphinx_plot(g)

        Plot with specific values of some free parameters::

            sage: var('a b')
            (a, b)
            sage: v = Tp((1+a, -b^2), name='v') ; v.display()
            v = (a + 1) d/dx - b^2 d/dy
            sage: X.plot() + v.plot(parameters={a: -2, b: 3})
            Graphics object consisting of 20 graphics primitives

        Special case of the zero vector::

            sage: v = Tp.zero() ; v
            Tangent vector zero at Point p on the 2-dimensional differentiable
             manifold M
            sage: X.plot() + v.plot()
            Graphics object consisting of 19 graphics primitives

        Vector tangent to a 4-dimensional manifold::

            sage: M = Manifold(4, 'M')
            sage: X.<t,x,y,z> = M.chart()
            sage: p = M((0,1,2,3), name='p')
            sage: Tp = M.tangent_space(p)
            sage: v = Tp((5,4,3,2), name='v') ; v
            Tangent vector v at Point p on the 4-dimensional differentiable
             manifold M

        We cannot make a 4D plot directly::

            sage: v.plot()
            Traceback (most recent call last):
            ...
            ValueError: the number of coordinates involved in the plot must
             be either 2 or 3, not 4

        Rather, we have to select some chart coordinates for the plot, via
        the argument ``ambient_coords``. For instance, for a 2-dimensional
        plot in terms of the coordinates `(x, y)`::

            sage: v.plot(ambient_coords=(x,y))
            Graphics object consisting of 2 graphics primitives

        .. PLOT::

            M = Manifold(4, 'M')
            X = M.chart('t x y z'); t,x,y,z = X[:]
            p = M((0,1,2,3), name='p'); Tp = M.tangent_space(p)
            v = Tp((5,4,3,2), name='v')
            g = X.plot(ambient_coords=(x,y)) + v.plot(ambient_coords=(x,y))
            sphinx_plot(g)

        This plot involves only the components `v^x` and `v^y` of `v`.
        Similarly, for a 3-dimensional plot in terms of the coordinates
        `(t, x, y)`::

            sage: g = v.plot(ambient_coords=(t,x,z))
            sage: print(g)
            Graphics3d Object

        This plot involves only the components `v^t`,  `v^x` and `v^z` of `v`.
        A nice 3D view atop the coordinate grid is obtained via::

            sage: (X.plot(ambient_coords=(t,x,z))  # long time
            ....:  + v.plot(ambient_coords=(t,x,z),
            ....:           label_offset=0.5, width=6))
            Graphics3d Object

        .. PLOT::

            M = Manifold(4, 'M')
            X = M.chart('t x y z'); t,x,y,z = X[:]
            p = M((0,1,2,3), name='p'); Tp = M.tangent_space(p)
            v = Tp((5,4,3,2), name='v')
            g = X.plot(ambient_coords=(t,x,z)) + v.plot(ambient_coords=(t,x,z),
                       label_offset=0.5, width=6)
            sphinx_plot(g)

        An example of plot via a differential mapping: plot of a vector tangent
        to a 2-sphere viewed in `\RR^3`::

            sage: S2 = Manifold(2, 'S^2')
            sage: U = S2.open_subset('U') # the open set covered by spherical coord.
            sage: XS.<th,ph> = U.chart(r'th:(0,pi):\theta ph:(0,2*pi):\phi')
            sage: R3 = Manifold(3, 'R^3')
            sage: X3.<x,y,z> = R3.chart()
            sage: F = S2.diff_map(R3, {(XS, X3): [sin(th)*cos(ph),
            ....:                                 sin(th)*sin(ph),
            ....:                                 cos(th)]}, name='F')
            sage: F.display() # the standard embedding of S^2 into R^3
            F: S^2 --> R^3
            on U: (th, ph) |--> (x, y, z) = (cos(ph)*sin(th), sin(ph)*sin(th), cos(th))
            sage: p = U.point((pi/4, 7*pi/4), name='p')
            sage: v = XS.frame()[1].at(p) ; v  # the coordinate vector d/dphi at p
            Tangent vector d/dph at Point p on the 2-dimensional differentiable
             manifold S^2
            sage: graph_v = v.plot(mapping=F)
            sage: graph_S2 = XS.plot(chart=X3, mapping=F, number_values=9)  # long time
            sage: graph_v + graph_S2  # long time
            Graphics3d Object

        .. PLOT::

            S2 = Manifold(2, 'S^2')
            U = S2.open_subset('U')
            XS = U.chart(r'th:(0,pi):\theta ph:(0,2*pi):\phi')
            th, ph = XS[:]
            R3 = Manifold(3, 'R^3')
            X3 = R3.chart('x y z')
            F = S2.diff_map(R3, {(XS, X3): [sin(th)*cos(ph), sin(th)*sin(ph),
                                            cos(th)]}, name='F')
            p = U.point((pi/4, 7*pi/4), name='p')
            v = XS.frame()[1].at(p)
            graph_v = v.plot(mapping=F)
            graph_S2 = XS.plot(chart=X3, mapping=F, number_values=9)
            sphinx_plot(graph_v + graph_S2)

        """
        from sage.plot.arrow import arrow2d
        from sage.plot.text import text
        from sage.plot.graphics import Graphics
        from sage.plot.plot3d.shapes import arrow3d
        from sage.plot.plot3d.shapes2 import text3d
        from sage.misc.functional import numerical_approx
        from sage.manifolds.differentiable.chart import DiffChart

        scale = extra_options.pop("scale")

        #
        # The "effective" vector to be plotted
        #
        if mapping is None:
            eff_vector = self
            base_point = self._point
        else:
            #!# check
            # For efficiency, the method FiniteRankFreeModuleMorphism._call_()
            # is called instead of FiniteRankFreeModuleMorphism.__call__()
            eff_vector = mapping.differential(self._point)._call_(self)
            base_point = mapping(self._point)
        #
        # The chart w.r.t. which the vector is plotted
        #
        if chart is None:
            chart = base_point.parent().default_chart()
        elif not isinstance(chart, DiffChart):
            raise TypeError("{} is not a chart".format(chart))
        #
        # Coordinates of the above chart w.r.t. which the vector is plotted
        #
        if ambient_coords is None:
            ambient_coords = chart[:]  # all chart coordinates are used
        n_pc = len(ambient_coords)
        if n_pc != 2 and n_pc != 3:
            raise ValueError("the number of coordinates involved in the " +
                             "plot must be either 2 or 3, not {}".format(n_pc))
        # indices coordinates involved in the plot:
        ind_pc = [chart[:].index(pc) for pc in ambient_coords]
        #
        # Components of the vector w.r.t. the chart frame
        #
        basis = chart.frame().at(base_point)
        vcomp = eff_vector.comp(basis=basis)[:]
        xp = base_point.coord(chart=chart)
        #
        # The arrow
        #
        resu = Graphics()
        if parameters is None:
            coord_tail = [numerical_approx(xp[i]) for i in ind_pc]
            coord_head = [
                numerical_approx(xp[i] + scale * vcomp[i]) for i in ind_pc
            ]
        else:
            coord_tail = [
                numerical_approx(xp[i].substitute(parameters)) for i in ind_pc
            ]
            coord_head = [
                numerical_approx(
                    (xp[i] + scale * vcomp[i]).substitute(parameters))
                for i in ind_pc
            ]
        if coord_head != coord_tail:
            if n_pc == 2:
                resu += arrow2d(tailpoint=coord_tail,
                                headpoint=coord_head,
                                color=color,
                                **extra_options)
            else:
                resu += arrow3d(coord_tail,
                                coord_head,
                                color=color,
                                **extra_options)
        #
        # The label
        #
        if print_label:
            if label is None:
                if n_pc == 2 and self._latex_name is not None:
                    label = r'$' + self._latex_name + r'$'
                if n_pc == 3 and self._name is not None:
                    label = self._name
            if label is not None:
                xlab = [xh + label_offset for xh in coord_head]
                if label_color is None:
                    label_color = color
                if n_pc == 2:
                    resu += text(label,
                                 xlab,
                                 fontsize=fontsize,
                                 color=label_color)
                else:
                    resu += text3d(label,
                                   xlab,
                                   fontsize=fontsize,
                                   color=label_color)
        return resu
Пример #14
0
def plot_hyperplane(hyperplane, **kwds):
    r"""
    Return the plot of a single hyperplane.

    INPUT:

    - ``**kwds`` -- plot options: see below

    OUTPUT:

    A graphics object of the plot.

    .. RUBRIC:: Plot Options

    Beside the usual plot options (enter ``plot?``), the plot command for
    hyperplanes includes the following:

    - ``hyperplane_label`` -- Boolean value or string (default: ``True``).
      If ``True``, the hyperplane is labeled with its equation, if a
      string, it is labeled by that string, otherwise it is not
      labeled.

    - ``label_color`` -- (Default: ``'black'``) Color for hyperplane_label.

    - ``label_fontsize`` -- Size for ``hyperplane_label`` font (default: 14)
      (does not work in 3d, yet).

    - ``label_offset`` -- (Default: 0-dim: 0.1, 1-dim: (0,1),
      2-dim: (0,0,0.2)) Amount by which label is offset from
      ``hyperplane.point()``.

    - ``point_size`` -- (Default: 50) Size of points in a zero-dimensional
      arrangement or of an arrangement over a finite field.

    - ``ranges`` -- Range for the parameters for the parametric plot of the
      hyperplane. If a single positive number ``r`` is given for the
      value of ``ranges``, then the ranges for all parameters are set to
      `[-r, r]`.  Otherwise, for a line in the plane, ``ranges`` has the
      form ``[a, b]`` (default: [-3,3]), and for a plane in 3-space, the
      ``ranges`` has the form ``[[a, b], [c, d]]`` (default: [[-3,3],[-3,3]]).
      (The ranges are centered around ``hyperplane.point()``.)

    EXAMPLES::

        sage: H1.<x> = HyperplaneArrangements(QQ)
        sage: a = 3*x + 4
        sage: a.plot()    # indirect doctest
        Graphics object consisting of 3 graphics primitives
        sage: a.plot(point_size=100,hyperplane_label='hello')
        Graphics object consisting of 3 graphics primitives

    
        sage: H2.<x,y> = HyperplaneArrangements(QQ)
        sage: b = 3*x + 4*y + 5
        sage: b.plot()
        Graphics object consisting of 2 graphics primitives
        sage: b.plot(ranges=(1,5),label_offset=(2,-1))
        Graphics object consisting of 2 graphics primitives
        sage: opts = {'hyperplane_label':True, 'label_color':'green',
        ....:         'label_fontsize':24, 'label_offset':(0,1.5)}
        sage: b.plot(**opts)
        Graphics object consisting of 2 graphics primitives

        sage: H3.<x,y,z> = HyperplaneArrangements(QQ)
        sage: c = 2*x + 3*y + 4*z + 5
        sage: c.plot()
        Graphics3d Object
        sage: c.plot(label_offset=(1,0,1), color='green', label_color='red', frame=False)
        Graphics3d Object
        sage: d = -3*x + 2*y + 2*z + 3
        sage: d.plot(opacity=0.8)
        Graphics3d Object
        sage: e = 4*x + 2*z + 3
        sage: e.plot(ranges=[[-1,1],[0,8]], label_offset=(2,2,1), aspect_ratio=1)
        Graphics3d Object
    """
    if hyperplane.base_ring().characteristic():
        raise NotImplementedError('base field must have characteristic zero')
    elif hyperplane.dimension() not in [
            0, 1, 2
    ]:  # dimension of hyperplane, not ambient space
        raise ValueError('can only plot hyperplanes in dimensions 1, 2, 3')
    # handle extra keywords
    if 'hyperplane_label' in kwds:
        hyp_label = kwds.pop('hyperplane_label')
        if not hyp_label:
            has_hyp_label = False
        else:
            has_hyp_label = True
    else:  # default
        hyp_label = True
        has_hyp_label = True
    if has_hyp_label:
        if hyp_label:  # then label hyperplane with its equation
            if hyperplane.dimension() == 2:  # jmol does not like latex
                label = hyperplane._repr_linear(include_zero=False)
            else:
                label = hyperplane._latex_()
        else:
            label = hyp_label  # a string
    if 'label_color' in kwds:
        label_color = kwds.pop('label_color')
    else:
        label_color = 'black'
    if 'label_fontsize' in kwds:
        label_fontsize = kwds.pop('label_fontsize')
    else:
        label_fontsize = 14
    if 'label_offset' in kwds:
        has_offset = True
        label_offset = kwds.pop('label_offset')
    else:
        has_offset = False  # give default values below
    if 'point_size' in kwds:
        pt_size = kwds.pop('point_size')
    else:
        pt_size = 50
    if 'ranges' in kwds:
        ranges_set = True
        ranges = kwds.pop('ranges')
    else:
        ranges_set = False  # give default values below
    # the extra keywords have now been handled
    # now create the plot
    if hyperplane.dimension() == 0:  # a point on a line
        x, = hyperplane.A()
        d = hyperplane.b()
        p = point((d / x, 0), size=pt_size, **kwds)
        if has_hyp_label:
            if not has_offset:
                label_offset = 0.1
            p += text(label, (d / x, label_offset),
                      color=label_color,
                      fontsize=label_fontsize)
            p += text('', (d / x, label_offset + 0.4))  # add space at top
        if 'ymax' not in kwds:
            kwds['ymax'] = 0.5
    elif hyperplane.dimension() == 1:  # a line in the plane
        pnt = hyperplane.point()
        w = hyperplane.linear_part().matrix()
        t = SR.var('t')
        if ranges_set:
            if isinstance(ranges, (list, tuple)):
                t0, t1 = ranges
            else:  # ranges should be a single positive number
                t0, t1 = -ranges, ranges
        else:  # default
            t0, t1 = -3, 3
        p = parametric_plot(pnt + t * w[0], (t, t0, t1), **kwds)
        if has_hyp_label:
            if has_offset:
                b0, b1 = label_offset
            else:
                b0, b1 = 0, 0.2
            label = text(label, (pnt[0] + b0, pnt[1] + b1),
                         color=label_color,
                         fontsize=label_fontsize)
            p += label
    elif hyperplane.dimension() == 2:  # a plane in 3-space
        pnt = hyperplane.point()
        w = hyperplane.linear_part().matrix()
        s, t = SR.var('s t')
        if ranges_set:
            if isinstance(ranges, (list, tuple)):
                s0, s1 = ranges[0]
                t0, t1 = ranges[1]
            else:  # ranges should be a single positive integers
                s0, s1 = -ranges, ranges
                t0, t1 = -ranges, ranges
        else:  # default
            s0, s1 = -3, 3
            t0, t1 = -3, 3
        p = parametric_plot3d(pnt + s * w[0] + t * w[1], (s, s0, s1),
                              (t, t0, t1), **kwds)
        if has_hyp_label:
            if has_offset:
                b0, b1, b2 = label_offset
            else:
                b0, b1, b2 = 0, 0, 0
            label = text3d(label, (pnt[0] + b0, pnt[1] + b1, pnt[2] + b2),
                           color=label_color,
                           fontsize=label_fontsize)
            p += label
    return p
Пример #15
0
def plot_hyperplane(hyperplane, **kwds):
    r"""
    Return the plot of a single hyperplane.

    INPUT:

    - ``**kwds`` -- plot options: see below

    OUTPUT:

    A graphics object of the plot.

    .. RUBRIC:: Plot Options

    Beside the usual plot options (enter ``plot?``), the plot command for
    hyperplanes includes the following:

    - ``hyperplane_label`` -- Boolean value or string (default: ``True``).
      If ``True``, the hyperplane is labeled with its equation, if a
      string, it is labeled by that string, otherwise it is not
      labeled.

    - ``label_color`` -- (Default: ``'black'``) Color for hyperplane_label.

    - ``label_fontsize`` -- Size for ``hyperplane_label`` font (default: 14)
      (does not work in 3d, yet).

    - ``label_offset`` -- (Default: 0-dim: 0.1, 1-dim: (0,1),
      2-dim: (0,0,0.2)) Amount by which label is offset from
      ``hyperplane.point()``.

    - ``point_size`` -- (Default: 50) Size of points in a zero-dimensional
      arrangement or of an arrangement over a finite field.

    - ``ranges`` -- Range for the parameters for the parametric plot of the
      hyperplane. If a single positive number ``r`` is given for the
      value of ``ranges``, then the ranges for all parameters are set to
      `[-r, r]`.  Otherwise, for a line in the plane, ``ranges`` has the
      form ``[a, b]`` (default: [-3,3]), and for a plane in 3-space, the
      ``ranges`` has the form ``[[a, b], [c, d]]`` (default: [[-3,3],[-3,3]]).
      (The ranges are centered around ``hyperplane.point()``.)

    EXAMPLES::

        sage: H1.<x> = HyperplaneArrangements(QQ)
        sage: a = 3*x + 4
        sage: a.plot()    # indirect doctest
        Graphics object consisting of 3 graphics primitives
        sage: a.plot(point_size=100,hyperplane_label='hello')
        Graphics object consisting of 3 graphics primitives

    
        sage: H2.<x,y> = HyperplaneArrangements(QQ)
        sage: b = 3*x + 4*y + 5
        sage: b.plot()
        Graphics object consisting of 2 graphics primitives
        sage: b.plot(ranges=(1,5),label_offset=(2,-1))
        Graphics object consisting of 2 graphics primitives
        sage: opts = {'hyperplane_label':True, 'label_color':'green',
        ....:         'label_fontsize':24, 'label_offset':(0,1.5)}
        sage: b.plot(**opts)
        Graphics object consisting of 2 graphics primitives

        sage: H3.<x,y,z> = HyperplaneArrangements(QQ)
        sage: c = 2*x + 3*y + 4*z + 5
        sage: c.plot()
        Graphics3d Object
        sage: c.plot(label_offset=(1,0,1), color='green', label_color='red', frame=False)
        Graphics3d Object
        sage: d = -3*x + 2*y + 2*z + 3
        sage: d.plot(opacity=0.8)
        Graphics3d Object
        sage: e = 4*x + 2*z + 3
        sage: e.plot(ranges=[[-1,1],[0,8]], label_offset=(2,2,1), aspect_ratio=1)
        Graphics3d Object
    """
    if hyperplane.base_ring().characteristic() != 0:
        raise NotImplementedError('base field must have characteristic zero')
    elif hyperplane.dimension() not in [0, 1, 2]: # dimension of hyperplane, not ambient space
        raise ValueError('can only plot hyperplanes in dimensions 1, 2, 3')
    # handle extra keywords
    if 'hyperplane_label' in kwds:
        hyp_label = kwds.pop('hyperplane_label')
        if not hyp_label:
            has_hyp_label = False
        else:
            has_hyp_label = True
    else: # default
        hyp_label = True
        has_hyp_label = True
    if has_hyp_label:
        if hyp_label: # then label hyperplane with its equation
            if hyperplane.dimension() == 2: # jmol does not like latex
                label = hyperplane._repr_linear(include_zero=False)
            else:
                label = hyperplane._latex_()
        else:
            label = hyp_label # a string
    if 'label_color' in kwds:
        label_color = kwds.pop('label_color')
    else:
        label_color = 'black'
    if 'label_fontsize' in kwds:
        label_fontsize = kwds.pop('label_fontsize')
    else:
        label_fontsize = 14
    if 'label_offset' in kwds:
        has_offset = True
        label_offset = kwds.pop('label_offset')
    else:
        has_offset = False # give default values below
    if 'point_size' in kwds:
        pt_size = kwds.pop('point_size')
    else:
        pt_size = 50
    if 'ranges' in kwds:
        ranges_set = True
        ranges = kwds.pop('ranges')
    else:
        ranges_set = False # give default values below
    # the extra keywords have now been handled
    # now create the plot
    if hyperplane.dimension() == 0: # a point on a line
        x, = hyperplane.A() 
        d = hyperplane.b()
        p = point((d/x,0), size = pt_size, **kwds)
        if has_hyp_label:
            if not has_offset:
                label_offset = 0.1
            p += text(label, (d/x,label_offset),
                    color=label_color,fontsize=label_fontsize)
            p += text('',(d/x,label_offset+0.4)) # add space at top
        if 'ymax' not in kwds:
            kwds['ymax'] = 0.5
    elif hyperplane.dimension() == 1: # a line in the plane
        pnt = hyperplane.point()
        w = hyperplane.linear_part().matrix()
        x, y = hyperplane.A()
        d = hyperplane.b()
        t = SR.var('t')
        if ranges_set:
            if type(ranges) in [list,tuple]:
                t0, t1 = ranges
            else:  # ranges should be a single positive number
                t0, t1 = -ranges, ranges
        else: # default
            t0, t1 = -3, 3
        p = parametric_plot(pnt+t*w[0], (t,t0,t1), **kwds)
        if has_hyp_label:
            if has_offset:
                b0, b1 = label_offset
            else:
                b0, b1 = 0, 0.2
            label = text(label,(pnt[0]+b0,pnt[1]+b1),
                    color=label_color,fontsize=label_fontsize)
            p += label
    elif hyperplane.dimension() == 2: # a plane in 3-space
        pnt = hyperplane.point()
        w = hyperplane.linear_part().matrix()
        a, b, c = hyperplane.A()
        d = hyperplane.b()
        s,t = SR.var('s t')
        if ranges_set:
            if type(ranges) in [list,tuple]:
                s0, s1 = ranges[0]
                t0, t1 = ranges[1]
            else: # ranges should be a single positive integers
                s0, s1 = -ranges, ranges
                t0, t1 = -ranges, ranges
        else: # default
            s0, s1 = -3, 3
            t0, t1 = -3, 3
        p = parametric_plot3d(pnt+s*w[0]+t*w[1],(s,s0,s1),(t,t0,t1),**kwds)
        if has_hyp_label: 
            if has_offset:
                b0, b1, b2 = label_offset
            else:
                b0, b1, b2 = 0, 0, 0
            label = text3d(label,(pnt[0]+b0,pnt[1]+b1,pnt[2]+b2),
                    color=label_color,fontsize=label_fontsize)
            p += label
    return p
Пример #16
0
    def plot(self, chart=None, ambient_coords=None, mapping=None,
             color='blue', print_label=True, label=None, label_color=None,
             fontsize=10, label_offset=0.1, parameters=None, **extra_options):
        r"""
        Plot the vector in a Cartesian graph based on the coordinates of some
        ambient chart.

        The vector is drawn in terms of two (2D graphics) or three (3D graphics)
        coordinates of a given chart, called hereafter the *ambient chart*.
        The vector's base point `p` (or its image `\Phi(p)` by some
        differentiable mapping `\Phi`) must lie in the ambient chart's domain.
        If `\Phi` is different from the identity mapping, the vector
        actually depicted is `\mathrm{d}\Phi_p(v)`, where `v` is the current
        vector (``self``) (see the example of a vector tangent to the
        2-sphere below, where `\Phi: S^2 \to \RR^3`).

        INPUT:

        - ``chart`` -- (default: ``None``) the ambient chart (see above); if
          ``None``, it is set to the default chart of the open set containing
          the point at which the vector (or the vector image via the
          differential `\mathrm{d}\Phi_p` of ``mapping``) is defined

        - ``ambient_coords`` -- (default: ``None``) tuple containing the 2
          or 3 coordinates of the ambient chart in terms of which the plot
          is performed; if ``None``, all the coordinates of the ambient
          chart are considered

        - ``mapping`` -- (default: ``None``)
          :class:`~sage.manifolds.differentiable.diff_map.DiffMap`;
          differentiable mapping `\Phi` providing the link between the
          point `p` at which the vector is defined and the ambient chart
          ``chart``: the domain of ``chart`` must contain `\Phi(p)`;
          if ``None``, the identity mapping is assumed

        - ``scale`` -- (default: 1) value by which the length of the arrow
          representing the vector is multiplied

        - ``color`` -- (default: 'blue') color of the arrow representing the
          vector

        - ``print_label`` -- (boolean; default: ``True``) determines whether a
          label is printed next to the arrow representing the vector

        - ``label`` -- (string; default: ``None``) label printed next to the
          arrow representing the vector; if ``None``, the vector's symbol is
          used, if any

        - ``label_color`` -- (default: ``None``) color to print the label;
          if ``None``, the value of ``color`` is used

        - ``fontsize`` -- (default: 10) size of the font used to print the
          label

        - ``label_offset`` -- (default: 0.1) determines the separation between
          the vector arrow and the label

        - ``parameters`` -- (default: ``None``) dictionary giving the numerical
          values of the parameters that may appear in the coordinate expression
          of ``self`` (see example below)

        - ``**extra_options`` -- extra options for the arrow plot, like
          ``linestyle``, ``width`` or ``arrowsize`` (see
          :func:`~sage.plot.arrow.arrow2d` and
          :func:`~sage.plot.plot3d.shapes.arrow3d` for details)

        OUTPUT:

        - a graphic object, either an instance of
          :class:`~sage.plot.graphics.Graphics` for a 2D plot (i.e. based on
          2 coordinates of ``chart``) or an instance of
          :class:`~sage.plot.plot3d.base.Graphics3d` for a 3D plot (i.e.
          based on 3 coordinates of ``chart``)

        EXAMPLES:

        Vector tangent to a 2-dimensional manifold::

            sage: M = Manifold(2, 'M')
            sage: X.<x,y> = M.chart()
            sage: p = M((2,2), name='p')
            sage: Tp = M.tangent_space(p)
            sage: v = Tp((2, 1), name='v') ; v
            Tangent vector v at Point p on the 2-dimensional differentiable
             manifold M

        Plot of the vector alone (arrow + label)::

            sage: v.plot()
            Graphics object consisting of 2 graphics primitives

        Plot atop of the chart grid::

            sage: X.plot() + v.plot()
            Graphics object consisting of 20 graphics primitives

        .. PLOT::

            M = Manifold(2, 'M')
            X = M.chart('x y'); x, y = X[:]
            p = M((2,2), name='p'); Tp = M.tangent_space(p)
            v = Tp((2, 1), name='v')
            g = X.plot() + v.plot()
            sphinx_plot(g)

        Plots with various options::

            sage: X.plot() + v.plot(color='green', scale=2, label='V')
            Graphics object consisting of 20 graphics primitives

        .. PLOT::

            M = Manifold(2, 'M')
            X = M.chart('x y'); x, y = X[:]
            p = M((2,2), name='p'); Tp = M.tangent_space(p)
            v = Tp((2, 1), name='v')
            g = X.plot() + v.plot(color='green', scale=2, label='V')
            sphinx_plot(g)

        ::

            sage: X.plot() + v.plot(print_label=False)
            Graphics object consisting of 19 graphics primitives

        .. PLOT::

            M = Manifold(2, 'M')
            X = M.chart('x y'); x, y = X[:]
            p = M((2,2), name='p'); Tp = M.tangent_space(p)
            v = Tp((2, 1), name='v')
            g = X.plot() + v.plot(print_label=False)
            sphinx_plot(g)

        ::

            sage: X.plot() + v.plot(color='green', label_color='black',
            ....:                   fontsize=20, label_offset=0.2)
            Graphics object consisting of 20 graphics primitives

        .. PLOT::

            M = Manifold(2, 'M')
            X = M.chart('x y'); x, y = X[:]
            p = M((2,2), name='p'); Tp = M.tangent_space(p)
            v = Tp((2, 1), name='v')
            g = X.plot() + v.plot(color='green', label_color='black', fontsize=20, label_offset=0.2)
            sphinx_plot(g)

        ::

            sage: X.plot() + v.plot(linestyle=':', width=4, arrowsize=8,
            ....:                   fontsize=20)
            Graphics object consisting of 20 graphics primitives

        .. PLOT::

            M = Manifold(2, 'M')
            X = M.chart('x y'); x, y = X[:]
            p = M((2,2), name='p'); Tp = M.tangent_space(p)
            v = Tp((2, 1), name='v')
            g = X.plot() + v.plot(linestyle=':', width=4, arrowsize=8, fontsize=20)
            sphinx_plot(g)

        Plot with specific values of some free parameters::

            sage: var('a b')
            (a, b)
            sage: v = Tp((1+a, -b^2), name='v') ; v.display()
            v = (a + 1) d/dx - b^2 d/dy
            sage: X.plot() + v.plot(parameters={a: -2, b: 3})
            Graphics object consisting of 20 graphics primitives

        Special case of the zero vector::

            sage: v = Tp.zero() ; v
            Tangent vector zero at Point p on the 2-dimensional differentiable
             manifold M
            sage: X.plot() + v.plot()
            Graphics object consisting of 19 graphics primitives

        Vector tangent to a 4-dimensional manifold::

            sage: M = Manifold(4, 'M')
            sage: X.<t,x,y,z> = M.chart()
            sage: p = M((0,1,2,3), name='p')
            sage: Tp = M.tangent_space(p)
            sage: v = Tp((5,4,3,2), name='v') ; v
            Tangent vector v at Point p on the 4-dimensional differentiable
             manifold M

        We cannot make a 4D plot directly::

            sage: v.plot()
            Traceback (most recent call last):
            ...
            ValueError: the number of coordinates involved in the plot must
             be either 2 or 3, not 4

        Rather, we have to select some chart coordinates for the plot, via
        the argument ``ambient_coords``. For instance, for a 2-dimensional
        plot in terms of the coordinates `(x, y)`::

            sage: v.plot(ambient_coords=(x,y))
            Graphics object consisting of 2 graphics primitives

        .. PLOT::

            M = Manifold(4, 'M')
            X = M.chart('t x y z'); t,x,y,z = X[:]
            p = M((0,1,2,3), name='p'); Tp = M.tangent_space(p)
            v = Tp((5,4,3,2), name='v')
            g = X.plot(ambient_coords=(x,y)) + v.plot(ambient_coords=(x,y))
            sphinx_plot(g)

        This plot involves only the components `v^x` and `v^y` of `v`.
        Similarly, for a 3-dimensional plot in terms of the coordinates
        `(t, x, y)`::

            sage: g = v.plot(ambient_coords=(t,x,z))
            sage: print(g)
            Graphics3d Object

        This plot involves only the components `v^t`,  `v^x` and `v^z` of `v`.
        A nice 3D view atop the coordinate grid is obtained via::

            sage: (X.plot(ambient_coords=(t,x,z))  # long time
            ....:  + v.plot(ambient_coords=(t,x,z),
            ....:           label_offset=0.5, width=6))
            Graphics3d Object

        .. PLOT::

            M = Manifold(4, 'M')
            X = M.chart('t x y z'); t,x,y,z = X[:]
            p = M((0,1,2,3), name='p'); Tp = M.tangent_space(p)
            v = Tp((5,4,3,2), name='v')
            g = X.plot(ambient_coords=(t,x,z)) + v.plot(ambient_coords=(t,x,z),
                       label_offset=0.5, width=6)
            sphinx_plot(g)

        An example of plot via a differential mapping: plot of a vector tangent
        to a 2-sphere viewed in `\RR^3`::

            sage: S2 = Manifold(2, 'S^2')
            sage: U = S2.open_subset('U') # the open set covered by spherical coord.
            sage: XS.<th,ph> = U.chart(r'th:(0,pi):\theta ph:(0,2*pi):\phi')
            sage: R3 = Manifold(3, 'R^3')
            sage: X3.<x,y,z> = R3.chart()
            sage: F = S2.diff_map(R3, {(XS, X3): [sin(th)*cos(ph),
            ....:                                 sin(th)*sin(ph),
            ....:                                 cos(th)]}, name='F')
            sage: F.display() # the standard embedding of S^2 into R^3
            F: S^2 --> R^3
            on U: (th, ph) |--> (x, y, z) = (cos(ph)*sin(th), sin(ph)*sin(th), cos(th))
            sage: p = U.point((pi/4, 7*pi/4), name='p')
            sage: v = XS.frame()[1].at(p) ; v  # the coordinate vector d/dphi at p
            Tangent vector d/dph at Point p on the 2-dimensional differentiable
             manifold S^2
            sage: graph_v = v.plot(mapping=F)
            sage: graph_S2 = XS.plot(chart=X3, mapping=F, number_values=9)  # long time
            sage: graph_v + graph_S2  # long time
            Graphics3d Object

        .. PLOT::

            S2 = Manifold(2, 'S^2')
            U = S2.open_subset('U')
            XS = U.chart(r'th:(0,pi):\theta ph:(0,2*pi):\phi')
            th, ph = XS[:]
            R3 = Manifold(3, 'R^3')
            X3 = R3.chart('x y z')
            F = S2.diff_map(R3, {(XS, X3): [sin(th)*cos(ph), sin(th)*sin(ph),
                                            cos(th)]}, name='F')
            p = U.point((pi/4, 7*pi/4), name='p')
            v = XS.frame()[1].at(p)
            graph_v = v.plot(mapping=F)
            graph_S2 = XS.plot(chart=X3, mapping=F, number_values=9)
            sphinx_plot(graph_v + graph_S2)

        """
        from sage.plot.arrow import arrow2d
        from sage.plot.text import text
        from sage.plot.graphics import Graphics
        from sage.plot.plot3d.shapes import arrow3d
        from sage.plot.plot3d.shapes2 import text3d
        from sage.misc.functional import numerical_approx
        from sage.manifolds.differentiable.chart import DiffChart

        scale = extra_options.pop("scale")

        #
        # The "effective" vector to be plotted
        #
        if mapping is None:
            eff_vector = self
            base_point = self._point
        else:
            #!# check
            # For efficiency, the method FiniteRankFreeModuleMorphism._call_()
            # is called instead of FiniteRankFreeModuleMorphism.__call__()
            eff_vector = mapping.differential(self._point)._call_(self)
            base_point = mapping(self._point)
        #
        # The chart w.r.t. which the vector is plotted
        #
        if chart is None:
            chart = base_point.parent().default_chart()
        elif not isinstance(chart, DiffChart):
            raise TypeError("{} is not a chart".format(chart))
        #
        # Coordinates of the above chart w.r.t. which the vector is plotted
        #
        if ambient_coords is None:
            ambient_coords = chart[:]  # all chart coordinates are used
        n_pc = len(ambient_coords)
        if n_pc != 2 and n_pc !=3:
            raise ValueError("the number of coordinates involved in the " +
                             "plot must be either 2 or 3, not {}".format(n_pc))
        # indices coordinates involved in the plot:
        ind_pc = [chart[:].index(pc) for pc in ambient_coords]
        #
        # Components of the vector w.r.t. the chart frame
        #
        basis = chart.frame().at(base_point)
        vcomp = eff_vector.comp(basis=basis)[:]
        xp = base_point.coord(chart=chart)
        #
        # The arrow
        #
        resu = Graphics()
        if parameters is None:
            coord_tail = [numerical_approx(xp[i]) for i in ind_pc]
            coord_head = [numerical_approx(xp[i] + scale*vcomp[i])
                          for i in ind_pc]
        else:
            coord_tail = [numerical_approx(xp[i].substitute(parameters))
                          for i in ind_pc]
            coord_head = [numerical_approx(
                           (xp[i] + scale*vcomp[i]).substitute(parameters))
                          for i in ind_pc]
        if coord_head != coord_tail:
            if n_pc == 2:
                resu += arrow2d(tailpoint=coord_tail, headpoint=coord_head,
                                color=color, **extra_options)
            else:
                resu += arrow3d(coord_tail, coord_head, color=color,
                                **extra_options)
        #
        # The label
        #
        if print_label:
            if label is None:
                if n_pc == 2 and self._latex_name is not None:
                    label = r'$' + self._latex_name + r'$'
                if n_pc == 3 and self._name is not None:
                    label = self._name
            if label is not None:
                xlab = [xh + label_offset for xh in coord_head]
                if label_color is None:
                    label_color = color
                if n_pc == 2:
                    resu += text(label, xlab, fontsize=fontsize,
                                 color=label_color)
                else:
                    resu += text3d(label, xlab, fontsize=fontsize,
                                   color=label_color)
        return resu
Пример #17
0
    def plot(self,
             chart=None,
             ambient_coords=None,
             mapping=None,
             size=10,
             color='black',
             label=None,
             label_color=None,
             fontsize=10,
             label_offset=0.1,
             parameters=None):
        r"""
        Plot the current point (``self``) in a Cartesian graph based on the
        coordinates of some ambient chart.

        The point is drawn in terms of two (2D graphics) or three (3D graphics)
        coordinates of a given chart, called hereafter the *ambient chart*.
        The domain of the ambient chart must contain the point, or its image
        by a differentiable mapping `\Phi`.

        INPUT:

        - ``chart`` -- (default: ``None``) the ambient chart (see above); if
          ``None``, the ambient chart is set the default chart of
          ``self.containing_set()``
        - ``ambient_coords`` -- (default: ``None``) tuple containing the 2 or 3
          coordinates of the ambient chart in terms of which the plot is
          performed; if ``None``, all the coordinates of the ambient chart are
          considered
        - ``mapping`` -- (default: ``None``) differentiable mapping `\Phi`
          (instance of
          :class:`~sage.geometry.manifolds.diffmapping.DiffMapping`)
          providing the link between the point `p` represented by ``self``
          and the ambient chart ``chart``: the domain of ``chart`` must
          contain `\Phi(p)`; if ``None``, the identity mapping is assumed
        - ``size`` -- (default: 10) size of the point once drawn as a small
          disk or sphere
        - ``color`` -- (default: 'black') color of the point
        - ``label`` -- (default: ``None``) label printed next to the point;
          if ``None``, the point's name is used.
        - ``label_color`` -- (default: ``None``) color to print the label;
          if ``None``, the value of ``color`` is used
        - ``fontsize`` -- (default: 10) size of the font used to print the
          label
        - ``label_offset`` -- (default: 0.1) determines the separation between
          the point and its label
        - ``parameters`` -- (default: ``None``) dictionary giving the numerical
          values of the parameters that may appear in the point coordinates

        OUTPUT:

        - a graphic object, either an instance of
          :class:`~sage.plot.graphics.Graphics` for a 2D plot (i.e. based on
          2 coordinates of the ambient chart) or an instance of
          :class:`~sage.plot.plot3d.base.Graphics3d` for a 3D plot (i.e.
          based on 3 coordinates of the ambient chart)

        EXAMPLES:

        Drawing a point on a 2-dimensional manifold::

            sage: M = Manifold(2, 'M')
            sage: X.<x,y> = M.chart()
            sage: p = M.point((1,3), name='p')
            sage: g = p.plot(X)
            sage: print g
            Graphics object consisting of 2 graphics primitives
            sage: gX = X.plot() # plot of the coordinate grid
            sage: show(g+gX) # display of the point atop the coordinate grid

        Actually, since ``X`` is the default chart of the open set in which
        ``p`` has been defined, it can be skipped in the arguments of
        ``plot``::

            sage: g = p.plot()
            sage: show(g+gX)

        Call with some options::

            sage: g = p.plot(chart=X, size=40, color='green', label='$P$',
            ....:            label_color='blue', fontsize=20, label_offset=0.3)
            sage: show(g+gX)

        Use of the ``parameters`` option to set a numerical value of some
        symbolic variable::

            sage: a = var('a')
            sage: q = M.point((a,2*a), name='q')
            sage: gq = q.plot(parameters={a:-2})
            sage: show(g+gX+gq)

        The numerical value is used only for the plot::

            sage: q.coord()
            (a, 2*a)

        Drawing a point on a 3-dimensional manifold::

            sage: M = Manifold(3, 'M')
            sage: X.<x,y,z> = M.chart()
            sage: p = M.point((2,1,3), name='p')
            sage: g = p.plot()
            sage: print g
            Graphics3d Object
            sage: gX = X.plot(nb_values=5) # coordinate mesh cube
            sage: show(g+gX) # display of the point atop the coordinate mesh

        Call with some options::

            sage: g = p.plot(chart=X, size=40, color='green', label='P_1',
            ....:            label_color='blue', fontsize=20, label_offset=0.3)
            sage: show(g+gX)

        An example of plot via a differential mapping: plot of a point on a
        2-sphere viewed in the 3-dimensional space ``M``::

            sage: S2 = Manifold(2, 'S^2')
            sage: U = S2.open_subset('U') # the open set covered by spherical coord.
            sage: XS.<th,ph> = U.chart(r'th:(0,pi):\theta ph:(0,2*pi):\phi')
            sage: p = U.point((pi/4, pi/8), name='p')
            sage: F = S2.diff_mapping(M, {(XS, X): [sin(th)*cos(ph),
            ....:                         sin(th)*sin(ph), cos(th)]}, name='F')
            sage: F.display()
            F: S^2 --> M
            on U: (th, ph) |--> (x, y, z) = (cos(ph)*sin(th), sin(ph)*sin(th), cos(th))
            sage: g = p.plot(chart=X, mapping=F)
            sage: gS2 = XS.plot(chart=X, mapping=F, nb_values=9)
            sage: show(g+gS2)

        Use of the option ``ambient_coords`` for plots on a 4-dimensional
        manifold::

            sage: M = Manifold(4, 'M')
            sage: X.<t,x,y,z> = M.chart()
            sage: p = M.point((1,2,3,4), name='p')
            sage: g = p.plot(X, ambient_coords=(t,x,y))  # the coordinate z is skipped
            sage: gX = X.plot(X, ambient_coords=(t,x,y), nb_values=5)
            sage: show(g+gX) # 3D plot
            sage: g = p.plot(X, ambient_coords=(t,y,z))  # the coordinate x is skipped
            sage: gX = X.plot(X, ambient_coords=(t,y,z), nb_values=5)
            sage: show(g+gX) # 3D plot
            sage: g = p.plot(X, ambient_coords=(y,z))  # the coordinates t and x are skipped
            sage: gX = X.plot(X, ambient_coords=(y,z))
            sage: show(g+gX) # 2D plot

        """
        from sage.plot.point import point2d
        from sage.plot.text import text
        from sage.plot.graphics import Graphics
        from sage.plot.plot3d.shapes2 import point3d, text3d
        from sage.geometry.manifolds.chart import Chart
        # The ambient chart:
        if chart is None:
            chart = self.containing_set().default_chart()
        elif not isinstance(chart, Chart):
            raise TypeError("the argument 'chart' must be a coordinate chart")
        # The effective point to be plotted:
        if mapping is None:
            eff_point = self
        else:
            eff_point = mapping(self)
        # The coordinates of the ambient chart used for the plot:
        if ambient_coords is None:
            ambient_coords = chart._xx
        elif not isinstance(ambient_coords, tuple):
            ambient_coords = tuple(ambient_coords)
        nca = len(ambient_coords)
        if nca != 2 and nca != 3:
            raise TypeError("Bad number of ambient coordinates: " + str(nca))
        # The point coordinates:
        coords = eff_point.coord(chart)
        xx = chart[:]
        xp = [coords[xx.index(c)] for c in ambient_coords]
        if parameters is not None:
            xps = [coord.substitute(parameters) for coord in xp]
            xp = xps
        xlab = [coord + label_offset for coord in xp]
        if label_color is None:
            label_color = color
        resu = Graphics()
        if nca == 2:
            if label is None:
                label = r'$' + self._latex_name + r'$'
            resu += point2d(xp, color=color, size=size) + \
                    text(label, xlab, fontsize=fontsize, color=label_color)
        else:
            if label is None:
                label = self._name
            resu += point3d(xp, color=color, size=size) + \
                    text3d(label, xlab, fontsize=fontsize, color=label_color)
        return resu
Пример #18
0
    def plot(self,
             chart=None,
             ambient_coords=None,
             mapping=None,
             label=None,
             parameters=None,
             **kwds):
        r"""
        For real manifolds, plot ``self`` in a Cartesian graph based
        on the coordinates of some ambient chart.

        The point is drawn in terms of two (2D graphics) or three (3D graphics)
        coordinates of a given chart, called hereafter the *ambient chart*.
        The domain of the ambient chart must contain the point, or its image
        by a continuous manifold map `\Phi`.

        INPUT:

        - ``chart`` -- (default: ``None``) the ambient chart (see above); if
          ``None``, the ambient chart is set the default chart of
          ``self.parent()``
        - ``ambient_coords`` -- (default: ``None``) tuple containing the 2
          or 3 coordinates of the ambient chart in terms of which the plot
          is performed; if ``None``, all the coordinates of the ambient
          chart are considered
        - ``mapping`` -- (default: ``None``)
          :class:`~sage.manifolds.continuous_map.ContinuousMap`; continuous
          manifold map `\Phi` providing the link between the current point
          `p` and the ambient chart ``chart``: the domain of ``chart`` must
          contain `\Phi(p)`; if ``None``, the identity map is assumed
        - ``label`` -- (default: ``None``) label printed next to the point;
          if ``None``, the point's name is used
        - ``parameters`` -- (default: ``None``) dictionary giving the numerical
          values of the parameters that may appear in the point coordinates
        - ``size`` -- (default: 10) size of the point once drawn as a small
          disk or sphere
        - ``color`` -- (default: ``'black'``) color of the point
        - ``label_color`` -- (default: ``None``) color to print the label;
          if ``None``, the value of ``color`` is used
        - ``fontsize`` -- (default: 10) size of the font used to print the
          label
        - ``label_offset`` -- (default: 0.1) determines the separation between
          the point and its label

        OUTPUT:

        - a graphic object, either an instance of
          :class:`~sage.plot.graphics.Graphics` for a 2D plot (i.e. based on
          2 coordinates of the ambient chart) or an instance of
          :class:`~sage.plot.plot3d.base.Graphics3d` for a 3D plot (i.e.
          based on 3 coordinates of the ambient chart)

        EXAMPLES:

        Drawing a point on a 2-dimensional manifold::

            sage: M = Manifold(2, 'M', structure='topological')
            sage: X.<x,y> = M.chart()
            sage: p = M.point((1,3), name='p')
            sage: g = p.plot(X)
            sage: print(g)
            Graphics object consisting of 2 graphics primitives
            sage: gX = X.plot(max_range=4) # plot of the coordinate grid
            sage: g + gX # display of the point atop the coordinate grid
            Graphics object consisting of 20 graphics primitives

        .. PLOT::

            M = Manifold(2, 'M', structure='topological')
            X = M.chart('x y'); x,y = X[:]
            p = M.point((1,3), name='p')
            g = p.plot(X)
            gX = X.plot(max_range=4)
            sphinx_plot(g+gX)

        Actually, since ``X`` is the default chart of the open set in which
        ``p`` has been defined, it can be skipped in the arguments of
        ``plot``::

            sage: g = p.plot()
            sage: g + gX
            Graphics object consisting of 20 graphics primitives

        Call with some options::

            sage: g = p.plot(chart=X, size=40, color='green', label='$P$',
            ....:            label_color='blue', fontsize=20, label_offset=0.3)
            sage: g + gX
            Graphics object consisting of 20 graphics primitives

        .. PLOT::

            M = Manifold(2, 'M', structure='topological')
            X = M.chart('x y'); x,y = X[:]
            p = M.point((1,3), name='p')
            g = p.plot(chart=X, size=40, color='green', label='$P$', \
                       label_color='blue', fontsize=20, label_offset=0.3)
            gX = X.plot(max_range=4)
            sphinx_plot(g+gX)

        Use of the ``parameters`` option to set a numerical value of some
        symbolic variable::

            sage: a = var('a')
            sage: q = M.point((a,2*a), name='q')
            sage: gq = q.plot(parameters={a:-2}, label_offset=0.2)
            sage: g + gX + gq
            Graphics object consisting of 22 graphics primitives

        .. PLOT::

            M = Manifold(2, 'M', structure='topological')
            X = M.chart('x y'); x,y = X[:]
            p = M.point((1,3), name='p')
            g = p.plot(chart=X, size=40, color='green', label='$P$', \
                       label_color='blue', fontsize=20, label_offset=0.3)
            var('a')
            q = M.point((a,2*a), name='q')
            gq = q.plot(parameters={a:-2}, label_offset=0.2)
            gX = X.plot(max_range=4)
            sphinx_plot(g+gX+gq)

        The numerical value is used only for the plot::

            sage: q.coord()
            (a, 2*a)

        Drawing a point on a 3-dimensional manifold::

            sage: M = Manifold(3, 'M', structure='topological')
            sage: X.<x,y,z> = M.chart()
            sage: p = M.point((2,1,3), name='p')
            sage: g = p.plot()
            sage: print(g)
            Graphics3d Object
            sage: gX = X.plot(number_values=5) # coordinate mesh cube
            sage: g + gX # display of the point atop the coordinate mesh
            Graphics3d Object

        Call with some options::

            sage: g = p.plot(chart=X, size=40, color='green', label='P_1',
            ....:            label_color='blue', fontsize=20, label_offset=0.3)
            sage: g + gX
            Graphics3d Object

        An example of plot via a mapping: plot of a point on a 2-sphere viewed
        in the 3-dimensional space ``M``::

            sage: S2 = Manifold(2, 'S^2', structure='topological')
            sage: U = S2.open_subset('U') # the open set covered by spherical coord.
            sage: XS.<th,ph> = U.chart(r'th:(0,pi):\theta ph:(0,2*pi):\phi')
            sage: p = U.point((pi/4, pi/8), name='p')
            sage: F = S2.continuous_map(M, {(XS, X): [sin(th)*cos(ph),
            ....:                           sin(th)*sin(ph), cos(th)]}, name='F')
            sage: F.display()
            F: S^2 --> M
            on U: (th, ph) |--> (x, y, z) = (cos(ph)*sin(th), sin(ph)*sin(th), cos(th))
            sage: g = p.plot(chart=X, mapping=F)
            sage: gS2 = XS.plot(chart=X, mapping=F, number_values=9)
            sage: g + gS2
            Graphics3d Object

        Use of the option ``ambient_coords`` for plots on a 4-dimensional
        manifold::

            sage: M = Manifold(4, 'M', structure='topological')
            sage: X.<t,x,y,z> = M.chart()
            sage: p = M.point((1,2,3,4), name='p')
            sage: g = p.plot(X, ambient_coords=(t,x,y), label_offset=0.4)  # the coordinate z is skipped
            sage: gX = X.plot(X, ambient_coords=(t,x,y), number_values=5)  # long time
            sage: g + gX # 3D plot  # long time
            Graphics3d Object
            sage: g = p.plot(X, ambient_coords=(t,y,z), label_offset=0.4)  # the coordinate x is skipped
            sage: gX = X.plot(X, ambient_coords=(t,y,z), number_values=5)  # long time
            sage: g + gX # 3D plot  # long time
            Graphics3d Object
            sage: g = p.plot(X, ambient_coords=(y,z), label_offset=0.4)  # the coordinates t and x are skipped
            sage: gX = X.plot(X, ambient_coords=(y,z))
            sage: g + gX # 2D plot
            Graphics object consisting of 20 graphics primitives

        .. PLOT::

            M = Manifold(4, 'M', structure='topological')
            X = M.chart('t x y z'); t,x,y,z = X[:]
            p = M.point((1,2,3,4), name='p')
            g = p.plot(X, ambient_coords=(y,z), label_offset=0.4)
            gX = X.plot(X, ambient_coords=(y,z))
            sphinx_plot(g+gX)

        """
        from sage.plot.point import point2d
        from sage.plot.text import text
        from sage.plot.graphics import Graphics
        from sage.plot.plot3d.shapes2 import point3d, text3d
        from sage.manifolds.chart import Chart
        if self._manifold.base_field_type() != 'real':
            raise NotImplementedError(
                'plot of points on manifolds over fields different'
                ' from the real field is not implemented')
        # The ambient chart:
        if chart is None:
            chart = self.parent().default_chart()
        elif not isinstance(chart, Chart):
            raise TypeError("the argument 'chart' must be a coordinate chart")
        # The effective point to be plotted:
        if mapping is None:
            eff_point = self
        else:
            eff_point = mapping(self)
        # The coordinates of the ambient chart used for the plot:
        if ambient_coords is None:
            ambient_coords = chart[:]
        elif not isinstance(ambient_coords, tuple):
            ambient_coords = tuple(ambient_coords)
        nca = len(ambient_coords)
        if nca != 2 and nca != 3:
            raise TypeError(
                "invalid number of ambient coordinates: {}".format(nca))

        # Extract the kwds options
        size = kwds['size']
        color = kwds['color']
        label_color = kwds['label_color']
        fontsize = kwds['fontsize']
        label_offset = kwds['label_offset']

        # The point coordinates:
        coords = eff_point.coord(chart)
        xx = chart[:]
        xp = [coords[xx.index(c)] for c in ambient_coords]
        if parameters is not None:
            xps = [coord.substitute(parameters) for coord in xp]
            xp = xps
        xlab = [coord + label_offset for coord in xp]
        if label_color is None:
            label_color = color
        resu = Graphics()
        if nca == 2:
            if label is None:
                label = r'$' + self._latex_name + r'$'
            resu += (point2d(xp, color=color, size=size) +
                     text(label, xlab, fontsize=fontsize, color=label_color))
        else:
            if label is None:
                label = self._name
            resu += (point3d(xp, color=color, size=size) +
                     text3d(label, xlab, fontsize=fontsize, color=label_color))
        return resu