2017-08-16 3 views
1

Je suis en train de créer un terrain un peu comme ceci:Python: complotaient Spaced Sphères dans Uniformément Matplotlib

enter image description here

Là où il y a tous les domaines ci-dessus minima.

La surface peut être approchée avec un sin (x) * sin (y) parcelle:

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

Cependant, je ne suis pas sûr comment ajouter des sphères régulièrement espacées dans ce. Quelqu'un pourrait-il aider?

+0

Peut-être que vous voulez mentionner où réside le problème. Je pense qu'avec un peu de recherche, vous trouverez comment tracer une sphère. Ensuite, le tracé de plus de sphères ne devrait pas être un problème non plus, et ne les placerait pas à certaines positions. Plus vous allez dans les détails sur le problème réel, plus les chances d'obtenir de l'aide. Sinon, on pourrait comprendre cette question comme "s'il vous plaît faites le travail pour moi", que beaucoup de gens sont allergiques. – ImportanceOfBeingErnest

+0

Ce n'était pas mon intention. Je ne pensais pas que poster des tentatives ratées serait utile pour un problème qui «semblait» ne pas prendre du tout de temps pour quelqu'un qui savait ce qu'ils faisaient - mais noté pour l'avenir. Malheureusement, comme la réponse de ml4294 met en évidence, il semble que cette question est insoluble dans matplotlib. –

Répondre

2

En utilisant matplotlib un inévitablement rencontrer des problèmes d'objets sont cachés derrière les autres. Ceci est également indiqué dans le matplotlib 3d FAQ et la recommandation est d'utiliser mayavi.

En mayavi la solution ressemblerait à ceci:

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

Merci pour ça!Je ne suis pas familier avec mayavi donc je vais devoir le regarder étant donné ce que je sais maintenant sur les limitations de matplotlib (normalement, je n'ai besoin que de faire des tracés 2D). Pour tous ceux qui lisent ceci et qui ne sont pas familiers avec mayavi; J'ai trouvé que c'est actuellement compatible uniquement avec Python <3.6 et qt4, donc pour utiliser cette solution, un environnement approprié doit d'abord être mis en place. Voir: https://www.scivision.co/mayavi-qt5-create-conda-env-qt4/ –

2

Vous devez déterminer les minima de la fonction, qui sont (avec votre paramétrisation) à (x = entier + 0,25, y = entier + 0,75) ou l'inverse. Ensuite, vous pouvez simplement paramétrer les sphères en utilisant des coordonnées sphériques (par exemple comme fait ici: python matplotlib: drawing 3D sphere with circumferences) et tracer les sphères.

vient maintenant quelques bonnes nouvelles et quelques mauvaises nouvelles:

1.) Les bonnes nouvelles sont que les minima sont correctement déterminés et que les sphères sont créées. Dans le graphique ci-dessous, vous pouvez voir qu'ils sont juste au-dessus des parties bleues de la parcelle de surface (où les parties bleues montrent en effet les minima). 2.) La mauvaise nouvelle est que vous aurez du mal à chercher un autre angle où les sphères sont réellement rendues correctement. Je ne connais pas de solution à ce comportement plutôt ennuyeux, donc vous devrez probablement jouer jusqu'à ce que vous ayez trouvé le bon angle. S'amuser!

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

C'est plutôt frustrant, mais merci beaucoup! Il semblerait basé sur ce https://stackoverflow.com/questions/23188561/matplotlib-3d-plot-zorder-issue que c'est un problème insoluble dans matplotlib. Je vais essayer la suggestion et jouer avec d'autres paquets. Je vais laisser cette question ouverte un peu dans l'espoir que quelqu'un trouvera une solution qui fonctionnera pleinement, sinon je marquerai le vôtre. –

+1

Je pense que vous ne serez pas capable de résoudre ce problème avec matplotlib, donc la solution de @ImportanceOfBeingErnest est probablement la solution. – ml4294