如何使用pyplot在曲面图后面画一条线

Alf*_*Alf 5 python matplotlib

我想在我用曲面图绘制的圆环内画一条线。该线不应该在环面内可见 - 就像环面的内侧一样,只能在环面的“末端”看到(我切断了环面的一半)。然而,我绘制的线随处可见(如您在图中所见)。

在此处输入图片说明

我使用了以下代码:

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

# theta: poloidal angle | phi: toroidal angle
# note: only plot half a torus, thus phi=0...pi
theta = np.linspace(0, 2.*np.pi, 200)
phi   = np.linspace(0, 1.*np.pi, 200)
theta, phi = np.meshgrid(theta, phi)

# major and minor radius
R0, a = 3., 1.

# torus parametrization
x_torus = (R0 + a*np.cos(theta)) * np.cos(phi)
y_torus = (R0 + a*np.cos(theta)) * np.sin(phi)
z_torus = a * np.sin(theta)

# parametrization for a circular line at theta=0
x_circle = (R0-a/2. + a*np.cos(.0)) * np.cos(phi)
y_circle = (R0-a/2. + a*np.cos(.0)) * np.sin(phi)
z_circle = a * np.sin(.0)

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

# plot half of a circular line
ax1.plot3D( x_circle, y_circle, z_circle )

# plot half of torus
ax1.plot_surface( x_torus, y_torus, z_torus )

ax1.view_init(elev=15, azim=270)
ax1.set_xlim( -3, 3)
ax1.set_ylim( -3, 3)
ax1.set_zlim( -3, 3)
ax1.set_axis_off()

plt.show()
Run Code Online (Sandbox Code Playgroud)

我以为只是绘制线第一要解决我的问题,但事实并非如此。非常感谢任何关于如何改变线路行为的建议或帮助。

numpy.__version__     : 1.12.1
matplotlib.__version__: 2.0.0
Run Code Online (Sandbox Code Playgroud)

Wil*_*ler 3

选项一 - 使用 Mayavi

更简单的方法是使用Mayavi库。这与 非常相似matplotlib,该脚本唯一有意义的区别是传递给绘制线的 、 和 数组x应该y是1d 并且 的设置有点不同(取决于它是在绘制之前还是之后设置,以及alt/az 是根据不同的参考测量的)。zplot3dview

import numpy as np
import mayavi.mlab as mlab
from mayavi.api import OffScreenEngine
mlab.options.offscreen = True

# theta: poloidal angle | phi: toroidal angle
# note: only plot half a torus, thus phi=0...pi
theta = np.linspace(0, 2.*np.pi, 200)
phi   = np.linspace(0, 1.*np.pi, 200)

# major and minor radius
R0, a = 3., 1.

x_circle = R0 * np.cos(phi)
y_circle = R0 * np.sin(phi)
z_circle = np.zeros_like(x_circle)

# Delay meshgrid until after circle construction
theta, phi = np.meshgrid(theta, phi)
x_torus = (R0 + a*np.cos(theta)) * np.cos(phi)
y_torus = (R0 + a*np.cos(theta)) * np.sin(phi)
z_torus = a * np.sin(theta)

mlab.figure(bgcolor=(1.0, 1.0, 1.0), size=(1000,1000))
mlab.view(azimuth=90, elevation=105)

mlab.plot3d(x_circle, y_circle, z_circle)
mlab.mesh(x_torus, y_torus, z_torus, color=(0.0, 0.5, 1.0))
mlab.savefig("./example.png")
# mlab.show() has issues with rendering for some setups
Run Code Online (Sandbox Code Playgroud)

使用 Mayavi 的带线环形线圈

选项二 - 使用 matplotlib (有一些额外的不愉快)

如果您不能使用,mayavi则可以使用 来完成此操作matplotlib,这只是......令人不愉快。该方法基于在曲面之间创建透明“桥梁”,然后将它们绘制在一起作为一个曲面的想法。对于更复杂的组合来说,这并不是微不足道的,但这里有一个带有线的环形线圈的示例,该示例相当简单

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

theta = np.linspace(0, 2.*np.pi, 200)
phi   = np.linspace(0, 1.*np.pi, 200)
theta, phi = np.meshgrid(theta, phi)

# major and minor radius
R0, a = 3., 1.
lw = 0.05 # Width of line

# Cue the unpleasantness - the circle must also be drawn as a toroid
x_circle = (R0 + lw*np.cos(theta)) * np.cos(phi)
y_circle = (R0 + lw*np.cos(theta)) * np.sin(phi)
z_circle = lw * np.sin(theta)
c_circle = np.full_like(x_circle, (1.0, 1.0, 1.0, 1.0), dtype=(float,4))

# Delay meshgrid until after circle construction
x_torus = (R0 + a*np.cos(theta)) * np.cos(phi)
y_torus = (R0 + a*np.cos(theta)) * np.sin(phi)
z_torus = a * np.sin(theta)
c_torus = np.full_like(x_torus, (0.0, 0.5, 1.0, 1.0), dtype=(float, 4))

# Create the bridge, filled with transparency
x_bridge = np.vstack([x_circle[-1,:],x_torus[0,:]])
y_bridge = np.vstack([y_circle[-1,:],y_torus[0,:]])
z_bridge = np.vstack([z_circle[-1,:],z_torus[0,:]])
c_bridge = np.full_like(z_bridge, (0.0, 0.0, 0.0, 0.0), dtype=(float, 4))

# Join the circle and torus with the transparent bridge
X = np.vstack([x_circle, x_bridge, x_torus])
Y = np.vstack([y_circle, y_bridge, y_torus])
Z = np.vstack([z_circle, z_bridge, z_torus])
C = np.vstack([c_circle, c_bridge, c_torus])

fig = plt.figure()
ax = fig.gca(projection='3d')
ax.plot_surface(X, Y, Z, rstride=1, cstride=1, facecolors=C, linewidth=0)
ax.view_init(elev=15, azim=270)
ax.set_xlim( -3, 3)
ax.set_ylim( -3, 3)
ax.set_zlim( -3, 3)
ax.set_axis_off()

plt.show()

Run Code Online (Sandbox Code Playgroud)

使用 mpl 的带线环形线圈

请注意,在这两种情况下,为了演示简单起见,我都更改了圆以匹配环形线圈的主半径,它可以根据需要轻松更改。