在表面图中切掉半个圆环

时间:2019-01-13 13:14:09

标签: python numpy matplotlib 3d

我正在尝试使用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()

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

有什么想法可以使表面干净吗?

1 个答案:

答案 0 :(得分:1)

nan切除表面通常可以做到这一点。这是由于以下事实:在输入数据的子集上使用线性插值绘制了表面的面片,并且在边界上具有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

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