astronoby 0.9.0 → 0.10.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 (102) hide show
  1. checksums.yaml +4 -4
  2. data/.ruby-version +1 -1
  3. data/CHANGELOG.md +101 -0
  4. data/README.md +6 -1
  5. data/UPGRADING.md +84 -0
  6. data/docs/README.md +80 -15
  7. data/docs/angles.md +1 -0
  8. data/docs/configuration.md +20 -17
  9. data/docs/coordinates.md +72 -12
  10. data/docs/deep_sky_bodies.md +1 -1
  11. data/docs/ephem.md +5 -2
  12. data/docs/equinoxes_solstices_times.md +4 -3
  13. data/docs/glossary.md +97 -1
  14. data/docs/iers.md +40 -0
  15. data/docs/instant.md +20 -15
  16. data/docs/lunar_eclipses.md +93 -0
  17. data/docs/lunar_observation.md +87 -0
  18. data/docs/moon_phases.md +4 -1
  19. data/docs/observer.md +20 -6
  20. data/docs/planetary_phenomena.md +78 -0
  21. data/docs/reference_frames.md +192 -34
  22. data/docs/rise_transit_set_times.md +6 -4
  23. data/docs/solar_system_bodies.md +26 -4
  24. data/docs/twilight_times.md +25 -21
  25. data/lib/astronoby/angle.rb +63 -2
  26. data/lib/astronoby/angles/dms.rb +18 -1
  27. data/lib/astronoby/angles/hms.rb +14 -1
  28. data/lib/astronoby/angular_velocity.rb +21 -0
  29. data/lib/astronoby/bodies/deep_sky_object.rb +6 -1
  30. data/lib/astronoby/bodies/deep_sky_object_position.rb +32 -17
  31. data/lib/astronoby/bodies/earth.rb +7 -44
  32. data/lib/astronoby/bodies/jupiter.rb +10 -0
  33. data/lib/astronoby/bodies/mars.rb +10 -0
  34. data/lib/astronoby/bodies/mercury.rb +10 -0
  35. data/lib/astronoby/bodies/moon.rb +158 -32
  36. data/lib/astronoby/bodies/neptune.rb +10 -0
  37. data/lib/astronoby/bodies/saturn.rb +10 -0
  38. data/lib/astronoby/bodies/solar_system_body.rb +240 -61
  39. data/lib/astronoby/bodies/sun.rb +79 -4
  40. data/lib/astronoby/bodies/uranus.rb +10 -0
  41. data/lib/astronoby/bodies/venus.rb +10 -0
  42. data/lib/astronoby/body.rb +6 -0
  43. data/lib/astronoby/center.rb +84 -0
  44. data/lib/astronoby/constellation.rb +9 -1
  45. data/lib/astronoby/coordinates/ecliptic.rb +10 -1
  46. data/lib/astronoby/coordinates/equatorial.rb +64 -8
  47. data/lib/astronoby/coordinates/geodetic.rb +102 -0
  48. data/lib/astronoby/coordinates/horizontal.rb +13 -1
  49. data/lib/astronoby/distance.rb +35 -0
  50. data/lib/astronoby/duration.rb +116 -0
  51. data/lib/astronoby/earth_rotation.rb +70 -0
  52. data/lib/astronoby/equinox_solstice.rb +31 -8
  53. data/lib/astronoby/errors.rb +11 -0
  54. data/lib/astronoby/events/conjunction.rb +51 -0
  55. data/lib/astronoby/events/conjunction_opposition_calculator.rb +84 -0
  56. data/lib/astronoby/events/eclipse_phase.rb +27 -0
  57. data/lib/astronoby/events/extremum_calculator.rb +23 -176
  58. data/lib/astronoby/events/greatest_elongation.rb +58 -0
  59. data/lib/astronoby/events/greatest_elongation_calculator.rb +56 -0
  60. data/lib/astronoby/events/lunar_eclipse.rb +99 -0
  61. data/lib/astronoby/events/lunar_eclipse_calculator.rb +285 -0
  62. data/lib/astronoby/events/opposition.rb +19 -0
  63. data/lib/astronoby/events/rise_transit_set_event.rb +12 -1
  64. data/lib/astronoby/events/rise_transit_set_events.rb +12 -1
  65. data/lib/astronoby/events/twilight_event.rb +24 -6
  66. data/lib/astronoby/events/twilight_events.rb +26 -6
  67. data/lib/astronoby/extremum_finder.rb +148 -0
  68. data/lib/astronoby/instant.rb +10 -7
  69. data/lib/astronoby/libration.rb +25 -0
  70. data/lib/astronoby/mean_obliquity.rb +8 -0
  71. data/lib/astronoby/moon_orientation_ephemeris.rb +69 -0
  72. data/lib/astronoby/moon_physical_ephemeris.rb +263 -0
  73. data/lib/astronoby/nutation.rb +10 -20
  74. data/lib/astronoby/observer.rb +67 -49
  75. data/lib/astronoby/orientation.rb +107 -0
  76. data/lib/astronoby/position.rb +16 -0
  77. data/lib/astronoby/precession.rb +61 -60
  78. data/lib/astronoby/reference_frame.rb +73 -7
  79. data/lib/astronoby/reference_frames/apparent.rb +26 -7
  80. data/lib/astronoby/reference_frames/astrometric.rb +14 -1
  81. data/lib/astronoby/reference_frames/geometric.rb +7 -1
  82. data/lib/astronoby/reference_frames/mean_of_date.rb +13 -1
  83. data/lib/astronoby/reference_frames/teme.rb +153 -0
  84. data/lib/astronoby/reference_frames/topocentric.rb +30 -4
  85. data/lib/astronoby/refraction.rb +26 -5
  86. data/lib/astronoby/root_finder.rb +83 -0
  87. data/lib/astronoby/rotation.rb +49 -0
  88. data/lib/astronoby/time/greenwich_apparent_sidereal_time.rb +9 -0
  89. data/lib/astronoby/time/greenwich_mean_sidereal_time.rb +42 -5
  90. data/lib/astronoby/time/greenwich_sidereal_time.rb +21 -0
  91. data/lib/astronoby/time/local_apparent_sidereal_time.rb +21 -0
  92. data/lib/astronoby/time/local_mean_sidereal_time.rb +21 -0
  93. data/lib/astronoby/time/local_sidereal_time.rb +24 -0
  94. data/lib/astronoby/time/sidereal_time.rb +23 -1
  95. data/lib/astronoby/true_obliquity.rb +4 -0
  96. data/lib/astronoby/util/maths.rb +8 -0
  97. data/lib/astronoby/util/time.rb +10 -485
  98. data/lib/astronoby/vector.rb +10 -0
  99. data/lib/astronoby/velocity.rb +39 -0
  100. data/lib/astronoby/version.rb +1 -1
  101. data/lib/astronoby.rb +22 -0
  102. metadata +45 -5
