astronoby 0.6.0 → 0.8.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 (96) hide show
  1. checksums.yaml +4 -4
  2. data/.ruby-version +1 -0
  3. data/.standard.yml +1 -0
  4. data/CHANGELOG.md +203 -3
  5. data/README.md +69 -288
  6. data/UPGRADING.md +267 -0
  7. data/docs/README.md +196 -0
  8. data/docs/angles.md +137 -0
  9. data/docs/celestial_bodies.md +107 -0
  10. data/docs/configuration.md +98 -0
  11. data/docs/coordinates.md +167 -0
  12. data/docs/ephem.md +85 -0
  13. data/docs/equinoxes_solstices_times.md +31 -0
  14. data/docs/glossary.md +152 -0
  15. data/docs/instant.md +139 -0
  16. data/docs/moon_phases.md +79 -0
  17. data/docs/observer.md +65 -0
  18. data/docs/reference_frames.md +138 -0
  19. data/docs/rise_transit_set_times.md +119 -0
  20. data/docs/twilight_times.md +123 -0
  21. data/lib/astronoby/aberration.rb +56 -31
  22. data/lib/astronoby/angle.rb +20 -16
  23. data/lib/astronoby/angles/dms.rb +2 -2
  24. data/lib/astronoby/angles/hms.rb +2 -2
  25. data/lib/astronoby/bodies/earth.rb +62 -0
  26. data/lib/astronoby/bodies/jupiter.rb +28 -0
  27. data/lib/astronoby/bodies/mars.rb +28 -0
  28. data/lib/astronoby/bodies/mercury.rb +32 -0
  29. data/lib/astronoby/bodies/moon.rb +51 -298
  30. data/lib/astronoby/bodies/neptune.rb +32 -0
  31. data/lib/astronoby/bodies/saturn.rb +37 -0
  32. data/lib/astronoby/bodies/solar_system_body.rb +232 -0
  33. data/lib/astronoby/bodies/sun.rb +33 -214
  34. data/lib/astronoby/bodies/uranus.rb +16 -0
  35. data/lib/astronoby/bodies/venus.rb +36 -0
  36. data/lib/astronoby/cache.rb +188 -0
  37. data/lib/astronoby/configuration.rb +92 -0
  38. data/lib/astronoby/constants.rb +17 -2
  39. data/lib/astronoby/constellation.rb +12 -0
  40. data/lib/astronoby/constellations/data.rb +42 -0
  41. data/lib/astronoby/constellations/finder.rb +35 -0
  42. data/lib/astronoby/constellations/repository.rb +20 -0
  43. data/lib/astronoby/coordinates/ecliptic.rb +2 -37
  44. data/lib/astronoby/coordinates/equatorial.rb +28 -10
  45. data/lib/astronoby/coordinates/horizontal.rb +0 -46
  46. data/lib/astronoby/corrections/light_time_delay.rb +90 -0
  47. data/lib/astronoby/data/constellations/constellation_names.dat +88 -0
  48. data/lib/astronoby/data/constellations/indexed_abbreviations.dat +88 -0
  49. data/lib/astronoby/data/constellations/radec_to_index.dat +238 -0
  50. data/lib/astronoby/data/constellations/sorted_declinations.dat +202 -0
  51. data/lib/astronoby/data/constellations/sorted_right_ascensions.dat +237 -0
  52. data/lib/astronoby/deflection.rb +187 -0
  53. data/lib/astronoby/distance.rb +9 -0
  54. data/lib/astronoby/ephem.rb +39 -0
  55. data/lib/astronoby/equinox_solstice.rb +22 -19
  56. data/lib/astronoby/errors.rb +4 -0
  57. data/lib/astronoby/events/moon_phases.rb +15 -13
  58. data/lib/astronoby/events/rise_transit_set_calculator.rb +376 -0
  59. data/lib/astronoby/events/rise_transit_set_event.rb +13 -0
  60. data/lib/astronoby/events/rise_transit_set_events.rb +13 -0
  61. data/lib/astronoby/events/twilight_calculator.rb +221 -0
  62. data/lib/astronoby/events/twilight_event.rb +28 -0
  63. data/lib/astronoby/events/twilight_events.rb +22 -115
  64. data/lib/astronoby/instant.rb +176 -0
  65. data/lib/astronoby/julian_date.rb +78 -0
  66. data/lib/astronoby/mean_obliquity.rb +24 -13
  67. data/lib/astronoby/nutation.rb +235 -42
  68. data/lib/astronoby/observer.rb +55 -0
  69. data/lib/astronoby/precession.rb +102 -18
  70. data/lib/astronoby/reference_frame.rb +50 -0
  71. data/lib/astronoby/reference_frames/apparent.rb +60 -0
  72. data/lib/astronoby/reference_frames/astrometric.rb +21 -0
  73. data/lib/astronoby/reference_frames/geometric.rb +20 -0
  74. data/lib/astronoby/reference_frames/mean_of_date.rb +38 -0
  75. data/lib/astronoby/reference_frames/topocentric.rb +72 -0
  76. data/lib/astronoby/time/greenwich_sidereal_time.rb +2 -2
  77. data/lib/astronoby/true_obliquity.rb +3 -3
  78. data/lib/astronoby/util/maths.rb +70 -73
  79. data/lib/astronoby/util/time.rb +455 -32
  80. data/lib/astronoby/vector.rb +36 -0
  81. data/lib/astronoby/velocity.rb +116 -0
  82. data/lib/astronoby/version.rb +1 -1
  83. data/lib/astronoby.rb +33 -5
  84. metadata +117 -24
  85. data/.tool-versions +0 -1
  86. data/Gemfile +0 -5
  87. data/Gemfile.lock +0 -80
  88. data/benchmark/README.md +0 -131
  89. data/benchmark/benchmark.rb +0 -259
  90. data/benchmark/data/imcce.csv.zip +0 -0
  91. data/benchmark/data/sun_calc.csv.zip +0 -0
  92. data/lib/astronoby/astronomical_models/ephemeride_lunaire_parisienne.rb +0 -143
  93. data/lib/astronoby/epoch.rb +0 -22
  94. data/lib/astronoby/events/observation_events.rb +0 -285
  95. data/lib/astronoby/events/rise_transit_set_iteration.rb +0 -218
  96. data/lib/astronoby/util/astrodynamics.rb +0 -60
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Astronoby
4
+ class Saturn < SolarSystemBody
5
+ EQUATORIAL_RADIUS = Distance.from_meters(60_268_000)
6
+ ABSOLUTE_MAGNITUDE = -8.914
7
+
8
+ def self.ephemeris_segments(_ephem_source)
9
+ [[SOLAR_SYSTEM_BARYCENTER, SATURN_BARYCENTER]]
10
+ end
11
+
12
+ def self.absolute_magnitude
13
+ ABSOLUTE_MAGNITUDE
14
+ end
15
+
16
+ private
17
+
18
+ # Source:
19
+ # Title: Computing Apparent Planetary Magnitudes for The Astronomical
20
+ # Almanac (2018)
21
+ # Authors: Anthony Mallama and James L. Hilton
22
+ def magnitude_correction_term
23
+ phase_angle_degrees = phase_angle.degrees
24
+ if phase_angle_degrees <= 6
25
+ -0.036 -
26
+ 3.7 * 10**-4 * phase_angle_degrees +
27
+ 6.16 * 10**-4 * phase_angle_degrees * phase_angle_degrees
28
+ else
29
+ 0.026 +
30
+ 2.446 * 10**-4 * phase_angle_degrees +
31
+ 2.672 * 10**-4 * phase_angle_degrees * phase_angle_degrees -
32
+ 1.505 * 10**-6 * phase_angle_degrees**3 +
33
+ 4.767 * 10**-9 * phase_angle_degrees**4
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,232 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Astronoby
4
+ class SolarSystemBody
5
+ SOLAR_SYSTEM_BARYCENTER = 0
6
+ SUN = 10
7
+ MERCURY_BARYCENTER = 1
8
+ MERCURY = 199
9
+ VENUS_BARYCENTER = 2
10
+ VENUS = 299
11
+ EARTH_MOON_BARYCENTER = 3
12
+ EARTH = 399
13
+ MOON = 301
14
+ MARS_BARYCENTER = 4
15
+ JUPITER_BARYCENTER = 5
16
+ SATURN_BARYCENTER = 6
17
+ URANUS_BARYCENTER = 7
18
+ NEPTUNE_BARYCENTER = 8
19
+
20
+ attr_reader :geometric, :instant
21
+
22
+ def self.geometric(ephem:, instant:)
23
+ compute_geometric(ephem: ephem, instant: instant)
24
+ end
25
+
26
+ def self.compute_geometric(ephem:, instant:)
27
+ segments = ephemeris_segments(ephem.type)
28
+ segment1 = segments[0]
29
+ segment2 = segments[1] if segments.size == 2
30
+ cache_key = CacheKey.generate(:geometric, instant, segment1, segment2)
31
+
32
+ Astronoby.cache.fetch(cache_key) do
33
+ state1 = ephem[*segment1].state_at(instant.tt)
34
+
35
+ if segment2
36
+ state2 = ephem[*segment2].state_at(instant.tt)
37
+ position = state1.position + state2.position
38
+ velocity = state1.velocity + state2.velocity
39
+ else
40
+ position = state1.position
41
+ velocity = state1.velocity
42
+ end
43
+
44
+ position_vector = Vector[
45
+ Distance.from_kilometers(position.x),
46
+ Distance.from_kilometers(position.y),
47
+ Distance.from_kilometers(position.z)
48
+ ]
49
+
50
+ velocity_vector = Vector[
51
+ Velocity.from_kilometers_per_day(velocity.x),
52
+ Velocity.from_kilometers_per_day(velocity.y),
53
+ Velocity.from_kilometers_per_day(velocity.z)
54
+ ]
55
+
56
+ Geometric.new(
57
+ position: position_vector,
58
+ velocity: velocity_vector,
59
+ instant: instant,
60
+ target_body: self
61
+ )
62
+ end
63
+ end
64
+
65
+ def self.ephemeris_segments(_ephem_source)
66
+ raise NotImplementedError
67
+ end
68
+
69
+ def self.absolute_magnitude
70
+ nil
71
+ end
72
+
73
+ def initialize(ephem:, instant:)
74
+ @instant = instant
75
+ @geometric = compute_geometric(ephem)
76
+ @earth_geometric = Earth.geometric(ephem: ephem, instant: instant)
77
+ @light_time_corrected_position,
78
+ @light_time_corrected_velocity =
79
+ Correction::LightTimeDelay.compute(
80
+ center: @earth_geometric,
81
+ target: @geometric,
82
+ ephem: ephem
83
+ )
84
+ compute_sun(ephem) if requires_sun_data?
85
+ end
86
+
87
+ def astrometric
88
+ @astrometric ||= Astrometric.build_from_geometric(
89
+ instant: @instant,
90
+ earth_geometric: @earth_geometric,
91
+ light_time_corrected_position: @light_time_corrected_position,
92
+ light_time_corrected_velocity: @light_time_corrected_velocity,
93
+ target_body: self
94
+ )
95
+ end
96
+
97
+ def mean_of_date
98
+ @mean_of_date ||= MeanOfDate.build_from_geometric(
99
+ instant: @instant,
100
+ target_geometric: @geometric,
101
+ earth_geometric: @earth_geometric,
102
+ target_body: self
103
+ )
104
+ end
105
+
106
+ def apparent
107
+ @apparent ||= Apparent.build_from_astrometric(
108
+ instant: @instant,
109
+ target_astrometric: astrometric,
110
+ earth_geometric: @earth_geometric,
111
+ target_body: self
112
+ )
113
+ end
114
+
115
+ def observed_by(observer)
116
+ Topocentric.build_from_apparent(
117
+ apparent: apparent,
118
+ observer: observer,
119
+ instant: @instant,
120
+ target_body: self
121
+ )
122
+ end
123
+
124
+ # Returns the constellation of the body
125
+ # @return [Astronoby::Constellation, nil]
126
+ def constellation
127
+ @constellation ||= Constellations::Finder.find(
128
+ Precession.for_equatorial_coordinates(
129
+ coordinates: astrometric.equatorial,
130
+ epoch: JulianDate::B1875
131
+ )
132
+ )
133
+ end
134
+
135
+ # Source:
136
+ # Title: Astronomical Algorithms
137
+ # Author: Jean Meeus
138
+ # Edition: 2nd edition
139
+ # Chapter: 48 - Illuminated Fraction of the Moon's Disk
140
+ # @return [Astronoby::Angle, nil] Phase angle of the body
141
+ def phase_angle
142
+ return unless @sun
143
+
144
+ @phase_angle ||= begin
145
+ geocentric_elongation = Angle.acos(
146
+ @sun.apparent.equatorial.declination.sin *
147
+ apparent.equatorial.declination.sin +
148
+ @sun.apparent.equatorial.declination.cos *
149
+ apparent.equatorial.declination.cos *
150
+ (
151
+ @sun.apparent.equatorial.right_ascension -
152
+ apparent.equatorial.right_ascension
153
+ ).cos
154
+ )
155
+
156
+ term1 = @sun.astrometric.distance.km * geocentric_elongation.sin
157
+ term2 = astrometric.distance.km -
158
+ @sun.astrometric.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
+ # Fraction between 0 and 1 of the body's disk that is illuminated.
166
+ # @return [Float, nil] Body's illuminated fraction, between 0 and 1.
167
+ def illuminated_fraction
168
+ return unless phase_angle
169
+
170
+ @illuminated_fraction ||= (1 + phase_angle.cos) / 2.0
171
+ end
172
+
173
+ # Source:
174
+ # Title: Astronomical Algorithms
175
+ # Author: Jean Meeus
176
+ # Edition: 2nd edition
177
+ # Chapter: 48 - Illuminated Fraction of the Moon's Disk
178
+ # Apparent magnitude of the body, as seen from Earth.
179
+ # @return [Float, nil] Apparent magnitude of the body.
180
+ def apparent_magnitude
181
+ return unless self.class.absolute_magnitude
182
+
183
+ @apparent_magnitude ||= begin
184
+ body_sun_distance =
185
+ (astrometric.position - @sun.astrometric.position).magnitude
186
+ self.class.absolute_magnitude +
187
+ 5 * Math.log10(body_sun_distance.au * astrometric.distance.au) +
188
+ magnitude_correction_term
189
+ end
190
+ end
191
+
192
+ # Angular diameter of the body, as seen from Earth. Based on the apparent
193
+ # position of the body.
194
+ # @return [Astronoby::Angle] Angular diameter of the body
195
+ def angular_diameter
196
+ @angular_radius ||= begin
197
+ return if apparent.position.zero?
198
+
199
+ Angle.from_radians(
200
+ Math.asin(self.class::EQUATORIAL_RADIUS.m / apparent.distance.m) * 2
201
+ )
202
+ end
203
+ end
204
+
205
+ private
206
+
207
+ # By default, Solar System bodies expose attributes that are dependent on
208
+ # the Sun's position, such as phase angle and illuminated fraction.
209
+ # If a body does not require Sun data, it should override this method to
210
+ # return false.
211
+ def requires_sun_data?
212
+ true
213
+ end
214
+
215
+ def compute_geometric(ephem)
216
+ self.class.compute_geometric(ephem: ephem, instant: @instant)
217
+ end
218
+
219
+ def compute_sun(ephem)
220
+ @sun ||= Sun.new(instant: @instant, ephem: ephem)
221
+ end
222
+
223
+ # Source:
224
+ # Title: Explanatory Supplement to the Astronomical Almanac
225
+ # Authors: Sean E. Urban and P. Kenneth Seidelmann
226
+ # Edition: University Science Books
227
+ # Chapter: 10.3 - Phases and Magnitudes
228
+ def magnitude_correction_term
229
+ -2.5 * Math.log10(illuminated_fraction)
230
+ end
231
+ end
232
+ end
@@ -1,29 +1,29 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Astronoby
4
- class Sun
5
- SEMI_MAJOR_AXIS_IN_METERS = 149_598_500_000
6
- ANGULAR_DIAMETER = Angle.from_degrees(0.533128)
7
- INTERPOLATION_FACTOR = 24.07
4
+ class Sun < SolarSystemBody
5
+ EQUATORIAL_RADIUS = Distance.from_meters(695_700_000)
6
+ ABSOLUTE_MAGNITUDE = -26.74
8
7
 
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
8
+ def self.ephemeris_segments(_ephem_source)
9
+ [[SOLAR_SYSTEM_BARYCENTER, SUN]]
10
+ end
20
11
 
