我有两个同心圆的x和y值的numpy数组,它们从任意3D方向旋转,并投影到绘图的xy平面xs1, ys1, xs2, ys2
。
我想用matplotlib绘制它们,填充它们之间的空间。我在fill_between之间遇到了麻烦,因为我填充的曲线是多值的。我在想蛮力方法是分成单值片段,沿着同一组x值插入曲线并使用fill_between,但想知道是否有更优雅的解决方案。代码:
import numpy as np
import matplotlib.pyplot as plt
phi = 0.5
theta = 1.2
Rphi = np.array([[np.cos(phi), -np.sin(phi), 0.], [np.sin(phi), np.cos(phi), 0.], [0.,0.,1.]])
Rtheta = np.array([[1.,0.,0.], [0., np.cos(theta), -np.sin(theta)], [0., np.sin(theta), np.cos(theta)]])
R = np.dot(Rphi, Rtheta)
Router = 0.06
Rinner = 0.04
rs = np.array([[np.cos(phi), np.sin(phi), 0.] for phi in np.linspace(0., 2*np.pi, 100)])
rs = np.dot(rs, R.T)
plt.plot(Rinner*rs[:,0], Rinner*rs[:,1], Router*rs[:,0], Router*rs[:,1])
plt.plot([0], [0], 'oy', ms=100)
我想填写两个戒指之间的空间(是的,我试图绘制土星!)
奖励:有没有一种简单的方法来获得正确的深度?也就是说,土星出现在后面的前面,如下面,但在正面的环后面?
答案 0 :(得分:4)
您使用了错误的功能:plt.fill()是您可能需要的功能:
plt.fill(Router*rs[:,0], Router*rs[:,1],'blue')
plt.fill(Rinner*rs[:,0], Rinner*rs[:,1],'white')
plt.plot([0], [0], 'oy', ms=100)
结果:
使中间圆圈隐藏背景位应该是非常手动的:即使是带有matplotlib的3d绘图在z顺序上也存在严重困难(每个对象要么完全在之前,要么完全在另一个对象之后)。您可能需要将省略号分成两部分,然后使用订单背景绘制它们 - >星球 - >前景。
此外,正如您所看到的,由于对matplotlib.rc
进行了一些调整,因此我的系统上的行星大小不同。我建议使用基于数据的维度正确地绘制地球:
Rsaturn = 0.018
rs0 = np.array([[np.cos(phi), np.sin(phi), 0.] for phi in np.linspace(0., 2*np.pi, 100)])
plt.fill(Rsaturn*rs0[:,0], Rsaturn*rs0[:,1],'yellow')
plt.axis('equal')
新结果:
奖金问题让我做得恰到好处。为了能够用环的前部隐藏土星,你必须正确地填充环,而不是相互绘制两个完整的椭圆。这是我的解决方案:
import numpy as np
import matplotlib.pyplot as plt
phi = 0.5
theta = 1.2
Rphi = np.array([[np.cos(phi), -np.sin(phi), 0.], [np.sin(phi), np.cos(phi), 0.], [0.,0.,1.]])
Rtheta = np.array([[1.,0.,0.], [0., np.cos(theta), -np.sin(theta)], [0., np.sin(theta), np.cos(theta)]])
R = np.dot(Rphi, Rtheta)
Router = 0.06
Rinner = 0.04
Rsaturn = 0.018
#rs0 = np.array([[np.cos(phi), np.sin(phi), 0.] for phi in np.linspace(0., 2*np.pi, 100)])
phivec1 = np.linspace(0., np.pi, 50)
phivec2 = np.linspace(np.pi,2*np.pi, 50)
rs1 = np.array([np.cos(phivec1), np.sin(phivec1), np.zeros_like(phivec1)]).T # first half arc
rs2 = np.array([np.cos(phivec2), np.sin(phivec2), np.zeros_like(phivec2)]).T # second half arc
rs0 = np.concatenate((rs1,rs2),axis=0) # full arc for Saturn
rs1 = np.dot(rs1, R.T) # rotate
rs2 = np.dot(rs2, R.T) # rotate
# draw foreground
semiring1 = np.concatenate((Router*rs1[:,:2],Rinner*rs1[::-1,:2]),axis=0)
plt.fill(semiring1[:,0], semiring1[:,1],'blue',edgecolor='none')
# draw Saturn
plt.fill(Rsaturn*rs0[:,0], Rsaturn*rs0[:,1],'yellow')
# draw foreground
semiring2 = np.concatenate((Router*rs2[:,:2],Rinner*rs2[::-1,:2]),axis=0)
plt.fill(semiring2[:,0], semiring2[:,1],'blue',edgecolor='none')
plt.axis('equal')
一个变化是我通过将角度范围分成两部分来使用两个半椭圆,并且我将两个同心半椭圆连接到fill
环部分一次一个。我们必须关闭fill
中的边缘颜色,否则数据中的跳跃会显示为黑色线条弄乱图形。如果需要边线,请使用plot
手动绘制它们。
以上是上述结果:
答案 1 :(得分:1)
这只是给Andras Deaks增添了非常好的答案。为了摆脱两个半环之间的微小间隙,只需更改边缘的颜色即可。到了'蓝色'
# draw foreground
semiring1 = np.concatenate((Router*rs1[:,:2],Rinner*rs1[::-1,:2]),axis=0)
plt.fill(semiring1[:,0], semiring1[:,1],'blue',edgecolor='blue')