@@ -1,6 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Astronoby
4
+ # Represents an angle with radians as its internal representation.
5
+ # Provides conversions between radians, degrees, hours, and sexagesimal
6
+ # formats (DMS and HMS), as well as trigonometric operations.
7
+ #
8
+ # @example Create an angle from degrees
9
+ # angle = Astronoby::Angle.from_degrees(180)
10
+ # angle.radians # => Math::PI
11
+ #
12
+ # @example Create an angle from hours, minutes, seconds
13
+ # angle = Astronoby::Angle.from_hms(12, 30, 0)
14
+ #
4
15
  class Angle
5
16
  include Comparable
6
17
 
@@ -8,29 +19,42 @@ module Astronoby
8
19
  FORMATS = %i[dms hms].freeze
9
20
 
10
21
  class << self
22
+ # @return [Astronoby::Angle] a zero angle
11
23
  def zero
12
24
  new(0)
13
25
  end
14
26
 
27
+ # @param radians [Numeric] the angle in radians
28
+ # @return [Astronoby::Angle] a new Angle, normalized to (-2π, 2π)
15
29
  def from_radians(radians)
16
30
  normalized_radians = radians.remainder(Constants::RADIANS_PER_CIRCLE)
17
31
  new(normalized_radians)
18
32
  end
