astro_chart 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +25 -0
- data/LICENSE +17 -16
- data/astro_chart.gemspec +7 -6
- data/lib/astro_chart/ephemeris.rb +76 -18
- data/lib/astro_chart/pure/core.rb +209 -0
- data/lib/astro_chart/pure/houses.rb +122 -0
- data/lib/astro_chart/pure/moon.rb +341 -0
- data/lib/astro_chart/pure/moon_elp.rb +931 -0
- data/lib/astro_chart/pure/pluto.rb +220 -0
- data/lib/astro_chart/pure/vsop87.rb +152 -0
- data/lib/astro_chart/pure/vsop87_data.rb +210 -0
- data/lib/astro_chart/pure.rb +63 -0
- data/lib/astro_chart/synastry.rb +118 -0
- data/lib/astro_chart/version.rb +1 -1
- data/lib/astro_chart.rb +6 -1
- metadata +19 -45
- data/ext/astro_chart/astro_chart_ext.c +0 -99
- data/ext/astro_chart/extconf.rb +0 -8
- data/ext/astro_chart/swecl.c +0 -6428
- data/ext/astro_chart/swedate.c +0 -588
- data/ext/astro_chart/swedate.h +0 -81
- data/ext/astro_chart/swedll.h +0 -403
- data/ext/astro_chart/sweephe4.c +0 -702
- data/ext/astro_chart/sweephe4.h +0 -239
- data/ext/astro_chart/swehel.c +0 -3511
- data/ext/astro_chart/swehouse.c +0 -3143
- data/ext/astro_chart/swehouse.h +0 -98
- data/ext/astro_chart/swejpl.c +0 -958
- data/ext/astro_chart/swejpl.h +0 -103
- data/ext/astro_chart/swemmoon.c +0 -1930
- data/ext/astro_chart/swemplan.c +0 -967
- data/ext/astro_chart/swemptab.h +0 -10640
- data/ext/astro_chart/swenut2000a.h +0 -2819
- data/ext/astro_chart/sweodef.h +0 -326
- data/ext/astro_chart/sweph.c +0 -8614
- data/ext/astro_chart/sweph.h +0 -849
- data/ext/astro_chart/swephexp.h +0 -1020
- data/ext/astro_chart/swephlib.c +0 -4634
- data/ext/astro_chart/swephlib.h +0 -189
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "core"
|
|
4
|
+
|
|
5
|
+
module AstroChart
|
|
6
|
+
module Pure
|
|
7
|
+
# Pluto — MIT-safe 純 Ruby 冥王星視黃經(零外部依賴)。
|
|
8
|
+
#
|
|
9
|
+
# 只使用公開文獻公式,不參考 Swiss Ephemeris C 原始碼:
|
|
10
|
+
# - 冥王星日心座標:Jean Meeus, "Astronomical Algorithms" 2nd ed.,
|
|
11
|
+
# Ch. 37(冥王星專用週期項級數,Table 37.A,適用 1885–2099,
|
|
12
|
+
# 座標基準 = J2000.0 平春分點)
|
|
13
|
+
# - 地球日心座標:Meeus Ch. 25(太陽幾何黃經 + 半徑向量,
|
|
14
|
+
# eq. 25.2–25.5,基準 = 當日平春分點;太陽精度 ~0.01°,
|
|
15
|
+
# 冥王星距離 ~31–50 AU,投影到地心方向後誤差稀釋 ~1/31,
|
|
16
|
+
# 對冥王星地心黃經貢獻 < 0.001°)
|
|
17
|
+
# - 歲差(J2000 → 當日黃道座標):Meeus Ch. 21(eq. 21.5 的
|
|
18
|
+
# η/Π/p 起始曆元 J2000 特化式 + eq. 21.7 球面旋轉)
|
|
19
|
+
# - 光行時 + 光行差:Meeus Ch. 33 — 行星與地球都取 t−τ 時刻
|
|
20
|
+
# 的位置,一次同時涵蓋光行時與(一階)光行差
|
|
21
|
+
# - 章動 Δψ:Core.nutation(Meeus Ch. 22)
|
|
22
|
+
#
|
|
23
|
+
# 時間尺度:apparent_longitude 吃 **JD(UT)**,內部自換 TT。
|
|
24
|
+
#
|
|
25
|
+
# 公開 API:
|
|
26
|
+
# Pluto.apparent_longitude(jd_ut) -> 視黃道經度(度,[0,360),
|
|
27
|
+
# 真春分點 of date,含光行時/光行差/章動)
|
|
28
|
+
# 超出 1885–2099 適用範圍 raise Core::DomainError(顯性失敗)。
|
|
29
|
+
module Pluto
|
|
30
|
+
DEG2RAD = Core::DEG2RAD
|
|
31
|
+
RAD2DEG = Core::RAD2DEG
|
|
32
|
+
|
|
33
|
+
# Meeus Ch. 37 級數適用範圍 1885–2099(TT)。
|
|
34
|
+
# JD 2409542.5 = 1885-01-01 00:00、JD 2488069.5 = 2100-01-01 00:00。
|
|
35
|
+
JD_TT_MIN = 2409542.5
|
|
36
|
+
JD_TT_MAX = 2488069.5
|
|
37
|
+
|
|
38
|
+
# 光行時常數:光走 1 AU 所需天數(Meeus Ch. 33)
|
|
39
|
+
LIGHT_TIME_PER_AU = 0.0057755183
|
|
40
|
+
|
|
41
|
+
# Meeus Table 37.A — 43 項週期級數。
|
|
42
|
+
# 每列:[j, s, p, lon_A, lon_B, lat_A, lat_B, rad_A, rad_B]
|
|
43
|
+
# 引數 α = j·J + s·S + p·P(J/S/P 為木星/土星/冥王星平黃經)
|
|
44
|
+
# longitude/latitude 單位 1e-6 度,radius 單位 1e-7 AU
|
|
45
|
+
# 各量 = Σ (A·sin α + B·cos α)
|
|
46
|
+
TERMS = [
|
|
47
|
+
[0, 0, 1, -19_799_805, 19_850_055, -5_452_852, -14_974_862, 66_865_439, 68_951_812],
|
|
48
|
+
[0, 0, 2, 897_144, -4_954_829, 3_527_812, 1_672_790, -11_827_535, -332_538],
|
|
49
|
+
[0, 0, 3, 611_149, 1_211_027, -1_050_748, 327_647, 1_593_179, -1_438_890],
|
|
50
|
+
[0, 0, 4, -341_243, -189_585, 178_690, -292_153, -18_444, 483_220],
|
|
51
|
+
[0, 0, 5, 129_287, -34_992, 18_650, 100_340, -65_977, -85_431],
|
|
52
|
+
[0, 0, 6, -38_164, 30_893, -30_697, -25_823, 31_174, -6_032],
|
|
53
|
+
[0, 1, -1, 20_442, -9_987, 4_878, 11_248, -5_794, 22_161],
|
|
54
|
+
[0, 1, 0, -4_063, -5_071, 226, -64, 4_601, 4_032],
|
|
55
|
+
[0, 1, 1, -6_016, -3_336, 2_030, -836, -1_729, 234],
|
|
56
|
+
[0, 1, 2, -3_956, 3_039, 69, -604, -415, 702],
|
|
57
|
+
[0, 1, 3, -667, 3_572, -247, -567, 239, 723],
|
|
58
|
+
[0, 2, -2, 1_276, 501, -57, 1, 67, -67],
|
|
59
|
+
[0, 2, -1, 1_152, -917, -122, 175, 1_034, -451],
|
|
60
|
+
[0, 2, 0, 630, -1_277, -49, -164, -129, 504],
|
|
61
|
+
[1, -1, 0, 2_571, -459, -197, 199, 480, -231],
|
|
62
|
+
[1, -1, 1, 899, -1_449, -25, 217, 2, -441],
|
|
63
|
+
[1, 0, -3, -1_016, 1_043, 589, -248, -3_359, 265],
|
|
64
|
+
[1, 0, -2, -2_343, -1_012, -269, 711, 7_856, -7_832],
|
|
65
|
+
[1, 0, -1, 7_042, 788, 185, 193, 36, 45_763],
|
|
66
|
+
[1, 0, 0, 1_199, -338, 315, 807, 8_663, 8_547],
|
|
67
|
+
[1, 0, 1, 418, -67, -130, -43, -809, -769],
|
|
68
|
+
[1, 0, 2, 120, -274, 5, 3, 263, -144],
|
|
69
|
+
[1, 0, 3, -60, -159, 2, 17, -126, 32],
|
|
70
|
+
[1, 0, 4, -82, -29, 2, 5, -35, -16],
|
|
71
|
+
[1, 1, -3, -36, -29, 2, 3, -19, -4],
|
|
72
|
+
[1, 1, -2, -40, 7, 3, 1, -15, 8],
|
|
73
|
+
[1, 1, -1, -14, 22, 2, -1, -4, 12],
|
|
74
|
+
[1, 1, 0, 4, 13, 1, -1, 5, 6],
|
|
75
|
+
[1, 1, 1, 5, 2, 0, -1, 3, 1],
|
|
76
|
+
[1, 1, 3, -1, 0, 0, 0, 6, -2],
|
|
77
|
+
[2, 0, -6, 2, 0, 0, -2, 2, 2],
|
|
78
|
+
[2, 0, -5, -4, 5, 2, 2, -2, -2],
|
|
79
|
+
[2, 0, -4, 4, -7, -7, 0, 14, 13],
|
|
80
|
+
[2, 0, -3, 14, 24, 10, -8, -63, 13],
|
|
81
|
+
[2, 0, -2, -49, -34, -3, 20, 136, -236],
|
|
82
|
+
[2, 0, -1, 163, -48, 6, 5, 273, 1_065],
|
|
83
|
+
[2, 0, 0, 9, -24, 14, 17, 251, 149],
|
|
84
|
+
[2, 0, 1, -4, 1, -2, 0, -25, -9],
|
|
85
|
+
[2, 0, 2, -3, 1, 0, 0, 9, -2],
|
|
86
|
+
[2, 0, 3, 1, 3, 0, 0, -8, 7],
|
|
87
|
+
[3, 0, -2, -3, -1, 0, 1, 2, -10],
|
|
88
|
+
[3, 0, -1, 5, -3, 0, 0, 19, 35],
|
|
89
|
+
[3, 0, 0, 0, 0, 1, 0, 10, 3],
|
|
90
|
+
].map(&:freeze).freeze
|
|
91
|
+
|
|
92
|
+
module_function
|
|
93
|
+
|
|
94
|
+
# 冥王星視黃道經度(度,真春分點 of date)。
|
|
95
|
+
# jd_ut: JD(UT)。超出 Meeus Ch. 37 適用範圍(1885–2099)raise DomainError。
|
|
96
|
+
def apparent_longitude(jd_ut)
|
|
97
|
+
jd_tt = Core.jd_tt(jd_ut)
|
|
98
|
+
unless jd_tt >= JD_TT_MIN && jd_tt < JD_TT_MAX
|
|
99
|
+
raise Core::DomainError,
|
|
100
|
+
"Pluto series (Meeus Ch.37) valid only 1885-2099, got JD(TT)=#{jd_tt}"
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# 光行時 + 光行差:行星與地球都取 t−τ 的位置(Meeus Ch. 33)。
|
|
104
|
+
# 地球在 τ 內的位移 = v·τ = v·Δ/c,換成方向偏移正是一階光行差 v/c。
|
|
105
|
+
gx = gy = gz = 0.0
|
|
106
|
+
tau = 0.0
|
|
107
|
+
10.times do |i|
|
|
108
|
+
px, py, pz = pluto_helio_rect(jd_tt - tau, jd_tt)
|
|
109
|
+
ex, ey, ez = earth_helio_rect(jd_tt - tau)
|
|
110
|
+
gx = px - ex
|
|
111
|
+
gy = py - ey
|
|
112
|
+
gz = pz - ez
|
|
113
|
+
delta = Math.sqrt(gx * gx + gy * gy + gz * gz)
|
|
114
|
+
new_tau = LIGHT_TIME_PER_AU * delta
|
|
115
|
+
if (new_tau - tau).abs < 1e-9
|
|
116
|
+
tau = new_tau
|
|
117
|
+
break
|
|
118
|
+
end
|
|
119
|
+
raise Core::DomainError, "Pluto light-time iteration did not converge" if i == 9
|
|
120
|
+
|
|
121
|
+
tau = new_tau
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
lambda_mean = Math.atan2(gy, gx) * RAD2DEG # 平春分點 of date
|
|
125
|
+
dpsi, = Core.nutation(jd_tt)
|
|
126
|
+
Core.norm360(lambda_mean + dpsi)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# --- 冥王星日心直角座標(AU,黃道座標,旋轉到 jd_frame_tt 的平春分點) ---
|
|
130
|
+
# Meeus Ch. 37:級數給出 J2000.0 平春分點下的日心 l/b/r,
|
|
131
|
+
# 再用 precess_from_j2000 旋轉到目標曆元。
|
|
132
|
+
def pluto_helio_rect(jd_tt, jd_frame_tt)
|
|
133
|
+
t = (jd_tt - 2_451_545.0) / 36_525.0
|
|
134
|
+
|
|
135
|
+
# 木星 / 土星 / 冥王星平黃經(度,Meeus Ch. 37)
|
|
136
|
+
j = 34.35 + 3034.9057 * t
|
|
137
|
+
s = 50.08 + 1222.1138 * t
|
|
138
|
+
p = 238.96 + 144.9600 * t
|
|
139
|
+
|
|
140
|
+
sum_l = 0.0
|
|
141
|
+
sum_b = 0.0
|
|
142
|
+
sum_r = 0.0
|
|
143
|
+
TERMS.each do |cj, cs, cp, la, lb, ba, bb, ra, rb|
|
|
144
|
+
alpha = (cj * j + cs * s + cp * p) * DEG2RAD
|
|
145
|
+
sin_a = Math.sin(alpha)
|
|
146
|
+
cos_a = Math.cos(alpha)
|
|
147
|
+
sum_l += la * sin_a + lb * cos_a
|
|
148
|
+
sum_b += ba * sin_a + bb * cos_a
|
|
149
|
+
sum_r += ra * sin_a + rb * cos_a
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
l = 238.958116 + 144.96 * t + sum_l * 1e-6 # 度,J2000 平春分點
|
|
153
|
+
b = -3.908239 + sum_b * 1e-6 # 度
|
|
154
|
+
r = 40.7241346 + sum_r * 1e-7 # AU
|
|
155
|
+
|
|
156
|
+
l, b = precess_from_j2000(l, b, jd_frame_tt)
|
|
157
|
+
|
|
158
|
+
l_rad = l * DEG2RAD
|
|
159
|
+
b_rad = b * DEG2RAD
|
|
160
|
+
cb = Math.cos(b_rad)
|
|
161
|
+
[r * cb * Math.cos(l_rad), r * cb * Math.sin(l_rad), r * Math.sin(b_rad)]
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
# --- 地球日心直角座標(AU,當日平春分點黃道座標) ---
|
|
165
|
+
# Meeus Ch. 25(eq. 25.2–25.5):太陽幾何黃經 ⊙ 與半徑向量 R,
|
|
166
|
+
# 地球日心黃經 = ⊙ + 180°、黃緯 ≈ 0、距離 = R。
|
|
167
|
+
def earth_helio_rect(jd_tt)
|
|
168
|
+
t = (jd_tt - 2_451_545.0) / 36_525.0
|
|
169
|
+
|
|
170
|
+
l0 = 280.46646 + 36_000.76983 * t + 0.0003032 * t * t # 太陽幾何平黃經
|
|
171
|
+
m = 357.52911 + 35_999.05029 * t - 0.0001537 * t * t # 太陽平近點角
|
|
172
|
+
e = 0.016708634 - 0.000042037 * t - 0.0000001267 * t * t # 地球軌道離心率
|
|
173
|
+
|
|
174
|
+
m_rad = m * DEG2RAD
|
|
175
|
+
c = (1.914602 - 0.004817 * t - 0.000014 * t * t) * Math.sin(m_rad) +
|
|
176
|
+
(0.019993 - 0.000101 * t) * Math.sin(2.0 * m_rad) +
|
|
177
|
+
0.000289 * Math.sin(3.0 * m_rad) # 中心差
|
|
178
|
+
|
|
179
|
+
sun_lon = l0 + c # 太陽真幾何黃經(平春分點 of date)
|
|
180
|
+
nu = m + c # 真近點角
|
|
181
|
+
r = 1.000001018 * (1.0 - e * e) / (1.0 + e * Math.cos(nu * DEG2RAD))
|
|
182
|
+
|
|
183
|
+
earth_lon_rad = (sun_lon + 180.0) * DEG2RAD
|
|
184
|
+
[r * Math.cos(earth_lon_rad), r * Math.sin(earth_lon_rad), 0.0]
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
# --- 黃道座標歲差:J2000.0 → jd_tt 的平春分點(Meeus Ch. 21) ---
|
|
188
|
+
# 起始曆元 = J2000(eq. 21.5 取 T=0):
|
|
189
|
+
# η = 47.0029″t − 0.03302″t² + 0.000060″t³
|
|
190
|
+
# Π = 174°.876384 − 869.8089″t + 0.03536″t²
|
|
191
|
+
# p = 5029.0966″t + 1.11113″t² − 0.000006″t³
|
|
192
|
+
# 再套 eq. 21.7 球面旋轉。
|
|
193
|
+
def precess_from_j2000(lon_deg, lat_deg, jd_tt)
|
|
194
|
+
t = (jd_tt - 2_451_545.0) / 36_525.0
|
|
195
|
+
return [lon_deg, lat_deg] if t.zero?
|
|
196
|
+
|
|
197
|
+
arcsec = 1.0 / 3600.0
|
|
198
|
+
eta = (47.0029 * t - 0.03302 * t * t + 0.000060 * t * t * t) * arcsec
|
|
199
|
+
pi_ = 174.876384 + (-869.8089 * t + 0.03536 * t * t) * arcsec
|
|
200
|
+
pp = (5029.0966 * t + 1.11113 * t * t - 0.000006 * t * t * t) * arcsec
|
|
201
|
+
|
|
202
|
+
eta_rad = eta * DEG2RAD
|
|
203
|
+
lat_rad = lat_deg * DEG2RAD
|
|
204
|
+
pi_lon = (pi_ - lon_deg) * DEG2RAD
|
|
205
|
+
|
|
206
|
+
cos_lat = Math.cos(lat_rad)
|
|
207
|
+
sin_lat = Math.sin(lat_rad)
|
|
208
|
+
sin_pl = Math.sin(pi_lon)
|
|
209
|
+
|
|
210
|
+
a = Math.cos(eta_rad) * cos_lat * sin_pl - Math.sin(eta_rad) * sin_lat
|
|
211
|
+
b = cos_lat * Math.cos(pi_lon)
|
|
212
|
+
c = Math.sin(eta_rad) * cos_lat * sin_pl + Math.cos(eta_rad) * sin_lat
|
|
213
|
+
|
|
214
|
+
new_lon = pp + pi_ - Math.atan2(a, b) * RAD2DEG
|
|
215
|
+
new_lat = Math.asin(c.clamp(-1.0, 1.0)) * RAD2DEG
|
|
216
|
+
[Core.norm360(new_lon), new_lat]
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
end
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'core'
|
|
4
|
+
require_relative 'vsop87_data'
|
|
5
|
+
|
|
6
|
+
module AstroChart
|
|
7
|
+
module Pure
|
|
8
|
+
# Vsop87 -- MIT-safe 純 Ruby 太陽 + 行星(水星~海王星)視黃道經度。
|
|
9
|
+
#
|
|
10
|
+
# 只使用公開文獻公式與公開發表資料,不參考 Swiss Ephemeris C 原始碼:
|
|
11
|
+
# - 行星日心座標:VSOP87D 截斷級數(Bretagnon & Francou 1988,
|
|
12
|
+
# A&A 202, 309;資料見 vsop87_data.rb)
|
|
13
|
+
# - 太陽視經度:Jean Meeus, "Astronomical Algorithms" 2nd ed.,
|
|
14
|
+
# Ch. 25(高精度法:地球日心經度 + 180°、FK5 修正、
|
|
15
|
+
# 光行差 -20.4898"/R、章動 Δψ)
|
|
16
|
+
# - 行星視經度:Meeus Ch. 33(日心 → 地心,光行時迭代;
|
|
17
|
+
# 地球與行星同取 t-τ 時刻,等效同時涵蓋光行時+光行差
|
|
18
|
+
# 〔planetary aberration〕),再加章動 Δψ
|
|
19
|
+
# - VSOP87 動力學分點 → FK5 修正:Meeus eq. 32.3
|
|
20
|
+
# - 章動 / ΔT / TT 換算:Core(Meeus Ch. 22 / Espenak & Meeus)
|
|
21
|
+
#
|
|
22
|
+
# 公開 API:
|
|
23
|
+
# Vsop87.apparent_longitude(planet_id, jd_ut) -> 視黃道經度(度, [0,360))
|
|
24
|
+
#
|
|
25
|
+
# planet_id 採 Swiss Ephemeris 慣例:SUN=0, MERCURY=2, VENUS=3,
|
|
26
|
+
# MARS=4, JUPITER=5, SATURN=6, URANUS=7, NEPTUNE=8。
|
|
27
|
+
# 月亮(1)/冥王星(9)/北交點(11) 不在本模組範圍,傳入會 raise。
|
|
28
|
+
module Vsop87
|
|
29
|
+
DEG2RAD = Core::DEG2RAD
|
|
30
|
+
RAD2DEG = Core::RAD2DEG
|
|
31
|
+
|
|
32
|
+
# 光行時常數:光走 1 au 所需天數(Meeus eq. 33.3)
|
|
33
|
+
LIGHT_TIME_DAYS_PER_AU = 0.0057755183
|
|
34
|
+
|
|
35
|
+
# planet_id (SE 慣例) => VSOP87 資料 key
|
|
36
|
+
PLANET_KEYS = {
|
|
37
|
+
2 => :mercury,
|
|
38
|
+
3 => :venus,
|
|
39
|
+
4 => :mars,
|
|
40
|
+
5 => :jupiter,
|
|
41
|
+
6 => :saturn,
|
|
42
|
+
7 => :uranus,
|
|
43
|
+
8 => :neptune
|
|
44
|
+
}.freeze
|
|
45
|
+
|
|
46
|
+
SUN_ID = 0
|
|
47
|
+
|
|
48
|
+
module_function
|
|
49
|
+
|
|
50
|
+
# 視黃道經度(apparent geocentric ecliptic longitude,度)。
|
|
51
|
+
# jd_ut 為 JD(UT);內部經 Core.jd_tt 換算 TT。
|
|
52
|
+
def apparent_longitude(planet_id, jd_ut)
|
|
53
|
+
tt = Core.jd_tt(jd_ut)
|
|
54
|
+
if planet_id == SUN_ID
|
|
55
|
+
sun_apparent_longitude(tt)
|
|
56
|
+
elsif PLANET_KEYS.key?(planet_id)
|
|
57
|
+
planet_apparent_longitude(PLANET_KEYS.fetch(planet_id), tt)
|
|
58
|
+
else
|
|
59
|
+
raise Core::DomainError,
|
|
60
|
+
"Vsop87 不支援 planet_id=#{planet_id}(僅太陽 0 與行星 2..8)"
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# --- 太陽(Meeus Ch. 25 高精度法) ---
|
|
65
|
+
def sun_apparent_longitude(jd_tt)
|
|
66
|
+
l, _b, r = heliocentric_fk5(:earth, jd_tt)
|
|
67
|
+
theta = l * RAD2DEG + 180.0 # 地心幾何經度(FK5)
|
|
68
|
+
theta -= (20.4898 / r) / 3600.0 # 光行差(Meeus 25.10)
|
|
69
|
+
dpsi_deg, = Core.nutation(jd_tt) # 章動
|
|
70
|
+
Core.norm360(theta + dpsi_deg)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# --- 行星(Meeus Ch. 33) ---
|
|
74
|
+
# 先以幾何位置求距離 Δ 得光行時 τ,再把「行星與地球」都取 t-τ
|
|
75
|
+
# 重算——兩者同取 t-τ 等效把光行時與(地球速度造成的)光行差
|
|
76
|
+
# 一併涵蓋(planetary aberration;Meeus Ch. 33 註)。τ 迭代兩輪。
|
|
77
|
+
def planet_apparent_longitude(planet_key, jd_tt)
|
|
78
|
+
tau = 0.0
|
|
79
|
+
x = y = 0.0
|
|
80
|
+
2.times do
|
|
81
|
+
ex, ey, ez = heliocentric_rect(:earth, jd_tt - tau)
|
|
82
|
+
px, py, pz = heliocentric_rect(planet_key, jd_tt - tau)
|
|
83
|
+
x = px - ex
|
|
84
|
+
y = py - ey
|
|
85
|
+
z = pz - ez
|
|
86
|
+
delta = Math.sqrt(x * x + y * y + z * z)
|
|
87
|
+
tau = LIGHT_TIME_DAYS_PER_AU * delta
|
|
88
|
+
end
|
|
89
|
+
lambda_deg = Math.atan2(y, x) * RAD2DEG
|
|
90
|
+
dpsi_deg, = Core.nutation(jd_tt)
|
|
91
|
+
Core.norm360(lambda_deg + dpsi_deg)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# --- 日心黃道直角座標(FK5 修正後;黃道與分點皆為 of date) ---
|
|
95
|
+
def heliocentric_rect(planet_key, jd_tt)
|
|
96
|
+
l, b, r = heliocentric_fk5(planet_key, jd_tt)
|
|
97
|
+
cb = Math.cos(b)
|
|
98
|
+
[r * cb * Math.cos(l), r * cb * Math.sin(l), r * Math.sin(b)]
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# --- 日心球座標 [L_rad, B_rad, R_au],含 VSOP87→FK5 修正(Meeus 32.3) ---
|
|
102
|
+
def heliocentric_fk5(planet_key, jd_tt)
|
|
103
|
+
l, b, r = heliocentric_raw(planet_key, jd_tt)
|
|
104
|
+
|
|
105
|
+
t_cent = (jd_tt - 2_451_545.0) / 36_525.0
|
|
106
|
+
lp = l - (1.397 * t_cent + 0.00031 * t_cent * t_cent) * DEG2RAD
|
|
107
|
+
cos_lp = Math.cos(lp)
|
|
108
|
+
sin_lp = Math.sin(lp)
|
|
109
|
+
dl_arcsec = -0.09033 + 0.03916 * (cos_lp + sin_lp) * Math.tan(b)
|
|
110
|
+
db_arcsec = 0.03916 * (cos_lp - sin_lp)
|
|
111
|
+
|
|
112
|
+
[l + dl_arcsec / 3600.0 * DEG2RAD,
|
|
113
|
+
b + db_arcsec / 3600.0 * DEG2RAD,
|
|
114
|
+
r]
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# --- VSOP87D 級數求和 -> [L_rad([0,2π)), B_rad, R_au](動力學分點) ---
|
|
118
|
+
def heliocentric_raw(planet_key, jd_tt)
|
|
119
|
+
series = Vsop87Data::SERIES.fetch(planet_key) do
|
|
120
|
+
raise Core::DomainError, "無 VSOP87 資料:#{planet_key}"
|
|
121
|
+
end
|
|
122
|
+
t = (jd_tt - 2_451_545.0) / 365_250.0 # Julian millennia (TT)
|
|
123
|
+
l = sum_series(series.fetch(:l), t) % (2.0 * Math::PI)
|
|
124
|
+
l += 2.0 * Math::PI if l.negative?
|
|
125
|
+
b = sum_series(series.fetch(:b), t)
|
|
126
|
+
r = sum_series(series.fetch(:r), t)
|
|
127
|
+
raise Core::DomainError, "VSOP87 R 非正值:#{planet_key} r=#{r}" unless r.positive?
|
|
128
|
+
|
|
129
|
+
[l, b, r]
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# orders = [order0_flat, order1_flat, ...];每個 flat 陣列為連續
|
|
133
|
+
# (A, B, C) 三元組:Σ_k T^k Σ_i A_i cos(B_i + C_i T)
|
|
134
|
+
def sum_series(orders, t)
|
|
135
|
+
total = 0.0
|
|
136
|
+
t_pow = 1.0
|
|
137
|
+
orders.each do |flat|
|
|
138
|
+
sum = 0.0
|
|
139
|
+
i = 0
|
|
140
|
+
n = flat.size
|
|
141
|
+
while i < n
|
|
142
|
+
sum += flat[i] * Math.cos(flat[i + 1] + flat[i + 2] * t)
|
|
143
|
+
i += 3
|
|
144
|
+
end
|
|
145
|
+
total += sum * t_pow
|
|
146
|
+
t_pow *= t
|
|
147
|
+
end
|
|
148
|
+
total
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
end
|