问题
I was able to previously generate and plot a spherical surface using np.outer:
u = np.linspace(0, 2*np.pi, 100)
v = np.linspace(0, np.pi, 100)
x = R * np.outer(np.cos(u), np.sin(v))
y = R * np.outer(np.sin(u), np.sin(v))
z = R * np.outer(np.ones(np.size(u)), np.cos(v))
where x, y, z are of dim 100 x 100. See figure for result and ignore "particle traces"
I understand the math and direction cosines of a sphere as well as cylinder so I think the confusion comes from not understanding what exactly np.outer is doing.
I would expect that the following would generate a cylinder:
u = np.linspace(0, 2*np.pi, 100)
h = 5
x = R * np.cos(u)
y = R * np.sin(u)
z = np.linspace(0, h, np.size(u))
but when I try to plot, nothing is generated and I believe it is due to the discrepancy in array dimensions: (100,). See Figure for result.
The other thing I tried was this:
u = np.linspace(0, 2*np.pi, 100)
h = 5
x = R * np.outer(np.ones(np.size(u)), np.cos(u))
y = R * np.outer(np.ones(np.size(u)), np.sin(u))
z = np.linspace(0, h, np.size(u)) * np.outer(np.ones(np.size(u)), np.ones(np.size(u)))
See figure for result.
I don't understand why I can't get this to work. Other notes: - Clearly this is only for the lateral surface of the cylinder so if there is any way to generate the top/bottom surfaces in the same x, y, z that would be ideal - This code must work independently of matplotlib as the points themselves are also essential - If this accomplishable with np.outer, this would also be ideal
I appreciate any help in advance.
EDIT:
How, then, could I generate the top and bottom surfaces? Would it not be?:
x = R * np.outer(np.ones(np.size(u)), np.cos(u))
y = R * np.outer(np.ones(np.size(u)), np.sin(u))
z = h * np.outer(np.ones(np.size(u)), np.ones(np.size(u)))
This gives me no result as before.
回答1:
Try this:
u = np.linspace(0, 2*np.pi, 100)
h = 5
x = R * np.outer(np.ones(np.size(u)), np.cos(u))
y = R * np.outer(np.ones(np.size(u)), np.sin(u))
z = np.outer(np.linspace(0, h, np.size(u)), np.ones(np.size(u)))
Also, check the docs on np.outer if you are unsure what it does. It simply take the outer product of two vectors and produces a matrix.
回答2:
Given you example you can create a plot in the following fashion:
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
R = 2
u = np.linspace(0, 2*np.pi, 100)
v = np.linspace(0, np.pi, 100)
x = R * np.outer(np.cos(u), np.sin(v))
y = R * np.outer(np.sin(u), np.sin(v))
z = R * np.outer(np.ones(np.size(u)), np.cos(v))
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot_surface(x,y,z)
fig.show()
This produces the following figure, basically the same as what you show in your edit:
The second and third bits of code are actually producing what appears to be a minimal representation of a cylinder. I will skip the code, but both produce the following:
It is important to note however, that the second bit of code produces x, y, and z with shapes (100,) while the third bit produces shapes (100,100), but the entries on the second dimension are all just repeats and equal to the values from the second bit of code. For example:
u = np.linspace(0, 2*np.pi, 100)
h = 5
x = R * np.cos(u)
y = R * np.sin(u)
z = np.linspace(0, h, np.size(u))
u2 = np.linspace(0, 2*np.pi, 100)
h2 = 5
x2 = R * np.outer(np.ones(np.size(u)), np.cos(u))
y2 = R * np.outer(np.ones(np.size(u)), np.sin(u))
z2 = np.linspace(0, h, np.size(u)) * np.outer(np.ones(np.size(u)), np.ones(np.size(u)))
print(np.all(x2 == x))
True
print(np.all(y2 == y))
True
print(np.all(z2 == z))
True
So it would seem that the problem is that you are not correctly constructing the surface. When I am constructing a surface I do so withnumpy.meshgrid. For your example I would do the following:
u = np.linspace(0, 2*np.pi, 100)
h = 5
R = 2
z = np.linspace(0, h, np.size(u))
us, zs = np.meshgrid(u, z)
xs = R * np.cos(us)
ys = R * np.cos(us)
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot_surface(xs,ys,zs)
You will get the following figure:
The difference between the two methods rests only in the values of z and zs. You will find that taking the transpose of z is equal to zs so to fix you code just change:
z = np.linspace(0, h, np.size(u)) * np.outer(np.ones(np.size(u)), np.ones(np.size(u)))
to:
z = (np.linspace(0, h, np.size(u)) * np.outer(np.ones(np.size(u)), np.ones(np.size(u)))).T
And all should be well.
来源:https://stackoverflow.com/questions/43921920/generating-a-cylindrical-surface-with-np-outer