19
33
 
34
+ # @param degrees [Numeric] the angle in degrees
35
+ # @return [Astronoby::Angle] a new Angle
20
36
  def from_degrees(degrees)
21
37
  radians = degrees / Constants::PI_IN_DEGREES * Math::PI
22
38
  from_radians(radians)
23
39
  end
24
40
 
41
+ # @param arcseconds [Numeric] the angle in arcseconds
42
+ # @return [Astronoby::Angle] a new Angle
25
43
  def from_degree_arcseconds(arcseconds)
26
44
  from_dms(0, 0, arcseconds)
27
45
  end
28
46
 
47
+ # @param hours [Numeric] the angle in hour-angle hours
48
+ # @return [Astronoby::Angle] a new Angle
29
49
  def from_hours(hours)
30
50
  radians = hours * Constants::RADIAN_PER_HOUR
31
51
  from_radians(radians)
32
52
  end
33
53
 
54
+ # @param hour [Numeric] hours component
55
+ # @param minute [Numeric] minutes component
56
+ # @param second [Numeric] seconds component
57
+ # @return [Astronoby::Angle] a new Angle
34
58
  def from_hms(hour, minute, second)
35
59
  hours = hour +
36
60
  minute / Constants::MINUTES_PER_HOUR +
@@ -38,89 +62,118 @@ module Astronoby
38
62
  from_hours(hours)
39
63
  end
40
64
 
65
+ # @param degree [Numeric] degrees component (sign determines overall sign)
66
+ # @param minute [Numeric] arcminutes component
67
+ # @param second [Numeric] arcseconds component
68
+ # @return [Astronoby::Angle] a new Angle
41
69
  def from_dms(degree, minute, second)
42
70
  sign = degree.negative? ? -1 : 1
43
71
  degrees = degree.abs +
44
- minute / Constants::MINUTES_PER_HOUR +
45
- second / Constants::SECONDS_PER_HOUR
72
+ minute / Constants::ARCMINUTES_PER_DEGREE +
73
+ second / Constants::ARCSECONDS_PER_DEGREE
46
74
  from_degrees(sign * degrees)
47
75
  end
48
76
 
77
+ # @param ratio [Numeric] the sine value (-1..1)
78
+ # @return [Astronoby::Angle] the arcsine
49
79
  def asin(ratio)
50
80
  radians = Math.asin(ratio)
51
81
  from_radians(radians)
52
82
  end
53
83
 
84
+ # @param ratio [Numeric] the cosine value (-1..1)
85
+ # @return [Astronoby::Angle] the arccosine
54
86
  def acos(ratio)
55
87
  radians = Math.acos(ratio)
56
88
  from_radians(radians)
57
89
  end
58
90
 
91
+ # @param ratio [Numeric] the tangent value
92
+ # @return [Astronoby::Angle] the arctangent
59
93
  def atan(ratio)
60
94
  radians = Math.atan(ratio)
61
95
  from_radians(radians)
62
96
  end
63
97
  end
64
98
 
99
+ # @return [Numeric] the angle in radians
65
100
  attr_reader :radians
66
101
 
102
+ # @param radians [Numeric] the angle in radians
67
103
  def initialize(radians)
68
104
  @radians = radians
69
105
  freeze
70
106
  end
71
107
 
108
+ # @return [Float] the angle in degrees
72
109
  def degrees
73
110
  @radians * Constants::PI_IN_DEGREES / Math::PI
74
111
  end
75
112
 
113
+ # @return [Float] the angle in milliarcseconds
76
114
  def degree_milliarcseconds
77
115
  degrees * Constants::MILLIARCSECONDS_PER_DEGREE
78
116
  end
79
117
 
118
+ # @return [Float] the angle in hour-angle hours
80
119
  def hours
81
120
  @radians / Constants::RADIAN_PER_HOUR
82
121
  end
83
122
 
123
+ # @param other [Astronoby::Angle] angle to add
124
+ # @return [Astronoby::Angle] the sum
84
125
  def +(other)
85
126
  self.class.from_radians(radians + other.radians)
86
127
  end
87
128
 
129
+ # @param other [Astronoby::Angle] angle to subtract
130
+ # @return [Astronoby::Angle] the difference
88
131
  def -(other)
89
132
  self.class.from_radians(@radians - other.radians)
90
133
  end
91
134
 
135
+ # @return [Astronoby::Angle] the negated angle
92
136
  def -@
93
137
  self.class.from_radians(-@radians)
94
138
  end
95
139
 
140
+ # @return [Float] the sine of the angle
96
141
  def sin
97
142
  Math.sin(radians)
98
143
  end
99
144
 
145
+ # @return [Float] the cosine of the angle
100
146
  def cos
101
147
  Math.cos(radians)
102
148
  end
103
149
 
150
+ # @return [Float] the tangent of the angle
104
151
  def tan
105
152
  Math.tan(radians)
106
153
  end
107
154
 
155
+ # @return [Boolean] true if the angle is positive
108
156
  def positive?
109
157
  radians > 0
110
158
  end
111
159
 
160
+ # @return [Boolean] true if the angle is negative
112
161
  def negative?
113
162
  radians < 0
114
163
  end
115
164
 
165
+ # @return [Boolean] true if the angle is zero
116
166
  def zero?
117
167
  radians.zero?
118
168
  end
119
169
 
170
+ # @return [Integer] hash value
120
171
  def hash
121
172
  [radians, self.class].hash
122
173
  end
123
174
 
175
+ # @param other [Astronoby::Angle] angle to compare with
176
+ # @return [Integer, nil] -1, 0, or 1; nil if not comparable
124
177
  def <=>(other)
125
178
  return unless other.is_a?(self.class)
126
179
 
@@ -128,6 +181,12 @@ module Astronoby
128
181
  end
129
182
  alias_method :eql?, :==
130
183
 
184
+ # Formats the angle as a string in the given format.
185
+ #
186
+ # @param format [Symbol] :dms or :hms
187
+ # @param precision [Integer] decimal places for seconds
188
+ # @return [String] the formatted angle
189
+ # @raise [Astronoby::UnsupportedFormatError] if format is not :dms or :hms
131
190
  def str(format, precision: 4)
132
191
  case format
133
192
  when :dms then to_dms.format(precision: precision)
@@ -139,6 +198,7 @@ module Astronoby
139
198
  end
140
199
  end
141
200
 
201
+ # @return [Astronoby::Dms] the angle in degrees, arcminutes, arcseconds
142
202
  def to_dms
143
203
  sign = degrees.negative? ? "-" : "+"
144
204
  absolute_degrees = degrees.abs
@@ -156,6 +216,7 @@ module Astronoby
156
216
  Dms.new(sign, deg, minutes, seconds)
157
217
  end
158
218
 
219
+ # @return [Astronoby::Hms] the angle in hours, minutes, seconds
159
220
  def to_hms
160
221
  absolute_hours = hours.abs
161
222
  hrs = absolute_hours.floor
@@ -1,9 +1,24 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Astronoby
4
+ # Represents an angle in degrees, arcminutes, arcseconds (DMS) notation.
4
5
  class Dms
5
- attr_reader :sign, :degrees, :minutes, :seconds
6
+ # @return [String] "+" or "-"
7
+ attr_reader :sign
6
8
 
9
+ # @return [Integer] degrees component
10
+ attr_reader :degrees
11
+
12
+ # @return [Integer] arcminutes component
13
+ attr_reader :minutes
14
+
15
+ # @return [Float] arcseconds component
16
+ attr_reader :seconds
17
+
18
+ # @param sign [String] "+" or "-"
19
+ # @param degrees [Integer] degrees component
20
+ # @param minutes [Integer] arcminutes component
21
+ # @param seconds [Float] arcseconds component
7
22
  def initialize(sign, degrees, minutes, seconds)
