3

I am trying to create a plot composed of multiple wireframe spheres using matplotlib. I found a code fragment to plot one such sphere here so I thought it would be easy to extend it to multiple spheres by just calling plot_wireframe multiple times. I was wrong. Here's a code fragment:

import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
u, v = np.mgrid[0:2*np.pi:20j, 0:np.pi:10j]
x=np.cos(u)*np.sin(v)
y=np.sin(u)*np.sin(v)
z=np.cos(v)
fig = plt.figure(figsize=(8,6))
ax = fig.gca(projection='3d')
ax.plot_wireframe(x*3.+5., y*3., z*3.,linewidths=.2)
ax.view_init(azim=30,elev=40)
ax.set_aspect("equal")
plt.show()
fig = plt.figure(figsize=(8,6))
ax = fig.gca(projection='3d')
ax.plot_wireframe(x*3.+5., y*3., z*3.,linewidths=.2)
spheres = [ [0,0,0,1], [3,0,0,1.6] ]
for v in spheres:
    ax.plot_wireframe(x*v[3]+v[0], y*v[3]+v[1], z*v[3]+v[2],linewidths=.2)
ax.view_init(azim=30,elev=40)
ax.set_aspect("equal")
plt.show()

If you run that code, the first plot will show a nice sphere, while in the second all the spheres are distorted and shifted. I searched to make sure plot_wireframe can be called multiple time on the same axis but couldn't find anything. Also, I'm a Python noob, but I don't think I'm doing anything wrong. Thank you for the help!

Community
  • 1
  • 1
Giovanni Botta
  • 9,626
  • 5
  • 51
  • 94

1 Answers1

1

Short answer: adjust the axes limits manually:

import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
u, v = np.mgrid[0:2*np.pi:20j, 0:np.pi:10j]
x=np.cos(u)*np.sin(v)
y=np.sin(u)*np.sin(v)
z=np.cos(v)

# I'm not sure what was this for.  
'''
fig = plt.figure(figsize=(8,6))
ax = fig.gca(projection='3d')
ax.plot_wireframe(x*3.+5., y*3., z*3.,linewidths=.2)
ax.view_init(azim=30,elev=40)
ax.set_aspect("equal")

plt.show()
'''

fig = plt.figure(figsize=(8,6))
ax = fig.gca(projection='3d')


ax.plot_wireframe(x*3.+5., y*3., z*3.,linewidths=.2)
spheres = [ [0,0,0,1], [3,0,0,1.6] ]
for v in spheres:
    ax.plot_wireframe(x*v[3]+v[0], y*v[3]+v[1], z*v[3]+v[2],linewidths=.2)
ax.view_init(azim=30,elev=40)

ax.set_xlim([0,7])   # Like so. 
ax.set_ylim([-3,3]) 
ax.set_zlim([-3,3]) 

ax.set_aspect("equal")
plt.show()
ev-br
  • 24,968
  • 9
  • 65
  • 78
  • The first plot was to show that the code worked fine for one sphere. This is awesome, although I'm not exactly sure why it works, can you explain the connection to the x,y,z limits? Thanks! – Giovanni Botta Sep 06 '12 at 16:21
  • More comments: it's still distorted. Setting the limits apparently clashes with setting equal aspect ratio (just try setting xlim to -10 10). I tried using ax.set_aspect('equal', 'datalim') but then if I click and drag it gets messed up. Is there some bug? – Giovanni Botta Sep 06 '12 at 16:50