使用 np.outer 生成圆柱面

Generating a Cylindrical Surface with np.outer

我之前能够使用 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))

其中 x、y、z 的亮度为 100 x 100。 结果见图,忽略"particle traces"

我理解球体和圆柱体的数学和方向余弦,所以我认为混淆来自不理解 np.outer 到底在做什么。

我希望以下内容会生成一个圆柱体:

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

但是当我尝试绘制时,没有生成任何东西,我认为这是由于数组维度的差异:(100,)。 结果见图。

我尝试的另一件事是:

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

结果见图。

我不明白为什么我不能让它工作。 其他注意事项: - 显然这仅适用于圆柱体的侧面,因此如果有任何方法可以在相同的 x、y、z 中生成 top/bottom 表面,那将是理想的 - 此代码必须独立于 matplotlib 工作,因为点本身也是必不可少的 - 如果用 np.outer 可以实现,这也是理想的

在此先感谢您的帮助。

编辑:

那么,如何生成顶面和底面? 不会吧?:

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

这没有像以前那样给我结果。

试试这个:

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

此外,如果您不确定它的作用,请检查 docs on np.outer。它只是取两个向量的外积并生成一个矩阵。

给你一个例子,你可以用以下方式创建一个图:

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

这将产生下图,与您在编辑中显示的基本相同:

代码的第二位和第三位实际上生成的似乎是圆柱体的最小表示。我将跳过代码,但两者都会产生以下内容:

然而,请务必注意,代码的第二位生成形状为 (100,)xyz,而第三位生成形状(100,100),但是第二个维度上的条目都只是重复并且等于代码第二位的值。例如:

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

所以看起来问题是你没有正确构建表面。当我构建一个曲面时,我会使用 numpy.meshgrid。对于您的示例,我将执行以下操作:

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)

你会得到下图:

两种方法的区别仅在于zzs的值。你会发现 z 的转置等于 zs 所以要修复你的代码只需更改:

z = np.linspace(0, h, np.size(u)) * np.outer(np.ones(np.size(u)), np.ones(np.size(u)))

至:

z = (np.linspace(0, h, np.size(u)) * np.outer(np.ones(np.size(u)), np.ones(np.size(u)))).T

一切都会好起来的。