マイコン宇宙講座-月齢表示
月の形は見かけ上、新月から満月、満月から新月まで変化していきます。また、新月から満月までを上弦の月、満月から新月までを下弦の月と呼びます。月の形の変化を月の満ち欠けとよび、この月の満ち欠けを数値で表したものを月齢といいます。月齢は、新月からの経過日数を表していますので、約15日で満月になります(厳密に言うと14.8〜15.6)。そして、満月から新月まで経過日数は増えていき、再び新月で経過日数は0になります。
月齢の登場は暦と密接な関係にあり、現在は太陽を基準とした新暦が使われていますが、旧暦は月の満ち欠けを基準とした暦でした。現在では、月齢はあまり重要視されませんが、カレンダーによっては月齢が掲載されていることもありますし、天文現象カレンダーには月齢が記載されています。前記事「マイコン宇宙講座-月の高度・方位角計算」でも述べましたが、淡い天体を観測する上で月明かりの影響は大きいため、やはり月齢に注意して観測プランを立てるということになります。
メインルーチン m57.py
# m57.py
# マイコン宇宙講座
# 月齢表示プログラム
from PIL import Image, ImageDraw, ImageFont
from tkinter.constants import SOLID
import tkinter as tk
import lib
import math
M2PI = 2.0 * math.pi
# 計算する場所の経度・緯度・地名
lg = 139.745 / lib.K[3]
la = 35.654 / lib.K[3]
obs = '東京'
# 月齢を表示する
def display_moon_age():
global photo
std = editbox.get()
# 入力されていない時は何にもしない
if std != '':
dy, dt = std.split(',')
dy = float(dy)
dt = float(dt)
jd, yy, mm, dd, hh, ms, ss = lib.mjd(dy, dt)
draw_moon_age(dy, jd, yy, mm, dd, hh, ms)
# 保存された画像を表示
photo = tk.PhotoImage(file='./images/geturei.png')
canvas.create_image(1, 1, image=photo, anchor=tk.NW)
# テキストボックスの中身をクリア
editbox.delete(0, tk.END)
# 日付と時刻の入力欄にフォーカスをセット
editbox.focus_set()
# 月齢を描く
def draw_moon_age(dy, jd, yy, mm, dd, hh, ms):
ia = 0
id = 0
ha = 0
hd = 0
sg = 0
dta = (jd - 15019.5) / 36525.0
a, b, c, d, e, g, j, l, m, n, v, w = lib.argument(dta)
# 月齢表示
img = Image.new('RGB', (640, 400), (0, 0, 0))
draw = ImageDraw.Draw(img)
# フォント名は実行環境に合わせて変更すること
# TrueTypeの等幅フォント名を指定する
fonts = ImageFont.truetype('TakaoGothic.ttf', 14)
eg = d
ge = eg / M2PI * 29.4
cc = math.cos(eg)
sdtime = '%4d年 %2d月 %2d日 %2d時 %2d分' % (yy, mm, dd, hh, ms)
smoonage = '月齢 = 約 %4.1f' % (ge)
draw.text((80, 16), sdtime, font=fonts)
draw.text((88, 48), smoonage, font=fonts)
il = 0
for y in range(20, 80):
lx = math.sqrt(-(math.pow((y - 50), 2)) + math.pow(30.0, 2))
if eg > math.pi:
lx *= -1
x = int(80 + lx * cc)
il = int(lx + 80)
if il > 80:
draw.line((x * 4, y * 4, il * 4, y * 4), width=4, fill=(255, 255, 255))
else:
draw.line((il * 4, y * 4, x * 4, y * 4), width=4, fill=(255, 255, 255))
dt = 90000.0
jd, yy, mm, dd, hh, ms, ss = lib.mjd(dy, dt)
# 出没時刻の計算
while True:
sg = 0
if ha > 15:
sg = -1
dta = (jd - 15019.5 + sg + ha / 24.0) / 36525.0
a, b, c, d, e, g, j, l, m, n, v, w = lib.argument(dta)
mx, my, mz = lib.moon(dta, a, b, d, e, n, g, w)
r0 = c
r1 = mx
r2 = my
r3 = mz
ra, dc, dl = lib.positions(r0, r1, r2, r3)
ds = dl / 23454.706
rd = 0
result = lib.appear(jd, lg, la, ra, dc, ds, rd, sg, hd, lib.K)
flags = False
while True:
if hd == 1:
break
ta = result[0]
if abs(ta - ha) < 2.0e-3:
break
if ia == 5:
break
ha = ta
ia += 1
flags = True
break
if flags:
continue
td = result[0]
al = result[1]
if hd == 0:
hd = 1
id = 0
ha = 0
continue
if abs(td - ha) < 2.0e-3:
break
if id == 5:
break
ha = td
id += 1
continue
ta1 = ta
ta += 9
if ta > 24:
ta -= 24
td1 = td
td += 9
if td > 24:
td -= 24
h1 = int(ta)
m1 = 60.0 * (ta - h1)
h2 = int(td)
m2 = 60.0 * (td - h2)
sfmt = '%s での 月の出: %2d 時 %4.1f 分 月の入: %2d 時 %4.1f 分' % (obs, h1, m1, h2, m2)
if ia == 5:
sfmt = '%s での 月の出: -- 時 --.- 分 月の入: %2d 時 %4.1f 分' % (obs, h2, m2)
if id == 5:
sfmt = '%s での 月の出: %2d 時 %4.1f 分 月の入: -- 時 --.-f 分' % (obs, h1, m1)
draw.text((72, 368), sfmt, font=fonts)
draw.text((400, 16), '月の入りでの', font=fonts)
sfmt = '北からの方位角 = %5.1f 度' % (al * lib.K[3])
draw.text((400, 32), sfmt, font=fonts)
# 画像を保存
# 必ずPNG形式で保存
img.save('./images/geturei.png')
# メイン
root = tk.Tk()
root.resizable(False, False)
root.geometry('640x440')
root.title('マイコン宇宙講座 - 月齢表示プログラム')
canvas = tk.Canvas(root, width=640, height=400, bg='black')
canvas.pack(anchor=tk.NW)
label = tk.Label(root, text='DATE AND TIME(JST):')
label.place(x=10, y=414)
editbox = tk.Entry(root, relief=SOLID)
editbox.place(x=155, y=412, width=140, height=24)
button = tk.Button(root, text='表示', width=6, relief=SOLID, cursor='hand1', command=display_moon_age)
button.place(x=480, y=409)
button = tk.Button(root, text='閉じる', width=6, relief=SOLID, cursor='hand1', command=root.destroy)
button.place(x=558, y=409)
# 日付と時刻の入力欄にフォーカスをセット
editbox.focus_set()
root.mainloop()
例題 1981年1月1日21時の月齢を表示してみよう。