Kedar_dg
Kedar_dg

Reputation: 41

Plotting x^2 + y^2 = z^2 = 1 using matplotlib without parametric form

I want to plot the unit sphere x^2 + y^2 + z^2 = 1 & I am trying to use sympy , numpy , and matplotlib for the same. Below is a code snippet:

x,y = sp.symbols('x y')

def g(x,y):
    return sqrt(1-x**2 - y**2)
xrange2 = np.linspace(-1, 1, 100)
yrange2 = np.linspace(-1, 1, 100)
X2, Y2 = np.meshgrid(xrange2, yrange2)
Z2 = g(X2, Y2)
Z2[(1- X2**2 - Y2**2 < 0)] = np.nan
Z2[(1- X2**2 - Y2**2 > 0)] = np.nan
ax.plot_surface(X2, Y2, Z2,cmap='Blues', antialiased=True, edgecolor='black')

I don't wish to use parametric equations for the sphere, but rather plot it using x , y and z. Currently getting below error: Z contains NaN values. This may result in rendering artifacts.

Upvotes: 0

Views: 2280

Answers (1)

JohanC
JohanC

Reputation: 80319

From the question it is very unclear which version of sqrt is used. Sympy's sqrt certainly won't work. math.sqrt doesn't work on arrays. Only np.sqrt can work. But then, function g needs to be numpy vectorized.

np.sqrt works on arrays, and gives NaN when operated on negative numbers.

ax.plot_surface doesn't want to draw colormapped faces when some of the Z values are NaN, it only draws plain colors in that case. Note that antialiasing doesn't work for plotting faces, only for edges.

To draw a complete sphere, both Z2 and -Z2 need to be drawn.

Due to the NaNs and an equation that doesn't define evenly distributed points, some artifacts will be present. Also, the surfaces will not completely fill up. See this post to draw a sphere via an angular representation.

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

@np.vectorize
def g(x,y):
    return np.sqrt(1-x**2 - y**2)

fig = plt.figure()
ax = fig.gca(projection='3d')

xrange2 = np.linspace(-1, 1, 100)
yrange2 = np.linspace(-1, 1, 100)
X2, Y2 = np.meshgrid(xrange2, yrange2)
Z2 = g(X2, Y2)
ax.plot_surface(X2, Y2, -Z2, color='lightblue', antialiased=True, edgecolor='black')
ax.plot_surface(X2, Y2, Z2, color='lightblue', antialiased=True, edgecolor='black')

plt.show()

resulting plot

PS: Note that you are not really using sympy in the code (def g(x,y) uses its own version of standard Python variables x and y). Also, mixing numpy and sympy doesn't work. This related post handles plotting a surface as parametric surface via sympy. Note that these parametric surfaces only work for 2 variables, in this case x, y and z are defined in function of phi and theta. As far as I am aware, plotting a general 3D equation doesn't work with sympy at the moment.

Upvotes: 1

Related Questions