椭圆轨道采用极坐标方法追踪相位,轴和地球方向

时间:2014-08-07 05:13:37

标签: python matplotlib plot ellipse polar-coordinates

我想代表两颗恒星二元系统的椭圆轨道。我的目标是这样的:

enter image description here

我有一个沿轴的大小网格,焦点上的一个星形星,以及二级星的轨道。沿轨道的十进制数是轨道相位。底部的箭头是地球方向,轨道上的厚部分与特定情况的观察有关 - 我不需要它。我想从这个阴谋中改变的是:

  1. 轨道阶段:我不想沿轨道上的数字,而是想从焦点到轨道的“虚线”,以及它们上方的轨道相位:

  2. 我不希望交叉(0,0);

  3. 我想重新定位轨道,以便0.0阶段位于绘图的左上角部分,地球方向是向上指向的直箭头(我的系统参数不同从这里绘制的那个)。

  4. 我试图寻找python示例,但我唯一提出的(from here)是极地情节:

    enter image description here

    这并不是我想要的真正代表,但仍然是一个开始:

    import numpy as np
    import matplotlib.pyplot as plt
    cos = np.cos
    pi = np.pi
    
    a = 10
    e = 0.1
    theta = np.linspace(0,2*pi, 360)
    r = (a*(1-e**2))/(1+e*cos(theta))
    
    fig = plt.figure()
    ax = fig.add_subplot(111, polar=True)
    ax.set_yticklabels([])
    ax.plot(theta,r)
    
    print(np.c_[r,theta])
    plt.show()
    

1 个答案:

答案 0 :(得分:3)

这是让你非常接近的东西。您不需要极坐标来绘制一个合适的椭圆。有一个你可以轻易利用的所谓artist 您可能必须自定义轴标签,如果需要,可以插入一两个箭头:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Ellipse

# initializing the figure:
fig = plt.figure()

# the (carthesian) axis:
ax = fig.add_subplot(111,aspect='equal')
ax.grid(True)

# parameters of the ellipse:
a = 5.0
e = 4.0
b = np.sqrt(a**2.0 - e**2.0)

# the center of the ellipse:
x = 6.0
y = 6.0

# the angle by which the ellipse is rotated:
angle = -45.0
#angle = 0.0

# plotting the ellipse, using an artist:
ax.add_artist(Ellipse(xy=[x,y], width=2.0*a, height=2.0*b, \
                                angle=angle, facecolor='none'))
ax.set_xlim(0,2.0*x)
ax.set_ylim(0,2.0*y)

# marking the focus (actually, both)
# and accounting for the rotation of the ellipse by angle
xf = [x - e*np.cos(angle * np.pi/180.0),
      x + e*np.cos(angle * np.pi/180.0)]

yf = [y - e*np.sin(angle * np.pi/180.0),
      y + e*np.sin(angle * np.pi/180.0)]

ax.plot(xf,yf,'xr')

# plotting lines from the focus to the ellipse:
# these should be your "rays"
t = np.arange(np.pi,3.0*np.pi,np.pi/5.0)
p = b**2.0 / a
E = e / a
r = [p/(1-E*np.cos(ti)) for ti in t]

# converting the radius based on the focus 
# into x,y coordinates on the ellipse:
xr = [ri*np.cos(ti) for ri,ti in zip(r,t)]
yr = [ri*np.sin(ti) for ri,ti in zip(r,t)]

# accounting for the rotation by anlge:
xrp = [xi*np.cos(angle * np.pi/180.0) - \
       yi*np.sin(angle * np.pi/180.0) for xi,yi in zip(xr,yr)]
yrp = [xi*np.sin(angle * np.pi/180.0) + \
       yi*np.cos(angle * np.pi/180.0) for xi,yi in zip(xr,yr)]

for q in range(0,len(t)):
    ax.plot([xf[0], xf[0]+xrp[q]],[yf[0], yf[0]+yrp[q]],'--b')

# put labels outside the "rays"
offset = 0.75
rLabel = [ri+offset for ri in r]
xrl = [ri*np.cos(ti) for ri,ti in zip(rLabel,t)]
yrl = [ri*np.sin(ti) for ri,ti in zip(rLabel,t)]

xrpl = [xi*np.cos(angle * np.pi/180.0) - \
        yi*np.sin(angle * np.pi/180.0) for xi,yi in zip(xrl,yrl)]
yrpl = [xi*np.sin(angle * np.pi/180.0) + \
        yi*np.cos(angle * np.pi/180.0) for xi,yi in zip(xrl,yrl)]

# for fancy label rotation reduce the range of the angle t:
tlabel = [(ti -np.pi)*180.0/np.pi for ti in t]
for q in range(0,len(tlabel)):
    if tlabel[q] >= 180.0:
        tlabel[q] -= 180.0

# convert the angle t from radians into degrees:
tl = [(ti-np.pi)*180.0/np.pi for ti in t]

for q in range(0,len(t)):
    rotate_label = angle + tlabel[q]
    label_text = '%.1f' % tl[q]
    ax.text(xf[0]+xrpl[q],yf[0]+yrpl[q],label_text,\
            va='center', ha='center',rotation=rotate_label)

plt.show()

上面的例子将导致这个数字:

example

解释:

  • 您可以使用artist to plot the ellipse,而不是使用极坐标
  • 术语基于Wikipedia
  • 上提供的定义
  • 艺术家设置中的angle会旋转椭圆。此角度稍后用于旋转光线和标签的坐标(这是只是数学)
  • 光线来自polar form of the ellipse relative to a focus
  • 角度 tpi3.0*pi,因为我认为这与您对射线应该从哪里开始的想法相对应。您获得02.0*pi的相同光线。我使用np.arange而不是linspace,因为我希望在此示例中定义增量(pi/5.0或36度)。
  • 光线末端的标签放置为text,变量offset控制椭圆与标签之间的距离。根据需要调整。
  • 为了使标签文字方向与光线对齐,我将角度t缩小到范围0180度。与0360度的全部范围相比,这提高了可读性。
  • 对于标签文本,我只使用了角度t,以简化。用适合您目的的任何信息替换它。
  • 角度t在放置标签的循环之前从弧度转换为度数。在循环内部,tl的每个元素都转换为字符串。这允许更多的格式控制(例如%.3f,如果您需要3位小数)