Generating a Cylindrical Surface with np.outer

↘锁芯ラ 提交于 2019-12-11 08:11:13

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!