Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to plot a perfectly smooth sphere

I am trying to plot a perfectly smooth sphere in python using matplotlib. I have been using the following code:

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

fig = plt.figure(1)    
ax = fig.add_subplot(111, projection='3d')

u = np.linspace(0, 2 * np.pi, 100)
v = np.linspace(0, np.pi, 100)
x = np.outer(np.cos(u), np.sin(v))
y = np.outer(np.sin(u), np.sin(v))
z = np.outer(np.ones(np.size(u)), np.cos(v))

ax.plot_surface(x, y, z, linewidth=0.0)

plt.show()

The plot I obtained is attached below: figure

The figure generated consists of patches of rectangular surfaces on it. Is it possible to smoothen out the boundaries or make it indistinguishable and to make a perfectly smooth sphere?

like image 431
Athul TR Avatar asked Mar 27 '26 06:03

Athul TR


1 Answers

Matplotlib plots 3d surfaces by breaking them down into small sub-polygons of equal colour, as is explained in the documentation, hence your result is not really a surprise. In order to get a smoother surface, you have to provide more data points. There is, however, a small twist, which is that plot_surface() may not use all the data you provide. This is controlled with the cstride and rstride keywords. How the defaults are calculated is not quite clear to me, but below a little example that demonstrates the effect:

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

fig,axes = plt.subplots(ncols=2,nrows=2,subplot_kw=dict(projection='3d'))

N=50
stride=2
ax = axes[0,0]
u = np.linspace(0, 2 * np.pi, N)
v = np.linspace(0, np.pi, N)
x = np.outer(np.cos(u), np.sin(v))
y = np.outer(np.sin(u), np.sin(v))
z = np.outer(np.ones(np.size(u)), np.cos(v))
ax.plot_surface(x, y, z, linewidth=0.0, cstride=stride, rstride=stride)
ax.set_title('{0}x{0} data points, stride={1}'.format(N,stride))

N=50
stride=1
ax = axes[0,1]
u = np.linspace(0, 2 * np.pi, N)
v = np.linspace(0, np.pi, N)
x = np.outer(np.cos(u), np.sin(v))
y = np.outer(np.sin(u), np.sin(v))
z = np.outer(np.ones(np.size(u)), np.cos(v))
ax.plot_surface(x, y, z, linewidth=0.0, cstride=stride, rstride=stride)
ax.set_title('{0}x{0} data points, stride={1}'.format(N,stride))

N=200
stride=2
ax = axes[1,0]
u = np.linspace(0, 2 * np.pi, N)
v = np.linspace(0, np.pi, N)
x = np.outer(np.cos(u), np.sin(v))
y = np.outer(np.sin(u), np.sin(v))
z = np.outer(np.ones(np.size(u)), np.cos(v))
ax.plot_surface(x, y, z, linewidth=0.0, cstride=stride, rstride=stride)
ax.set_title('{0}x{0} data points, stride={1}'.format(N,stride))

N=200
stride=1
ax = axes[1,1]
u = np.linspace(0, 2 * np.pi, N)
v = np.linspace(0, np.pi, N)
x = np.outer(np.cos(u), np.sin(v))
y = np.outer(np.sin(u), np.sin(v))
z = np.outer(np.ones(np.size(u)), np.cos(v))
ax.plot_surface(x, y, z, linewidth=0.0, cstride=stride, rstride=stride)
ax.set_title('{0}x{0} data points, stride={1}'.format(N,stride))

plt.show()

The resulting figure looks like this:

result of the above code

As you can see, the outcome of the plot is sensitive to both the density of your data and the stride keywords. Be careful though with the amount of data you provide -- plot_surface() can take up a considerable amount of time to provide a result. Hope this helps.

like image 84
Thomas Kühn Avatar answered Mar 28 '26 19:03

Thomas Kühn



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!