Note: This page has been translated by MathWorks. Please click here

To view all translated materals including this page, select Japan from the country navigator on the bottom of this page.

To view all translated materals including this page, select Japan from the country navigator on the bottom of this page.

**MuPAD® notebooks are not recommended. Use MATLAB® live scripts instead.**

**MATLAB live scripts support most MuPAD functionality, though there are some differences. For more information, see Convert MuPAD Notebooks to MATLAB Live Scripts.**

In the previous section,
we introduced `plotfunc2d`

and `plotfunc3d`

that serve
for plotting functions in 2D and 3D with simple calls in easy syntax.
Although all plot attributes accepted by function graphs (of type `plot::Function2d`

or `plot::Function3d`

, respectively)
are also accepted by `plotfunc2d/3d`

, there remains
a serious restriction: the attributes are used for all functions simultaneously.

If attributes are to be applied to functions individually, one needs to invoke a (slightly) more elaborate calling syntax to generate the plot:

plot( plot::Function2d(f1, x1 = a1..b1, attrib11, attrib12, ...), plot::Function2d(f2, x2 = a2..b2, attrib21, attrib22, ...), ... ):

In this call, each call of `plot::Function2d`

creates
a separate object that represents the graph of the function passed
as the first argument over the plotting range passed as the second
argument. An arbitrary number of plot attributes can be associated
with each function graph. The objects themselves are not displayed
directly. The `plot`

command triggers the evaluation
of the functions on some suitable numerical mesh and calls the renderer
to display these numerical data in the form specified by the given
attributes.

In fact, `plotfunc2d`

and `plotfunc3d`

do precisely
the same: Internally, they generate plot objects of type `plot::Function2d`

or `plot::Function3d`

,
respectively, and call the renderer via `plot`

.

In general, graphical scenes are collections of “graphical
primitives.” There are simple primitives such as points, line
segments, polygons, rectangles and boxes, circles and spheres, histogram
plots, pie charts etc. An example of a more advanced primitive is `plot::VectorField2d`

that
represents a collection of arrows attached to a regular mesh visualizing
a vector field over a rectangular region in *ℝ*^{2}.
Yet more advanced primitives are function graphs and parametrized
curves that come equipped with some internal intelligence, e.g., knowing
how to evaluate themselves numerically on adaptive meshes and how
to clip themselves in case of singularities. The most advanced primitives
in the present `plot`

library are `plot::Ode2d`

, `plot::Ode3d`

and `plot::Implicit2d`

, `plot::Implicit3d`

. The
first automatically solve systems of ordinary differential equations
numerically and display the solutions graphically. The latter display
the solution curves or surfaces of algebraic equations *f*(*x*, *y*)
= 0 or *f*(*x*, *y*, *z*)
= 0, respectively, by solving these equation
numerically.

All these primitives are just “objects” representing some graphical entities. They are not rendered directly when they are created, but just serve as data structures encoding the graphical meaning, collecting attributes defining the presentation style and providing numerical routines to convert the input parameters to some numerical data that are to be sent to the renderer.

An arbitrary number of such primitives can be collected to form
a graphical scene. Finally, a call to `plot`

passing
a sequence of all primitives in the scene invokes the renderer to
draw the plot. The following example shows the graph of the function *f*(*x*)
= *x* *sin*(*x*).
At the point (*x*_{0}, *f*(*x*_{0})),
a graphical point is inserted and the tangent to the graph through
this point is added:

f := x -> x*sin(x): x0 := 1.2: dx := 1: g := plot::Function2d(f(x), x = 0..2*PI): p := plot::Point2d(x0, f(x0)): t := plot::Line2d([x0 - dx, f(x0) - f'(x0)*dx], [x0 + dx, f(x0) + f'(x0)*dx]):

The picture is drawn by calling `plot`

:

plot(g, p, t):

Each primitive accepts a variety of plot attributes that may
be passed as a sequence of equations `AttributeName = AttributeValue`

to
the generating call. Most prominently, each primitive allows to set
the color explicitly:

g := plot::Function2d(f(x), x = 0..2*PI, Color = RGB::Blue):

Alternatively, the generated objects allow to set attributes
via slot assignments of the form ```
primitive::AttributeName
:= AttributeValue
```

as in

p::Color := RGB::Black: p::PointSize := 3.0*unit::mm: t::Color := RGB::Red: t::LineWidth := 1.0*unit::mm:

The help page of each primitive provides a list of all attributes the primitive is reacting to.

Certain attributes such as axes style, the visibility of grid
lines in the background etc. are associated with the whole scene rather
than with the individual primitives. These attributes may be included
in the `plot`

call:

plot(g, p, t, GridVisible = TRUE):

As explained in detail in section The Full Picture: Graphical Trees,
the `plot`

command automatically embeds the graphical
primitives in a coordinate system, which in turn is embedded in a
graphical scene, which is drawn inside a canvas. The various attributes
associated with the general appearance of the whole picture are associated
with these “grouping structures”: a concise list of
all such attributes is provided on the help pages of `plot::Canvas`

, `plot::Scene2d`

, `plot::Scene3d`

