2017-08-16 105 views
1

出图均匀分布的球,我想创建一个情节有点像这样:的Python:在Matplotlib

enter image description here

如果有上述所有的最低领域。

import numpy as np 
import matplotlib.pyplot as plt 

def func(x, y): 
    return np.sin(2*np.pi*x)*np.sin(2*np.pi*y)/3 

fig = plt.figure() 
ax = fig.add_subplot(111, projection='3d') 
x = y = np.arange(-1.0, 1.0, 0.05) 
X, Y = np.meshgrid(x, y) 
zs = np.array([func(x,y) for x,y in zip(np.ravel(X), np.ravel(Y))]) 
Z = zs.reshape(X.shape) 

ax.plot_surface(X, Y, Z, color="grey") 
ax.set_zlim3d(-1,1) 

plt.show() 

但是我不确定如何均匀分布的球体加入到这一点:

的表面可以用的sin(x)*罪(Y)的情节来近似。任何人都可以提供帮助吗?

+0

也许你想提的问题所在。我想通过一点搜索你会发现如何绘制一个球体。那么,绘制更多的领域也不应该成为一个问题,也不应该把它们放在某个位置上。对于实际问题的细节越多,获得帮助的可能性就越高。否则,人们可能会将这个问题理解为“请为我做的工作”,这是许多人过敏的原因。 – ImportanceOfBeingErnest

+0

那不是我的意图。我不认为发布失败的尝试对于“似乎”不会花费很长时间的人知道他们在做什么 - 但在将来注意到的问题上是有用的。可悲的是,正如ml4294的答案所强调的,似乎这个问题在matplotlib中是无法解决的。 –

回答

2

使用matplotlib一个难免会碰到物体的问题被隐藏于人后。这也在matplotlib 3d FAQ中说明,建议使用mayavi

在Mayavi的解决方案是这样的:

from mayavi import mlab 
import numpy as np 

### SURFACE ''' 
x,y = np.meshgrid(np.linspace(-2.5,2), np.linspace(-2,2)) 
f = lambda x,y: .4*np.sin(2*np.pi*x)*np.sin(2*np.pi*y) 
z=f(x,y) 
mlab.surf(x.T,y.T,z.T, colormap="copper") 

### SPHERES ''' 
px,py = np.meshgrid(np.arange(-2,2)+.25, np.arange(-2,2)+.75) 
px,py = px.flatten(),py.flatten() 
pz = np.ones_like(px)*0.05 
r = np.ones_like(px)*.4 
mlab.points3d(px,py,pz,r, color=(0.9,0.05,.3), scale_factor=1) 


mlab.show() 

enter image description here

+0

感谢您的支持!我不熟悉mayavi,所以我不得不考虑一下,因为我现在知道关于matplotlib的限制(我通常只需要制作2D图)。对于读这个也不熟悉mayavi的人来说;我发现它目前只与Python <3.6和qt4兼容,所以要使用此解决方案,必须首先设置适当的环境。请参阅:https://www.scivision.co/mayavi-qt5-create-conda-env-qt4/ –

2

您需要确定函数的最小值(在参数化时)(x =整数+0.25,y =整数+0.75)或反过来。然后,您可以简单地使用球坐标对球体进行参数化(例如,在此处完成:python matplotlib: drawing 3D sphere with circumferences)并绘制球体。

现在到了一些好消息和一个坏消息:

1)好消息是,最小值是正确的决定,且已创建的球体。在下面的图中,您可以看到它们正好在曲面图的蓝色部分上方(蓝色部分的确显示了最小值)。 2)坏消息是,你会很难找到球体实际上正确渲染的另一个角度。我不知道这个相当恼人的行为的解决方案,因此,您可能需要四处游玩,直到找到正确的角度。玩的开心!

import numpy as np 
import matplotlib.pyplot as plt 
from mpl_toolkits.mplot3d import Axes3D 

def func(x, y): 
    return np.sin(2*np.pi*x)*np.sin(2*np.pi*y)/3 

fig = plt.figure() 
ax = fig.add_subplot(111, projection='3d') 
x = y = np.arange(-2.0, 2.0, 0.05) 

# Get the minima of the function. 
minsx1 = np.arange(int(np.amin(x)) + 0.25, int(np.amax(x)) + 0.25 + 1, 1) 
minsy1 = np.arange(int(np.amin(y)) + 0.75, int(np.amax(y)) + 0.75 + 1, 1) 
minsx2 = np.arange(int(np.amin(x)) + 0.75, int(np.amax(x)) + 0.75 + 1, 1) 
minsy2 = np.arange(int(np.amin(y)) + 0.25, int(np.amax(y)) + 0.25 + 1, 1) 

X, Y = np.meshgrid(x, y) 
zs = np.array([func(x,y) for x,y in zip(np.ravel(X), np.ravel(Y))]) 
Z = zs.reshape(X.shape) 

# Color map for better detection of minima (blue) 
ax.plot_surface(X, Y, Z, cmap="viridis") 
ax.set_zlim3d(-1,1) 

# Spherical coordinates 
r = 0.15 
phi = np.linspace(0, 2 * np.pi, 30) 
theta = np.linspace(0, np.pi, 30) 

# Write spherical coordinates in cartesian coordinates. 
x = r * np.outer(np.cos(phi), np.sin(theta)) 
y = r * np.outer(np.sin(phi), np.sin(theta)) 
z = r * np.outer(np.ones(np.size(phi)), np.cos(theta)) 

# Plot the spheres. 
for xp in minsx1: 
    for yp in minsy1: 
     sphere = ax.plot_surface(x+xp, y+yp, z+0.35, color='r') 
for xp in minsx2: 
    for yp in minsy2: 
     sphere = ax.plot_surface(x+xp, y+yp, z+0.35, color='r') 
ax.view_init(elev=90, azim=0) 
plt.savefig('test.png') 
plt.show() 

enter image description here

+0

这很让人沮丧,但非常感谢!它似乎基于这个https://stackoverflow.com/questions/23188561/matplotlib-3d-plot-zorder-issue,这是matplotlib中无法解决的问题。我将尝试那里的建议,并与其他软件包一起玩。我会稍微留下这个问题,希望有人能提出一个完整的解决方案,否则我会标记你的。 –

+1

我认为你不能用matplotlib来解决这个问题,所以可能是@ImportanceOfBeingErnest的解决方案就是要走这里。 – ml4294