21
- PERIODS_OF_THE_DAY = [
22
- MORNING = :morning,
23
- EVENING = :evening
24
- ].freeze
12
+ def self.absolute_magnitude
13
+ ABSOLUTE_MAGNITUDE
14
+ end
25
15
 
26
- attr_reader :time
16
+ # Source:
17
+ # Title: Explanatory Supplement to the Astronomical Almanac
18
+ # Authors: Sean E. Urban and P. Kenneth Seidelmann
19
+ # Edition: University Science Books
20
+ # Chapter: 10.3 - Phases and Magnitudes
21
+ # Apparent magnitude of the body, as seen from Earth.
22
+ # @return [Float] Apparent magnitude of the body.
23
+ def apparent_magnitude
24
+ @apparent_magnitude ||=
25
+ self.class.absolute_magnitude + 5 * Math.log10(astrometric.distance.au)
26
+ end
27
27
 
28
28
  # Source:
29
29
  # Title: Astronomical Algorithms
@@ -31,215 +31,34 @@ module Astronoby
31
31
  # Edition: 2nd edition
32
32
  # Chapter: 28 - Equation of Time
33
33
 
34
- # @param date_or_time [Date, Time] Requested date
35
34
  # @return [Integer] Equation of time in seconds
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
42
- .apparent_ecliptic_coordinates
43
- .to_apparent_equatorial(epoch: epoch)
44
- .right_ascension
45
- t = (epoch - Epoch::J2000) / Constants::DAYS_PER_JULIAN_MILLENIA
35
+ def equation_of_time
36
+ right_ascension = apparent.equatorial.right_ascension
37
+ t = (@instant.julian_date - JulianDate::J2000) / Constants::DAYS_PER_JULIAN_MILLENIA
46
38
  l0 = (280.4664567 +
47
39
  360_007.6982779 * t +
48
40
  0.03032028 * t**2 +
49
41
  t**3 / 49_931 -
50
42
  t**4 / 15_300 -
51
43
  t**5 / 2_000_000) % Constants::DEGREES_PER_CIRCLE
