皆既月食で,皆既中の写真を2地点から撮影して,周りの星との位置のずれから視差を測定し,月までの距離を求めるための計算プログラム。

2地点の緯度・経度から,距離を求める式は,長谷川一郎著「天文計算入門」(恒星社)30pに出ている公式を使いました。月の方向と2地点の向きが直交するように月の視線方向に対して,2地点の方位角と月の方位と地平高度から補正して計算するものです。たとえば,もし2地点を結んだ方向が月の見える方向(視線方向)と一致していたら,視差は0になってしまいます。もっとも視差が大きくなるのは視線方向と2地点が直交している場合ですが,通常その中間の状態にあるわけです。そこで,月の視線方向(撮影時の方位角と地平高度)と2地点の方向(方位角)について,視差が直交している場合の値に補正して計算する方法を考えました。2地点の方位角と,月の方位角のなす角(90度以下になる)Aと月の地平高度Bから,2地点の中間を中心とする球面で,月と2地点を通る大円上での月と月に近い2地点の地平方位と成す角度Cを直角球面三角形の公式で計算し,直交する方向(90°)からの差の角のコサインで,観測された視差を割れば良いということになると考えました。pythonをインストールしてお使い頂ければと思います。また,実行ファイル(exe形式)も作りました。こちらからダウンロードできます。

こちらのコードをドラッグしてコピーできます(行番号はコピーされません)。

'''
2地点の観測による視差から月までの距離を求めるプログラム(Python3)
'''

import sys
import tkinter as tk  # graphical user interface module
import math # 数学関数の標準モジュール

def baseline(lon_a, lat_a, lon_b, lat_b): # 基線長をもとめる関数
    ra = 6371.0  # earth radius (km)
    lat_a = math.radians(lat_a)  # to radian unit
    lon_a = math.radians(lon_a)
    lat_b = math.radians(lat_b)
    lon_b = math.radians(lon_b)
    # 2地点,緯度経度から方位角Az,中心角DDを求める(公式)
    SDs = math.cos(lat_b) * math.sin(lon_b - lon_a)
    SDc = math.cos(lat_a) * math.sin(lat_b) - math.sin(lat_a) * math.cos(lat_b) * math.cos(lon_b - lon_a)
    Az = math.atan(SDs/SDc)  # 方位角(Azimuth)# を求める
    Az = math.degrees(Az)
    if SDc < 0:
        Az = Az + 180
    if Az < 0:
        Az = Az + 360
    CD = math.sin(lat_a) * math.sin(lat_b) + math.cos(lat_a) * math.cos(lat_b) * math.cos(lon_b - lon_a)
    # K = SDs * SDs + SDc * SDc + CD * CD
    # print(K)   # 検算 = 1
    DD = math.acos(CD) # 2地点の弧の中心角 DD
    # print(math.degrees(DD))
    Dist = 2 * ra * math.sin(DD/2)  # 弦の長さ=基線長
    return [Dist, Az]


def hoseikaku(h, Am, Az): # 月の方位角と高度,基線の方位から補正角をもとめる関数
    if Az > 180:
        Az = Az - 180
    a = abs(Am - Az)
    a = math.radians(a)
    b = math.radians(h)
    c = math.cos(a) * math.cos(b) # 直角球面三角形の公式
    c = math.acos(c)
    c = math.degrees(c)
    return c

def main(lon_a, lat_a, lon_b, lat_b, horizon, Am, P_obs):

    Dist,Az = baseline(lon_a, lat_a, lon_b, lat_b) # 関数にわたす
    print("")
    print(" 基線長 Dist = ", format(Dist,'5g'),"km")  # 基線長(Dist)とaからbへの方位角(Az)
    print(" 基線方位角 Az = ", format(Az,'f'),"°")
    C = hoseikaku(horizon, Am, Az)
    Z = 90 - C
    Z = math.radians(Z)

    Px = P_obs / math.cos(Z)   # 補正
    print(" 観測された視差 Observed P= ", P_obs," 秒")
    print(" 視線方向に補正した視差 Px= ",format(Px,'f')," 秒")
    MD = 206264.8 * Dist / Px    # 視差から距離をもとめる(1秒のラジアン単位の逆数倍)
    print(" 月の距離 Moon_Distance = ",format(MD,'.8g')," km")
    return MD


"""        =========  GUI  ==========       """

