아이디어
2017년 추석 오전 5시(2017-10-04T05:00:00+09)에 서울 부근(37.5908, 127.0292)에서 M42를 보았을 때 보이는 오리온 자리의 모양(α, β, γ, δ, ε, ζ, κ Ori를 이은 것)을 로고마크로 하려고 한다.
좌표의 계산
import astropy.units as u
from astropy.time import Time
from astropy.coordinates import SkyCoord, EarthLocation, AltAz
location = EarthLocation(lat=37.5908*u.deg, lon=127.0292*u.deg)
time = Time('2017-10-04T05:00:00') - 9 * u.hour
star_names = ['M42', 'alpha ori', 'beta ori', 'gamma ori', 'delta ori', 'epsilon ori', 'zeta ori', 'kappa ori']
print([SkyCoord.from_name(name).transform_to(AltAz(obstime=time, location=location)) for name in star_names])
[
(173.73551283, 46.84306689),
(162.06947888, 58.66289377),
(181.23271073, 44.22017205),
(176.58999249, 58.73144979),
(174.33127561, 51.98557433),
(172.78083327, 50.99118912),
(171.13556489, 50.12738586),
(170.11343254, 42.23919504)
]
방위각은 북에서 동으로 잰다. 각각을 (azimuth, altitude) 라 하자. M42를 바라보도록 좌표계 변환을 해야 하는데, 일단 M42의 방위각을 로 맞추는 것은 간단하다.
[
(180., 46.84306689),
(168.33396605, 58.66289377),
(187.4971979, 44.22017205),
(182.85447966, 58.73144979),
(180.59576278, 51.98557433),
(179.04532044, 50.99118912),
(177.40005206, 50.12738586),
(176.37791971, 42.23919504)
]
이것을 반지름을 로 하고 을 , 을 , 를 로 하는 직교좌표계로 만들자.
[
(-0.68399898, 0., 0.72948297),
(-0.50932916, -0.10516215, 0.8541222),
(-0.71053852, 0.09350882, 0.69741746),
(-0.518406, 0.02584841, 0.85474387),
(-0.61582656, 0.00640361, 0.78785572),
(-0.62935252, -0.01048743, 0.77704918),
(-0.64042295, -0.02908085, 0.76747166),
(-0.73886604, -0.04677138, 0.6722272)
]
이것을 축을 기준으로 만큼 회전변환 하자. 회전변환행렬은
이 된다.
[
(-1., 0., 0.),
(-0.97144822, -0.10516211, 0.21267178),
(-0.99476177, 0.09350888, -0.04129289),
(-0.97811026, 0.02584845, 0.20647561),
(-0.99595207, 0.00640366, 0.08965754),
(-0.99732062, -0.01048738, 0.07239892),
(-0.99790615, -0.0290808 , 0.05777222),
(-0.99576191, -0.04677132, -0.07918745)
]
각각을 원점과 이었을 때 과 만나는 점을 구한다. 이미 거의 이기는 하다.
[
(0.0, 0.0),
(-0.10825291990642123, 0.2189224017746473),
(0.09400127691763133, -0.041510326969010296),
(0.02642693266897339, 0.21109645394247914),
(0.006429686270859082, 0.09002194408057741),
(-0.01051555581999568, 0.07259342846922238),
(-0.029141819265636422, 0.05789343911761977),
(-0.04697038877373099, -0.07952448164500331)
]
결론적으로 코드는 다음과 같이 된다.
import numpy as np
import matplotlib.pyplot as plt
import astropy.units as u
from astropy.time import Time
from astropy.coordinates import SkyCoord, EarthLocation, AltAz
location = EarthLocation(lat=37.5908*u.deg, lon=127.0292*u.deg)
time = Time('2017-10-04T05:00:00') - 9 * u.hour
star_names = ['M42', 'alpha ori', 'beta ori', 'gamma ori', 'delta ori', 'epsilon ori', 'zeta ori', 'kappa ori']
a = [SkyCoord.from_name(name).transform_to(AltAz(obstime=time, location=location)) for name in star_names]
dA = a[0].az - 180 * u.deg
b = [(x.az - dA, x.alt) for x in a]
c = [(np.cos(x[1]) * np.cos(x[0]), -np.cos(x[1]) * np.sin(x[0]), np.sin(x[1])) for x in b]
m = np.array([[-c[0][0], 0, -c[0][2]], [0, 1, 0], [c[0][2], 0, -c[0][0]]])
d = [m.dot(x) for x in c]
e = [(x[1] / -x[0], x[2] / -x[0]) for x in d]
print(e)
plt.plot([p[0] for p in e], [p[1] for p in e], 'ro')
plt.axis([-.3, .3, -.3, .3])
plt.show()
matplot 출력 결과: https://imgur.com/8ixr6HG
SVG 생성
로고마크를 만들기 위해 사용한 코드는 다음과 같다.
import numpy as np
import matplotlib.pyplot as plt
import astropy.units as u
from astropy.time import Time
from astropy.coordinates import SkyCoord, EarthLocation, AltAz
location = EarthLocation(lat=37.5908*u.deg, lon=127.0292*u.deg)
time = Time('2017-10-04T05:00:00') - 9 * u.hour
star_names = ['M42', 'zeta ori', 'alpha ori', 'gamma ori', 'delta ori', 'zeta ori', 'kappa ori', 'beta ori', 'delta ori']
a = [SkyCoord.from_name(name).transform_to(AltAz(obstime=time, location=location)) for name in star_names]
dA = a[0].az - 180 * u.deg
b = [(x.az - dA, x.alt) for x in a]
c = [(np.cos(x[1]) * np.cos(x[0]), -np.cos(x[1]) * np.sin(x[0]), np.sin(x[1])) for x in b]
m = np.array([[-c[0][0], 0, -c[0][2]], [0, 1, 0], [c[0][2], 0, -c[0][0]]])
d = [m.dot(x) for x in c]
e = [(x[1] / -x[0], x[2] / -x[0]) for x in d]
f = [(x[0] * 1300 + 256 + 17, (x[1] - .1) * 1300 + 256 + 41) for x in e]
print('<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512">')
for i in range(1, len(f) - 1):
print('<line x1="' + str(f[i][0]) + '" y1="' + str(512 - f[i][1]) + '" x2="' + str(f[i + 1][0]) + '" y2="' + str(512 - f[i + 1][1]) + '" stroke="white" stroke-width="65" />')
print('\n'.join(['<circle cx="' + str(x[0]) + '" cy="' + str(512 - x[1]) + '" r="60" fill="white" />' for x in f]))
for i in range(1, len(f) - 1):
print('<line x1="' + str(f[i][0]) + '" y1="' + str(512 - f[i][1]) + '" x2="' + str(f[i + 1][0]) + '" y2="' + str(512 - f[i + 1][1]) + '" stroke="#222" stroke-width="25" />')
print('<circle cx="' + str(f[0][0]) + '" cy="' + str(512 - f[0][1]) + '" r="40" fill="#222" />')
print('\n'.join(['<circle cx="' + str(x[0]) + '" cy="' + str(512 - x[1]) + '" r="40" fill="#222" />' for x in f[1:]]))
print('</svg>')
가운데에 있는 것은 뺐다.