, `plot::CoordinateSystem2d`

,
and `plot::CoordinateSystem3d`

,
respectively.

The object browser provided by the MuPAD^{®} graphics tool
allows to select each primitive in the plot. After selection, the
attributes of the primitive can be changed interactively in the property
inspector (see section Viewer,
Browser, and Inspector: Interactive Manipulation).

Next, we wish to demonstrate a animation. It is remarkably simple
to generate an animated picture. We want to let the point *x*_{0} at
which the tangent is added move along the graph of the function. In MuPAD,
you do not need to create an animation frame by frame. Instead, each
primitive can be told to animate itself by simply defining it with
a symbolic animation parameter and adding an animation range for this
parameter. Static and animated objects can be mixed and rendered together.
The static function graph of *f*(*x*) used
in the previous plot is recycled for the animation. The graphical
point at (*x*_{0}, *f*(*x*_{0})) and
the tangent through this point shall be animated using the coordinate `x0`

as
the animation parameter. Deleting its value set above, we can use
the same definitions as before, now with a symbolic `x0`

.
We just have to add the range specification `x0 = 0..2*PI`

for
this parameter:

delete x0: dx := 2/sqrt(1 + f'(x0)^2): p := plot::Point2d(x0, f(x0), x0 = 0..2*PI, Color = RGB::Black, PointSize = 2.0*unit::mm): t := plot::Line2d([x0 - dx, f(x0) - f'(x0)*dx], [x0 + dx, f(x0) + f'(x0)*dx], x0 = 0..2*PI, Color = RGB::Red, LineWidth = 1.0*unit::mm): plot(g, p, t, GridVisible = TRUE):

Details on animations and further examples are provided in section Graphics and Animations.

We summarize the construction principles for graphics with the MuPAD `plot`

library:

Graphical scenes are built from graphical primitives. Section Graphics and Animations provides
a survey of the primitives that are available in the `plot`

library.

Primitives generated by the `plot`

library
are symbolic objects that are not rendered directly. The call ```
plot(Primitive1,
Primitive2, ...)
```

generates the pictures.

Graphical attributes are specified as equations ```
AttributeName
= AttributeValue
```

. Attributes for a graphical primitive may
be passed in the call that generates the primitive. The help page
of each primitive provides a complete list of all attributes the primitive
reacts to.

Attributes determining the general appearance of the picture
may be passed in the `plot`

call. The help pages
of `plot::Canvas`

, `plot::Scene2d`

, `plot::Scene3d`

, `plot::CoordinateSystem2d`

,
and `plot::CoordinateSystem3d`

,
respectively, provide a complete list of all attributes determining
the general appearance.

All attributes can be changed interactively in the viewer.

Presently, 2D and 3D plots are strictly separated. Objects of different dimension cannot be rendered in the same plot.

Animations are not created frame by frame but objectwise (also see section Frame by Frame Animations). An object is animated by generating it with a symbolic animation parameter and providing a range for this parameter in the generating call. Section Graphics and Animations provides for further details on animations.

Presently, it is not possible to add objects to an existing plot. However, using animations, it is possible to let primitives appear one after another in the animated picture. See Graphics and Animations.

We wish to visualize the interpolation of a discrete data sample
by cubic splines. First, we define the data sample, consisting of
a list of points [[*x*_{1}, *y*_{1}],
[*x*_{2}, *y*_{2}],
…]. Suppose they are equidistant sample
points from the graph of the function :

f := x -> x*exp(-x)*sin(5*x): data := [[i/3, f(i/3)] $ i = 0..9]:

We use `numeric::cubicSpline`

to
define the cubic spline interpolant through these data:

S := numeric::cubicSpline(op(data)):

The plot shall consist of the function *f*(*x*) that
provides the data of the sample points and of the spline interpolant *S*(*x*).
The graphs of *f*(*x*) and *S*(*x*) are
generated via `plot::Function2d`

.
The data points are plotted as a `plot::PointList2d`

:

plot( plot::Function2d(f(x), x = 0..3, Color = RGB::Red, LegendText = expr2text(f(x))), plot::PointList2d(data, Color = RGB::Black), plot::Function2d(S(x), x = 0..3, Color = RGB::Blue, LegendText = "spline interpolant"), GridVisible = TRUE, SubgridVisible = TRUE, LegendVisible = TRUE ):

A cycloid is the curve that you get when following a point fixed
to a wheel rolling along a straight line. We visualize this construction
by an animation in which we use the *x* coordinate
of the hub as the animation parameter. The wheel is realized as a
circle. There are 3 points fixed to the wheel: a green point on the
rim, a red point inside the wheel and a blue point outside the wheel:

WheelRadius := 1: WheelCenter := [x, WheelRadius]: WheelRim := plot::Circle2d(WheelRadius, WheelCenter, x = 0..4*PI, LineColor = RGB::Black): WheelHub := plot::Point2d(WheelCenter, x = 0..4*PI, PointColor = RGB::Black): WheelSpoke := plot::Line2d(WheelCenter, [WheelCenter[1] + 1.5*WheelRadius*sin(x), WheelCenter[2] + 1.5*WheelRadius*cos(x)], x = 0..4*PI, LineColor = RGB::Black): color:= [RGB::Red, RGB::Green, RGB::Blue]: r := [1.5*WheelRadius, 1.0*WheelRadius, 0.5*WheelRadius]: for i from 1 to 3 do Point[i] := plot::Point2d([WheelCenter[1] + r[i]*sin(x), WheelCenter[2] + r[i]*cos(x)], x = 0..4*PI, PointColor = color[i], PointSize = 2.0*unit::mm): Cycloid[i] := plot::Curve2d([y + r[i]*sin(y), WheelRadius + r[i]*cos(y)], y = 0..x, x = 0..4*PI, LineColor = color[i]): end_for: plot(WheelRim, WheelHub, WheelSpoke, Point[i] $ i = 1..3, Cycloid[i] $ i = 1..3, Scaling = Constrained, Width = 120*unit::mm, Height = 60*unit::mm):

We wish to visualize the solution of the ordinary differential
equation (ODE) with
the initial condition *y*(0)
= 0. The solution shall be drawn together with
the vector field associated
with this ODE (along the solution curve, the vectors of this field
are tangents of the curve). We use `numeric::odesolve2`

to generate the solution
as a function plot. Since the numerical integrator returns the result
as a list of one floating-point value, one has to pass the single
list entry as `Y(x)[1]`

to `plot::Function2d`

. The vector field is
generated via `plot::VectorField2d`

:

f := (x, y) -> -y^3 + cos(x): Y := numeric::odesolve2( numeric::ode2vectorfield({y'(x) = f(x, y), y(0) = 0}, [y(x)])): plot( plot::Function2d(Y(x)[1], x = 0..6, Color = RGB::Red, LineWidth = 0.7*unit::mm), plot::VectorField2d([1, f(x, y)], x = 0..6, y = -1..1, Color = RGB::Blue, Mesh = [25, 25]), GridVisible = TRUE, SubgridVisible = TRUE, Axes = Frame ):

The radius *r* of
an object with rotational symmetry around the *x*-axis
is measured at various *x* positions:

x | 0.00 | 0.10 | 0.20 | 0.30 | 0.40 | 0.50 | 0.60 | 0.70 | 0.80 | 0.90 | 0.95 | 1.00 |

r(x) | 0.60 | 0.58 | 0.55 | 0.51 | 0.46 | 0.40 | 0.30 | 0.15 | 0.23 | 0.24 | 0.20 | 0.00 |

A spline interpolation is used to define a smooth function *r*(*x*) from
the measurements:

samplepoints := [0.00, 0.60], [0.10, 0.58], [0.20, 0.55], [0.30, 0.51], [0.40, 0.46], [0.50, 0.40], [0.60, 0.30], [0.70, 0.15], [0.80, 0.23], [0.90, 0.24], [0.95, 0.20], [1.00, 0.00]: r := numeric::cubicSpline(samplepoints):

We reconstruct the object as a surface of revolution via `plot::XRotate`

. The
rotation angle is restricted to a range that leaves a gap in the surface.
The spline curve and the sample points are added as a `plot::Curve3d`

and a `plot::PointList3d`

,
respectively, and displayed in this gap:

plot( plot::XRotate(r(x), x = 0..1, AngleRange = 0.6*PI..2.4*PI, Color = RGB::MuPADGold), plot::Curve3d([x, 0, r(x)], x = 0..1, LineWidth = 0.5*unit::mm, Color = RGB::Black), plot::PointList3d([[p[1], 0, p[2]] $ p in samplepoints], PointSize = 2.0*unit::mm, Color = RGB::Red), CameraDirection = [70, -70, 40] ):

The following sum is a Fourier representation of a periodic step function:

We wish to show the convergence of the partial sums

for some small values of *n*.
To this end, we assign the value of *f*_{n}(*x*) to
the MuPAD `identifier`

`f_n`

. For
our second and third example, we will need to accept fractional values
of *n*,
so the code uses `floor`

to
get a “proper” integer value for the sum:

f_n := sum(sin((2*k-1)*x)/(2*k-1), k = 1..floor(n))

First, we use `plotfunc2d`

and
the sequence operator `$`

to plot the first 5 partial
sums into the same coordinate system (and switch off the legend, which
is not useful for this application).

plotfunc2d(f_n $ n = 1..5, LegendVisible = FALSE)

This plot clearly shows what is known as Gibbs' phenomenon:
At the discontinuities of the step function, the approximation “overshoots.”
Plotting more approximations simultaneously is going to create a too
crowded plot to be of use, so to show that using more terms in the
sum does not help against Gibbs' phenomenon, we revert to animations
to show the first 30 partial
sums – this is one of the reasons we used `floor(n)`

above:

plotfunc2d(f_n, x = -5..5, n = 1..30, Frames = 15)

Another possibility of showing the convergence behavior is to create a 3D plot with the second ordinate being the number of terms used in the approximation:

plotfunc3d(f_n, x = -5..5, n = 1..30, Submesh = [5,1], FillColorType = Rainbow)

Was this topic helpful?