在Matplotlib中,我想绘制一个在其表面上有网格的球体,在球面坐标中分成30度的步长。
代码:
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')
u = np.linspace(0, 2 * np.pi, 13)
v = np.linspace(0, np.pi, 7)
x = 10 * np.outer(np.cos(u), np.sin(v))
y = 10 * np.outer(np.sin(u), np.sin(v))
z = 10 * np.outer(np.ones(np.size(u)), np.cos(v))
ax.plot_surface(x, y, z, rstride=1, cstride=1, color='w', shade=0)
plt.show()
产生数字:
但是,我希望球体上的轮廓是平滑的,而不是直接在绘制的点之间绘制。如果我增加采样密度,我会得到一个更平滑的球体,但线条绘得太密集了:
如何在光滑的球体上绘制相隔30度的线?
答案 0 :(得分:0)
您可以先插入数据,然后使用更大的步幅进行绘图。
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
import scipy.ndimage
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
u = np.linspace(0, 2 * np.pi, 13)
v = np.linspace(0, np.pi, 7)
x = 10 * np.outer(np.cos(u), np.sin(v))
y = 10 * np.outer(np.sin(u), np.sin(v))
z = 10 * np.outer(np.ones(np.size(u)), np.cos(v))
# use scipy to interpolate
xdata = scipy.ndimage.zoom(x, 3)
ydata = scipy.ndimage.zoom(y, 3)
zdata = scipy.ndimage.zoom(z, 3)
ax.plot_surface(xdata, ydata, zdata, rstride=3, cstride=3, color='w', shade=0)
plt.show()
基于另一个问题here。
请注意,scipy.ndimage.zoom
可能有点矫枉过正。我不明白为什么你不能在u
和v
上使用较小的分辨率,然后相应地提高步幅。这似乎也很好:
...
# increased num pts by 3
u = np.linspace(0, 2 * np.pi, 39)
v = np.linspace(0, np.pi, 21)
x = 10 * np.outer(np.cos(u), np.sin(v))
y = 10 * np.outer(np.sin(u), np.sin(v))
z = 10 * np.outer(np.ones(np.size(u)), np.cos(v))
# Use 3x the stride, no scipy zoom
ax.plot_surface(x, y, z, rstride=3, cstride=3, color='w', shade=0)
...
答案 1 :(得分:0)
天生的解决方案看起来摇摇晃晃,因为你没有预期的实际表面。所以你有点看透它,这就是线框看起来弯曲的原因。
很难找到其他解决方案,因为你需要一个好的分辨率范围(也就是说,使用小参数步骤),否则你会看到"通过"它。那么你需要在这个良好的分辨率范围之上绘制线条。
您可以在matplotlib中查看底图模块:http://matplotlib.org/basemap/users/examples.html 这可能有点矫枉过正,但它会起作用。
可能有Poly3DColelction和Line3D Collection的解决方案:Transparency for Poly3DCollection plot in matplotlib