8
23
  @sign = sign
9
24
  @degrees = degrees
@@ -11,6 +26,8 @@ module Astronoby
11
26
  @seconds = seconds
12
27
  end
13
28
 
29
+ # @param precision [Integer] decimal places for the seconds component
30
+ # @return [String] the formatted DMS string (e.g., "+45° 30′ 15.0000″")
14
31
  def format(precision: 4)
15
32
  "#{sign}#{degrees}° #{minutes}′ #{seconds.floor(precision)}″"
16
33
  end
@@ -1,15 +1,28 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Astronoby
4
+ # Represents an angle in hours, minutes, seconds (HMS) notation.
4
5
  class Hms
5
- attr_reader :hours, :minutes, :seconds
6
+ # @return [Integer] hours component
7
+ attr_reader :hours
6
8
 
9
+ # @return [Integer] minutes component
10
+ attr_reader :minutes
11
+
12
+ # @return [Float] seconds component
13
+ attr_reader :seconds
14
+
15
+ # @param hours [Integer] hours component
16
+ # @param minutes [Integer] minutes component
17
+ # @param seconds [Float] seconds component
7
18
  def initialize(hours, minutes, seconds)
8
19
  @hours = hours
9
20
  @minutes = minutes
10
21
  @seconds = seconds
11
22
  end
12
23
 
24
+ # @param precision [Integer] decimal places for the seconds component
25
+ # @return [String] the formatted HMS string (e.g., "12h 30m 45.0000s")
13
26
  def format(precision: 4)
14
27
  "#{hours}h #{minutes}m #{seconds.floor(precision)}s"
15
28
  end
@@ -1,18 +1,25 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Astronoby
4
+ # Represents an angular velocity with radians per second as its internal
5
+ # representation. Used primarily for stellar proper motion.
4
6
  class AngularVelocity
5
7
  include Comparable
6
8
 
7
9
  class << self
10
+ # @return [Astronoby::AngularVelocity] a zero angular velocity
8
11
  def zero
9
12
  new(0)
10
13
  end
11
14
 
15
+ # @param radians_per_second [Numeric] the angular velocity in rad/s
16
+ # @return [Astronoby::AngularVelocity] a new AngularVelocity
12
17
  def from_radians_per_second(radians_per_second)
13
18
  new(radians_per_second)
14
19
  end
15
20
 
21
+ # @param mas_per_year [Numeric] the angular velocity in mas/yr
22
+ # @return [Astronoby::AngularVelocity] a new AngularVelocity
16
23
  def from_milliarcseconds_per_year(mas_per_year)
17
24
  angle = Angle.from_degree_arcseconds(mas_per_year / 1000.0)
18
25
  radians_per_second = angle.radians / Constants::SECONDS_PER_JULIAN_YEAR
@@ -20,52 +27,66 @@ module Astronoby
20
27
  end
21
28
  end
22
29
 
30
+ # @return [Numeric] the angular velocity in radians per second
23
31
  attr_reader :radians_per_second
24
32
  alias_method :rps, :radians_per_second
25
33
 
34
+ # @param radians_per_second [Numeric] the angular velocity in rad/s
26
35
  def initialize(radians_per_second)
27
36
  @radians_per_second = radians_per_second
28
37
  freeze
29
38
  end
30
39
 
40
+ # @return [Float] the angular velocity in milliarcseconds per year
31
41
  def milliarcseconds_per_year
32
42
  angle = Angle.from_radians(@radians_per_second)
33
43
  angle.degree_milliarcseconds * Constants::SECONDS_PER_JULIAN_YEAR
34
44
  end
35
45
  alias_method :mas_per_year, :milliarcseconds_per_year
36
46
 
