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.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +25 -0
  3. data/LICENSE +17 -16
  4. data/astro_chart.gemspec +7 -6
  5. data/lib/astro_chart/ephemeris.rb +76 -18
  6. data/lib/astro_chart/pure/core.rb +209 -0
  7. data/lib/astro_chart/pure/houses.rb +122 -0
  8. data/lib/astro_chart/pure/moon.rb +341 -0
  9. data/lib/astro_chart/pure/moon_elp.rb +931 -0
  10. data/lib/astro_chart/pure/pluto.rb +220 -0
  11. data/lib/astro_chart/pure/vsop87.rb +152 -0
  12. data/lib/astro_chart/pure/vsop87_data.rb +210 -0
  13. data/lib/astro_chart/pure.rb +63 -0
  14. data/lib/astro_chart/synastry.rb +118 -0
  15. data/lib/astro_chart/version.rb +1 -1
  16. data/lib/astro_chart.rb +6 -1
  17. metadata +19 -45
  18. data/ext/astro_chart/astro_chart_ext.c +0 -99
  19. data/ext/astro_chart/extconf.rb +0 -8
  20. data/ext/astro_chart/swecl.c +0 -6428
  21. data/ext/astro_chart/swedate.c +0 -588
  22. data/ext/astro_chart/swedate.h +0 -81
  23. data/ext/astro_chart/swedll.h +0 -403
  24. data/ext/astro_chart/sweephe4.c +0 -702
  25. data/ext/astro_chart/sweephe4.h +0 -239
  26. data/ext/astro_chart/swehel.c +0 -3511
  27. data/ext/astro_chart/swehouse.c +0 -3143
  28. data/ext/astro_chart/swehouse.h +0 -98
  29. data/ext/astro_chart/swejpl.c +0 -958
  30. data/ext/astro_chart/swejpl.h +0 -103
  31. data/ext/astro_chart/swemmoon.c +0 -1930
  32. data/ext/astro_chart/swemplan.c +0 -967
  33. data/ext/astro_chart/swemptab.h +0 -10640
  34. data/ext/astro_chart/swenut2000a.h +0 -2819
  35. data/ext/astro_chart/sweodef.h +0 -326
  36. data/ext/astro_chart/sweph.c +0 -8614
  37. data/ext/astro_chart/sweph.h +0 -849
  38. data/ext/astro_chart/swephexp.h +0 -1020
  39. data/ext/astro_chart/swephlib.c +0 -4634
  40. 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