5

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 axis. I need to plot parabola and line in 2D and solid revolution 3D, How do it? I have installed anaconda.

Robby
  • 269
  • 4
  • 8
  • It looks like you want us to write some code for you. While many users are willing to produce code for a coder in distress, they usually only help when the poster has already tried to solve the problem on their own. A good way to demonstrate this effort is to include the code you've written so far, example input (if there is any), the expected output, and the output you actually get (console output, tracebacks, etc.). The more detail you provide, the more answers you are likely to receive. Check the [FAQ] and [ask]. – idjaw Apr 07 '16 at 01:12

2 Answers2

7

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()

enter image description here

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.

unutbu
  • 842,883
  • 184
  • 1,785
  • 1,677
  • Your answer is for x-axis. Could you please help me to find the solid of revolution around y-axis? – haccks Apr 23 '17 at 19:10
  • @haccks: Using the above code, simply change `ax.plot_surface(X, Y1, Z1,...)` to `ax.plot_surface(Y1, X, Z1,...)` and do similarly for the second `ax.plot_surface` call. Voila, the surface of revolution will now be around the y-axis. Of course, `X` is now playing the role of "y", and `Y1` and `Y2` are now "x" values, so for clarity you'd also want to change the variable names. But the result is achieved simply by "swapping" `X` and `Y` variables. – unutbu Apr 23 '17 at 19:31
  • I tried that but no luck. Rotation along different axes gives different [area and shape](https://www.wyzant.com/resources/lessons/math/calculus/integration/finding_volume). Swapping `Y1` and `X` will give same area and shape. – haccks Apr 23 '17 at 19:36
  • It should be something like [this](https://mathematica.stackexchange.com/questions/82865/revolution-of-two-curves-around-the-y-axis). – haccks Apr 23 '17 at 19:38
  • You need to solve for `x` as a function of `y` then. With `X` and `Y1` swapped, `X` can then be expressed as a function of `U` (which is the same as `Y1`) and `V`. So instead of `Y1 = (U**2 + 1)*np.cos(V)` you would have `X = (...)*np.cos(V)`, where `(...)` comes from your expression for `x` as a function of `y`. – unutbu Apr 23 '17 at 20:48
  • You mean inverse function? – haccks Apr 23 '17 at 20:55
  • Yes. Find the inverse function expressing `x` as a function of `y`. Then substitute `U` for `y`. Use that in place of `(...)` in `X = (...)*np.cos(V)`. – unutbu Apr 23 '17 at 21:26
  • Yes. That works for function like `y = x**2`, `y = 3*x + 5`. But for function like `y = x**3 + x**2`, it won't work. You can't find inverse for this polynomial (AFAIK). – haccks Apr 23 '17 at 21:29
  • I see a way to plot this without having to solve the cubic (although [there is a formula](https://math.vanderbilt.edu/schectex/courses/cubic/) for that). The code is too long to describe in the comments. If you post a question, I could answer it there. – unutbu Apr 24 '17 at 10:21
  • Let me ask a question then. – haccks Apr 24 '17 at 10:36
  • How would you rotate around a line such as y=-2? – Nathan Dai Dec 18 '21 at 21:42
0

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))
jfkoehler
  • 269
  • 2
  • 17