astronoby 0.7.0 → 0.9.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/.ruby-version +1 -1
- data/CHANGELOG.md +145 -3
- data/README.md +59 -33
- data/UPGRADING.md +75 -21
- data/docs/README.md +224 -0
- data/docs/angles.md +137 -0
- data/docs/configuration.md +98 -0
- data/docs/coordinates.md +167 -0
- data/docs/deep_sky_bodies.md +101 -0
- data/docs/ephem.md +85 -0
- data/docs/equinoxes_solstices_times.md +31 -0
- data/docs/glossary.md +152 -0
- data/docs/instant.md +139 -0
- data/docs/moon_phases.md +79 -0
- data/docs/observer.md +65 -0
- data/docs/reference_frames.md +138 -0
- data/docs/rise_transit_set_times.md +119 -0
- data/docs/solar_system_bodies.md +107 -0
- data/docs/twilight_times.md +123 -0
- data/lib/astronoby/angle.rb +6 -2
- data/lib/astronoby/angular_velocity.rb +76 -0
- data/lib/astronoby/bodies/deep_sky_object.rb +44 -0
- data/lib/astronoby/bodies/deep_sky_object_position.rb +127 -0
- data/lib/astronoby/bodies/earth.rb +12 -2
- data/lib/astronoby/bodies/jupiter.rb +17 -0
- data/lib/astronoby/bodies/mars.rb +17 -0
- data/lib/astronoby/bodies/mercury.rb +21 -0
- data/lib/astronoby/bodies/moon.rb +50 -36
- data/lib/astronoby/bodies/neptune.rb +21 -0
- data/lib/astronoby/bodies/saturn.rb +26 -0
- data/lib/astronoby/bodies/solar_system_body.rb +162 -27
- data/lib/astronoby/bodies/sun.rb +25 -2
- data/lib/astronoby/bodies/uranus.rb +5 -0
- data/lib/astronoby/bodies/venus.rb +25 -0
- data/lib/astronoby/cache.rb +189 -0
- data/lib/astronoby/configuration.rb +92 -0
- data/lib/astronoby/constants.rb +11 -3
- data/lib/astronoby/constellation.rb +12 -0
- data/lib/astronoby/constellations/data.rb +42 -0
- data/lib/astronoby/constellations/finder.rb +35 -0
- data/lib/astronoby/constellations/repository.rb +20 -0
- data/lib/astronoby/coordinates/equatorial.rb +5 -8
- data/lib/astronoby/data/constellations/constellation_names.dat +88 -0
- data/lib/astronoby/data/constellations/indexed_abbreviations.dat +88 -0
- data/lib/astronoby/data/constellations/radec_to_index.dat +238 -0
- data/lib/astronoby/data/constellations/sorted_declinations.dat +202 -0
- data/lib/astronoby/data/constellations/sorted_right_ascensions.dat +237 -0
- data/lib/astronoby/distance.rb +6 -0
- data/lib/astronoby/equinox_solstice.rb +2 -2
- data/lib/astronoby/events/extremum_calculator.rb +233 -0
- data/lib/astronoby/events/extremum_event.rb +15 -0
- data/lib/astronoby/events/moon_phases.rb +15 -14
- data/lib/astronoby/events/rise_transit_set_calculator.rb +39 -12
- data/lib/astronoby/events/twilight_calculator.rb +116 -61
- data/lib/astronoby/events/twilight_events.rb +28 -0
- data/lib/astronoby/instant.rb +34 -6
- data/lib/astronoby/julian_date.rb +78 -0
- data/lib/astronoby/mean_obliquity.rb +8 -10
- data/lib/astronoby/nutation.rb +11 -3
- data/lib/astronoby/observer.rb +1 -1
- data/lib/astronoby/precession.rb +48 -38
- data/lib/astronoby/reference_frame.rb +2 -1
- data/lib/astronoby/reference_frames/apparent.rb +1 -11
- data/lib/astronoby/reference_frames/mean_of_date.rb +1 -1
- data/lib/astronoby/reference_frames/topocentric.rb +2 -12
- data/lib/astronoby/stellar_propagation.rb +162 -0
- data/lib/astronoby/time/greenwich_apparent_sidereal_time.rb +22 -0
- data/lib/astronoby/time/greenwich_mean_sidereal_time.rb +64 -0
- data/lib/astronoby/time/greenwich_sidereal_time.rb +20 -58
- data/lib/astronoby/time/local_apparent_sidereal_time.rb +42 -0
- data/lib/astronoby/time/local_mean_sidereal_time.rb +42 -0
- data/lib/astronoby/time/local_sidereal_time.rb +35 -26
- data/lib/astronoby/time/sidereal_time.rb +42 -0
- data/lib/astronoby/true_obliquity.rb +2 -3
- data/lib/astronoby/util/time.rb +62 -44
- data/lib/astronoby/velocity.rb +5 -0
- data/lib/astronoby/version.rb +1 -1
- data/lib/astronoby.rb +19 -1
- metadata +71 -11
- data/Gemfile +0 -5
- data/Gemfile.lock +0 -102
- data/benchmark/README.md +0 -131
- data/benchmark/benchmark.rb +0 -259
- data/benchmark/data/imcce.csv.zip +0 -0
- data/benchmark/data/sun_calc.csv.zip +0 -0
- data/lib/astronoby/epoch.rb +0 -22
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
-85.0
|
|
2
|
+
-82.5
|
|
3
|
+
-76.0
|
|
4
|
+
-75.0
|
|
5
|
+
-70.0
|
|
6
|
+
-67.5
|
|
7
|
+
-65.0
|
|
8
|
+
-64.0
|
|
9
|
+
-63.583333333333336
|
|
10
|
+
-61.0
|
|
11
|
+
-60.0
|
|
12
|
+
-59.0
|
|
13
|
+
-58.5
|
|
14
|
+
-58.0
|
|
15
|
+
-57.5
|
|
16
|
+
-57.0
|
|
17
|
+
-56.5
|
|
18
|
+
-55.0
|
|
19
|
+
-54.5
|
|
20
|
+
-54.0
|
|
21
|
+
-53.5
|
|
22
|
+
-53.166666666666664
|
|
23
|
+
-53.0
|
|
24
|
+
-52.5
|
|
25
|
+
-51.5
|
|
26
|
+
-51.0
|
|
27
|
+
-50.75
|
|
28
|
+
-50.0
|
|
29
|
+
-49.0
|
|
30
|
+
-48.166666666666664
|
|
31
|
+
-48.0
|
|
32
|
+
-46.5
|
|
33
|
+
-46.0
|
|
34
|
+
-45.5
|
|
35
|
+
-44.0
|
|
36
|
+
-43.0
|
|
37
|
+
-42.0
|
|
38
|
+
-40.0
|
|
39
|
+
-39.75
|
|
40
|
+
-39.583333333333336
|
|
41
|
+
-37.0
|
|
42
|
+
-36.75
|
|
43
|
+
-36.0
|
|
44
|
+
-35.0
|
|
45
|
+
-33.0
|
|
46
|
+
-31.166666666666668
|
|
47
|
+
-30.0
|
|
48
|
+
-29.5
|
|
49
|
+
-29.166666666666668
|
|
50
|
+
-28.0
|
|
51
|
+
-27.25
|
|
52
|
+
-26.5
|
|
53
|
+
-25.5
|
|
54
|
+
-24.583333333333332
|
|
55
|
+
-24.5
|
|
56
|
+
-24.383333333333333
|
|
57
|
+
-24.0
|
|
58
|
+
-22.0
|
|
59
|
+
-20.0
|
|
60
|
+
-19.25
|
|
61
|
+
-19.0
|
|
62
|
+
-18.25
|
|
63
|
+
-17.0
|
|
64
|
+
-16.0
|
|
65
|
+
-15.0
|
|
66
|
+
-14.5
|
|
67
|
+
-12.033333333333333
|
|
68
|
+
-11.666666666666666
|
|
69
|
+
-11.0
|
|
70
|
+
-10.0
|
|
71
|
+
-9.0
|
|
72
|
+
-8.0
|
|
73
|
+
-7.0
|
|
74
|
+
-6.0
|
|
75
|
+
-4.0
|
|
76
|
+
-3.25
|
|
77
|
+
-1.75
|
|
78
|
+
0.0
|
|
79
|
+
1.5
|
|
80
|
+
1.75
|
|
81
|
+
2.0
|
|
82
|
+
2.75
|
|
83
|
+
3.0
|
|
84
|
+
4.0
|
|
85
|
+
4.5
|
|
86
|
+
5.5
|
|
87
|
+
6.0
|
|
88
|
+
6.25
|
|
89
|
+
7.0
|
|
90
|
+
7.5
|
|
91
|
+
8.0
|
|
92
|
+
8.5
|
|
93
|
+
9.916666666666666
|
|
94
|
+
10.0
|
|
95
|
+
11.0
|
|
96
|
+
11.833333333333334
|
|
97
|
+
12.0
|
|
98
|
+
12.5
|
|
99
|
+
12.833333333333334
|
|
100
|
+
13.5
|
|
101
|
+
14.0
|
|
102
|
+
14.333333333333334
|
|
103
|
+
15.0
|
|
104
|
+
15.5
|
|
105
|
+
15.75
|
|
106
|
+
16.0
|
|
107
|
+
16.166666666666668
|
|
108
|
+
17.5
|
|
109
|
+
18.0
|
|
110
|
+
18.5
|
|
111
|
+
19.0
|
|
112
|
+
19.166666666666668
|
|
113
|
+
19.5
|
|
114
|
+
20.0
|
|
115
|
+
20.5
|
|
116
|
+
21.0
|
|
117
|
+
21.083333333333332
|
|
118
|
+
21.25
|
|
119
|
+
21.5
|
|
120
|
+
22.0
|
|
121
|
+
22.833333333333332
|
|
122
|
+
23.5
|
|
123
|
+
23.75
|
|
124
|
+
25.0
|
|
125
|
+
25.5
|
|
126
|
+
26.0
|
|
127
|
+
27.0
|
|
128
|
+
27.25
|
|
129
|
+
27.5
|
|
130
|
+
28.0
|
|
131
|
+
28.5
|
|
132
|
+
29.0
|
|
133
|
+
30.0
|
|
134
|
+
30.666666666666668
|
|
135
|
+
30.75
|
|
136
|
+
31.333333333333332
|
|
137
|
+
32.0
|
|
138
|
+
32.083333333333336
|
|
139
|
+
33.0
|
|
140
|
+
33.5
|
|
141
|
+
34.0
|
|
142
|
+
34.5
|
|
143
|
+
35.0
|
|
144
|
+
35.5
|
|
145
|
+
36.0
|
|
146
|
+
36.5
|
|
147
|
+
36.75
|
|
148
|
+
39.75
|
|
149
|
+
40.0
|
|
150
|
+
42.0
|
|
151
|
+
43.5
|
|
152
|
+
43.75
|
|
153
|
+
44.0
|
|
154
|
+
44.5
|
|
155
|
+
45.0
|
|
156
|
+
46.0
|
|
157
|
+
47.0
|
|
158
|
+
47.5
|
|
159
|
+
48.0
|
|
160
|
+
48.5
|
|
161
|
+
50.0
|
|
162
|
+
50.5
|
|
163
|
+
51.5
|
|
164
|
+
52.5
|
|
165
|
+
52.75
|
|
166
|
+
53.0
|
|
167
|
+
54.0
|
|
168
|
+
54.833333333333336
|
|
169
|
+
55.0
|
|
170
|
+
55.5
|
|
171
|
+
56.0
|
|
172
|
+
56.25
|
|
173
|
+
57.0
|
|
174
|
+
57.5
|
|
175
|
+
58.0
|
|
176
|
+
58.5
|
|
177
|
+
59.083333333333336
|
|
178
|
+
59.5
|
|
179
|
+
60.0
|
|
180
|
+
60.916666666666664
|
|
181
|
+
61.5
|
|
182
|
+
62.0
|
|
183
|
+
63.0
|
|
184
|
+
64.0
|
|
185
|
+
66.0
|
|
186
|
+
66.5
|
|
187
|
+
67.0
|
|
188
|
+
68.0
|
|
189
|
+
70.0
|
|
190
|
+
73.5
|
|
191
|
+
75.0
|
|
192
|
+
77.0
|
|
193
|
+
80.0
|
|
194
|
+
82.0
|
|
195
|
+
85.0
|
|
196
|
+
86.0
|
|
197
|
+
86.16666666666667
|
|
198
|
+
86.5
|
|
199
|
+
88.0
|
|
200
|
+
89.0
|
|
201
|
+
89.5
|
|
202
|
+
90.0
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
0.06666666666666667
|
|
2
|
+
0.14166666666666666
|
|
3
|
+
0.16666666666666666
|
|
4
|
+
0.3333333333333333
|
|
5
|
+
0.7166666666666667
|
|
6
|
+
0.75
|
|
7
|
+
0.85
|
|
8
|
+
0.8666666666666667
|
|
9
|
+
1.1166666666666667
|
|
10
|
+
1.3333333333333333
|
|
11
|
+
1.3666666666666667
|
|
12
|
+
1.4083333333333334
|
|
13
|
+
1.5833333333333333
|
|
14
|
+
1.6666666666666667
|
|
15
|
+
1.7
|
|
16
|
+
1.8333333333333333
|
|
17
|
+
1.9083333333333334
|
|
18
|
+
1.9166666666666667
|
|
19
|
+
2.0
|
|
20
|
+
2.0416666666666665
|
|
21
|
+
2.1666666666666665
|
|
22
|
+
2.3333333333333335
|
|
23
|
+
2.4166666666666665
|
|
24
|
+
2.433333333333333
|
|
25
|
+
2.5166666666666666
|
|
26
|
+
2.566666666666667
|
|
27
|
+
2.65
|
|
28
|
+
2.6666666666666665
|
|
29
|
+
2.716666666666667
|
|
30
|
+
3.0
|
|
31
|
+
3.1
|
|
32
|
+
3.1666666666666665
|
|
33
|
+
3.2
|
|
34
|
+
3.283333333333333
|
|
35
|
+
3.3333333333333335
|
|
36
|
+
3.3666666666666667
|
|
37
|
+
3.4166666666666665
|
|
38
|
+
3.5
|
|
39
|
+
3.5083333333333333
|
|
40
|
+
3.5833333333333335
|
|
41
|
+
3.75
|
|
42
|
+
3.8333333333333335
|
|
43
|
+
3.8666666666666667
|
|
44
|
+
4.0
|
|
45
|
+
4.083333333333333
|
|
46
|
+
4.266666666666667
|
|
47
|
+
4.333333333333333
|
|
48
|
+
4.5
|
|
49
|
+
4.583333333333333
|
|
50
|
+
4.616666666666666
|
|
51
|
+
4.666666666666667
|
|
52
|
+
4.691666666666666
|
|
53
|
+
4.7
|
|
54
|
+
4.75
|
|
55
|
+
4.833333333333333
|
|
56
|
+
4.916666666666667
|
|
57
|
+
4.966666666666667
|
|
58
|
+
5.0
|
|
59
|
+
5.083333333333333
|
|
60
|
+
5.333333333333333
|
|
61
|
+
5.5
|
|
62
|
+
5.6
|
|
63
|
+
5.7
|
|
64
|
+
5.766666666666667
|
|
65
|
+
5.833333333333333
|
|
66
|
+
5.883333333333334
|
|
67
|
+
6.0
|
|
68
|
+
6.1
|
|
69
|
+
6.116666666666666
|
|
70
|
+
6.166666666666667
|
|
71
|
+
6.216666666666667
|
|
72
|
+
6.241666666666666
|
|
73
|
+
6.308333333333334
|
|
74
|
+
6.5
|
|
75
|
+
6.533333333333333
|
|
76
|
+
6.583333333333333
|
|
77
|
+
6.8
|
|
78
|
+
6.833333333333333
|
|
79
|
+
6.933333333333334
|
|
80
|
+
7.0
|
|
81
|
+
7.016666666666667
|
|
82
|
+
7.2
|
|
83
|
+
7.366666666666666
|
|
84
|
+
7.5
|
|
85
|
+
7.666666666666667
|
|
86
|
+
7.75
|
|
87
|
+
7.808333333333334
|
|
88
|
+
7.883333333333334
|
|
89
|
+
7.925
|
|
90
|
+
7.966666666666667
|
|
91
|
+
8.0
|
|
92
|
+
8.083333333333334
|
|
93
|
+
8.166666666666666
|
|
94
|
+
8.366666666666667
|
|
95
|
+
8.416666666666666
|
|
96
|
+
8.45
|
|
97
|
+
8.583333333333334
|
|
98
|
+
8.833333333333334
|
|
99
|
+
9.033333333333333
|
|
100
|
+
9.083333333333334
|
|
101
|
+
9.166666666666666
|
|
102
|
+
9.25
|
|
103
|
+
9.366666666666667
|
|
104
|
+
9.583333333333334
|
|
105
|
+
9.75
|
|
106
|
+
9.883333333333333
|
|
107
|
+
10.166666666666666
|
|
108
|
+
10.25
|
|
109
|
+
10.5
|
|
110
|
+
10.583333333333334
|
|
111
|
+
10.666666666666666
|
|
112
|
+
10.75
|
|
113
|
+
10.783333333333333
|
|
114
|
+
10.833333333333334
|
|
115
|
+
11.0
|
|
116
|
+
11.25
|
|
117
|
+
11.333333333333334
|
|
118
|
+
11.5
|
|
119
|
+
11.516666666666667
|
|
120
|
+
11.833333333333334
|
|
121
|
+
11.866666666666667
|
|
122
|
+
12.0
|
|
123
|
+
12.083333333333334
|
|
124
|
+
12.25
|
|
125
|
+
12.333333333333334
|
|
126
|
+
12.583333333333334
|
|
127
|
+
12.833333333333334
|
|
128
|
+
13.0
|
|
129
|
+
13.25
|
|
130
|
+
13.5
|
|
131
|
+
13.583333333333334
|
|
132
|
+
13.666666666666666
|
|
133
|
+
13.958333333333334
|
|
134
|
+
14.0
|
|
135
|
+
14.033333333333333
|
|
136
|
+
14.166666666666666
|
|
137
|
+
14.25
|
|
138
|
+
14.416666666666666
|
|
139
|
+
14.5
|
|
140
|
+
14.533333333333333
|
|
141
|
+
14.666666666666666
|
|
142
|
+
14.75
|
|
143
|
+
14.916666666666666
|
|
144
|
+
15.05
|
|
145
|
+
15.083333333333334
|
|
146
|
+
15.166666666666666
|
|
147
|
+
15.183333333333334
|
|
148
|
+
15.25
|
|
149
|
+
15.333333333333334
|
|
150
|
+
15.433333333333334
|
|
151
|
+
15.666666666666666
|
|
152
|
+
15.75
|
|
153
|
+
15.916666666666666
|
|
154
|
+
16.0
|
|
155
|
+
16.033333333333335
|
|
156
|
+
16.083333333333332
|
|
157
|
+
16.166666666666668
|
|
158
|
+
16.266666666666666
|
|
159
|
+
16.333333333333332
|
|
160
|
+
16.375
|
|
161
|
+
16.420833333333334
|
|
162
|
+
16.533333333333335
|
|
163
|
+
16.583333333333332
|
|
164
|
+
16.75
|
|
165
|
+
16.833333333333332
|
|
166
|
+
17.0
|
|
167
|
+
17.166666666666668
|
|
168
|
+
17.25
|
|
169
|
+
17.5
|
|
170
|
+
17.583333333333332
|
|
171
|
+
17.6
|
|
172
|
+
17.666666666666668
|
|
173
|
+
17.833333333333332
|
|
174
|
+
17.966666666666665
|
|
175
|
+
18.0
|
|
176
|
+
18.175
|
|
177
|
+
18.233333333333334
|
|
178
|
+
18.25
|
|
179
|
+
18.366666666666667
|
|
180
|
+
18.425
|
|
181
|
+
18.583333333333332
|
|
182
|
+
18.662222222222223
|
|
183
|
+
18.866666666666667
|
|
184
|
+
19.0
|
|
185
|
+
19.083333333333332
|
|
186
|
+
19.166666666666668
|
|
187
|
+
19.25
|
|
188
|
+
19.258333333333333
|
|
189
|
+
19.358333333333334
|
|
190
|
+
19.4
|
|
191
|
+
19.416666666666668
|
|
192
|
+
19.666666666666668
|
|
193
|
+
19.766666666666666
|
|
194
|
+
19.833333333333332
|
|
195
|
+
20.0
|
|
196
|
+
20.141666666666666
|
|
197
|
+
20.166666666666668
|
|
198
|
+
20.25
|
|
199
|
+
20.3
|
|
200
|
+
20.333333333333332
|
|
201
|
+
20.416666666666668
|
|
202
|
+
20.533333333333335
|
|
203
|
+
20.536666666666665
|
|
204
|
+
20.566666666666666
|
|
205
|
+
20.6
|
|
206
|
+
20.666666666666668
|
|
207
|
+
20.833333333333332
|
|
208
|
+
20.875
|
|
209
|
+
20.916666666666668
|
|
210
|
+
21.0
|
|
211
|
+
21.05
|
|
212
|
+
21.116666666666667
|
|
213
|
+
21.25
|
|
214
|
+
21.333333333333332
|
|
215
|
+
21.416666666666668
|
|
216
|
+
21.466666666666665
|
|
217
|
+
21.666666666666668
|
|
218
|
+
21.733333333333334
|
|
219
|
+
21.866666666666667
|
|
220
|
+
21.875
|
|
221
|
+
21.908333333333335
|
|
222
|
+
21.966666666666665
|
|
223
|
+
22.0
|
|
224
|
+
22.133333333333333
|
|
225
|
+
22.316666666666666
|
|
226
|
+
22.75
|
|
227
|
+
22.816666666666666
|
|
228
|
+
22.866666666666667
|
|
229
|
+
23.0
|
|
230
|
+
23.166666666666668
|
|
231
|
+
23.333333333333332
|
|
232
|
+
23.5
|
|
233
|
+
23.583333333333332
|
|
234
|
+
23.75
|
|
235
|
+
23.833333333333332
|
|
236
|
+
23.916666666666668
|
|
237
|
+
24.0
|
data/lib/astronoby/distance.rb
CHANGED
|
@@ -26,6 +26,12 @@ module Astronoby
|
|
|
26
26
|
end
|
|
27
27
|
alias_method :from_au, :from_astronomical_units
|
|
28
28
|
|
|
29
|
+
def from_parsecs(parsecs)
|
|
30
|
+
meters = parsecs * Constants::PARSEC_IN_METERS
|
|
31
|
+
from_meters(meters)
|
|
32
|
+
end
|
|
33
|
+
alias_method :from_pc, :from_parsecs
|
|
34
|
+
|
|
29
35
|
def vector_from_meters(array)
|
|
30
36
|
Vector.elements(array.map { from_meters(_1) })
|
|
31
37
|
end
|
|
@@ -110,7 +110,7 @@ module Astronoby
|
|
|
110
110
|
private
|
|
111
111
|
|
|
112
112
|
def compute
|
|
113
|
-
t = (julian_day -
|
|
113
|
+
t = (julian_day - JulianDate::J2000) / Constants::DAYS_PER_JULIAN_CENTURY
|
|
114
114
|
w = Angle.from_degrees(35999.373 * t) - Angle.from_degrees(2.47)
|
|
115
115
|
delta = 1 +
|
|
116
116
|
0.0334 * w.cos +
|
|
@@ -123,7 +123,7 @@ module Astronoby
|
|
|
123
123
|
delta_days = 0.00001 * s / delta
|
|
124
124
|
epoch = julian_day + delta_days
|
|
125
125
|
|
|
126
|
-
|
|
126
|
+
Instant.from_terrestrial_time(epoch).to_time
|
|
127
127
|
end
|
|
128
128
|
|
|
129
129
|
def julian_day
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Astronoby
|
|
4
|
+
# Calculates extrema (minima and maxima) in the distance between two
|
|
5
|
+
# celestial bodies over a given time range using adaptive sampling and golden
|
|
6
|
+
# section search refinement.
|
|
7
|
+
class ExtremumCalculator
|
|
8
|
+
# Mathematical constants
|
|
9
|
+
PHI = (1 + Math.sqrt(5)) / 2
|
|
10
|
+
INVPHI = 1 / PHI
|
|
11
|
+
GOLDEN_SECTION_TOLERANCE = 1e-5
|
|
12
|
+
|
|
13
|
+
# Algorithm parameters
|
|
14
|
+
MIN_SAMPLES_PER_PERIOD = 20
|
|
15
|
+
DUPLICATE_THRESHOLD_DAYS = 0.5
|
|
16
|
+
BOUNDARY_BUFFER_DAYS = 0.01
|
|
17
|
+
|
|
18
|
+
# Orbital periods
|
|
19
|
+
ORBITAL_PERIODS = {
|
|
20
|
+
"Astronoby::Moon" => 27.504339,
|
|
21
|
+
"Astronoby::Mercury" => 87.969,
|
|
22
|
+
"Astronoby::Venus" => 224.701,
|
|
23
|
+
"Astronoby::Earth" => 365.256,
|
|
24
|
+
"Astronoby::Mars" => 686.98,
|
|
25
|
+
"Astronoby::Jupiter" => 4332.59,
|
|
26
|
+
"Astronoby::Saturn" => 10759.22,
|
|
27
|
+
"Astronoby::Uranus" => 30688.5,
|
|
28
|
+
"Astronoby::Neptune" => 60182.0
|
|
29
|
+
}.freeze
|
|
30
|
+
|
|
31
|
+
# @param ephem [::Ephem::SPK] Ephemeris data source
|
|
32
|
+
# @param body [Astronoby::SolarSystemBody] The celestial body to track
|
|
33
|
+
# @param primary_body [Astronoby::SolarSystemBody] The reference body
|
|
34
|
+
# (e.g., Sun for planetary orbits)
|
|
35
|
+
# @param samples_per_period [Integer] Number of samples to take per orbital
|
|
36
|
+
# period
|
|
37
|
+
def initialize(
|
|
38
|
+
body:,
|
|
39
|
+
primary_body:,
|
|
40
|
+
ephem:,
|
|
41
|
+
samples_per_period: 60
|
|
42
|
+
)
|
|
43
|
+
@ephem = ephem
|
|
44
|
+
@body = body
|
|
45
|
+
@primary_body = primary_body
|
|
46
|
+
@orbital_period = ORBITAL_PERIODS.fetch(body.name)
|
|
47
|
+
@samples_per_period = samples_per_period
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Finds all apoapsis events between two times
|
|
51
|
+
# @param start_time [Time] Start time
|
|
52
|
+
# @param end_time [Time] End time
|
|
53
|
+
# @return [Array<Astronoby::ExtremumEvent>] Array of apoapsis events
|
|
54
|
+
def apoapsis_events_between(start_time, end_time)
|
|
55
|
+
find_extrema(
|
|
56
|
+
Astronoby::Instant.from_time(start_time).tt,
|
|
57
|
+
Astronoby::Instant.from_time(end_time).tt,
|
|
58
|
+
type: :maximum
|
|
59
|
+
)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Finds all periapsis events between two times
|
|
63
|
+
# @param start_time [Time] Start time
|
|
64
|
+
# @param end_time [Time] End time
|
|
65
|
+
# @return [Array<Astronoby::ExtremumEvent>] Array of periapsis events
|
|
66
|
+
def periapsis_events_between(start_time, end_time)
|
|
67
|
+
find_extrema(
|
|
68
|
+
Astronoby::Instant.from_time(start_time).tt,
|
|
69
|
+
Astronoby::Instant.from_time(end_time).tt,
|
|
70
|
+
type: :minimum
|
|
71
|
+
)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Finds extrema (minima or maxima) in the distance between bodies within
|
|
75
|
+
# a time range
|
|
76
|
+
# @param start_jd [Float] Start time in Julian Date (Terrestrial Time)
|
|
77
|
+
# @param end_jd [Float] End time in Julian Date (Terrestrial Time)
|
|
78
|
+
# @param type [Symbol] :maximum or :minimum
|
|
79
|
+
# @return [Array<Astronoby::ExtremumEvent>] Array of extrema events
|
|
80
|
+
def find_extrema(start_jd, end_jd, type: :maximum)
|
|
81
|
+
# 1: Find extrema candidates through adaptive sampling
|
|
82
|
+
candidates = find_extrema_candidates(start_jd, end_jd, type)
|
|
83
|
+
|
|
84
|
+
# 2: Refine each candidate using golden section search
|
|
85
|
+
refined_extrema = candidates
|
|
86
|
+
.map { |candidate| refine_extremum(candidate, type) }
|
|
87
|
+
.compact
|
|
88
|
+
|
|
89
|
+
# 3: Remove duplicates and boundary artifacts
|
|
90
|
+
refined_extrema = remove_duplicates(refined_extrema)
|
|
91
|
+
filter_boundary_artifacts(refined_extrema, start_jd, end_jd)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
private
|
|
95
|
+
|
|
96
|
+
def distance_at(jd)
|
|
97
|
+
instant = Instant.from_terrestrial_time(jd)
|
|
98
|
+
body_geometric = @body.geometric(ephem: @ephem, instant: instant)
|
|
99
|
+
primary_geometric = @primary_body
|
|
100
|
+
.geometric(ephem: @ephem, instant: instant)
|
|
101
|
+
|
|
102
|
+
distance_vector = body_geometric.position - primary_geometric.position
|
|
103
|
+
distance_vector.magnitude
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def find_extrema_candidates(start_jd, end_jd, type)
|
|
107
|
+
samples = collect_samples(start_jd, end_jd)
|
|
108
|
+
find_local_extrema_in_samples(samples, type)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def collect_samples(start_jd, end_jd)
|
|
112
|
+
duration = end_jd - start_jd
|
|
113
|
+
sample_count = calculate_sample_count(duration)
|
|
114
|
+
step = duration / sample_count
|
|
115
|
+
|
|
116
|
+
(0..sample_count).map do |i|
|
|
117
|
+
jd = start_jd + (i * step)
|
|
118
|
+
{jd: jd, value: distance_at(jd)}
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def calculate_sample_count(duration)
|
|
123
|
+
# Adaptive sampling: scale with duration and orbital period
|
|
124
|
+
periods_in_range = duration / @orbital_period
|
|
125
|
+
base_samples = (periods_in_range * @samples_per_period).to_i
|
|
126
|
+
|
|
127
|
+
# Ensure minimum sample density for short ranges
|
|
128
|
+
[base_samples, MIN_SAMPLES_PER_PERIOD].max
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def find_local_extrema_in_samples(samples, type)
|
|
132
|
+
candidates = []
|
|
133
|
+
|
|
134
|
+
# Check each interior point for local extrema
|
|
135
|
+
(1...samples.length - 1).each do |i|
|
|
136
|
+
if local_extremum?(samples, i, type)
|
|
137
|
+
candidates << {
|
|
138
|
+
start_jd: samples[i - 1][:jd],
|
|
139
|
+
end_jd: samples[i + 1][:jd],
|
|
140
|
+
center_jd: samples[i][:jd]
|
|
141
|
+
}
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
candidates
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def local_extremum?(samples, index, type)
|
|
149
|
+
current_val = samples[index][:value].m
|
|
150
|
+
prev_val = samples[index - 1][:value].m
|
|
151
|
+
next_val = samples[index + 1][:value].m
|
|
152
|
+
|
|
153
|
+
if type == :maximum
|
|
154
|
+
current_val > prev_val && current_val > next_val
|
|
155
|
+
else
|
|
156
|
+
current_val < prev_val && current_val < next_val
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def refine_extremum(candidate, type)
|
|
161
|
+
golden_section_search(candidate[:start_jd], candidate[:end_jd], type)
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def golden_section_search(a, b, type)
|
|
165
|
+
return nil if b <= a
|
|
166
|
+
|
|
167
|
+
tol = GOLDEN_SECTION_TOLERANCE * (b - a).abs
|
|
168
|
+
|
|
169
|
+
# Initial points using golden ratio
|
|
170
|
+
x1 = a + (1 - INVPHI) * (b - a)
|
|
171
|
+
x2 = a + INVPHI * (b - a)
|
|
172
|
+
|
|
173
|
+
f1 = distance_at(x1).m
|
|
174
|
+
f2 = distance_at(x2).m
|
|
175
|
+
|
|
176
|
+
while (b - a).abs > tol
|
|
177
|
+
should_keep_left = (type == :maximum) ? (f1 > f2) : (f1 < f2)
|
|
178
|
+
|
|
179
|
+
if should_keep_left
|
|
180
|
+
b = x2
|
|
181
|
+
x2 = x1
|
|
182
|
+
f2 = f1
|
|
183
|
+
x1 = a + (1 - INVPHI) * (b - a)
|
|
184
|
+
f1 = distance_at(x1).m
|
|
185
|
+
else
|
|
186
|
+
a = x1
|
|
187
|
+
x1 = x2
|
|
188
|
+
f1 = f2
|
|
189
|
+
x2 = a + INVPHI * (b - a)
|
|
190
|
+
f2 = distance_at(x2).m
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
mid = (a + b) / 2
|
|
195
|
+
ExtremumEvent.new(
|
|
196
|
+
Instant.from_terrestrial_time(mid),
|
|
197
|
+
distance_at(mid)
|
|
198
|
+
)
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
def remove_duplicates(extrema)
|
|
202
|
+
return extrema if extrema.length <= 1
|
|
203
|
+
|
|
204
|
+
cleaned = [extrema.first]
|
|
205
|
+
|
|
206
|
+
extrema.each_with_index do |current, i|
|
|
207
|
+
next if i == 0
|
|
208
|
+
|
|
209
|
+
is_duplicate = cleaned.any? do |existing|
|
|
210
|
+
time_diff = (
|
|
211
|
+
current.instant.tt - existing.instant.tt
|
|
212
|
+
).abs
|
|
213
|
+
time_diff < DUPLICATE_THRESHOLD_DAYS
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
cleaned << current unless is_duplicate
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
cleaned
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
def filter_boundary_artifacts(extrema, start_jd, end_jd)
|
|
223
|
+
extrema.reject do |extreme|
|
|
224
|
+
start_diff = (extreme.instant.tt - start_jd).abs
|
|
225
|
+
end_diff = (extreme.instant.tt - end_jd).abs
|
|
226
|
+
|
|
227
|
+
too_close_to_start = start_diff < BOUNDARY_BUFFER_DAYS
|
|
228
|
+
too_close_to_end = end_diff < BOUNDARY_BUFFER_DAYS
|
|
229
|
+
too_close_to_start || too_close_to_end
|
|
230
|
+
end
|
|
231
|
+
end
|
|
232
|
+
end
|
|
233
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Astronoby
|
|
4
|
+
# Represents an extremum event with its timing and value
|
|
5
|
+
class ExtremumEvent
|
|
6
|
+
attr_reader :instant, :value
|
|
7
|
+
|
|
8
|
+
# @param instant [Astronoby::Instant] When the event occurs
|
|
9
|
+
# @param value [Object] The extreme value
|
|
10
|
+
def initialize(instant, value)
|
|
11
|
+
@instant = instant
|
|
12
|
+
@value = value
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|