class Application(tk.Frame):
    def __init__(self, master=None):
        super().__init__(master)
        master.title("Calculating Distance of the Moon from Parallax")
        master.geometry("640x380")
        self.pack()
        self.lat_a = tk.DoubleVar(value=35.0)
        self.lon_a = tk.DoubleVar(value=138.0)
        self.lat_b = tk.DoubleVar(value=36.0)
        self.lon_b = tk.DoubleVar(value=139.0)
        self.horizon = tk.DoubleVar(value=30.0)
        self.Am = tk.DoubleVar(value=130.0)
        self.P_obs = tk.DoubleVar(value=77.0)
        self.Distance = tk.DoubleVar(value=0.0)
        self.create_widgets()

    def create_widgets(self):
        self.lb1 = tk.Label(self, text='\n月の視差から距離を測定するプログラム\n ',
                            width=300, font=('MSゴシック', 11), anchor='c')
        self.lb1.pack()
        self.lb2 = tk.Label(self,
                            text='\n\n     観測点A,Bの緯度と経度を(°単位)小数表示で入力してください。\n   ',
                            font=('MSゴシック', 10), width=300, anchor='w')
        self.lb2.pack()
        self.lb01 = tk.Label(text='Aの緯度',width=15)
        self.lb01.place(x=20, y=100)
        self.Entry1 = tk.Entry(textvariable=self.lat_a, width=15)
        self.Entry1.place(x=30, y=120)
        self.lb02 = tk.Label(text='Aの経度', width=15)
        self.lb02.place(x=150, y=100)
        self.Entry2 = tk.Entry(textvariable=self.lon_a, width=15)
        self.Entry2.place(x=160, y=120)
        self.lb03 = tk.Label(text='Bの緯度', width=15)
        self.lb03.place(x=280, y=100)
        self.Entry3 = tk.Entry(textvariable=self.lat_b, width=15)
        self.Entry3.place(x=290, y=120)
        self.lb04 = tk.Label(text='Bの経度', width=15)
        self.lb04.place(x=400, y=100)
        self.Entry4 = tk.Entry(textvariable=self.lon_b, width=15)
        self.Entry4.place(x=410, y=120)
        self.lb3 = tk.Label(self,text='\n\n\n\n\n     月の地平高度(°)と方位角(°),観測された視差(秒)を入力してください。\n',
                            font=('MSゴシック',10),width=300,anchor='w')
        self.lb3.pack()
        self.lb05 = tk.Label(text='地平高度(°)', width=15)
        self.lb05.place(x=20, y=200)
        self.Entry5 = tk.Entry(textvariable=self.horizon,width=15)
        self.Entry5.place(x=30, y=220)
        self.lb06 = tk.Label(text='方位角(°)', width=15)
        self.lb06.place(x=150, y=200)
        self.Entry6 = tk.Entry(textvariable=self.Am,width=15)
        self.Entry6.place(x=160, y=220)
        self.lb07 = tk.Label(text='視差(”)', width=15)
        self.lb07.place(x=310, y=200)
        self.Entry7 = tk.Entry(textvariable=self.P_obs,width=15)
        self.Entry7.place(x=310, y=220)

        self.bt3 = tk.Button(text='計算実行', width=15, command=self.excute)
        self.bt3.place(x=430, y=280)
        self.lb08 = tk.Label(text='方位角は,北を基準に時計回り360°の値です。')
        self.lb08.place(x=100, y=250)
        self.bt4 = tk.Button(text='終了(EXIT)', width=15, command=self.end)
        self.bt4.place(x=470, y=50)
        self.lb09 = tk.Label(text='月までの距離(km)',width=15,font=('MSゴシック',11))
        self.lb09.place(x=50, y=300)
        self.Entry8 = tk.Entry(textvariable=self.Distance,font=('MSゴシック',11),width=20)
        self.Entry8.place(x=180, y=300)

    def excute(self): # 計算ボタンで実行する
        lta = self.lat_a.get()
        loa = self.lon_a.get()
        ltb = self.lat_b.get()
        lob = self.lon_b.get()
        h = self.horizon.get()
        A = self.Am.get()
        P = self.P_obs.get()
        self.Distance = main(loa,lta,lob,ltb,h,A,P)
        self.Entry8.delete(0,tk.END)
        self.Entry8.insert(0,str(format(self.Distance,'.7g')))

    def end(self): # 終了ボタンで終了
        root.destroy()
        sys.exit()

if __name__ == '__main__':
    root = tk.Tk()
    app = Application(master = root)
    app.mainloop()

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください