astronoby 0.4.0 → 0.5.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 +60 -0
- data/Gemfile.lock +17 -15
- data/README.md +147 -12
- data/UPGRADING.md +48 -0
- data/lib/astronoby/astronomical_models/ephemeride_lunaire_parisienne.rb +143 -0
- data/lib/astronoby/astronomical_models/moon_phases_periodic_terms.rb +249 -0
- data/lib/astronoby/bodies/moon.rb +335 -0
- data/lib/astronoby/bodies/sun.rb +15 -13
- data/lib/astronoby/constants.rb +6 -0
- data/lib/astronoby/coordinates/equatorial.rb +4 -3
- data/lib/astronoby/coordinates/horizontal.rb +18 -10
- data/lib/astronoby/distance.rb +83 -0
- data/lib/astronoby/events/moon_phases.rb +143 -0
- data/lib/astronoby/events/observation_events.rb +74 -134
- data/lib/astronoby/events/rise_transit_set_iteration.rb +215 -0
- data/lib/astronoby/geocentric_parallax.rb +36 -56
- data/lib/astronoby/moon_phase.rb +43 -0
- data/lib/astronoby/observer.rb +6 -4
- data/lib/astronoby/refraction.rb +8 -10
- data/lib/astronoby/util/maths.rb +1 -1
- data/lib/astronoby/version.rb +1 -1
- data/lib/astronoby.rb +7 -0
- metadata +9 -2
@@ -0,0 +1,249 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Astronoby
|
4
|
+
class MoonPhasesPeriodicTerms
|
5
|
+
# Lunar Solution ELP 2000-82B (Chapront-Touze+, 1988)
|
6
|
+
|
7
|
+
# Source:
|
8
|
+
# Title: Astronomical Algorithms
|
9
|
+
# Author: Jean Meeus
|
10
|
+
# Edition: 2nd edition
|
11
|
+
# Chapter: 49 - Phases of the Moon
|
12
|
+
|
13
|
+
# @param julian_centuries [Float] Julian centuries
|
14
|
+
# @param time [Float] Time
|
15
|
+
# @param eccentricity_correction [Float] Eccentricity correction
|
16
|
+
# @param moon_mean_anomaly [Float] Moon mean anomaly
|
17
|
+
# @param sun_mean_anomaly [Float] Sun mean anomaly
|
18
|
+
# @param moon_argument_of_latitude [Float] Moon argument of latitude
|
19
|
+
# @param longitude_of_the_ascending_node [Float] Longitude of the ascending node
|
20
|
+
def initialize(
|
21
|
+
julian_centuries:,
|
22
|
+
time:,
|
23
|
+
eccentricity_correction:,
|
24
|
+
moon_mean_anomaly:,
|
25
|
+
sun_mean_anomaly:,
|
26
|
+
moon_argument_of_latitude:,
|
27
|
+
longitude_of_the_ascending_node:
|
28
|
+
|
29
|
+
)
|
30
|
+
@julian_centuries = julian_centuries
|
31
|
+
@time = time
|
32
|
+
@eccentricity_correction = eccentricity_correction
|
33
|
+
@moon_mean_anomaly = moon_mean_anomaly
|
34
|
+
@sun_mean_anomaly = sun_mean_anomaly
|
35
|
+
@moon_argument_of_latitude = moon_argument_of_latitude
|
36
|
+
@longitude_of_the_ascending_node = longitude_of_the_ascending_node
|
37
|
+
end
|
38
|
+
|
39
|
+
# @return [Float] New moon correction
|
40
|
+
def new_moon_correction
|
41
|
+
ecc = @eccentricity_correction
|
42
|
+
mma = @moon_mean_anomaly.radians
|
43
|
+
sma = @sun_mean_anomaly.radians
|
44
|
+
maol = @moon_argument_of_latitude.radians
|
45
|
+
lotan = @longitude_of_the_ascending_node.radians
|
46
|
+
[
|
47
|
+
[-0.40720, mma],
|
48
|
+
[0.17241 * ecc, sma],
|
49
|
+
[0.01608, 2 * mma],
|
50
|
+
[0.01039, 2 * maol],
|
51
|
+
[0.00739 * ecc, mma - sma],
|
52
|
+
[-0.00514 * ecc, mma + sma],
|
53
|
+
[0.00208 * ecc * ecc, 2 * sma],
|
54
|
+
[-0.00111, mma - 2 * maol],
|
55
|
+
[-0.00057, mma + 2 * maol],
|
56
|
+
[0.00056 * ecc, 2 * mma + sma],
|
57
|
+
[-0.00042, 3 * mma],
|
58
|
+
[0.00042 * ecc, sma + 2 * maol],
|
59
|
+
[0.00038 * ecc, sma - 2 * maol],
|
60
|
+
[-0.00024 * ecc, 2 * mma - sma],
|
61
|
+
[-0.00017, lotan],
|
62
|
+
[-0.00007, mma + 2 * sma],
|
63
|
+
[0.00004, 2 * mma - 2 * maol],
|
64
|
+
[0.00004, 3 * sma],
|
65
|
+
[0.00003, mma + sma - 2 * maol],
|
66
|
+
[0.00003, 2 * mma + 2 * maol],
|
67
|
+
[-0.00003, mma + sma + 2 * maol],
|
68
|
+
[0.00003, mma - sma + 2 * maol],
|
69
|
+
[-0.00002, mma - sma - 2 * maol],
|
70
|
+
[-0.00002, 3 * mma + sma],
|
71
|
+
[0.00002, 4 * mma]
|
72
|
+
].map { _1.first * Math.sin(_1.last) }.sum
|
73
|
+
end
|
74
|
+
|
75
|
+
# @return [Float] First quarter correction
|
76
|
+
def first_quarter_correction
|
77
|
+
first_and_last_quarter_correction + first_and_last_quarter_final_correction
|
78
|
+
end
|
79
|
+
|
80
|
+
# @return [Float] Full moon correction
|
81
|
+
def full_moon_correction
|
82
|
+
ecc = @eccentricity_correction
|
83
|
+
mma = @moon_mean_anomaly.radians
|
84
|
+
sma = @sun_mean_anomaly.radians
|
85
|
+
maol = @moon_argument_of_latitude.radians
|
86
|
+
lotan = @longitude_of_the_ascending_node.radians
|
87
|
+
[
|
88
|
+
[-0.40614, mma],
|
89
|
+
[0.17302 * ecc, sma],
|
90
|
+
[0.01614, 2 * mma],
|
91
|
+
[0.01043, 2 * maol],
|
92
|
+
[0.00734 * ecc, mma - sma],
|
93
|
+
[-0.00515 * ecc, mma + sma],
|
94
|
+
[0.00209 * ecc * ecc, 2 * sma],
|
95
|
+
[-0.00111, mma - 2 * maol],
|
96
|
+
[-0.00057, mma + 2 * maol],
|
97
|
+
[0.00056 * ecc, 2 * mma + sma],
|
98
|
+
[-0.00042, 3 * mma],
|
99
|
+
[0.00042 * ecc, sma + 2 * maol],
|
100
|
+
[0.00038 * ecc, sma - 2 * maol],
|
101
|
+
[-0.00024 * ecc, 2 * mma - sma],
|
102
|
+
[-0.00017, lotan],
|
103
|
+
[-0.00007, mma + 2 * sma],
|
104
|
+
[0.00004, 2 * mma - 2 * maol],
|
105
|
+
[0.00004, 3 * sma],
|
106
|
+
[0.00003, mma + sma - 2 * maol],
|
107
|
+
[0.00003, 2 * mma + 2 * maol],
|
108
|
+
[-0.00003, mma + sma + 2 * maol],
|
109
|
+
[0.00003, mma - sma + 2 * maol],
|
110
|
+
[-0.00002, mma - sma - 2 * maol],
|
111
|
+
[-0.00002, 3 * mma + sma],
|
112
|
+
[0.00002, 4 * mma]
|
113
|
+
].map { _1.first * Math.sin(_1.last) }.sum
|
114
|
+
end
|
115
|
+
|
116
|
+
# @return [Float] Last quarter correction
|
117
|
+
def last_quarter_correction
|
118
|
+
first_and_last_quarter_correction - first_and_last_quarter_final_correction
|
119
|
+
end
|
120
|
+
|
121
|
+
# @return [Float] Additional corrections
|
122
|
+
def additional_corrections
|
123
|
+
[
|
124
|
+
[0.000325, a1],
|
125
|
+
[0.000165, a2],
|
126
|
+
[0.000164, a3],
|
127
|
+
[0.000126, a4],
|
128
|
+
[0.000110, a5],
|
129
|
+
[0.000062, a6],
|
130
|
+
[0.000060, a7],
|
131
|
+
[0.000056, a8],
|
132
|
+
[0.000047, a9],
|
133
|
+
[0.000042, a10],
|
134
|
+
[0.000040, a11],
|
135
|
+
[0.000037, a12],
|
136
|
+
[0.000035, a13],
|
137
|
+
[0.000023, a14]
|
138
|
+
].map { _1.first * _1.last.sin }.sum
|
139
|
+
end
|
140
|
+
|
141
|
+
private
|
142
|
+
|
143
|
+
def a1
|
144
|
+
Angle.from_degrees(
|
145
|
+
(
|
146
|
+
299.77 +
|
147
|
+
0.107408 * @time -
|
148
|
+
0.009173 * @julian_centuries**2
|
149
|
+
) % 360
|
150
|
+
)
|
151
|
+
end
|
152
|
+
|
153
|
+
def a2
|
154
|
+
Angle.from_degrees (251.88 + 0.016321 * @time) % 360
|
155
|
+
end
|
156
|
+
|
157
|
+
def a3
|
158
|
+
Angle.from_degrees (251.83 + 26.651886 * @time) % 360
|
159
|
+
end
|
160
|
+
|
161
|
+
def a4
|
162
|
+
Angle.from_degrees (349.42 + 36.412478 * @time) % 360
|
163
|
+
end
|
164
|
+
|
165
|
+
def a5
|
166
|
+
Angle.from_degrees (84.66 + 18.206239 * @time) % 360
|
167
|
+
end
|
168
|
+
|
169
|
+
def a6
|
170
|
+
Angle.from_degrees (141.74 + 53.303771 * @time) % 360
|
171
|
+
end
|
172
|
+
|
173
|
+
def a7
|
174
|
+
Angle.from_degrees (207.14 + 2.453732 * @time) % 360
|
175
|
+
end
|
176
|
+
|
177
|
+
def a8
|
178
|
+
Angle.from_degrees (154.84 + 7.306860 * @time) % 360
|
179
|
+
end
|
180
|
+
|
181
|
+
def a9
|
182
|
+
Angle.from_degrees (34.52 + 27.261239 * @time) % 360
|
183
|
+
end
|
184
|
+
|
185
|
+
def a10
|
186
|
+
Angle.from_degrees (207.19 + 0.121824 * @time) % 360
|
187
|
+
end
|
188
|
+
|
189
|
+
def a11
|
190
|
+
Angle.from_degrees (291.34 + 1.844379 * @time) % 360
|
191
|
+
end
|
192
|
+
|
193
|
+
def a12
|
194
|
+
Angle.from_degrees (161.72 + 24.198154 * @time) % 360
|
195
|
+
end
|
196
|
+
|
197
|
+
def a13
|
198
|
+
Angle.from_degrees (239.56 + 25.513099 * @time) % 360
|
199
|
+
end
|
200
|
+
|
201
|
+
def a14
|
202
|
+
Angle.from_degrees (331.55 + 3.592518 * @time) % 360
|
203
|
+
end
|
204
|
+
|
205
|
+
def first_and_last_quarter_final_correction
|
206
|
+
0.00306 -
|
207
|
+
0.00038 * @eccentricity_correction * @sun_mean_anomaly.cos +
|
208
|
+
0.00026 * @moon_mean_anomaly.cos -
|
209
|
+
0.00002 * (@moon_mean_anomaly - @sun_mean_anomaly).cos +
|
210
|
+
0.00002 * (@moon_mean_anomaly + @sun_mean_anomaly).cos +
|
211
|
+
0.00002 * Math.cos(2 * @moon_argument_of_latitude.radians)
|
212
|
+
end
|
213
|
+
|
214
|
+
def first_and_last_quarter_correction
|
215
|
+
ecc = @eccentricity_correction
|
216
|
+
mma = @moon_mean_anomaly.radians
|
217
|
+
sma = @sun_mean_anomaly.radians
|
218
|
+
maol = @moon_argument_of_latitude.radians
|
219
|
+
lotan = @longitude_of_the_ascending_node.radians
|
220
|
+
[
|
221
|
+
[-0.62801, mma],
|
222
|
+
[0.17172 * ecc, sma],
|
223
|
+
[-0.01183, mma + sma],
|
224
|
+
[0.00862, 2 * mma],
|
225
|
+
[0.00804, 2 * maol],
|
226
|
+
[0.00454 * ecc, mma - sma],
|
227
|
+
[0.00204 * ecc**2, 2 * sma],
|
228
|
+
[-0.00180, mma - 2 * maol],
|
229
|
+
[-0.00070, mma + 2 * maol],
|
230
|
+
[-0.00040, 3 * mma],
|
231
|
+
[-0.00034 * ecc, 2 * mma - sma],
|
232
|
+
[0.00032 * ecc, sma + 2 * maol],
|
233
|
+
[0.00032, sma - 2 * maol],
|
234
|
+
[-0.00028 * ecc**2, mma + 2 * sma],
|
235
|
+
[0.00027 * ecc, 2 * mma + sma],
|
236
|
+
[-0.00017, lotan],
|
237
|
+
[-0.00005, mma - sma - 2 * maol],
|
238
|
+
[0.00004, 2 * mma + 2 * maol],
|
239
|
+
[-0.00004, mma + sma + 2 * maol],
|
240
|
+
[0.00004, mma - 2 * sma],
|
241
|
+
[0.00003, mma + sma - 2 * maol],
|
242
|
+
[0.00003, 3 * sma],
|
243
|
+
[0.00002, 2 * mma - 2 * maol],
|
244
|
+
[0.00002, mma - sma + 2 * maol],
|
245
|
+
[-0.00002, 3 * mma + sma]
|
246
|
+
].map { _1.first * Math.sin(_1.last) }.sum
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end
|
@@ -0,0 +1,335 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Astronoby
|
4
|
+
class Moon
|
5
|
+
SEMIDIAMETER_VARIATION = 0.7275
|
6
|
+
MEAN_GEOCENTRIC_DISTANCE = Astronoby::Distance.from_meters(385_000_560)
|
7
|
+
|
8
|
+
# Source:
|
9
|
+
# Title: Astronomical Algorithms
|
10
|
+
# Author: Jean Meeus
|
11
|
+
# Edition: 2nd edition
|
12
|
+
# Chapter: 49 - Phases of the Moon
|
13
|
+
|
14
|
+
# @param year [Integer] Requested year
|
15
|
+
# @param month [Integer] Requested month
|
16
|
+
# @return [Array<Astronoby::MoonPhase>] Moon phases for the requested year
|
17
|
+
def self.monthly_phase_events(year:, month:)
|
18
|
+
Events::MoonPhases.phases_for(year: year, month: month)
|
19
|
+
end
|
20
|
+
|
21
|
+
def initialize(time:)
|
22
|
+
@time = time
|
23
|
+
end
|
24
|
+
|
25
|
+
# @return [Astronoby::Coordinates::Ecliptic] Apparent ecliptic coordinates
|
26
|
+
# of the Moon
|
27
|
+
def apparent_ecliptic_coordinates
|
28
|
+
@ecliptic_coordinates ||= begin
|
29
|
+
latitude = Astronoby::Angle.from_degrees(
|
30
|
+
(latitude_terms + additive_latitude_terms) *
|
31
|
+
EphemerideLunaireParisienne::DEGREES_UNIT
|
32
|
+
)
|
33
|
+
|
34
|
+
longitude = mean_longitude + Astronoby::Angle.from_degrees(
|
35
|
+
(longitude_terms + additive_longitude_terms) *
|
36
|
+
EphemerideLunaireParisienne::DEGREES_UNIT
|
37
|
+
) + nutation
|
38
|
+
|
39
|
+
Coordinates::Ecliptic.new(
|
40
|
+
latitude: latitude,
|
41
|
+
longitude: longitude
|
42
|
+
)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# Source:
|
47
|
+
# Title: Astronomical Algorithms
|
48
|
+
# Author: Jean Meeus
|
49
|
+
# Edition: 2nd edition
|
50
|
+
# Chapter: 47 - Position of the Moon
|
51
|
+
|
52
|
+
# @return [Astronoby::Coordinates::Equatorial] Apparent geocentric
|
53
|
+
# equatorial coordinates of the Moon
|
54
|
+
def apparent_equatorial_coordinates
|
55
|
+
@apparent_equatorial_coordinates ||=
|
56
|
+
apparent_ecliptic_coordinates
|
57
|
+
.to_apparent_equatorial(epoch: Epoch.from_time(@time))
|
58
|
+
end
|
59
|
+
|
60
|
+
def horizontal_coordinates(observer:)
|
61
|
+
apparent_topocentric_equatorial_coordinates =
|
62
|
+
Astronoby::GeocentricParallax.for_equatorial_coordinates(
|
63
|
+
observer: observer,
|
64
|
+
time: @time,
|
65
|
+
coordinates: apparent_equatorial_coordinates,
|
66
|
+
distance: distance
|
67
|
+
)
|
68
|
+
|
69
|
+
apparent_topocentric_equatorial_coordinates.to_horizontal(
|
70
|
+
observer: observer,
|
71
|
+
time: @time
|
72
|
+
)
|
73
|
+
end
|
74
|
+
|
75
|
+
# @return [Astronoby::Distance] Distance between the Earth and the Moon centers
|
76
|
+
def distance
|
77
|
+
@distance ||= Astronoby::Distance.from_meters(
|
78
|
+
(MEAN_GEOCENTRIC_DISTANCE.meters + distance_terms).round
|
79
|
+
)
|
80
|
+
end
|
81
|
+
|
82
|
+
# @return [Angle] Moon's mean longitude
|
83
|
+
def mean_longitude
|
84
|
+
@mean_longitude ||= Angle.from_degrees(
|
85
|
+
(
|
86
|
+
218.3164477 +
|
87
|
+
481267.88123421 * elapsed_centuries -
|
88
|
+
0.0015786 * elapsed_centuries**2 +
|
89
|
+
elapsed_centuries**3 / 538841 -
|
90
|
+
elapsed_centuries**4 / 65194000
|
91
|
+
) % 360
|
92
|
+
)
|
93
|
+
end
|
94
|
+
|
95
|
+
# @return [Angle] Moon's mean elongation
|
96
|
+
def mean_elongation
|
97
|
+
@mean_elongation ||= Angle.from_degrees(
|
98
|
+
(
|
99
|
+
297.8501921 +
|
100
|
+
445267.1114034 * elapsed_centuries -
|
101
|
+
0.0018819 * elapsed_centuries**2 +
|
102
|
+
elapsed_centuries**3 / 545868 -
|
103
|
+
elapsed_centuries**4 / 113065000
|
104
|
+
) % 360
|
105
|
+
)
|
106
|
+
end
|
107
|
+
|
108
|
+
# @return [Angle] Moon's mean anomaly
|
109
|
+
def mean_anomaly
|
110
|
+
@mean_anomaly ||= Angle.from_degrees(
|
111
|
+
(
|
112
|
+
134.9633964 +
|
113
|
+
477198.8675055 * elapsed_centuries +
|
114
|
+
0.0087414 * elapsed_centuries**2 +
|
115
|
+
elapsed_centuries**3 / 69699 -
|
116
|
+
elapsed_centuries**4 / 14712000
|
117
|
+
) % 360
|
118
|
+
)
|
119
|
+
end
|
120
|
+
|
121
|
+
# @return [Angle] Moon's argument of latitude
|
122
|
+
def argument_of_latitude
|
123
|
+
@argument_of_latitude ||= Angle.from_degrees(
|
124
|
+
(
|
125
|
+
93.2720950 +
|
126
|
+
483202.0175233 * elapsed_centuries -
|
127
|
+
0.0036539 * elapsed_centuries**2 -
|
128
|
+
elapsed_centuries**3 / 3526000
|
129
|
+
) % 360
|
130
|
+
)
|
131
|
+
end
|
132
|
+
|
133
|
+
# Source:
|
134
|
+
# Title: Astronomical Algorithms
|
135
|
+
# Author: Jean Meeus
|
136
|
+
# Edition: 2nd edition
|
137
|
+
# Chapter: 48 - Illuminated Fraction of the Moon's Disk
|
138
|
+
|
139
|
+
# @return [Angle] Moon's phase angle
|
140
|
+
def phase_angle
|
141
|
+
@phase_angle ||= begin
|
142
|
+
sun_apparent_equatorial_coordinates = sun
|
143
|
+
.apparent_ecliptic_coordinates
|
144
|
+
.to_apparent_equatorial(epoch: Epoch.from_time(@time))
|
145
|
+
moon_apparent_equatorial_coordinates = apparent_equatorial_coordinates
|
146
|
+
geocentric_elongation = Angle.acos(
|
147
|
+
sun_apparent_equatorial_coordinates.declination.sin *
|
148
|
+
moon_apparent_equatorial_coordinates.declination.sin +
|
149
|
+
sun_apparent_equatorial_coordinates.declination.cos *
|
150
|
+
moon_apparent_equatorial_coordinates.declination.cos *
|
151
|
+
(
|
152
|
+
sun_apparent_equatorial_coordinates.right_ascension -
|
153
|
+
moon_apparent_equatorial_coordinates.right_ascension
|
154
|
+
).cos
|
155
|
+
)
|
156
|
+
|
157
|
+
term1 = sun.earth_distance.km * geocentric_elongation.sin
|
158
|
+
term2 = distance.km - sun.earth_distance.km * geocentric_elongation.cos
|
159
|
+
angle = Angle.atan(term1 / term2)
|
160
|
+
Astronoby::Util::Trigonometry
|
161
|
+
.adjustement_for_arctangent(term1, term2, angle)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
# @return [Float] Moon's illuminated fraction
|
166
|
+
def illuminated_fraction
|
167
|
+
@illuminated_fraction ||= (1 + phase_angle.cos) / 2
|
168
|
+
end
|
169
|
+
|
170
|
+
# @param observer [Astronoby::Observer] Observer of the event
|
171
|
+
# @return [Astronoby::Events::ObservationEvents] Moon's observation events
|
172
|
+
def observation_events(observer:)
|
173
|
+
today = @time.to_date
|
174
|
+
leap_seconds = Util::Time.terrestrial_universal_time_delta(today)
|
175
|
+
yesterday = today.prev_day
|
176
|
+
yesterday_midnight_terrestrial_time =
|
177
|
+
Time.utc(yesterday.year, yesterday.month, yesterday.day) - leap_seconds
|
178
|
+
today_midnight_terrestrial_time =
|
179
|
+
Time.utc(today.year, today.month, today.day) - leap_seconds
|
180
|
+
tomorrow = today.next_day
|
181
|
+
tomorrow_midnight_terrestrial_time =
|
182
|
+
Time.utc(tomorrow.year, tomorrow.month, tomorrow.day) - leap_seconds
|
183
|
+
|
184
|
+
coordinates_of_the_previous_day = self.class
|
185
|
+
.new(time: yesterday_midnight_terrestrial_time)
|
186
|
+
.apparent_equatorial_coordinates
|
187
|
+
coordinates_of_the_day = self.class
|
188
|
+
.new(time: today_midnight_terrestrial_time)
|
189
|
+
.apparent_equatorial_coordinates
|
190
|
+
coordinates_of_the_next_day = self.class
|
191
|
+
.new(time: tomorrow_midnight_terrestrial_time)
|
192
|
+
.apparent_equatorial_coordinates
|
193
|
+
additional_altitude = -Angle.from_degrees(
|
194
|
+
SEMIDIAMETER_VARIATION *
|
195
|
+
GeocentricParallax.angle(distance: distance).degrees
|
196
|
+
)
|
197
|
+
|
198
|
+
Events::ObservationEvents.new(
|
199
|
+
observer: observer,
|
200
|
+
date: today,
|
201
|
+
coordinates_of_the_previous_day: coordinates_of_the_previous_day,
|
202
|
+
coordinates_of_the_day: coordinates_of_the_day,
|
203
|
+
coordinates_of_the_next_day: coordinates_of_the_next_day,
|
204
|
+
additional_altitude: additional_altitude
|
205
|
+
)
|
206
|
+
end
|
207
|
+
|
208
|
+
private
|
209
|
+
|
210
|
+
def terrestrial_time
|
211
|
+
@terrestrial_time ||= begin
|
212
|
+
delta = Util::Time.terrestrial_universal_time_delta(@time)
|
213
|
+
@time + delta
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
def julian_date
|
218
|
+
Epoch.from_time(terrestrial_time)
|
219
|
+
end
|
220
|
+
|
221
|
+
def elapsed_centuries
|
222
|
+
(julian_date - Epoch::DEFAULT_EPOCH) / Constants::DAYS_PER_JULIAN_CENTURY
|
223
|
+
end
|
224
|
+
|
225
|
+
def sun
|
226
|
+
@sun ||= Sun.new(time: @time)
|
227
|
+
end
|
228
|
+
|
229
|
+
def sun_mean_anomaly
|
230
|
+
@sun_mean_anomaly ||= sun.mean_anomaly
|
231
|
+
end
|
232
|
+
|
233
|
+
def a1
|
234
|
+
@a1 ||= Angle.from_degrees(
|
235
|
+
(119.75 + 131.849 * elapsed_centuries) % 360
|
236
|
+
)
|
237
|
+
end
|
238
|
+
|
239
|
+
def a2
|
240
|
+
@a2 ||= Angle.from_degrees(
|
241
|
+
(53.09 + 479264.290 * elapsed_centuries) % 360
|
242
|
+
)
|
243
|
+
end
|
244
|
+
|
245
|
+
def a3
|
246
|
+
@a3 ||= Angle.from_degrees(
|
247
|
+
(313.45 + 481266.484 * elapsed_centuries) % 360
|
248
|
+
)
|
249
|
+
end
|
250
|
+
|
251
|
+
def eccentricity_correction
|
252
|
+
@eccentricity_correction ||=
|
253
|
+
1 - 0.002516 * elapsed_centuries - 0.0000074 * elapsed_centuries**2
|
254
|
+
end
|
255
|
+
|
256
|
+
def latitude_terms
|
257
|
+
@latitude_terms ||=
|
258
|
+
Astronoby::EphemerideLunaireParisienne
|
259
|
+
.periodic_terms_for_moon_latitude
|
260
|
+
.inject(0) do |sum, terms|
|
261
|
+
value = terms[4] * Math.sin(
|
262
|
+
terms[0] * mean_elongation.radians +
|
263
|
+
terms[1] * sun_mean_anomaly.radians +
|
264
|
+
terms[2] * mean_anomaly.radians +
|
265
|
+
terms[3] * argument_of_latitude.radians
|
266
|
+
)
|
267
|
+
|
268
|
+
value *= eccentricity_correction if terms[1].abs == 1
|
269
|
+
value *= eccentricity_correction**2 if terms[1].abs == 2
|
270
|
+
|
271
|
+
sum + value
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
def additive_latitude_terms
|
276
|
+
@additive_latitude_terms ||=
|
277
|
+
-2235 * mean_longitude.sin +
|
278
|
+
382 * a3.sin +
|
279
|
+
175 * (a1 - argument_of_latitude).sin +
|
280
|
+
175 * (a1 + argument_of_latitude).sin +
|
281
|
+
127 * (mean_longitude - mean_anomaly).sin -
|
282
|
+
115 * (mean_longitude + mean_anomaly).sin
|
283
|
+
end
|
284
|
+
|
285
|
+
def longitude_terms
|
286
|
+
@longitude_terms ||=
|
287
|
+
Astronoby::EphemerideLunaireParisienne
|
288
|
+
.periodic_terms_for_moon_longitude_and_distance
|
289
|
+
.inject(0) do |sum, terms|
|
290
|
+
value = terms[4] * Math.sin(
|
291
|
+
terms[0] * mean_elongation.radians +
|
292
|
+
terms[1] * sun_mean_anomaly.radians +
|
293
|
+
terms[2] * mean_anomaly.radians +
|
294
|
+
terms[3] * argument_of_latitude.radians
|
295
|
+
)
|
296
|
+
|
297
|
+
value *= eccentricity_correction if terms[1].abs == 1
|
298
|
+
value *= eccentricity_correction**2 if terms[1].abs == 2
|
299
|
+
|
300
|
+
sum + value
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
def additive_longitude_terms
|
305
|
+
@additive_longitude_terms ||=
|
306
|
+
3958 * a1.sin +
|
307
|
+
1962 * (mean_longitude - argument_of_latitude).sin +
|
308
|
+
318 * a2.sin
|
309
|
+
end
|
310
|
+
|
311
|
+
def distance_terms
|
312
|
+
@distance_terms ||=
|
313
|
+
EphemerideLunaireParisienne
|
314
|
+
.periodic_terms_for_moon_longitude_and_distance
|
315
|
+
.inject(0) do |sum, terms|
|
316
|
+
value = terms[5] * Math.cos(
|
317
|
+
terms[0] * mean_elongation.radians +
|
318
|
+
terms[1] * sun_mean_anomaly.radians +
|
319
|
+
terms[2] * mean_anomaly.radians +
|
320
|
+
terms[3] * argument_of_latitude.radians
|
321
|
+
)
|
322
|
+
|
323
|
+
value *= eccentricity_correction if terms[1].abs == 1
|
324
|
+
value *= eccentricity_correction**2 if terms[1].abs == 2
|
325
|
+
|
326
|
+
sum + value
|
327
|
+
end
|
328
|
+
end
|
329
|
+
|
330
|
+
def nutation
|
331
|
+
@nutation ||=
|
332
|
+
Astronoby::Nutation.for_ecliptic_longitude(epoch: julian_date)
|
333
|
+
end
|
334
|
+
end
|
335
|
+
end
|
data/lib/astronoby/bodies/sun.rb
CHANGED
@@ -101,13 +101,12 @@ module Astronoby
|
|
101
101
|
|
102
102
|
# Computes the Sun's horizontal coordinates
|
103
103
|
#
|
104
|
-
# @param
|
105
|
-
# @param longitude [Astronoby::Angle] Longitude of the observer
|
104
|
+
# @param observer [Astronoby::Observer] Observer of the event
|
106
105
|
# @return [Astronoby::Coordinates::Horizontal] Sun's horizontal coordinates
|
107
|
-
def horizontal_coordinates(
|
106
|
+
def horizontal_coordinates(observer:)
|
108
107
|
apparent_ecliptic_coordinates
|
109
108
|
.to_apparent_equatorial(epoch: epoch)
|
110
|
-
.to_horizontal(time: @time,
|
109
|
+
.to_horizontal(time: @time, observer: observer)
|
111
110
|
end
|
112
111
|
|
113
112
|
# @param observer [Astronoby::Observer] Observer of the event
|
@@ -156,9 +155,11 @@ module Astronoby
|
|
156
155
|
Events::TwilightEvents.new(sun: self, observer: observer)
|
157
156
|
end
|
158
157
|
|
159
|
-
# @return [
|
158
|
+
# @return [Astronoby::Distance] Earth-Sun distance
|
160
159
|
def earth_distance
|
161
|
-
|
160
|
+
Distance.from_meters(
|
161
|
+
SEMI_MAJOR_AXIS_IN_METERS / distance_angular_size_factor
|
162
|
+
)
|
162
163
|
end
|
163
164
|
|
164
165
|
# @return [Astronoby::Angle] Apparent Sun's angular size
|
@@ -186,6 +187,14 @@ module Astronoby
|
|
186
187
|
)
|
187
188
|
end
|
188
189
|
|
190
|
+
# @return [Astronoby::Angle] Sun's mean anomaly
|
191
|
+
def mean_anomaly
|
192
|
+
Angle.from_degrees(
|
193
|
+
(longitude_at_base_epoch - longitude_at_perigee).degrees %
|
194
|
+
Constants::DEGREES_PER_CIRCLE
|
195
|
+
)
|
196
|
+
end
|
197
|
+
|
189
198
|
# @return [Astronoby::Angle] Sun's longitude at perigee
|
190
199
|
def longitude_at_perigee
|
191
200
|
Angle.from_degrees(
|
@@ -211,13 +220,6 @@ module Astronoby
|
|
211
220
|
)
|
212
221
|
end
|
213
222
|
|
214
|
-
def mean_anomaly
|
215
|
-
Angle.from_degrees(
|
216
|
-
(longitude_at_base_epoch - longitude_at_perigee).degrees %
|
217
|
-
Constants::DEGREES_PER_CIRCLE
|
218
|
-
)
|
219
|
-
end
|
220
|
-
|
221
223
|
def days_since_epoch
|
222
224
|
Epoch::DEFAULT_EPOCH - epoch
|
223
225
|
end
|
data/lib/astronoby/constants.rb
CHANGED
@@ -21,5 +21,11 @@ module Astronoby
|
|
21
21
|
PI_IN_DEGREES = 180.0
|
22
22
|
|
23
23
|
EQUATION_OF_TIME_CONSTANT = 0.0057183
|
24
|
+
|
25
|
+
KILOMETER_IN_METERS = 1_000
|
26
|
+
ASTRONOMICAL_UNIT_IN_METERS = 149_597_870_700
|
27
|
+
EARTH_EQUATORIAL_RADIUS_IN_METERS = 6378140
|
28
|
+
|
29
|
+
EARTH_FLATTENING_CORRECTION = 0.996647
|
24
30
|
end
|
25
31
|
end
|
@@ -28,7 +28,9 @@ module Astronoby
|
|
28
28
|
Angle.from_hours(ha)
|
29
29
|
end
|
30
30
|
|
31
|
-
def to_horizontal(time:,
|
31
|
+
def to_horizontal(time:, observer:)
|
32
|
+
latitude = observer.latitude
|
33
|
+
longitude = observer.longitude
|
32
34
|
ha = @hour_angle || compute_hour_angle(time: time, longitude: longitude)
|
33
35
|
t0 = @declination.sin * latitude.sin +
|
34
36
|
@declination.cos * latitude.cos * ha.cos
|
@@ -46,8 +48,7 @@ module Astronoby
|
|
46
48
|
Horizontal.new(
|
47
49
|
azimuth: azimuth,
|
48
50
|
altitude: altitude,
|
49
|
-
|
50
|
-
longitude: longitude
|
51
|
+
observer: observer
|
51
52
|
)
|
52
53
|
end
|
53
54
|
|