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.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/.ruby-version +1 -0
  3. data/.standard.yml +1 -0
  4. data/CHANGELOG.md +116 -0
  5. data/Gemfile.lock +45 -23
  6. data/README.md +42 -285
  7. data/UPGRADING.md +238 -0
  8. data/lib/astronoby/aberration.rb +56 -31
  9. data/lib/astronoby/angle.rb +20 -16
  10. data/lib/astronoby/angles/dms.rb +2 -2
  11. data/lib/astronoby/angles/hms.rb +2 -2
  12. data/lib/astronoby/bodies/earth.rb +56 -0
  13. data/lib/astronoby/bodies/jupiter.rb +11 -0
  14. data/lib/astronoby/bodies/mars.rb +11 -0
  15. data/lib/astronoby/bodies/mercury.rb +11 -0
  16. data/lib/astronoby/bodies/moon.rb +50 -290
  17. data/lib/astronoby/bodies/neptune.rb +11 -0
  18. data/lib/astronoby/bodies/saturn.rb +11 -0
  19. data/lib/astronoby/bodies/solar_system_body.rb +122 -0
  20. data/lib/astronoby/bodies/sun.rb +16 -220
  21. data/lib/astronoby/bodies/uranus.rb +11 -0
  22. data/lib/astronoby/bodies/venus.rb +11 -0
  23. data/lib/astronoby/constants.rb +13 -1
  24. data/lib/astronoby/coordinates/ecliptic.rb +2 -37
  25. data/lib/astronoby/coordinates/equatorial.rb +25 -7
  26. data/lib/astronoby/coordinates/horizontal.rb +0 -46
  27. data/lib/astronoby/corrections/light_time_delay.rb +90 -0
  28. data/lib/astronoby/deflection.rb +187 -0
  29. data/lib/astronoby/distance.rb +9 -0
  30. data/lib/astronoby/ephem.rb +39 -0
  31. data/lib/astronoby/equinox_solstice.rb +21 -18
  32. data/lib/astronoby/errors.rb +4 -0
  33. data/lib/astronoby/events/moon_phases.rb +2 -1
  34. data/lib/astronoby/events/rise_transit_set_calculator.rb +352 -0
  35. data/lib/astronoby/events/rise_transit_set_event.rb +13 -0
  36. data/lib/astronoby/events/rise_transit_set_events.rb +13 -0
  37. data/lib/astronoby/events/twilight_calculator.rb +166 -0
  38. data/lib/astronoby/events/twilight_event.rb +28 -0
  39. data/lib/astronoby/instant.rb +171 -0
  40. data/lib/astronoby/mean_obliquity.rb +23 -10
  41. data/lib/astronoby/nutation.rb +227 -42
  42. data/lib/astronoby/observer.rb +55 -0
  43. data/lib/astronoby/precession.rb +91 -17
  44. data/lib/astronoby/reference_frame.rb +49 -0
  45. data/lib/astronoby/reference_frames/apparent.rb +60 -0
  46. data/lib/astronoby/reference_frames/astrometric.rb +21 -0
  47. data/lib/astronoby/reference_frames/geometric.rb +20 -0
  48. data/lib/astronoby/reference_frames/mean_of_date.rb +38 -0
  49. data/lib/astronoby/reference_frames/topocentric.rb +82 -0
  50. data/lib/astronoby/true_obliquity.rb +2 -1
  51. data/lib/astronoby/util/maths.rb +70 -73
  52. data/lib/astronoby/util/time.rb +454 -31
  53. data/lib/astronoby/vector.rb +36 -0
  54. data/lib/astronoby/velocity.rb +116 -0
  55. data/lib/astronoby/version.rb +1 -1
  56. data/lib/astronoby.rb +26 -5
  57. metadata +61 -16
  58. data/.tool-versions +0 -1
  59. data/lib/astronoby/astronomical_models/ephemeride_lunaire_parisienne.rb +0 -143
  60. data/lib/astronoby/events/observation_events.rb +0 -285
  61. data/lib/astronoby/events/rise_transit_set_iteration.rb +0 -218
  62. data/lib/astronoby/events/twilight_events.rb +0 -121
  63. 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