マイコン宇宙講座-楕円軌道表示

離心率を与えて平均近点離角を0°から360°まで変化させながら楕円軌道を表示します。前記事「離心近点離角計算」では数値だけでしたので、なかなかイメージしにくいものでしたが、実際の軌道を表示させるとよく解ると思います。これをベースにして、惑星、小惑星、彗星といった太陽系天体の軌道を表示させたり、ある日の天体の位置を視覚的に表示させることもできます。ただ、これからたくさんの計算が必要ですが、挑戦してみるのもよいと思います。

メインルーチン m29.py

楕円軌道を視覚的に表示しています。Pythonでこれを実現するのにTKinterというグラフィックライブラリを利用しています。また、このプログラムは、「マイコン宇宙講座」のプログラムと基本的な部分は同じであるものの、大部分が異なりますのでコメントをつけてあります。

# m29.py
# マイコン宇宙講座
# 2-9 楕円軌道表示プログラム
from PIL import Image, ImageDraw, ImageFont
from tkinter.constants import SOLID
from tkinter import messagebox as msgbox
import tkinter as tk
import math
import lib


# 「表示」ボタンがクリックされたときの処理
def display_orbit():
    global photo  # これを忘れると表示されない

    std = editbox.get()
    if std != '':
        ec = float(std)

        # 軌道を描く
        drawing_orbit(ec)

        # 保存された画像を表示
        photo = tk.PhotoImage(file='./images/orbit.png')
        canvas.create_image(1, 1, image=photo, anchor=tk.NW)
    else:
        msgbox.showerror('入力エラー', '離心率が入力されていません。')

    # 画像を表示したらテキストボックスの中身をクリア
    editbox.delete(0, tk.END)

    # 離心率editboxにフォーカスをセット
    editbox.focus_set()


# 軌道を表示
def drawing_orbit(ec):
    img = Image.new('RGB', (640, 400), (0, 0, 0))
    draw = ImageDraw.Draw(img)

    # フォント名は実行環境に合わせて変更すること
    # TrueTypeのフォント名を指定する
    fonts = ImageFont.truetype('TakaoGothic.ttf', 13)

    a = 44
    b = a * math.sqrt(1.0 - ec * ec)

    # 太陽を描く
    cx = 280
    cy = 180
    draw.ellipse((cx - 4, cy - 4, cx + 4, cy + 4), fill=(255, 80, 0))
    draw.text((cx + 8, cy - 6), 'Sun', font=fonts, fill=(255, 255, 255))

    # 軌道を描く
    for m in range(0, 360, 5):
        mo = m / (180.0 / math.pi)

        ss, cc, ff = lib.kepler(mo, ec)

        x = -(a * ff) * 4
        y = -(b * ss) * 4
        x = int(x + cx)
        y = int(y + cy)
        draw.ellipse((x, y, x + 1, y + 1), fill=(0, 100, 255))

    if ec != 0:
        a = a / 2.0
        q1 = int(a * (1 - ec))
        q2 = int(a * (1 + ec))

        # 離心率、近日点、遠日点を描画
        # 近日点と遠日点の文字位置は実際に描画してみて調整してある
        draw.text((5, 5), 'E = ' + str(ec), font=fonts, fill=(255, 255, 255))
        draw.text(((35 - 4 - q1) * 8, 11 * 16), 'q', font=fonts, fill=(255, 255, 255))
        if ec > 0.8:
            xp = 2
        else:
            xp = 4
        draw.text(((35 + xp + q2) * 8, 11 * 16), 'Q', font=fonts, fill=(255, 255, 255))

        # 画像を保存
        # 必ずPNG形式で保存
        img.save('./images/orbit.png')


# メイン
root = tk.Tk()
root.resizable(False, False)
root.geometry('642x440')
root.title('マイコン宇宙講座 - 楕円軌道表示プログラム')

canvas = tk.Canvas(root, width=640, height=400, bg='black')
canvas.pack(anchor=tk.NW)

label = tk.Label(root, text='離心率(EC):')
label.place(x=10, y=410)

editbox = tk.Entry(root, relief=SOLID)
editbox.place(x=85, y=408, width=100, height=24)

button = tk.Button(root, text='表示', width=6, relief=SOLID, cursor='hand1', command=display_orbit)
button.place(x=480, y=407)

button = tk.Button(root, text='閉じる', width=6, relief=SOLID, cursor='hand1', command=root.destroy)
button.place(x=558, y=407)

# 離心率editoboxにフォーカスをセット
editbox.focus_set()

root.mainloop()

例題 離心率を入力して楕円軌道を表示させてみよう。

離心率を入力して楕円軌道を表示させる
離心率0.7の楕円軌道