皆既月食で,皆既中の写真を2地点から撮影して,周りの星との位置のずれから視差を測定し,月までの距離を求めるための計算とpyhtonによるプログラム。
2地点の緯度・経度から,距離を求める式は,長谷川一郎著「天文計算入門」(恒星社)30pに出ている公式(式9-1,p26)を使いました。
- 2地点の基線長とその方位角の計算
地球の半径=6371kmとしました。
地球の半径をr,地点Aの(経度x1, 緯度y1)、地点Bの(経度x2, 緯度y2)とすると
SDs = cos(y2)sin(x2 – x1) SDc = cos(y1)sin(y2) – sin(y1)cos(y2)cos(x2 – x1)
# 方位角(Azimuth)は Az = tan-1(SDs/SDc) (方位角は北:0°、東:90°、南:180°、西270°)
CD = sin(y1)sin(y2) + cos(y1)cos(y2)cos(x2 – x1)
# 検算 K = SDs2 + SDc2 + CD2 で K = 1 になります。
# 2地点の弧の中心角 DDは DD = cos-1(CD)
# 基線長(弦の長さ)は Dist = 2 r × sin(DD/2)
2地点からの視差が観測されたとしても普通,基線となる2地点の方向は,月の視線方向とは直交していませんので,月からみた2地点を投影した基線長にするか,視差を視線方向に直交する値に補正するかしなければなりません。ここでは後者の方法を考えました(下図参照)。2地点を直径とする球面上で考えます。月と2地点を通る大円上で地平線から月までの角(X)を,2地点の方位角と月の方位角のなす角(D)と月の地平高度(h)から,直角球面三角形の公式で求め,基線と直交する方向(90°)からの差の角度(Z)の(cosZ)で,観測された視差を割れば,補正した視差になると考えました。あるいはこの図では分かりずらいと思うのですが,月のから基線の長さをみると,AB間の距離が,cosZ倍に短くなると考えるのと同じ計算(逆数で割るので)になります。
- 視線方向への視差の補正計算
月の地平高度:h 月の方位角※: Am 基線の方位角:Az とする。
D = |Am – Az| #絶対値
X = cos(D) × cos(h) (直角球面三角形の公式)
Z = 90 – cos-1(X)
# 補正視差Pxは 観測された視差Poに対して Px = Po / cos(Z)
2地点の緯度経度と月の高度方位角,観測された視差から,月までの距離を求めるプログラムを組んでみました。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()