【问题标题】:Cut-off half a torus in a surface plot在曲面图中截断半个圆环
【发布时间】:2019-06-07 17:10:15
【问题描述】:

我正在尝试使用 matplotlib 仅绘制半个圆环。

这是我目前的方法:

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
x[x>0] = np.nan

fig = plt.figure()
ax1 = fig.add_subplot(111, projection='3d')
ax1.set_zlim(-3,3)
ax1.plot_surface(x, y, z, 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()

这样做,确实给了我半个圆环,但是其中一个切割面不清楚,如图所示(这里有问题的是左侧切割面)。

任何想法如何制作干净的切割表面?

【问题讨论】:

    标签: python numpy matplotlib 3d


    【解决方案1】:

    nans 切割表面通常会做到这一点。这是因为表面的补丁是在输入数据的子集上使用线性插值绘制的,并且在边界上有nans 将导致某些边缘补丁的值的nan 结果。

    在您的具体情况下,您可以将环形角限制为半个圆环:

    theta = np.linspace(0, 2*np.pi, n) 
    phi   = np.linspace(0, np.pi, n) 
    

    您还必须手动设置 x/y 限制以获得漂亮的纵横比:

    ax1.axis([-3, 3]*2)
    

    通过将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() 
    

    【讨论】:

    • phi = np.linspace(0, np.pi, n) 与使用y[y>0] = np.nan 而不是x[x>0] = np.nan 相同。尽管由于对称性,您的回答实际上解决了问题,但它并未评论 x[x>0] = np.nan 出了什么问题。
    • @Bazingaa 是的,我想可以添加一个 pi/2 转换以使其完全相同。我认为很明显,截断值会干扰plot_surface 使用的插值。我会尝试详细说明。
    • 嗯,这很容易(我的猜测是试图对plot_surface 进行“更柔和”或更平滑的插值)
    • @Alf 另一个更通用但更混乱的选项是将facecolors 的显式数组传递给plot_surface,但是您必须自己决定颜色,所以我不会将其添加到考虑到上述情况,我的回答对你有用。
    • @AndrasDeak 我明白你的意思,感谢您的洞察力!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多