1

I want to get 2d and 3d plots as shown below.
The equation of the curve is given.
How can we do so in python?
I know there may be duplicates but at the time of posting I could not fine any useful posts.

My initial attempt is like this:

# Imports
import numpy as np
import matplotlib.pyplot as plt


# to plot the surface rho = b*cosh(z/b) with rho^2 = r^2 + b^2
z = np.arange(-3, 3, 0.01)
rho = np.cosh(z)  # take constant b = 1

plt.plot(rho,z)
plt.show()

Some related links are following:
Rotate around z-axis only in plotly

The 3d-plot should look like this:
enter image description here

Community
  • 1
  • 1
BhishanPoudel
  • 15,974
  • 21
  • 108
  • 169

2 Answers2

2

Ok so I think you are really asking to revolve a 2d curve around an axis to create a surface. I come from a CAD background so that is how i explain things. and I am not the greatest at math so forgive any clunky terminology. Unfortunately you have to do the rest of the math to get all the points for the mesh.

Heres your code:

#import for 3d
from mpl_toolkits.mplot3d import Axes3D

import numpy as np
import matplotlib.pyplot as plt

change arange to linspace which captures the endpoint otherwise arange will be missing the 3.0 at the end of the array:

z = np.linspace(-3, 3, 600)
rho = np.cosh(z)  # take constant b = 1

since rho is your radius at every z height we need to calculate x,y points around that radius. and before that we have to figure out at what positions on that radius to get x,y co-ordinates:

#steps around circle from 0 to 2*pi(360degrees)
#reshape at the end is to be able to use np.dot properly
revolve_steps = np.linspace(0, np.pi*2, 600).reshape(1,600)

the Trig way of getting points around a circle is:
x = r*cos(theta)
y = r*sin(theta)

for you r is your rho, and theta is revolve_steps

by using np.dot to do matrix multiplication you get a 2d array back where the rows of x's and y's will correspond to the z's

theta = revolve_steps
#convert rho to a column vector
rho_column = rho.reshape(600,1)
x = rho_column.dot(np.cos(theta))
y = rho_column.dot(np.sin(theta))
# expand z into a 2d array that matches dimensions of x and y arrays..
# i used np.meshgrid
zs, rs = np.meshgrid(z, rho)

#plotting
fig, ax = plt.subplots(subplot_kw=dict(projection='3d'))
fig.tight_layout(pad = 0.0)
#transpose zs or you get a helix not a revolve.
# you could add rstride = int or cstride = int kwargs to control the mesh density
ax.plot_surface(x, y, zs.T, color = 'white', shade = False)
#view orientation
ax.elev = 30 #30 degrees for a typical isometric view
ax.azim = 30
#turn off the axes to closely mimic picture in original question
ax.set_axis_off()
plt.show()

#ps 600x600x600 pts takes a bit of time to render

I am not sure if it's been fixed in latest version of matplotlib but the setting the aspect ratio of 3d plots with:

ax.set_aspect('equal')

has not worked very well. you can find solutions at this stack overflow question

Community
  • 1
  • 1
Drafter250
  • 138
  • 9
  • Sorry could you please then edit your original question and state that you want the plot to look exactly like the picture. With the only thing visible as the surface lines. Otherwise i feel i answered the question quite completely. That being said regarding the specific 3d view there are azimuth and rotation kwargs to the plot i believe. And numerous ways to turn axes off one of which i believe is plt.axes_off=True or something close. I havnt had much time to tackle the rest of the question. – Drafter250 Feb 29 '16 at 03:53
0

Only rotate the axis, in this case x

import numpy as np
import matplotlib.pyplot as plt
import mpl_toolkits.mplot3d.axes3d as axes3d

np.seterr(divide='ignore', invalid='ignore')

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

x = np.linspace(-3, 3, 60)
rho = np.cosh(x) 
v = np.linspace(0, 2*np.pi, 60)
X, V = np.meshgrid(x, v)

Y = np.cosh(X) * np.cos(V) 
Z = np.cosh(X) * np.sin(V)
ax.set_xlabel('eje X')
ax.set_ylabel('eje Y')
ax.set_zlabel('eje Z')

ax.plot_surface(X, Y, Z, cmap='YlGnBu_r')
plt.plot(x, rho, 'or') #Muestra la curva que se va a rotar
plt.show()

The result:

Solid from red curve

Machavity
  • 30,841
  • 27
  • 92
  • 100