47
+ # @param other [Astronoby::AngularVelocity] angular velocity to add
48
+ # @return [Astronoby::AngularVelocity] the sum
37
49
  def +(other)
38
50
  self.class.from_radians_per_second(
39
51
  @radians_per_second + other.radians_per_second
40
52
  )
41
53
  end
42
54
 
55
+ # @param other [Astronoby::AngularVelocity] angular velocity to subtract
56
+ # @return [Astronoby::AngularVelocity] the difference
43
57
  def -(other)
44
58
  self.class.from_radians_per_second(
45
59
  @radians_per_second - other.radians_per_second
46
60
  )
47
61
  end
48
62
 
63
+ # @return [Astronoby::AngularVelocity] the negated angular velocity
49
64
  def -@
50
65
  self.class.from_radians_per_second(-@radians_per_second)
51
66
  end
52
67
 
68
+ # @return [Boolean] true if the angular velocity is positive
53
69
  def positive?
54
70
  @radians_per_second > 0
55
71
  end
56
72
 
73
+ # @return [Boolean] true if the angular velocity is negative
57
74
  def negative?
58
75
  @radians_per_second < 0
59
76
  end
60
77
 
78
+ # @return [Boolean] true if the angular velocity is zero
61
79
  def zero?
62
80
  @radians_per_second.zero?
63
81
  end
64
82
 
83
+ # @return [Integer] hash value
65
84
  def hash
66
85
  [@radians_per_second, self.class].hash
67
86
  end
68
87
 
88
+ # @param other [Astronoby::AngularVelocity] angular velocity to compare with
89
+ # @return [Integer, nil] -1, 0, or 1; nil if not comparable
69
90
  def <=>(other)
70
91
  return unless other.is_a?(self.class)
71
92
 
@@ -1,7 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Astronoby
4
+ # Represents a deep-sky object (star, galaxy, nebula, etc.) with optional
5
+ # proper motion and parallax data.
4
6
  class DeepSkyObject
7
+ include Body
8
+
5
9
  # @param equatorial_coordinates [Astronoby::Coordinates::Equatorial]
6
10
  # Equatorial coordinates at epoch J2000.0
7
11
  # @param proper_motion_ra [Astronoby::AngularVelocity, nil] Proper motion in
@@ -37,7 +41,8 @@ module Astronoby
37
41
  proper_motion_ra: @proper_motion_ra,
38
42
  proper_motion_dec: @proper_motion_dec,
39
43
  parallax: @parallax,
40
- radial_velocity: @radial_velocity
44
+ radial_velocity: @radial_velocity,
45
+ deep_sky_object: self
41
46
  )
42
47
  end
43
48
  end
@@ -1,20 +1,33 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Astronoby
4
+ # Represents the computed position of a deep-sky object at a specific
5
+ # instant, providing astrometric, apparent, and topocentric reference frames.
4
6
  class DeepSkyObjectPosition
7
+ include Position
8
+
5
9
  DEFAULT_DISTANCE = Distance.from_parsecs(1e9)
6
10
 
7
- attr_reader :instant, :apparent
11
+ # @return [Astronoby::Instant] the time instant
12
+ attr_reader :instant
13
+
14
+ # @return [Astronoby::Apparent] the apparent reference frame
15
+ attr_reader :apparent
16
+
17
+ # @return [Astronoby::DeepSkyObject, nil] the body definition
18
+ attr_reader :body
8
19
 
9
20
  # @param instant [Astronoby::Instant] Instant of the observation
10
21
  # @param equatorial_coordinates [Astronoby::Coordinates::Equatorial]
11
22
  # Equatorial coordinates at epoch J2000.0
23
+ # @param ephem [::Ephem::SPK, nil] Ephemeris data source for Earth position
12
24
  # @param proper_motion_ra [Astronoby::AngularVelocity, nil] Proper motion in
13
25
  # right ascension
14
26
  # @param proper_motion_dec [Astronoby::AngularVelocity, nil] Proper motion
15
27
  # in declination
16
28
  # @param parallax [Astronoby::Angle, nil] Parallax angle
