I have this half cylinder plot, but it is not closed on the surface. How to make it close?
Is it possible to plot cylinder from vertices and sides? With 2 vertices become an arc?
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d.art3d import Poly3DCollection, Line3DCollection
import numpy as np
def data_for_cylinder_along_z(center_x,center_y,radius,height_z):
z = np.linspace(0, height_z, 50)
theta = np.linspace(0, 1*np.pi, 50)
theta_grid, z_grid=np.meshgrid(theta, z)
x_grid = radius*np.cos(theta_grid) + center_x
y_grid = radius*np.sin(theta_grid) + center_y
return x_grid,y_grid,z_grid
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
Xc,Yc,Zc = data_for_cylinder_along_z(0.2,0.2,0.05,0.1)
ax.plot_surface(Xc, Yc, Zc, alpha=0.5)
# Annotation
ax.set_title("Half Cylinder"))
plt.show()
If you can accept manually plotting each plane to enclose the shape, here's the code:
def data_for_horizontal_plane(center_x, center_y, radius, height_z):
# define the horizontal surface using polar coordinates
_radius = np.linspace(0, radius)
_theta = np.linspace(0, np.pi)
R, T = np.meshgrid(_radius, _theta)
# convert polar to cartesian coordinates and add translation
X = R*np.cos(T) + center_x
Y = R*np.sin(T) + center_y
Z = np.zeros(X.shape) + height_z
return X, Y, Z
def data_for_vertical_plane(center_x, center_y, radius, height_z):
# define the vertical rectangle on the X-Z plane
x = np.linspace(center_x - radius, center_x + radius)
z = np.linspace(0, height_z)
X, Z = np.meshgrid(x, z)
Y = np.zeros(X.shape) + center_y
return X, Y, Z
X, Y, Z = data_for_horizontal_plane(0.2, 0.2, 0.05, 0.0)
ax.plot_surface(X, Y, Z, alpha=0.5)
X, Y, Z = data_for_horizontal_plane(0.2, 0.2, 0.05, 0.1)
ax.plot_surface(X, Y, Z, alpha=0.5)
X, Y, Z = data_for_vertical_plane(0.2, 0.2, 0.05, 0.1)
ax.plot_surface(X, Y, Z, alpha=0.5)
Related
I am trying to plot the following function on a unit sphere, the points should be on the sphere and fill up the whole sphere however some of the points are falling off. Any suggestions why? I believe it is because the sphere is not spanning 1,1,1 3D grid but I am not sure how to edit my code to fix this.
from itertools import product, combinations
import matplotlib
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
def d(kx,ky):
M = 1
B = 1
vf = 1
kxx,kyy = np.meshgrid(kx,ky)
x = (vf*kxx)/(np.sqrt(((((vf**2)*(kxx**2)))+((vf**2)*(kyy**2))+(M-B*(kxx**2+(kyy**2)))**2)))
y = (vf*kxx)/(np.sqrt(((((vf**2)*(kxx**2)))+((vf**2)*(kyy**2))+(M-B*(kxx**2+(kyy**2)))**2)))
z = (M-B*(kxx**2+(kyy**2)))/(np.sqrt(((((vf**2)*(kxx**2)))+((vf**2)*(kyy**2))+(M-B*(kxx**2+(kyy**2)))**2)))
return x,y,z
kx = np.linspace(-2, 2, 10)
ky = np.linspace(-2, 2, 10)
xi, yi, zi = d(kx,ky)
phi = np.linspace(0, np.pi, 100)
theta = np.linspace(0, 2*np.pi, 100)
phi, theta = np.meshgrid(phi, theta)
x = np.sin(phi) * np.cos(theta)
y = np.sin(phi) * np.sin(theta)
z = np.cos(phi)
fig = plt.figure(figsize=plt.figaspect(1.))
ax = fig.add_subplot(111, projection='3d')
ax.plot_surface(x, y, z, color="w", rstride=1, cstride=1)
ax.scatter(xi,yi,zi,color="k",s=20)
plt.show()
Thank you kindly,
I'm looking for help to draw a 3D cone using matplotlib.
My goal is to draw a HSL cone, then base on the vertex coordinats i will select the color.
from matplotlib import cm
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
theta1 = np.linspace(0, 2*np.pi, 100)
r1 = np.linspace(-2, 0, 100)
t1, R1 = np.meshgrid(theta1, r1)
X1 = R1*np.cos(t1)
Y1 = R1*np.sin(t1)
Z1 = 5+R1*2.5
theta2 = np.linspace(0, 2*np.pi, 100)
r2 = np.linspace(0, 2, 100)
t2, R2 = np.meshgrid(theta2, r2)
X2 = R2*np.cos(t2)
Y2 = R2*np.sin(t2)
Z2 = -5+R2*2.5
ax.set_xlabel('x axis')
ax.set_ylabel('y axis')
ax.set_zlabel('z axis')
# ax.set_xlim(-2.5, 2.5)
# ax.set_ylim(-2.5, 2.5)
# ax.set_zlim(0, 5)
ax.set_aspect('equal')
ax.plot_surface(X1, Y1, Z1, alpha=0.8, color="blue")
ax.plot_surface(X2, Y2, Z2, alpha=0.8, color="blue")
# ax.plot_surface(X, Y, Z, alpha=0.8)
#fig. savefig ("Cone.png", dpi=100, transparent = False)
plt.show()
HSL CONE
My cone
So my question now is how to define color of each element.
i have found a solution, maybe it will be usefull for others.
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
import matplotlib.pyplot as plt
import numpy as np
import colorsys
from matplotlib.tri import Triangulation
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
n_angles = 80
n_radii = 20
# An array of radii
# Does not include radius r=0, this is to eliminate duplicate points
radii = np.linspace(0.0, 0.5, n_radii)
# An array of angles
angles = np.linspace(0, 2*np.pi, n_angles, endpoint=False)
# Repeat all angles for each radius
angles = np.repeat(angles[..., np.newaxis], n_radii, axis=1)
# Convert polar (radii, angles) coords to cartesian (x, y) coords
# (0, 0) is added here. There are no duplicate points in the (x, y) plane
x = np.append(0, (radii*np.cos(angles)).flatten())
y = np.append(0, (radii*np.sin(angles)).flatten())
# Pringle surface
z = 1+-np.sqrt(x**2+y**2)*2
print(x.shape, y.shape, angles.shape, radii.shape, z.shape)
# NOTE: This assumes that there is a nice projection of the surface into the x/y-plane!
tri = Triangulation(x, y)
triangle_vertices = np.array([np.array([[x[T[0]], y[T[0]], z[T[0]]],
[x[T[1]], y[T[1]], z[T[1]]],
[x[T[2]], y[T[2]], z[T[2]]]]) for T in tri.triangles])
x2 = np.append(0, (radii*np.cos(angles)).flatten())
y2 = np.append(0, (radii*np.sin(angles)).flatten())
# Pringle surface
z2 = -1+np.sqrt(x**2+y**2)*2
# NOTE: This assumes that there is a nice projection of the surface into the x/y-plane!
tri2 = Triangulation(x2, y2)
triangle_vertices2 = np.array([np.array([[x2[T[0]], y2[T[0]], z2[T[0]]],
[x2[T[1]], y2[T[1]], z2[T[1]]],
[x2[T[2]], y2[T[2]], z2[T[2]]]]) for T in tri2.triangles])
triangle_vertices = np.concatenate([triangle_vertices, triangle_vertices2])
midpoints = np.average(triangle_vertices, axis=1)
def find_color_for_point(pt):
c_x, c_y, c_z = pt
angle = np.arctan2(c_x, c_y)*180/np.pi
if (angle < 0):
angle = angle + 360
if c_z < 0:
l = 0.5 - abs(c_z)/2
#l=0
if c_z == 0:
l = 0.5
if c_z > 0:
l = (1 - (1-c_z)/2)
if c_z > 0.97:
l = (1 - (1-c_z)/2)
col = colorsys.hls_to_rgb(angle/360, l, 1)
return col
facecolors = [find_color_for_point(pt) for pt in midpoints] # smooth gradient
# facecolors = [np.random.random(3) for pt in midpoints] # random colors
coll = Poly3DCollection(
triangle_vertices, facecolors=facecolors, edgecolors=None)
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.add_collection(coll)
ax.set_xlim(-1, 1)
ax.set_ylim(-1, 1)
ax.set_zlim(-1, 1)
ax.elev = 50
plt.show()
Inspired from Jake Vanderplas with Python Data Science Handbook, when you are drawing some 3-D plot whose base is a circle, it is likely that you would try:
# Actually not sure about the math here though:
u, v = np.mgrid[0:2*np.pi:100j, 0:np.pi:20j]
x = np.cos(u)*np.sin(v)
y = np.sin(u)*np.sin(v)
and then think about the z-axis. Since viewing from the z-axis the cone is just a circle, so the relationships between z and x and y is clear, which is simply: z = np.sqrt(x ** 2 + y ** 2). Then you can draw the cone based on the codes below:
from mpl_toolkits import mplot3d
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm
def f(x, y):
return np.sqrt(x ** 2 + y ** 2)
fig = plt.figure()
ax = plt.axes(projection='3d')
# Can manipulate with 100j and 80j values to make your cone looks different
u, v = np.mgrid[0:2*np.pi:100j, 0:np.pi:80j]
x = np.cos(u)*np.sin(v)
y = np.sin(u)*np.sin(v)
z = f(x, y)
ax.plot_surface(x, y, z, cmap=cm.coolwarm)
# Some other effects you may want to try based on your needs:
# ax.plot_surface(x, y, -z, cmap=cm.coolwarm)
# ax.scatter3D(x, y, z, color="b")
# ax.plot_wireframe(x, y, z, color="b")
# ax.plot_wireframe(x, y, -z, color="r")
# Can set your view from different angles.
ax.view_init(azim=15, elev=15)
ax.set_xlabel("x")
ax.set_ylabel("y")
ax.set_zlabel("z")
plt.show()
ax.set_ylabel("y")
ax.set_zlabel("z")
plt.show()
And from my side, the cone looks like:
and hope it helps.
Basically I have two graphs and I want to plot them both without overlapping one over the other.
from matplotlib import cm
from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
X = np.arange(0, 5, 0.05)
Y = np.arange(0, 5, 0.05)
X, Y = np.meshgrid(X, Y)
Z = (np.sin(X) / X) + 2
X1 = np.arange(0, 5, 0.05)
Y1 = np.arange(0, 5, 0.05)
X1, Y1 = np.meshgrid(X1, Y1)
Z1 = (X / X) + 1
ax.plot_surface(X, Y, Z, alpha = 1, rstride=10, cstride=10, cmap=cm.autumn,linewidth=0.5, antialiased=True, zorder = 0.3)
ax.plot_surface(X, Y, Z1, alpha = 1, rstride=10, cstride=10, cmap=cm.winter, linewidth=0.5, antialiased=True, zorder = 0.5)
plt.show()
We can see here that we have two graphs However when viewed at 90 degrees
Why does this happen and how to proceed?
I am trying to plot a wireframe using plot_wireframe from the Axes3D module. My dataset: three 2D arrays: two created with np.arange and then np.meshgrid. The third one is an array containing results of function "f2" (f2 = f(x, y)). I expected 3D plot, but result is 2D plot in 3D space. Now I made some code that looks like a part of documantation of mpl, but still doesn't work. Code:
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
def f2(x, y):
'''Return f(x, y) = exp(-(x * x + y * y)) * sin(-5. * (x * x + y * y))'''
return np.exp(-(x**2 + y**2)) * np.sin(-5.0 * (x**2 + y**2))
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
x2 = np.arange(-1.5, 1.5, 0.02)
y2 = np.arange(1.5, -1.5, -0.02)
X, Y = np.meshgrid(x2, y2)
z2 = f2(X, Y)
ax.plot_wireframe(X, X, z2, rstride=10, cstride=10, linewidth=0.1,
label='$\exp(-(x^2 + y^2)){sin}(-5.0(x^2 + y^2)$')
plt.show()
That is what I want:
Beautiful 3D plot
But the reality is cruel:
"A plot I've got"
I have no idea what I'm doing wrong. Is it a problem with values of vectors?
Change
ax.plot_wireframe(X, X, z2, rstride=10, cstride=10, linewidth=0.1,
label='$\exp(-(x^2 + y^2)){sin}(-5.0(x^2 + y^2)$')
to
ax.plot_wireframe(X, Y, z2, rstride=10, cstride=10, linewidth=0.1,
label='$\exp(-(x^2 + y^2)){sin}(-5.0(x^2 + y^2)$')
You are using X instead of Y as the second argument to ax.plot_wireframe. Thus, all points fall on top of the diagonal Y=X.
Provided we have a contour on the xy plane, how can we plot "a curtain" raised from the contour to the limiting surface?
An example:
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
def figure():
fig = plt.figure(figsize=(8,6))
axes = fig.gca(projection='3d')
x = np.linspace(-2, 2, 100)
y = np.linspace(-2, 2, 100)
x, y = np.meshgrid(x, y)
t1 = np.linspace(0, 8/9, 100)
x1 = t1
y1 = (2*t1)**0.5
f1 = lambda x, y: y
plt.plot(x1, y1)
axes.plot_surface(x, y, f1(x, y),color ='red', alpha=0.1)
axes.set_xlim(-2,2)
axes.set_ylim(-2,2)
figure()
How to plot a surface from the given line to the limiting surface?
Somebody wanted help plotting an intersection here cylinder "cuts" a sphere in python you could use the vertical cylinder part. It uses u, v parameters to generate x, y, z values