astronoby 0.6.0 → 0.7.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 -0
- data/.standard.yml +1 -0
- data/CHANGELOG.md +116 -0
- data/Gemfile.lock +45 -23
- data/README.md +42 -285
- data/UPGRADING.md +238 -0
- data/lib/astronoby/aberration.rb +56 -31
- data/lib/astronoby/angle.rb +20 -16
- data/lib/astronoby/angles/dms.rb +2 -2
- data/lib/astronoby/angles/hms.rb +2 -2
- data/lib/astronoby/bodies/earth.rb +56 -0
- data/lib/astronoby/bodies/jupiter.rb +11 -0
- data/lib/astronoby/bodies/mars.rb +11 -0
- data/lib/astronoby/bodies/mercury.rb +11 -0
- data/lib/astronoby/bodies/moon.rb +50 -290
- data/lib/astronoby/bodies/neptune.rb +11 -0
- data/lib/astronoby/bodies/saturn.rb +11 -0
- data/lib/astronoby/bodies/solar_system_body.rb +122 -0
- data/lib/astronoby/bodies/sun.rb +16 -220
- data/lib/astronoby/bodies/uranus.rb +11 -0
- data/lib/astronoby/bodies/venus.rb +11 -0
- data/lib/astronoby/constants.rb +13 -1
- data/lib/astronoby/coordinates/ecliptic.rb +2 -37
- data/lib/astronoby/coordinates/equatorial.rb +25 -7
- data/lib/astronoby/coordinates/horizontal.rb +0 -46
- data/lib/astronoby/corrections/light_time_delay.rb +90 -0
- data/lib/astronoby/deflection.rb +187 -0
- data/lib/astronoby/distance.rb +9 -0
- data/lib/astronoby/ephem.rb +39 -0
- data/lib/astronoby/equinox_solstice.rb +21 -18
- data/lib/astronoby/errors.rb +4 -0
- data/lib/astronoby/events/moon_phases.rb +2 -1
- data/lib/astronoby/events/rise_transit_set_calculator.rb +352 -0
- data/lib/astronoby/events/rise_transit_set_event.rb +13 -0
- data/lib/astronoby/events/rise_transit_set_events.rb +13 -0
- data/lib/astronoby/events/twilight_calculator.rb +166 -0
- data/lib/astronoby/events/twilight_event.rb +28 -0
- data/lib/astronoby/instant.rb +171 -0
- data/lib/astronoby/mean_obliquity.rb +23 -10
- data/lib/astronoby/nutation.rb +227 -42
- data/lib/astronoby/observer.rb +55 -0
- data/lib/astronoby/precession.rb +91 -17
- data/lib/astronoby/reference_frame.rb +49 -0
- data/lib/astronoby/reference_frames/apparent.rb +60 -0
- data/lib/astronoby/reference_frames/astrometric.rb +21 -0
- data/lib/astronoby/reference_frames/geometric.rb +20 -0
- data/lib/astronoby/reference_frames/mean_of_date.rb +38 -0
- data/lib/astronoby/reference_frames/topocentric.rb +82 -0
- data/lib/astronoby/true_obliquity.rb +2 -1
- data/lib/astronoby/util/maths.rb +70 -73
- data/lib/astronoby/util/time.rb +454 -31
- data/lib/astronoby/vector.rb +36 -0
- data/lib/astronoby/velocity.rb +116 -0
- data/lib/astronoby/version.rb +1 -1
- data/lib/astronoby.rb +26 -5
- metadata +61 -16
- data/.tool-versions +0 -1
- data/lib/astronoby/astronomical_models/ephemeride_lunaire_parisienne.rb +0 -143
- data/lib/astronoby/events/observation_events.rb +0 -285
- data/lib/astronoby/events/rise_transit_set_iteration.rb +0 -218
- data/lib/astronoby/events/twilight_events.rb +0 -121
- data/lib/astronoby/util/astrodynamics.rb +0 -60
@@ -1,218 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Astronoby
|
4
|
-
class RiseTransitSetIteration
|
5
|
-
EARTH_SIDEREAL_ROTATION_RATE = 360.98564736629
|
6
|
-
|
7
|
-
# Source:
|
8
|
-
# Title: Astronomical Algorithms
|
9
|
-
# Author: Jean Meeus
|
10
|
-
# Edition: 2nd edition
|
11
|
-
# Chapter: 15 - Rising, Transit, and Setting
|
12
|
-
|
13
|
-
# @param observer [Astronoby::Observer] Observer
|
14
|
-
# @param date [Date] Date of the event
|
15
|
-
# @param coordinates_of_the_previous_day [Astronoby::Coordinates::Equatorial]
|
16
|
-
# Coordinates of the body of the previous day
|
17
|
-
# @param coordinates_of_the_day [Astronoby::Coordinates::Equatorial]
|
18
|
-
# Coordinates of the body of the day
|
19
|
-
# @param coordinates_of_the_next_day [Astronoby::Coordinates::Equatorial]
|
20
|
-
# Coordinates of the body of the next day
|
21
|
-
# @param shift [Astronoby::Angle] Altitude shift
|
22
|
-
# @param initial_rising [Float] Initial rising
|
23
|
-
# @param initial_transit [Float] Initial transit
|
24
|
-
# @param initial_setting [Float] Initial setting
|
25
|
-
def initialize(
|
26
|
-
observer:,
|
27
|
-
date:,
|
28
|
-
coordinates_of_the_previous_day:,
|
29
|
-
coordinates_of_the_day:,
|
30
|
-
coordinates_of_the_next_day:,
|
31
|
-
shift:,
|
32
|
-
initial_rising:,
|
33
|
-
initial_transit:,
|
34
|
-
initial_setting:
|
35
|
-
)
|
36
|
-
@observer = observer
|
37
|
-
@date = date
|
38
|
-
@coordinates_of_the_previous_day = coordinates_of_the_previous_day
|
39
|
-
@coordinates_of_the_day = coordinates_of_the_day
|
40
|
-
@coordinates_of_the_next_day = coordinates_of_the_next_day
|
41
|
-
@shift = shift
|
42
|
-
@initial_rising = initial_rising
|
43
|
-
@initial_transit = initial_transit
|
44
|
-
@initial_setting = initial_setting
|
45
|
-
end
|
46
|
-
|
47
|
-
# @return [Array<Float>] Iteration results
|
48
|
-
def iterate
|
49
|
-
[
|
50
|
-
delta_m_rising,
|
51
|
-
delta_m_transit,
|
52
|
-
delta_m_setting
|
53
|
-
]
|
54
|
-
end
|
55
|
-
|
56
|
-
private
|
57
|
-
|
58
|
-
def delta_m_rising
|
59
|
-
(local_horizontal_altitude_rising - @shift).degrees./(
|
60
|
-
Constants::DEGREES_PER_CIRCLE *
|
61
|
-
declination_rising.cos *
|
62
|
-
@observer.latitude.cos *
|
63
|
-
local_hour_angle_rising.sin
|
64
|
-
)
|
65
|
-
end
|
66
|
-
|
67
|
-
def delta_m_transit
|
68
|
-
-local_hour_angle_transit.degrees / Constants::DEGREES_PER_CIRCLE
|
69
|
-
end
|
70
|
-
|
71
|
-
def delta_m_setting
|
72
|
-
(local_horizontal_altitude_setting - @shift).degrees./(
|
73
|
-
Constants::DEGREES_PER_CIRCLE *
|
74
|
-
declination_setting.cos *
|
75
|
-
@observer.latitude.cos *
|
76
|
-
local_hour_angle_setting.sin
|
77
|
-
)
|
78
|
-
end
|
79
|
-
|
80
|
-
def observer_longitude
|
81
|
-
# Longitude must be treated positively westwards from the meridian of
|
82
|
-
# Greenwich, and negatively to the east
|
83
|
-
@observer_longitude ||= -@observer.longitude
|
84
|
-
end
|
85
|
-
|
86
|
-
def apparent_gst_at_midnight
|
87
|
-
@apparent_gst_at_midnight ||= Angle.from_hours(
|
88
|
-
GreenwichSiderealTime.from_utc(
|
89
|
-
Time.utc(@date.year, @date.month, @date.day)
|
90
|
-
).time
|
91
|
-
)
|
92
|
-
end
|
93
|
-
|
94
|
-
def gst_rising
|
95
|
-
@gst_rising ||= Angle.from_degrees(
|
96
|
-
apparent_gst_at_midnight.degrees +
|
97
|
-
EARTH_SIDEREAL_ROTATION_RATE * @initial_rising
|
98
|
-
)
|
99
|
-
end
|
100
|
-
|
101
|
-
def gst_transit
|
102
|
-
@gst_transit ||= Angle.from_degrees(
|
103
|
-
apparent_gst_at_midnight.degrees +
|
104
|
-
EARTH_SIDEREAL_ROTATION_RATE * @initial_transit
|
105
|
-
)
|
106
|
-
end
|
107
|
-
|
108
|
-
def gst_setting
|
109
|
-
@gst_setting ||= Angle.from_degrees(
|
110
|
-
apparent_gst_at_midnight.degrees +
|
111
|
-
EARTH_SIDEREAL_ROTATION_RATE * @initial_setting
|
112
|
-
)
|
113
|
-
end
|
114
|
-
|
115
|
-
def local_hour_angle_rising
|
116
|
-
@local_hour_angle_rising ||=
|
117
|
-
gst_rising - observer_longitude - right_ascension_rising
|
118
|
-
end
|
119
|
-
|
120
|
-
def local_hour_angle_transit
|
121
|
-
gst_transit - observer_longitude - right_ascension_transit
|
122
|
-
end
|
123
|
-
|
124
|
-
def local_hour_angle_setting
|
125
|
-
@local_hour_angle_setting ||=
|
126
|
-
gst_setting - observer_longitude - right_ascension_setting
|
127
|
-
end
|
128
|
-
|
129
|
-
def local_horizontal_altitude_rising
|
130
|
-
Angle.asin(
|
131
|
-
@observer.latitude.sin * declination_rising.sin +
|
132
|
-
@observer.latitude.cos * declination_rising.cos * local_hour_angle_rising.cos
|
133
|
-
)
|
134
|
-
end
|
135
|
-
|
136
|
-
def local_horizontal_altitude_setting
|
137
|
-
Angle.asin(
|
138
|
-
@observer.latitude.sin * declination_setting.sin +
|
139
|
-
@observer.latitude.cos * declination_setting.cos * local_hour_angle_setting.cos
|
140
|
-
)
|
141
|
-
end
|
142
|
-
|
143
|
-
def right_ascension_rising
|
144
|
-
Angle.from_degrees(
|
145
|
-
Util::Maths.interpolate(
|
146
|
-
Util::Maths.normalize_angles_for_interpolation(
|
147
|
-
[
|
148
|
-
@coordinates_of_the_previous_day.right_ascension.degrees,
|
149
|
-
@coordinates_of_the_day.right_ascension.degrees,
|
150
|
-
@coordinates_of_the_next_day.right_ascension.degrees
|
151
|
-
]
|
152
|
-
),
|
153
|
-
@initial_rising
|
154
|
-
)
|
155
|
-
)
|
156
|
-
end
|
157
|
-
|
158
|
-
def right_ascension_transit
|
159
|
-
Angle.from_degrees(
|
160
|
-
Util::Maths.interpolate(
|
161
|
-
Util::Maths.normalize_angles_for_interpolation(
|
162
|
-
[
|
163
|
-
@coordinates_of_the_previous_day.right_ascension.degrees,
|
164
|
-
@coordinates_of_the_day.right_ascension.degrees,
|
165
|
-
@coordinates_of_the_next_day.right_ascension.degrees
|
166
|
-
]
|
167
|
-
),
|
168
|
-
@initial_transit
|
169
|
-
)
|
170
|
-
)
|
171
|
-
end
|
172
|
-
|
173
|
-
def right_ascension_setting
|
174
|
-
Angle.from_degrees(
|
175
|
-
Util::Maths.interpolate(
|
176
|
-
Util::Maths.normalize_angles_for_interpolation(
|
177
|
-
[
|
178
|
-
@coordinates_of_the_previous_day.right_ascension.degrees,
|
179
|
-
@coordinates_of_the_day.right_ascension.degrees,
|
180
|
-
@coordinates_of_the_next_day.right_ascension.degrees
|
181
|
-
]
|
182
|
-
),
|
183
|
-
@initial_setting
|
184
|
-
)
|
185
|
-
)
|
186
|
-
end
|
187
|
-
|
188
|
-
def declination_rising
|
189
|
-
Angle.from_degrees(
|
190
|
-
Util::Maths.interpolate(
|
191
|
-
Util::Maths.normalize_angles_for_interpolation(
|
192
|
-
[
|
193
|
-
@coordinates_of_the_previous_day.declination.degrees,
|
194
|
-
@coordinates_of_the_day.declination.degrees,
|
195
|
-
@coordinates_of_the_next_day.declination.degrees
|
196
|
-
]
|
197
|
-
),
|
198
|
-
@initial_rising
|
199
|
-
)
|
200
|
-
)
|
201
|
-
end
|
202
|
-
|
203
|
-
def declination_setting
|
204
|
-
Angle.from_degrees(
|
205
|
-
Util::Maths.interpolate(
|
206
|
-
Util::Maths.normalize_angles_for_interpolation(
|
207
|
-
[
|
208
|
-
@coordinates_of_the_previous_day.declination.degrees,
|
209
|
-
@coordinates_of_the_day.declination.degrees,
|
210
|
-
@coordinates_of_the_next_day.declination.degrees
|
211
|
-
]
|
212
|
-
),
|
213
|
-
@initial_setting
|
214
|
-
)
|
215
|
-
)
|
216
|
-
end
|
217
|
-
end
|
218
|
-
end
|
@@ -1,121 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Astronoby
|
4
|
-
module Events
|
5
|
-
class TwilightEvents
|
6
|
-
TWILIGHTS = [
|
7
|
-
CIVIL = :civil,
|
8
|
-
NAUTICAL = :nautical,
|
9
|
-
ASTRONOMICAL = :astronomical
|
10
|
-
].freeze
|
11
|
-
|
12
|
-
TWILIGHT_ANGLES = {
|
13
|
-
CIVIL => Angle.from_degrees(96),
|
14
|
-
NAUTICAL => Angle.from_degrees(102),
|
15
|
-
ASTRONOMICAL => Angle.from_degrees(108)
|
16
|
-
}.freeze
|
17
|
-
|
18
|
-
PERIODS_OF_THE_DAY = [
|
19
|
-
MORNING = :morning,
|
20
|
-
EVENING = :evening
|
21
|
-
].freeze
|
22
|
-
|
23
|
-
attr_reader :morning_civil_twilight_time,
|
24
|
-
:evening_civil_twilight_time,
|
25
|
-
:morning_nautical_twilight_time,
|
26
|
-
:evening_nautical_twilight_time,
|
27
|
-
:morning_astronomical_twilight_time,
|
28
|
-
:evening_astronomical_twilight_time
|
29
|
-
|
30
|
-
def initialize(observer:, sun:)
|
31
|
-
@observer = observer
|
32
|
-
@sun = sun
|
33
|
-
PERIODS_OF_THE_DAY.each do |period_of_the_day|
|
34
|
-
TWILIGHT_ANGLES.each do |twilight, _|
|
35
|
-
zenith_angle = TWILIGHT_ANGLES[twilight]
|
36
|
-
instance_variable_set(
|
37
|
-
:"@#{period_of_the_day}_#{twilight}_twilight_time",
|
38
|
-
compute(period_of_the_day, zenith_angle)
|
39
|
-
)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
# @param period_of_the_day [Symbol] :morning or :evening
|
45
|
-
# @param zenith_angle [Angle] The zenith angle of the twilight
|
46
|
-
def time_for_zenith_angle(period_of_the_day:, zenith_angle:)
|
47
|
-
unless PERIODS_OF_THE_DAY.include?(period_of_the_day)
|
48
|
-
raise IncompatibleArgumentsError,
|
49
|
-
"Only #{PERIODS_OF_THE_DAY.join(" or ")} are allowed as period_of_the_day, got #{period_of_the_day}"
|
50
|
-
end
|
51
|
-
|
52
|
-
compute(period_of_the_day, zenith_angle)
|
53
|
-
end
|
54
|
-
|
55
|
-
private
|
56
|
-
|
57
|
-
# Source:
|
58
|
-
# Title: Practical Astronomy with your Calculator or Spreadsheet
|
59
|
-
# Authors: Peter Duffett-Smith and Jonathan Zwart
|
60
|
-
# Edition: Cambridge University Press
|
61
|
-
# Chapter: 50 - Twilight
|
62
|
-
def compute(period_of_the_day, zenith_angle)
|
63
|
-
period_time = if period_of_the_day == MORNING
|
64
|
-
observation_events.rising_time
|
65
|
-
else
|
66
|
-
observation_events.setting_time
|
67
|
-
end
|
68
|
-
|
69
|
-
hour_angle_at_period = equatorial_coordinates_at_midday
|
70
|
-
.compute_hour_angle(time: period_time, longitude: @observer.longitude)
|
71
|
-
|
72
|
-
term1 = zenith_angle.cos -
|
73
|
-
@observer.latitude.sin *
|
74
|
-
@equatorial_coordinates_at_midday.declination.sin
|
75
|
-
term2 = @observer.latitude.cos *
|
76
|
-
equatorial_coordinates_at_midday.declination.cos
|
77
|
-
hour_angle_ratio_at_twilight = term1 / term2
|
78
|
-
|
79
|
-
return unless hour_angle_ratio_at_twilight.between?(-1, 1)
|
80
|
-
|
81
|
-
hour_angle_at_twilight = Angle.acos(hour_angle_ratio_at_twilight)
|
82
|
-
time_sign = -1
|
83
|
-
|
84
|
-
if period_of_the_day == MORNING
|
85
|
-
hour_angle_at_twilight = Angle.from_degrees(
|
86
|
-
Constants::DEGREES_PER_CIRCLE - hour_angle_at_twilight.degrees
|
87
|
-
)
|
88
|
-
time_sign = 1
|
89
|
-
end
|
90
|
-
|
91
|
-
twilight_in_hours =
|
92
|
-
time_sign * (hour_angle_at_twilight - hour_angle_at_period).hours *
|
93
|
-
GreenwichSiderealTime::SIDEREAL_MINUTE_IN_UT_MINUTE
|
94
|
-
twilight_in_seconds = time_sign *
|
95
|
-
twilight_in_hours *
|
96
|
-
Constants::SECONDS_PER_HOUR
|
97
|
-
|
98
|
-
(period_time + twilight_in_seconds).round
|
99
|
-
end
|
100
|
-
|
101
|
-
def observation_events
|
102
|
-
@observation_events ||= @sun.observation_events(observer: @observer)
|
103
|
-
end
|
104
|
-
|
105
|
-
def midday
|
106
|
-
date = @sun.time.to_date
|
107
|
-
Time.utc(date.year, date.month, date.day, 12)
|
108
|
-
end
|
109
|
-
|
110
|
-
def sun_at_midday
|
111
|
-
Sun.new(time: midday)
|
112
|
-
end
|
113
|
-
|
114
|
-
def equatorial_coordinates_at_midday
|
115
|
-
@equatorial_coordinates_at_midday ||= sun_at_midday
|
116
|
-
.apparent_ecliptic_coordinates
|
117
|
-
.to_apparent_equatorial(epoch: Epoch.from_time(midday))
|
118
|
-
end
|
119
|
-
end
|
120
|
-
end
|
121
|
-
end
|
@@ -1,60 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Astronoby
|
4
|
-
module Util
|
5
|
-
module Astrodynamics
|
6
|
-
class << self
|
7
|
-
# Source:
|
8
|
-
# Title: Celestial Calculations
|
9
|
-
# Author: J. L. Lawrence
|
10
|
-
# Edition: MIT Press
|
11
|
-
# Chapter: 4 - Orbits and Coordinate Systems
|
12
|
-
def eccentric_anomaly_newton_raphson(
|
13
|
-
mean_anomaly,
|
14
|
-
orbital_eccentricity,
|
15
|
-
precision,
|
16
|
-
maximum_iteration_count,
|
17
|
-
current_iteration = 0,
|
18
|
-
solution_on_previous_interation = nil
|
19
|
-
)
|
20
|
-
previous_solution = solution_on_previous_interation&.radians
|
21
|
-
|
22
|
-
solution = if previous_solution.nil?
|
23
|
-
if orbital_eccentricity <= 0.75
|
24
|
-
mean_anomaly.radians
|
25
|
-
else
|
26
|
-
Math::PI
|
27
|
-
end
|
28
|
-
else
|
29
|
-
previous_solution - (
|
30
|
-
(
|
31
|
-
previous_solution -
|
32
|
-
orbital_eccentricity * Math.sin(previous_solution) -
|
33
|
-
mean_anomaly.radians
|
34
|
-
) / (
|
35
|
-
1 - orbital_eccentricity * Math.cos(previous_solution)
|
36
|
-
)
|
37
|
-
)
|
38
|
-
end
|
39
|
-
|
40
|
-
if current_iteration >= maximum_iteration_count ||
|
41
|
-
(
|
42
|
-
previous_solution &&
|
43
|
-
(solution - previous_solution).abs <= precision
|
44
|
-
)
|
45
|
-
return Angle.from_radians(solution)
|
46
|
-
end
|
47
|
-
|
48
|
-
eccentric_anomaly_newton_raphson(
|
49
|
-
mean_anomaly,
|
50
|
-
orbital_eccentricity,
|
51
|
-
precision,
|
52
|
-
maximum_iteration_count,
|
53
|
-
current_iteration + 1,
|
54
|
-
Angle.from_radians(solution)
|
55
|
-
)
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|