Обрезка поверхностей с помощью nan
s обычно делает это. Это связано с тем, что участки поверхности нарисованы с использованием линейной интерполяции по подмножеству входных данных, и наличие nan
s на границе приведет к nan
результатам для значений для некоторых участков края.
В вашем конкретном случае вы можете ограничить свой тороидальный угол до половины тора:
theta = np.linspace(0, 2*np.pi, n)
phi = np.linspace(0, np.pi, n)
Вам также нужно будет установить ручные ограничения по x / y для хорошего соотношения сторон:
ax1.axis([-3, 3]*2)
![result](https://i.stack.imgur.com/drXpx.png)
Существует очень общая, но практическая альтернатива, передавая явный массив от facecolors
до plot_surface
и манипулируя прозрачностью значений внутри. Это будет намного хуже, чем по умолчанию, если вы не будете усердно работать, так как затенение будет отсутствовать с плоскими цветами Вот очень простой (и ужасный) пример того, что я имею в виду:
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
n = 100
# theta: poloidal angle; phi: toroidal angle
theta = np.linspace(0, 2*np.pi, n)
phi = np.linspace(0, 2*np.pi, n)
theta, phi = np.meshgrid(theta, phi)
# R0: major radius; a: minor radius
R0, a = 2., 1.
# torus parametrization
x = (R0 + a*np.cos(theta)) * np.cos(phi)
y = (R0 + a*np.cos(theta)) * np.sin(phi)
z = a * np.sin(theta)
# "cut-off" half of the torus using transparent colors
c = np.full(x.shape + (4,), [0, 0, 0.85, 1]) # shape (nx, ny, 4)
c[x>0, -1] = 0 # set these to transparent
fig = plt.figure()
ax1 = fig.add_subplot(111, projection='3d')
ax1.set_zlim(-3,3)
ax1.plot_surface(x, y, z, facecolors=c, rstride=5, cstride=5,)
# elev: elevation angle in z-plane
# azim: azimuth angle in x,y plane
ax1.view_init(elev=15, azim=0)
plt.show()
![facecolors example result](https://i.stack.imgur.com/AATHU.png)