2017-08-16 182 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