17
29
  # @param radial_velocity [Astronoby::Velocity, nil] Radial velocity
30
+ # @param deep_sky_object [Astronoby::DeepSkyObject, nil] the body definition
18
31
  def initialize(
19
32
  instant:,
20
33
  equatorial_coordinates:,
@@ -22,7 +35,8 @@ module Astronoby
22
35
  proper_motion_ra: nil,
23
36
  proper_motion_dec: nil,
24
37
  parallax: nil,
25
- radial_velocity: nil
38
+ radial_velocity: nil,
39
+ deep_sky_object: nil
26
40
  )
27
41
  @instant = instant
28
42
  @initial_equatorial_coordinates = equatorial_coordinates
@@ -30,6 +44,7 @@ module Astronoby
30
44
  @proper_motion_dec = proper_motion_dec
31
45
  @parallax = parallax
32
46
  @radial_velocity = radial_velocity
47
+ @body = deep_sky_object
33
48
  if ephem
34
49
  @earth_geometric = Earth.geometric(ephem: ephem, instant: @instant)
35
50
  end
@@ -42,24 +57,24 @@ module Astronoby
42
57
  instant: @instant,
43
58
  position: astrometric_position,
44
59
  velocity: astrometric_velocity,
45
- center_identifier: SolarSystemBody::EARTH,
46
- target_body: self
47
- )
48
- end
49
-
50
- def observed_by(observer)
51
- Topocentric.build_from_apparent(
52
- apparent: @apparent,
53
- observer: observer,
54
- instant: @instant,
55
- target_body: self
60
+ center: Center.geocentric,
61
+ target_body: body
56
62
  )
57
63
  end
58
64
 
59
65
  private
60
66
 
61
67
  def astrometric_position
62
- @astrometric_position ||= if use_stellar_propagation?
68
+ @astrometric_position ||=
69
+ if @earth_geometric
70
+ barycentric_position - @earth_geometric.position
71
+ else
72
+ barycentric_position
73
+ end
74
+ end
75
+
76
+ def barycentric_position
77
+ if use_stellar_propagation?
63
78
  stellar_propagation.position
64
79
  else
65
80
  astronomical_distance = DEFAULT_DISTANCE.meters
@@ -103,7 +118,7 @@ module Astronoby
103
118
  instant: @instant,
104
119
  target_astrometric: astrometric,
105
120
  earth_geometric: @earth_geometric,
106
- target_body: self
121
+ target_body: body
107
122
  )
108
123
  else
109
124
  precession_matrix = Precession.matrix_for(@instant)
@@ -118,8 +133,8 @@ module Astronoby
118
133
  position: corrected_position,
119
134
  velocity: corrected_velocity,
120
135
  instant: @instant,
121
- center_identifier: SolarSystemBody::EARTH,
122
- target_body: self
136
+ center: Center.geocentric,
137
+ target_body: body
123
138
  )
124
139
  end
125
140
  end
@@ -1,7 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Astronoby
4
+ # Represents the Earth. Provides ephemeris segments for computing Earth's
5
+ # geometric position.
4
6
  class Earth < SolarSystemBody
7
+ ORBITAL_PERIOD = 365.256
8
+
9
+ # @param ephem_source [Symbol] the ephemeris source type
10
+ # @return [Array<Array>] ephemeris segment identifiers
5
11
  def self.ephemeris_segments(ephem_source)
6
12
  if ephem_source == ::Ephem::SPK::JPL_DE