52
- nutation = Nutation.for_ecliptic_longitude(epoch: epoch)
53
- obliquity = TrueObliquity.for_epoch(epoch)
44
+ nutation = Nutation.new(instant: instant).nutation_in_longitude
45
+ obliquity = TrueObliquity.at(@instant)
54
46
 
55
47
  (
56
48
  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
49
+ .from_degrees(
50
+ l0 -
51
+ Constants::EQUATION_OF_TIME_CONSTANT -
52
+ right_ascension.degrees +
53
+ nutation.degrees * obliquity.cos
54
+ ).hours * Constants::SECONDS_PER_HOUR
63
55
  ).round
64
56
  end
65
57
 
66
- # Source:
67
- # Title: Celestial Calculations
68
- # Author: J. L. Lawrence
69
- # Edition: MIT Press
70
- # Chapter: 6 - The Sun
71
-
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)
79
- end
80
-
81
- def true_ecliptic_coordinates
82
- Coordinates::Ecliptic.new(
83
- latitude: Angle.zero,
84
- longitude: true_longitude
85
- )
86
- end
87
-
88
- def apparent_ecliptic_coordinates
89
- nutation = Nutation.for_ecliptic_longitude(epoch: epoch)
90
- longitude_with_aberration = Aberration.for_ecliptic_coordinates(
91
- coordinates: true_ecliptic_coordinates,
92
- epoch: epoch
93
- ).longitude
94
- apparent_longitude = nutation + longitude_with_aberration
95
-
96
- Coordinates::Ecliptic.new(
97
- latitude: Angle.zero,
98
- longitude: apparent_longitude
99
- )
100
- end
101
-
102
- # Computes the Sun's horizontal coordinates
103
- #
104
- # @param observer [Astronoby::Observer] Observer of the event
105
- # @return [Astronoby::Coordinates::Horizontal] Sun's horizontal coordinates
106
- def horizontal_coordinates(observer:)
107
- apparent_ecliptic_coordinates
108
- .to_apparent_equatorial(epoch: epoch)
109
- .to_horizontal(time: @time, observer: observer)
110
- end
111
-
112
- # @param observer [Astronoby::Observer] Observer of the event
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)
149
- )
150
- end
151
-
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)
156
- end
157
-
158
- # @return [Astronoby::Distance] Earth-Sun distance
159
- def earth_distance
160
- Distance.from_meters(
161
- SEMI_MAJOR_AXIS_IN_METERS / distance_angular_size_factor
162
- )
163
- end
164
-
165
- # @return [Astronoby::Angle] Apparent Sun's angular size
166
- def angular_size
167
- Angle.from_degrees(
168
- ANGULAR_DIAMETER.degrees * distance_angular_size_factor
169
- )
170
- end
171
-
172
- # @return [Astronoby::Angle] Sun's true anomaly
173
- def true_anomaly
174
- eccentric_anomaly = Util::Astrodynamics.eccentric_anomaly_newton_raphson(
175
- mean_anomaly,
176
- orbital_eccentricity.degrees,
177
- 2e-06,
178
- 10
179
- )
180
-
181
- tan = Math.sqrt(
182
- (1 + orbital_eccentricity.degrees) / (1 - orbital_eccentricity.degrees)
183
- ) * Math.tan(eccentric_anomaly.radians / 2)
184
-
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
- )
196
- end
197
-
198
- # @return [Astronoby::Angle] Sun's longitude at perigee
199
- def longitude_at_perigee
200
- Angle.from_degrees(
201
- (281.2208444 + 1.719175 * centuries + 0.000452778 * centuries**2) %
202
- Constants::DEGREES_PER_CIRCLE
203
- )
204
- end
205
-
206
- # @return [Astronoby::Angle] Sun's orbital eccentricity
207
- def orbital_eccentricity
208
- Angle.from_degrees(
209
- (0.01675104 - 0.0000418 * centuries - 0.000000126 * centuries**2) %
210
- Constants::DEGREES_PER_CIRCLE
211
- )
212
- end
213
-
214
58
  private
