问题
I would like to know how using plot3d_parametric_surface in Sympy we can plot a perfect sphere. By perfect I mean with equal axes. The result with this function has an oval shape!
from sympy import *
from sympy.plotting.plot import plot3d_parametric_surface
from sympy.abc import theta , phi
plot3d_parametric_surface(sin(phi)*cos(theta) , sin(phi)*sin(theta), cos(phi), (phi,0,pi),(theta,0,2*pi))
I tried to implement the answers in the matplotlib (equal unit length): with 'equal' aspect ratio z-axis is not equal to x- and y- but I didn't have any success.
回答1:
One of the main problems is that ax.set_aspect('equal')
is not implemented yet in matplotlib. The current versions of matplotlib (3.1) raise an explicit error as soon as set_aspect('equal')
is called. Older versions gave a quite wrong projection, although often the user was not aware of the error. Other StackOverflow answers about setting the equal aspect ratio in 3D just set the xyz limits equal, which gets you closer to the desired result, but without being a fully equal projection.
A workaround is to manually set the figure axis until the sphere has the desired aspect ratio. This is cumbersome, because the plot dimensions include space for the axes labels and for padding.
For example, setting the figsize to 6, 5.6
seems to go well
from sympy import sin, cos, pi
from sympy.plotting.plot import plot3d_parametric_surface
from sympy.abc import theta, phi
import matplotlib.pyplot as plt
plt.rcParams['figure.figsize'] = 6, 5.6
plot3d_parametric_surface(sin(phi) * cos(theta), sin(phi) * sin(theta), cos(phi),
(phi, 0, pi), (theta, 0, 2 * pi))
Inserting an invisible box (in case you're not drawing a sphere), could be achieved with just a diagonal line:
from sympy import sin, cos, pi
from sympy.plotting.plot import plot3d_parametric_surface, plot3d_parametric_line
from sympy.abc import theta, phi, t
import matplotlib.pyplot as plt
plt.rcParams['figure.figsize'] = 6, 5.6
p1 = plot3d_parametric_surface(sin(phi) * cos(theta), sin(phi) * sin(theta), cos(phi),
(phi, 0, pi), (theta, 0, 2 * pi), show=False)
p2 = plot3d_parametric_line(t, t, t, (t, -1, 1), line_color='none', show=False)
p1.append(p2[0])
#p1.backend(p1).ax[0].set_aspect('equal') # this raises a NotImplementedError
p1.show()
来源:https://stackoverflow.com/questions/60332066/plot-a-perfect-sphere-with-equal-axes-by-parametric-plot-in-sympy