7
13
  [
@@ -15,52 +21,9 @@ module Astronoby
15
21
  end
16
22
  end
17
23
 
24
+ # @return [nil] Earth has no phase angle as seen from itself
18
25
  def phase_angle
19
26
  nil
20
27
  end
21
-
22
- private
23
-
24
- # Attributes that require Sun data like phase angle or magnitude are not
25
- # applicable for Earth.
26
- def requires_sun_data?
27
- true
28
- end
29
-
30
- def compute_astrometric(_ephem)
31
- Astrometric.new(
32
- position: Vector[
33
- Distance.zero,
34
- Distance.zero,
35
- Distance.zero
36
- ],
37
- velocity: Vector[
38
- Velocity.zero,
39
- Velocity.zero,
40
- Velocity.zero
41
- ],
42
- instant: @instant,
43
- center_identifier: EARTH,
44
- target_body: self.class
45
- )
46
- end
47
-
48
- def compute_mean_of_date(_ephem)
49
- MeanOfDate.new(
50
- position: Vector[
51
- Distance.zero,
52
- Distance.zero,
53
- Distance.zero
54
- ],
55
- velocity: Vector[
56
- Velocity.zero,
57
- Velocity.zero,
58
- Velocity.zero
59
- ],
60
- instant: @instant,
61
- center_identifier: EARTH,
62
- target_body: self.class
63
- )
64
- end
65
28
  end
66
29
  end
@@ -1,14 +1,24 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Astronoby
4
+ # Represents Jupiter.
4
5
  class Jupiter < SolarSystemBody
5
6
  EQUATORIAL_RADIUS = Distance.from_meters(71_492_000)
6
7
  ABSOLUTE_MAGNITUDE = -9.395
8
+ ORBITAL_PERIOD = 4332.59
7
9
 
10
+ # @return [Boolean] true; Jupiter is a superior planet
11
+ def self.superior_planet?
12
+ true
13
+ end
14
+
15
+ # @param _ephem_source [Symbol] the ephemeris source type
16
+ # @return [Array<Array>] ephemeris segment identifiers
8
17
  def self.ephemeris_segments(_ephem_source)
9
18
  [[SOLAR_SYSTEM_BARYCENTER, JUPITER_BARYCENTER]]
10
19
  end
11
20
 
21
+ # @return [Float] absolute magnitude
12
22
  def self.absolute_magnitude
13
23
  ABSOLUTE_MAGNITUDE
14
24
  end
@@ -1,14 +1,24 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Astronoby
4
+ # Represents Mars.
4
5
  class Mars < SolarSystemBody
5
6
  EQUATORIAL_RADIUS = Distance.from_meters(3_396_200)
6
7
  ABSOLUTE_MAGNITUDE = -1.601
8
+ ORBITAL_PERIOD = 686.98
7
9
 
10
+ # @return [Boolean] true; Mars is a superior planet
11
+ def self.superior_planet?
12
+ true
13
+ end
14
+
15
+ # @param _ephem_source [Symbol] the ephemeris source type
16
+ # @return [Array<Array>] ephemeris segment identifiers
8
17
  def self.ephemeris_segments(_ephem_source)
9
18
  [[SOLAR_SYSTEM_BARYCENTER, MARS_BARYCENTER]]
10
19
  end
11
20
 
21
+ # @return [Float] absolute magnitude
12
22
  def self.absolute_magnitude
13
23
  ABSOLUTE_MAGNITUDE
14
24
  end
@@ -1,14 +1,24 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Astronoby
4
+ # Represents Mercury.
4
5
  class Mercury < SolarSystemBody
5
6
  EQUATORIAL_RADIUS = Distance.from_meters(2_439_700)
6
7
  ABSOLUTE_MAGNITUDE = -0.613
8
+ ORBITAL_PERIOD = 87.969
7
9
 
10
+ # @return [Boolean] true; Mercury is an inferior planet
11
+ def self.inferior_planet?
12
+ true
13
+ end
14
+
15
+ # @param _ephem_source [Symbol] the ephemeris source type
16
+ # @return [Array<Array>] ephemeris segment identifiers
8
17
  def self.ephemeris_segments(_ephem_source)
9
18
  [[SOLAR_SYSTEM_BARYCENTER, MERCURY_BARYCENTER]]
10
19
  end
11
20
 
21
+ # @return [Float] absolute magnitude
12
22
  def self.absolute_magnitude
13
23
  ABSOLUTE_MAGNITUDE
14
24
  end