215
59
 
216
- def true_longitude
217
- Angle.from_degrees(
218
- (true_anomaly + longitude_at_perigee).degrees %
219
- Constants::DEGREES_PER_CIRCLE
220
- )
221
- end
222
-
223
- def days_since_epoch
224
- Epoch::DEFAULT_EPOCH - epoch
225
- end
226
-
227
- def centuries
228
- @centuries ||= (epoch - Epoch::J1900) / Constants::DAYS_PER_JULIAN_CENTURY
229
- end
230
-
231
- def longitude_at_base_epoch
232
- Angle.from_degrees(
233
- (279.6966778 + 36000.76892 * centuries + 0.0003025 * centuries**2) %
234
- Constants::DEGREES_PER_CIRCLE
235
- )
236
- end
237
-
238
- def distance_angular_size_factor
239
- term1 = 1 + orbital_eccentricity.degrees * true_anomaly.cos
240
- term2 = 1 - orbital_eccentricity.degrees**2
241
-
242
- term1 / term2
60
+ def requires_sun_data?
61
+ false
243
62
  end
244
63
  end
245
64
  end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Astronoby
4
+ class Uranus < SolarSystemBody
5
+ EQUATORIAL_RADIUS = Distance.from_meters(25_559_000)
6
+ ABSOLUTE_MAGNITUDE = -7.11
7
+
8
+ def self.ephemeris_segments(_ephem_source)
9
+ [[SOLAR_SYSTEM_BARYCENTER, URANUS_BARYCENTER]]
10
+ end
11
+
12
+ def self.absolute_magnitude
13
+ ABSOLUTE_MAGNITUDE
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Astronoby
4
+ class Venus < SolarSystemBody
5
+ EQUATORIAL_RADIUS = Distance.from_meters(6_051_800)
6
+ ABSOLUTE_MAGNITUDE = -4.384
7
+
8
+ def self.ephemeris_segments(_ephem_source)
9
+ [[SOLAR_SYSTEM_BARYCENTER, VENUS_BARYCENTER]]
10
+ end
11
+
12
+ def self.absolute_magnitude
13
+ ABSOLUTE_MAGNITUDE
14
+ end
15
+
16
+ private
17
+
18
+ # Source:
19
+ # Title: Computing Apparent Planetary Magnitudes for The Astronomical
20
+ # Almanac (2018)
21
+ # Authors: Anthony Mallama and James L. Hilton
22
+ def magnitude_correction_term
23
+ phase_angle_degrees = phase_angle.degrees
24
+ if phase_angle_degrees < 163.7
25
+ -1.044 * 10**-3 * phase_angle_degrees +
26
+ 3.687 * 10**-4 * phase_angle_degrees * phase_angle_degrees -
27
+ 2.814 * 10**-6 * phase_angle_degrees**3 +
28
+ 8.938 * 10**-9 * phase_angle_degrees**4
29
+
30
+ else
31
+ 240.44228 - 2.81914 * phase_angle_degrees +
32
+ 8.39034 * 10**-3 * phase_angle_degrees * phase_angle_degrees
33
+ end
34
+ end
35
+ end
36
+ end