Greetings the problem:
R is a region in the xy plane bounded by the parabola y=x^2+1 and line y=x+3. A solid of revolution is formed by rotating R around the x axi
Piggybacking on above, you can make these dynamic with widgets or gifs.
Make a gif: Use the gif package:
import gif
@gif.frame
def plot_volume(angle):
fig = plt.figure(figsize = (20, 15))
ax2 = fig.add_subplot(1, 1, 1, projection = '3d')
angles = np.linspace(0, 360, 20)
x = np.linspace(-1, 2, 60)
v = np.linspace(0, 2*angle, 60)
U, V = np.meshgrid(x, v)
Y1 = (U**2 + 1)*np.cos(V)
Z1 = (U**2 + 1)*np.sin(V)
Y2 = (U + 3)*np.cos(V)
Z2 = (U + 3)*np.sin(V)
X = U
ax2.plot_surface(X, Y1, Z1, alpha = 0.2, color = 'blue', rstride = 6, cstride = 6)
ax2.plot_surface(X, Y2, Z2, alpha = 0.2, color = 'red', rstride = 6, cstride = 6)
ax2.set_xlim(-3,3)
ax2.set_ylim(-5,5)
ax2.set_zlim(-5,5)
ax2.view_init(elev = 50, azim = 30*angle)
ax2.plot_wireframe(X, Y2, Z2)
ax2.plot_wireframe(X, Y1, Z1, color = 'black')
ax2._axis3don = False
frames = []
for i in np.linspace(0, 2*np.pi, 20):
frame = plot_volume(i)
frames.append(frame)
gif.save(frames, 'images/vol1.gif', duration = 500)
from IPython.display import Image
Image('images/vol1.gif')
Make Interactive: Use ipywidgets.
def three_d_plotter(angle, rotate, turn):
fig = plt.figure(figsize = (13, 6))
ax = fig.add_subplot(1, 1, 1, projection='3d')
u = np.linspace(-1, 2, 60)
v = np.linspace(0, angle, 60)
U, V = np.meshgrid(u, v)
X = U
Y1 = (U**2 + 1)*np.cos(V)
Z1 = (U**2 + 1)*np.sin(V)
Y2 = (U + 3)*np.cos(V)
Z2 = (U + 3)*np.sin(V)
ax.plot_surface(X, Y1, Z1, alpha=0.3, color='red', rstride=6, cstride=12)
ax.plot_surface(X, Y2, Z2, alpha=0.3, color='blue', rstride=6, cstride=12)
ax.plot_wireframe(X, Y2, Z2, alpha=0.3, color='blue', rstride=6, cstride=12)
ax._axis3don = False
ax.view_init(elev = rotate, azim = turn)
plt.show()
from ipywidgets import interact
import ipywidgets as widgets
interact(three_d_plotter, angle = widgets.FloatSlider(0, min = 0, max = 2*np.pi, step = np.pi/10),
rotate = widgets.FloatSlider(0, min = 0, max = 360, step = 5),
turn = widgets.FloatSlider(0, min = 0, max = 500, step = 5))
You could use plot_surface:
import numpy as np
import matplotlib.pyplot as plt
import mpl_toolkits.mplot3d.axes3d as axes3d
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1, projection='3d')
u = np.linspace(-1, 2, 60)
v = np.linspace(0, 2*np.pi, 60)
U, V = np.meshgrid(u, v)
X = U
Y1 = (U**2 + 1)*np.cos(V)
Z1 = (U**2 + 1)*np.sin(V)
Y2 = (U + 3)*np.cos(V)
Z2 = (U + 3)*np.sin(V)
ax.plot_surface(X, Y1, Z1, alpha=0.3, color='red', rstride=6, cstride=12)
ax.plot_surface(X, Y2, Z2, alpha=0.3, color='blue', rstride=6, cstride=12)
plt.show()
To plot a surface using plot_surface
you begin by identifying two 1-dimensional parameters, u
and v
:
u = np.linspace(-1, 2, 60)
v = np.linspace(0, 2*np.pi, 60)
such that x
, y
, z
are functions of the parameters u
and v
:
x = x(u, v)
y = y(u, v)
z = z(u, v)
The thing to notice about ax.plot_surface
is that its first three arguments
must be 2D arrays. So we use np.meshgrid
to create coordinate matrices (U
and V
) out of coordinate vectors (u
and v
), and define 2D arrays X
, Y
, Z
to be functions of U
and V
:
X = U
Y1 = (U**2 + 1)*np.cos(V)
Z1 = (U**2 + 1)*np.sin(V)
For each location on the coordinate matrices U
and V
, there is a corresponding value for X
and Y
and Z
. This creates a map from 2-dimensional uv
-space to 3-dimensional xyz
-space. For every rectangle in uv
-space there is a face on our surface in xyz
-space. The curved surface drawn by plot_surface
is composed of these flat faces.