```
using CalculusWithJulia
using Plots
plotly()
import Contour: contours, levels, level, lines, coordinates
using LinearAlgebra
using ForwardDiff
```

# 59 2D and 3D plots in Julia with Plots

This section uses these add-on packages:

This covers plotting the typical 2D and 3D plots in Julia with the `Plots`

package.

We will make use of some helper functions that will simplify plotting provided by the `CalculusWithJulia`

package. As well, we will need to manipulate contours directly, so pull in the `Contours`

package, using `import`

to avoid name collisions and explicitly listing the methods we will use.

## 59.1 Parametrically described curves in space

Let \(r(t)\) be a vector-valued function with values in \(R^d\), \(d\) being \(2\) or \(3\). A familiar example is the equation for a line that travels in the direction of \(\vec{v}\) and goes through the point \(P\): \(r(t) = P + t \cdot \vec{v}\). A *parametric plot* over \([a,b]\) is the collection of all points \(r(t)\) for \(a \leq t \leq b\).

In `Plots`

, parameterized curves can be plotted through two interfaces, here illustrated for \(d=2\): `plot(f1, f2, a, b)`

or `plot(xs, ys)`

. The former is convenient for some cases, but typically we will have a function `r(t)`

which is vector-valued, as opposed to a vector of functions. As such, we only discuss the latter.

An example helps illustrate. Suppose \(r(t) = \langle \sin(t), 2\cos(t) \rangle\) and the goal is to plot the full ellipse by plotting over \(0 \leq t \leq 2\pi\). As with plotting of curves, the goal would be to take many points between `a`

and `b`

and from there generate the \(x\) values and \(y\) values.

Let’s see this with 5 points, the first and last being identical due to the curve:

```
r₂(t) = [sin(t), 2cos(t)]
= range(0, stop=2pi, length=5) ts
```

`0.0:1.5707963267948966:6.283185307179586`

Then we can create the \(5\) points easily through broadcasting:

`= r₂.(ts) vs `

```
5-element Vector{Vector{Float64}}:
[0.0, 2.0]
[1.0, 1.2246467991473532e-16]
[1.2246467991473532e-16, -2.0]
[-1.0, -3.6739403974420594e-16]
[-2.4492935982947064e-16, 2.0]
```

This returns a vector of points (stored as vectors). The plotting function wants two collections: the set of \(x\) values for the points and the set of \(y\) values. The data needs to be generated differently or reshaped. The function `unzip`

above takes data in this style and returns the desired format, returning a tuple with the \(x\) values and \(y\) values pulled out:

`unzip(vs)`

`([0.0, 1.0, 1.2246467991473532e-16, -1.0, -2.4492935982947064e-16], [2.0, 1.2246467991473532e-16, -2.0, -3.6739403974420594e-16, 2.0])`

To plot this, we “splat” the tuple so that `plot`

gets the arguments separately:

`plot(unzip(vs)...)`

This basic plot is lacking, of course, as there are not enough points. Using more initially is a remedy.

```
= range(0, 2pi, length=100)
ts plot(unzip(r₂.(ts))...)
```

As a convenience, `CalculusWithJulia`

provides `plot_parametric`

to produce this plot. The interval is specified with the `a..b`

notation of `IntervalSets`

(which is available when the `CalculusWithJulia`

package is loaded), the points to plot are adaptively chosen:

`plot_parametric(0..2pi, r₂) # interval first`

### 59.1.1 Plotting a space curve in 3 dimensions

A parametrically described curve in 3D is similarly created. For example, a helix is described mathematically by \(r(t) = \langle \sin(t), \cos(t), t \rangle\). Here we graph two turns:

```
r₃(t) = [sin(t), cos(t), t]
plot_parametric(0..4pi, r₃)
```

### 59.1.2 Adding a vector

The tangent vector indicates the instantaneous direction one would travel were they walking along the space curve. We can add a tangent vector to the graph. The `quiver!`

function would be used to add a 2D vector, but `Plots`

does not currently have a `3D`

analog. In addition, `quiver!`

has a somewhat cumbersome calling pattern when adding just one vector. The `CalculusWithJulia`

package defines an `arrow!`

function that uses `quiver`

for 2D arrows and a simple line for 3D arrows. As a vector incorporates magnitude and direction, but not a position, `arrow!`

needs both a point for the position and a vector.

Here is how we can visualize the tangent vector at a few points on the helix:

```
plot_parametric(0..4pi, r₃, legend=false)
= range(0, 4pi, length=5)
ts for t in ts
arrow!(r₃(t), r₃'(t))
end
```

Adding many arrows this way would be inefficient.

### 59.1.3 Setting a viewing angle for 3D plots

For 3D plots, the viewing angle can make the difference in visualizing the key features. In `Plots`

, some backends allow the viewing angle to be set with the mouse by clicking and dragging. Not all do. For such, the `camera`

argument is used, as in `camera(azimuthal, elevation)`

where the angles are given in degrees. If the \(x\)-\(y\)-\(z\) coordinates are given, then `elevation`

or *inclination*, is the angle between the \(z\) axis and the \(x-y\) plane (so `90`

is a top view) and `azimuthal`

is the angle in the \(x-y\) plane from the \(x\) axes.

## 59.2 Visualizing functions from \(R^2 \rightarrow R\)

If a function \(f: R^2 \rightarrow R\) then a graph of \((x,y,f(x,y))\) can be represented in 3D. It will form a surface. Such graphs can be most simply made by specifying a set of \(x\) values, a set of \(y\) values and a function \(f\), as with:

```
= range(-2, stop=2, length=100)
xs = range(-pi, stop=pi, length=100)
ys f(x,y) = x*sin(y)
surface(xs, ys, f)
```

Rather than pass in a function, values can be passed in. Here they are generated with a list comprehension. The `y`

values are innermost to match the graphic when passing in a function object:

```
= [f(x,y) for y in ys, x in xs]
zs surface(xs, ys, zs)
```

Remembering if the `ys`

or `xs`

go first in the above can be hard. Alternatively, broadcasting can be used. The command `f.(xs,ys)`

would return a vector, as the `xs`

and `ys`

match in shape–they are both column vectors. But the *transpose* of `xs`

looks like a *row* vector and `ys`

looks like a column vector, so broadcasting will create a matrix of values, as desired here:

`surface(xs, ys, f.(xs', ys))`