astronoby 0.3.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 +132 -0
- data/Gemfile.lock +19 -17
- data/README.md +195 -25
- data/UPGRADING.md +72 -0
- data/lib/astronoby/aberration.rb +7 -5
- data/lib/astronoby/angle.rb +26 -34
- 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 +129 -132
- data/lib/astronoby/constants.rb +31 -0
- data/lib/astronoby/coordinates/ecliptic.rb +4 -4
- data/lib/astronoby/coordinates/equatorial.rb +7 -5
- data/lib/astronoby/coordinates/horizontal.rb +24 -12
- data/lib/astronoby/distance.rb +83 -0
- data/lib/astronoby/epoch.rb +0 -2
- data/lib/astronoby/equinox_solstice.rb +3 -2
- data/lib/astronoby/events/moon_phases.rb +143 -0
- data/lib/astronoby/events/observation_events.rb +259 -0
- data/lib/astronoby/events/rise_transit_set_iteration.rb +215 -0
- data/lib/astronoby/events/twilight_events.rb +121 -0
- data/lib/astronoby/geocentric_parallax.rb +36 -56
- data/lib/astronoby/mean_obliquity.rb +2 -2
- data/lib/astronoby/moon_phase.rb +43 -0
- data/lib/astronoby/nutation.rb +5 -3
- data/lib/astronoby/observer.rb +39 -18
- data/lib/astronoby/precession.rb +1 -1
- data/lib/astronoby/refraction.rb +8 -10
- data/lib/astronoby/time/greenwich_sidereal_time.rb +18 -29
- data/lib/astronoby/time/local_sidereal_time.rb +4 -4
- data/lib/astronoby/util/maths.rb +72 -0
- data/lib/astronoby/util/time.rb +88 -0
- data/lib/astronoby/util/trigonometry.rb +4 -4
- data/lib/astronoby/version.rb +1 -1
- data/lib/astronoby.rb +12 -1
- metadata +15 -4
- data/lib/astronoby/body.rb +0 -155
@@ -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
@@ -4,30 +4,63 @@ module Astronoby
|
|
4
4
|
class Sun
|
5
5
|
SEMI_MAJOR_AXIS_IN_METERS = 149_598_500_000
|
6
6
|
ANGULAR_DIAMETER = Angle.from_degrees(0.533128)
|
7
|
-
INTERPOLATION_FACTOR =
|
7
|
+
INTERPOLATION_FACTOR = 24.07
|
8
|
+
|
9
|
+
TWILIGHTS = [
|
10
|
+
CIVIL = :civil,
|
11
|
+
NAUTICAL = :nautical,
|
12
|
+
ASTRONOMICAL = :astronomical
|
13
|
+
].freeze
|
14
|
+
|
15
|
+
TWILIGHT_ANGLES = {
|
16
|
+
CIVIL => Angle.from_degrees(96),
|
17
|
+
NAUTICAL => Angle.from_degrees(102),
|
18
|
+
ASTRONOMICAL => Angle.from_degrees(108)
|
19
|
+
}.freeze
|
20
|
+
|
21
|
+
PERIODS_OF_THE_DAY = [
|
22
|
+
MORNING = :morning,
|
23
|
+
EVENING = :evening
|
24
|
+
].freeze
|
25
|
+
|
26
|
+
attr_reader :time
|
8
27
|
|
9
28
|
# Source:
|
10
|
-
# Title:
|
11
|
-
#
|
12
|
-
# Edition:
|
13
|
-
# Chapter:
|
29
|
+
# Title: Astronomical Algorithms
|
30
|
+
# Author: Jean Meeus
|
31
|
+
# Edition: 2nd edition
|
32
|
+
# Chapter: 28 - Equation of Time
|
14
33
|
|
15
|
-
# @param
|
34
|
+
# @param date_or_time [Date, Time] Requested date
|
16
35
|
# @return [Integer] Equation of time in seconds
|
17
|
-
def self.equation_of_time(
|
18
|
-
noon = Time.utc(
|
19
|
-
|
20
|
-
|
21
|
-
|
36
|
+
def self.equation_of_time(date_or_time:)
|
37
|
+
noon = Time.utc(date_or_time.year, date_or_time.month, date_or_time.day, 12)
|
38
|
+
time = date_or_time.is_a?(Time) ? date_or_time : noon
|
39
|
+
epoch = Epoch.from_time(time)
|
40
|
+
sun = new(time: time)
|
41
|
+
right_ascension = sun
|
22
42
|
.apparent_ecliptic_coordinates
|
23
|
-
.to_apparent_equatorial(epoch:
|
43
|
+
.to_apparent_equatorial(epoch: epoch)
|
24
44
|
.right_ascension
|
25
|
-
|
26
|
-
|
27
|
-
.
|
28
|
-
.
|
29
|
-
|
30
|
-
|
45
|
+
t = (epoch - Epoch::J2000) / Constants::DAYS_PER_JULIAN_MILLENIA
|
46
|
+
l0 = (280.4664567 +
|
47
|
+
360_007.6982779 * t +
|
48
|
+
0.03032028 * t**2 +
|
49
|
+
t**3 / 49_931 -
|
50
|
+
t**4 / 15_300 -
|
51
|
+
t**5 / 2_000_000) % Constants::DEGREES_PER_CIRCLE
|
52
|
+
nutation = Nutation.for_ecliptic_longitude(epoch: epoch)
|
53
|
+
obliquity = TrueObliquity.for_epoch(epoch)
|
54
|
+
|
55
|
+
(
|
56
|
+
Angle
|
57
|
+
.from_degrees(
|
58
|
+
l0 -
|
59
|
+
Constants::EQUATION_OF_TIME_CONSTANT -
|
60
|
+
right_ascension.degrees +
|
61
|
+
nutation.degrees * obliquity.cos
|
62
|
+
).hours * Constants::SECONDS_PER_HOUR
|
63
|
+
).round
|
31
64
|
end
|
32
65
|
|
33
66
|
# Source:
|
@@ -36,9 +69,13 @@ module Astronoby
|
|
36
69
|
# Edition: MIT Press
|
37
70
|
# Chapter: 6 - The Sun
|
38
71
|
|
39
|
-
# @param
|
40
|
-
def initialize(
|
41
|
-
@
|
72
|
+
# @param time [Time] Considered time
|
73
|
+
def initialize(time:)
|
74
|
+
@time = time
|
75
|
+
end
|
76
|
+
|
77
|
+
def epoch
|
78
|
+
@epoch ||= Epoch.from_time(@time)
|
42
79
|
end
|
43
80
|
|
44
81
|
def true_ecliptic_coordinates
|
@@ -49,10 +86,10 @@ module Astronoby
|
|
49
86
|
end
|
50
87
|
|
51
88
|
def apparent_ecliptic_coordinates
|
52
|
-
nutation = Nutation.for_ecliptic_longitude(epoch:
|
89
|
+
nutation = Nutation.for_ecliptic_longitude(epoch: epoch)
|
53
90
|
longitude_with_aberration = Aberration.for_ecliptic_coordinates(
|
54
91
|
coordinates: true_ecliptic_coordinates,
|
55
|
-
epoch:
|
92
|
+
epoch: epoch
|
56
93
|
).longitude
|
57
94
|
apparent_longitude = nutation + longitude_with_aberration
|
58
95
|
|
@@ -64,74 +101,65 @@ module Astronoby
|
|
64
101
|
|
65
102
|
# Computes the Sun's horizontal coordinates
|
66
103
|
#
|
67
|
-
# @param
|
68
|
-
# @param longitude [Astronoby::Angle] Longitude of the observer
|
104
|
+
# @param observer [Astronoby::Observer] Observer of the event
|
69
105
|
# @return [Astronoby::Coordinates::Horizontal] Sun's horizontal coordinates
|
70
|
-
def horizontal_coordinates(
|
71
|
-
time = Epoch.to_utc(@epoch)
|
72
|
-
|
106
|
+
def horizontal_coordinates(observer:)
|
73
107
|
apparent_ecliptic_coordinates
|
74
|
-
.to_apparent_equatorial(epoch:
|
75
|
-
.to_horizontal(time: time,
|
76
|
-
end
|
77
|
-
|
78
|
-
# @param observer [Astronoby::Observer] Observer of the event
|
79
|
-
# @return [Time] Time of sunrise
|
80
|
-
def rising_time(observer:)
|
81
|
-
event_date = Epoch.to_utc(@epoch).to_date
|
82
|
-
lst1 = event_local_sidereal_time_for_date(event_date, observer, :rising)
|
83
|
-
next_day = event_date.next_day(1)
|
84
|
-
lst2 = event_local_sidereal_time_for_date(next_day, observer, :rising)
|
85
|
-
time = (INTERPOLATION_FACTOR * lst1) / (INTERPOLATION_FACTOR + lst1 - lst2)
|
86
|
-
|
87
|
-
LocalSiderealTime.new(
|
88
|
-
date: event_date,
|
89
|
-
time: time,
|
90
|
-
longitude: observer.longitude
|
91
|
-
).to_gst.to_utc
|
108
|
+
.to_apparent_equatorial(epoch: epoch)
|
109
|
+
.to_horizontal(time: @time, observer: observer)
|
92
110
|
end
|
93
111
|
|
94
112
|
# @param observer [Astronoby::Observer] Observer of the event
|
95
|
-
# @return [Astronoby::
|
96
|
-
def
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
113
|
+
# @return [Astronoby::Events::ObservationEvents] Sun's observation events
|
114
|
+
def observation_events(observer:)
|
115
|
+
today = @time.to_date
|
116
|
+
leap_seconds = Util::Time.terrestrial_universal_time_delta(today)
|
117
|
+
yesterday = today.prev_day
|
118
|
+
yesterday_midnight_terrestrial_time =
|
119
|
+
Time.utc(yesterday.year, yesterday.month, yesterday.day) - leap_seconds
|
120
|
+
yesterday_epoch = Epoch.from_time(yesterday_midnight_terrestrial_time)
|
121
|
+
today_midnight_terrestrial_time =
|
122
|
+
Time.utc(today.year, today.month, today.day) - leap_seconds
|
123
|
+
today_epoch = Epoch.from_time(today_midnight_terrestrial_time)
|
124
|
+
tomorrow = today.next_day
|
125
|
+
tomorrow_midnight_terrestrial_time =
|
126
|
+
Time.utc(tomorrow.year, tomorrow.month, tomorrow.day) - leap_seconds
|
127
|
+
tomorrow_epoch = Epoch.from_time(tomorrow_midnight_terrestrial_time)
|
128
|
+
|
129
|
+
coordinates_of_the_previous_day = self.class
|
130
|
+
.new(time: yesterday_midnight_terrestrial_time)
|
131
|
+
.apparent_ecliptic_coordinates
|
132
|
+
.to_apparent_equatorial(epoch: yesterday_epoch)
|
133
|
+
coordinates_of_the_day = self.class
|
134
|
+
.new(time: today_midnight_terrestrial_time)
|
135
|
+
.apparent_ecliptic_coordinates
|
136
|
+
.to_apparent_equatorial(epoch: today_epoch)
|
137
|
+
coordinates_of_the_next_day = self.class
|
138
|
+
.new(time: tomorrow_midnight_terrestrial_time)
|
139
|
+
.apparent_ecliptic_coordinates
|
140
|
+
.to_apparent_equatorial(epoch: tomorrow_epoch)
|
141
|
+
|
142
|
+
Events::ObservationEvents.new(
|
143
|
+
observer: observer,
|
144
|
+
date: today,
|
145
|
+
coordinates_of_the_previous_day: coordinates_of_the_previous_day,
|
146
|
+
coordinates_of_the_day: coordinates_of_the_day,
|
147
|
+
coordinates_of_the_next_day: coordinates_of_the_next_day,
|
148
|
+
additional_altitude: Angle.from_degrees(angular_size.degrees / 2)
|
102
149
|
)
|
103
150
|
end
|
104
151
|
|
105
|
-
# @param observer [Astronoby::Observer] Observer of the
|
106
|
-
# @return [
|
107
|
-
def
|
108
|
-
|
109
|
-
lst1 = event_local_sidereal_time_for_date(event_date, observer, :setting)
|
110
|
-
next_day = event_date.next_day(1)
|
111
|
-
lst2 = event_local_sidereal_time_for_date(next_day, observer, :setting)
|
112
|
-
time = (INTERPOLATION_FACTOR * lst1) / (INTERPOLATION_FACTOR + lst1 - lst2)
|
113
|
-
|
114
|
-
LocalSiderealTime.new(
|
115
|
-
date: event_date,
|
116
|
-
time: time,
|
117
|
-
longitude: observer.longitude
|
118
|
-
).to_gst.to_utc
|
152
|
+
# @param observer [Astronoby::Observer] Observer of the events
|
153
|
+
# @return [Astronoby::Events::TwilightEvents] Sun's twilight events
|
154
|
+
def twilight_events(observer:)
|
155
|
+
Events::TwilightEvents.new(sun: self, observer: observer)
|
119
156
|
end
|
120
157
|
|
121
|
-
# @
|
122
|
-
# @return [Astronoby::Angle, nil] Azimuth of sunset
|
123
|
-
def setting_azimuth(observer:)
|
124
|
-
equatorial_coordinates = apparent_ecliptic_coordinates
|
125
|
-
.to_apparent_equatorial(epoch: @epoch)
|
126
|
-
Body.new(equatorial_coordinates).setting_azimuth(
|
127
|
-
latitude: observer.latitude,
|
128
|
-
vertical_shift: vertical_shift
|
129
|
-
)
|
130
|
-
end
|
131
|
-
|
132
|
-
# @return [Numeric] Earth-Sun distance in meters
|
158
|
+
# @return [Astronoby::Distance] Earth-Sun distance
|
133
159
|
def earth_distance
|
134
|
-
|
160
|
+
Distance.from_meters(
|
161
|
+
SEMI_MAJOR_AXIS_IN_METERS / distance_angular_size_factor
|
162
|
+
)
|
135
163
|
end
|
136
164
|
|
137
165
|
# @return [Astronoby::Angle] Apparent Sun's angular size
|
@@ -154,20 +182,32 @@ module Astronoby
|
|
154
182
|
(1 + orbital_eccentricity.degrees) / (1 - orbital_eccentricity.degrees)
|
155
183
|
) * Math.tan(eccentric_anomaly.radians / 2)
|
156
184
|
|
157
|
-
Angle.from_degrees(
|
185
|
+
Angle.from_degrees(
|
186
|
+
(Angle.atan(tan).degrees * 2) % Constants::DEGREES_PER_CIRCLE
|
187
|
+
)
|
188
|
+
end
|
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
|
+
)
|
158
196
|
end
|
159
197
|
|
160
198
|
# @return [Astronoby::Angle] Sun's longitude at perigee
|
161
199
|
def longitude_at_perigee
|
162
200
|
Angle.from_degrees(
|
163
|
-
(281.2208444 + 1.719175 * centuries + 0.000452778 * centuries**2) %
|
201
|
+
(281.2208444 + 1.719175 * centuries + 0.000452778 * centuries**2) %
|
202
|
+
Constants::DEGREES_PER_CIRCLE
|
164
203
|
)
|
165
204
|
end
|
166
205
|
|
167
206
|
# @return [Astronoby::Angle] Sun's orbital eccentricity
|
168
207
|
def orbital_eccentricity
|
169
208
|
Angle.from_degrees(
|
170
|
-
(0.01675104 - 0.0000418 * centuries - 0.000000126 * centuries**2) %
|
209
|
+
(0.01675104 - 0.0000418 * centuries - 0.000000126 * centuries**2) %
|
210
|
+
Constants::DEGREES_PER_CIRCLE
|
171
211
|
)
|
172
212
|
end
|
173
213
|
|
@@ -175,27 +215,23 @@ module Astronoby
|
|
175
215
|
|
176
216
|
def true_longitude
|
177
217
|
Angle.from_degrees(
|
178
|
-
(true_anomaly + longitude_at_perigee).degrees %
|
179
|
-
|
180
|
-
end
|
181
|
-
|
182
|
-
def mean_anomaly
|
183
|
-
Angle.from_degrees(
|
184
|
-
(longitude_at_base_epoch - longitude_at_perigee).degrees % 360
|
218
|
+
(true_anomaly + longitude_at_perigee).degrees %
|
219
|
+
Constants::DEGREES_PER_CIRCLE
|
185
220
|
)
|
186
221
|
end
|
187
222
|
|
188
223
|
def days_since_epoch
|
189
|
-
Epoch::DEFAULT_EPOCH -
|
224
|
+
Epoch::DEFAULT_EPOCH - epoch
|
190
225
|
end
|
191
226
|
|
192
227
|
def centuries
|
193
|
-
@centuries ||= (
|
228
|
+
@centuries ||= (epoch - Epoch::J1900) / Constants::DAYS_PER_JULIAN_CENTURY
|
194
229
|
end
|
195
230
|
|
196
231
|
def longitude_at_base_epoch
|
197
232
|
Angle.from_degrees(
|
198
|
-
(279.6966778 + 36000.76892 * centuries + 0.0003025 * centuries**2) %
|
233
|
+
(279.6966778 + 36000.76892 * centuries + 0.0003025 * centuries**2) %
|
234
|
+
Constants::DEGREES_PER_CIRCLE
|
199
235
|
)
|
200
236
|
end
|
201
237
|
|
@@ -205,44 +241,5 @@ module Astronoby
|
|
205
241
|
|
206
242
|
term1 / term2
|
207
243
|
end
|
208
|
-
|
209
|
-
def event_local_sidereal_time_for_date(date, observer, event)
|
210
|
-
midnight_utc = Time.utc(date.year, date.month, date.day)
|
211
|
-
epoch = Epoch.from_time(midnight_utc)
|
212
|
-
sun_at_midnight = self.class.new(epoch: epoch)
|
213
|
-
shift = Body::DEFAULT_REFRACTION_VERTICAL_SHIFT +
|
214
|
-
GeocentricParallax.angle(distance: sun_at_midnight.earth_distance) +
|
215
|
-
Angle.from_degrees(sun_at_midnight.angular_size.degrees / 2)
|
216
|
-
ecliptic_coordinates = sun_at_midnight.apparent_ecliptic_coordinates
|
217
|
-
equatorial_coordinates = ecliptic_coordinates
|
218
|
-
.to_apparent_equatorial(epoch: epoch)
|
219
|
-
|
220
|
-
event_time = if event == :rising
|
221
|
-
Body.new(equatorial_coordinates).rising_time(
|
222
|
-
latitude: observer.latitude,
|
223
|
-
longitude: observer.longitude,
|
224
|
-
date: midnight_utc.to_date,
|
225
|
-
vertical_shift: shift
|
226
|
-
)
|
227
|
-
else
|
228
|
-
Body.new(equatorial_coordinates).setting_time(
|
229
|
-
latitude: observer.latitude,
|
230
|
-
longitude: observer.longitude,
|
231
|
-
date: midnight_utc.to_date,
|
232
|
-
vertical_shift: shift
|
233
|
-
)
|
234
|
-
end
|
235
|
-
|
236
|
-
GreenwichSiderealTime
|
237
|
-
.from_utc(event_time.utc)
|
238
|
-
.to_lst(longitude: observer.longitude)
|
239
|
-
.time
|
240
|
-
end
|
241
|
-
|
242
|
-
def vertical_shift
|
243
|
-
Astronoby::Body::DEFAULT_REFRACTION_VERTICAL_SHIFT +
|
244
|
-
Astronoby::GeocentricParallax.angle(distance: earth_distance) +
|
245
|
-
Astronoby::Angle.from_degrees(angular_size.degrees / 2)
|
246
|
-
end
|
247
244
|
end
|
248
245
|
end
|