astronoby 0.9.0 → 0.11.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 (116) hide show
  1. checksums.yaml +4 -4
  2. data/.ruby-version +1 -1
  3. data/CHANGELOG.md +235 -0
  4. data/README.md +19 -1
  5. data/UPGRADING.md +270 -0
  6. data/docs/README.md +105 -16
  7. data/docs/altitude_crossings.md +92 -0
  8. data/docs/angles.md +1 -0
  9. data/docs/configuration.md +28 -17
  10. data/docs/coordinates.md +72 -12
  11. data/docs/deep_sky_bodies.md +46 -1
  12. data/docs/ephem.md +5 -2
  13. data/docs/equinoxes_solstices_times.md +4 -3
  14. data/docs/glossary.md +99 -1
  15. data/docs/iers.md +40 -0
  16. data/docs/instant.md +33 -21
  17. data/docs/lunar_eclipses.md +208 -0
  18. data/docs/lunar_observation.md +87 -0
  19. data/docs/moon_phases.md +4 -1
  20. data/docs/observer.md +20 -6
  21. data/docs/planetary_phenomena.md +78 -0
  22. data/docs/reference_frames.md +192 -34
  23. data/docs/rise_transit_set_times.md +6 -4
  24. data/docs/solar_system_bodies.md +26 -4
  25. data/docs/twilight_times.md +43 -24
  26. data/lib/astronoby/angle.rb +63 -2
  27. data/lib/astronoby/angles/dms.rb +18 -1
  28. data/lib/astronoby/angles/hms.rb +14 -1
  29. data/lib/astronoby/angular_velocity.rb +21 -0
  30. data/lib/astronoby/bodies/deep_sky_object.rb +6 -1
  31. data/lib/astronoby/bodies/deep_sky_object_position.rb +35 -38
  32. data/lib/astronoby/bodies/earth.rb +7 -44
  33. data/lib/astronoby/bodies/jupiter.rb +10 -0
  34. data/lib/astronoby/bodies/mars.rb +10 -0
  35. data/lib/astronoby/bodies/mercury.rb +10 -0
  36. data/lib/astronoby/bodies/moon.rb +158 -32
  37. data/lib/astronoby/bodies/neptune.rb +10 -0
  38. data/lib/astronoby/bodies/saturn.rb +10 -0
  39. data/lib/astronoby/bodies/solar_system_body.rb +240 -61
  40. data/lib/astronoby/bodies/sun.rb +79 -4
  41. data/lib/astronoby/bodies/uranus.rb +10 -0
  42. data/lib/astronoby/bodies/venus.rb +10 -0
  43. data/lib/astronoby/body.rb +6 -0
  44. data/lib/astronoby/cache.rb +13 -0
  45. data/lib/astronoby/center.rb +84 -0
  46. data/lib/astronoby/constants.rb +1 -2
  47. data/lib/astronoby/constellation.rb +9 -1
  48. data/lib/astronoby/constellations/data.rb +1 -1
  49. data/lib/astronoby/coordinates/ecliptic.rb +10 -1
  50. data/lib/astronoby/coordinates/equatorial.rb +79 -13
  51. data/lib/astronoby/coordinates/geodetic.rb +102 -0
  52. data/lib/astronoby/coordinates/horizontal.rb +13 -1
  53. data/lib/astronoby/delta_t.rb +44 -0
  54. data/lib/astronoby/distance.rb +35 -0
  55. data/lib/astronoby/duration.rb +116 -0
  56. data/lib/astronoby/earth_rotation.rb +70 -0
  57. data/lib/astronoby/equinox_solstice.rb +31 -8
  58. data/lib/astronoby/errors.rb +11 -0
  59. data/lib/astronoby/events/altitude_crossing.rb +29 -0
  60. data/lib/astronoby/events/altitude_crossing_calculator.rb +511 -0
  61. data/lib/astronoby/events/altitude_extreme.rb +31 -0
  62. data/lib/astronoby/events/conjunction.rb +51 -0
  63. data/lib/astronoby/events/conjunction_opposition_calculator.rb +84 -0
  64. data/lib/astronoby/events/extremum_calculator.rb +23 -176
  65. data/lib/astronoby/events/greatest_elongation.rb +58 -0
  66. data/lib/astronoby/events/greatest_elongation_calculator.rb +56 -0
  67. data/lib/astronoby/events/lunar_eclipse.rb +111 -0
  68. data/lib/astronoby/events/lunar_eclipse_calculator.rb +397 -0
  69. data/lib/astronoby/events/lunar_eclipse_geometry.rb +115 -0
  70. data/lib/astronoby/events/lunar_eclipse_phase.rb +45 -0
  71. data/lib/astronoby/events/lunar_eclipse_visibility.rb +296 -0
  72. data/lib/astronoby/events/opposition.rb +19 -0
  73. data/lib/astronoby/events/rise_transit_set_calculator.rb +9 -13
  74. data/lib/astronoby/events/rise_transit_set_event.rb +12 -1
  75. data/lib/astronoby/events/rise_transit_set_events.rb +12 -1
  76. data/lib/astronoby/events/twilight_calculator.rb +37 -147
  77. data/lib/astronoby/events/twilight_event.rb +24 -6
  78. data/lib/astronoby/events/twilight_events.rb +26 -6
  79. data/lib/astronoby/extremum_finder.rb +148 -0
  80. data/lib/astronoby/horizon.rb +40 -0
  81. data/lib/astronoby/horizontal_transformation.rb +112 -0
  82. data/lib/astronoby/instant.rb +56 -16
  83. data/lib/astronoby/libration.rb +25 -0
  84. data/lib/astronoby/mean_obliquity.rb +8 -0
  85. data/lib/astronoby/moon_orientation_ephemeris.rb +69 -0
  86. data/lib/astronoby/moon_physical_ephemeris.rb +263 -0
  87. data/lib/astronoby/nutation.rb +10 -20
  88. data/lib/astronoby/observer.rb +67 -49
  89. data/lib/astronoby/orientation.rb +107 -0
  90. data/lib/astronoby/position.rb +16 -0
  91. data/lib/astronoby/precession.rb +62 -61
  92. data/lib/astronoby/reference_frame.rb +80 -9
  93. data/lib/astronoby/reference_frames/apparent.rb +43 -12
  94. data/lib/astronoby/reference_frames/astrometric.rb +14 -1
  95. data/lib/astronoby/reference_frames/geometric.rb +7 -1
  96. data/lib/astronoby/reference_frames/mean_of_date.rb +19 -1
  97. data/lib/astronoby/reference_frames/teme.rb +159 -0
  98. data/lib/astronoby/reference_frames/topocentric.rb +36 -4
  99. data/lib/astronoby/refraction.rb +26 -5
  100. data/lib/astronoby/root_finder.rb +90 -0
  101. data/lib/astronoby/rotation.rb +49 -0
  102. data/lib/astronoby/time/greenwich_apparent_sidereal_time.rb +19 -8
  103. data/lib/astronoby/time/greenwich_mean_sidereal_time.rb +44 -5
  104. data/lib/astronoby/time/greenwich_sidereal_time.rb +21 -0
  105. data/lib/astronoby/time/local_apparent_sidereal_time.rb +21 -0
  106. data/lib/astronoby/time/local_mean_sidereal_time.rb +21 -0
  107. data/lib/astronoby/time/local_sidereal_time.rb +24 -0
  108. data/lib/astronoby/time/sidereal_time.rb +23 -1
  109. data/lib/astronoby/true_obliquity.rb +4 -0
  110. data/lib/astronoby/util/maths.rb +8 -0
  111. data/lib/astronoby/util/time.rb +0 -497
  112. data/lib/astronoby/vector.rb +10 -0
  113. data/lib/astronoby/velocity.rb +39 -0
  114. data/lib/astronoby/version.rb +1 -1
  115. data/lib/astronoby.rb +30 -0
  116. metadata +80 -5
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Astronoby
4
+ # Computes Earth rotation matrices using Greenwich Sidereal Time.
5
+ # Provides both apparent (GAST-based) and mean (GMST-based) rotation
6
+ # matrices for transforming between Earth-fixed and celestial frames.
7
+ class EarthRotation
8
+ # Computes the apparent Earth rotation matrix R₃(GAST) for a given
9
+ # instant.
10
+ #
11
+ # @param instant [Astronoby::Instant] the time instant
12
+ # @return [Matrix] 3x3 Earth rotation matrix
13
+ def self.matrix_for(instant)
14
+ new(instant: instant).matrix
15
+ end
16
+
17
+ # Computes the mean Earth rotation matrix R₃(GMST) for a given
18
+ # instant.
19
+ #
20
+ # @param instant [Astronoby::Instant] the time instant
21
+ # @return [Matrix] 3x3 mean Earth rotation matrix
22
+ def self.mean_matrix_for(instant)
23
+ new(instant: instant).mean_matrix
24
+ end
25
+
26
+ # @param instant [Astronoby::Instant] the time instant
27
+ def initialize(instant:)
28
+ @instant = instant
29
+ end
30
+
31
+ # Computes R₃(GAST), the apparent Earth rotation matrix.
32
+ # GAST = GMST + equation of the equinoxes (Δψ cos ε₀).
33
+ #
34
+ # @return [Matrix] 3x3 rotation matrix
35
+ def matrix
36
+ rotation_matrix_for(gast)
37
+ end
38
+
39
+ # Computes R₃(GMST), the mean Earth rotation matrix.
40
+ #
41
+ # @return [Matrix] 3x3 rotation matrix
42
+ def mean_matrix
43
+ rotation_matrix_for(gmst)
44
+ end
45
+
46
+ private
47
+
48
+ def gmst
49
+ Angle.from_hours(@instant.gmst)
50
+ end
51
+
52
+ def gast
53
+ nutation = Nutation.new(instant: @instant)
54
+ dpsi = nutation.nutation_in_longitude
55
+ mean_obliquity = MeanObliquity.at(@instant)
56
+ Angle.from_radians(
57
+ gmst.radians + dpsi.radians * mean_obliquity.cos
58
+ )
59
+ end
60
+
61
+ def rotation_matrix_for(angle)
62
+ c, s = angle.cos, angle.sin
63
+ Matrix[
64
+ [c, -s, 0],
65
+ [s, c, 0],
66
+ [0, 0, 1]
67
+ ]
68
+ end
69
+ end
70
+ end
@@ -1,13 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Astronoby
4
+ # Computes the time of equinoxes and solstices for a given year.
5
+ #
6
+ # Source:
7
+ # Title: Astronomical Algorithms
8
+ # Author: Jean Meeus
9
+ # Edition: 2nd edition
10
+ # Chapter: 27 - Equinoxes and Soltices
4
11
  class EquinoxSolstice
5
- # Source:
6
- # Title: Astronomical Algorithms
7
- # Author: Jean Meeus
8
- # Edition: 2nd edition
9
- # Chapter: 27 - Equinoxes and Soltices
10
-
11
12
  EVENTS = [
12
13
  MARCH_EQUINOX = 0,
13
14
  JUNE_SOLSTICE = 1,
@@ -73,22 +74,39 @@ module Astronoby
73
74
  [8, 15.45, 16859.074]
74
75
  ].freeze
75
76
 
77
+ # @param year [Integer] the year
78
+ # @param ephem [::Ephem::SPK] ephemeris data source
79
+ # @return [Time] time of the March equinox
76
80
  def self.march_equinox(year, ephem)
77
81
  new(year, MARCH_EQUINOX, ephem).time
78
82
  end
79
83
 
84
+ # @param year [Integer] the year
85
+ # @param ephem [::Ephem::SPK] ephemeris data source
86
+ # @return [Time] time of the June solstice
80
87
  def self.june_solstice(year, ephem)
81
88
  new(year, JUNE_SOLSTICE, ephem).time
82
89
  end
83
90
 
91
+ # @param year [Integer] the year
92
+ # @param ephem [::Ephem::SPK] ephemeris data source
93
+ # @return [Time] time of the September equinox
84
94
  def self.september_equinox(year, ephem)
85
95
  new(year, SEPTEMBER_EQUINOX, ephem).time
86
96
  end
87
97
 
98
+ # @param year [Integer] the year
99
+ # @param ephem [::Ephem::SPK] ephemeris data source
100
+ # @return [Time] time of the December solstice
88
101
  def self.december_solstice(year, ephem)
89
102
  new(year, DECEMBER_SOLSTICE, ephem).time
90
103
  end
91
104
 
105
+ # @param year [Integer] the year
106
+ # @param event [Integer] one of MARCH_EQUINOX, JUNE_SOLSTICE,
107
+ # SEPTEMBER_EQUINOX, or DECEMBER_SOLSTICE
108
+ # @param ephem [::Ephem::SPK] ephemeris data source
109
+ # @raise [Astronoby::UnsupportedEventError] if event is invalid
92
110
  def initialize(year, event, ephem)
93
111
  unless EVENTS.include?(event)
94
112
  raise UnsupportedEventError.new(
@@ -97,12 +115,13 @@ module Astronoby
97
115
  end
98
116
 
99
117
  @event = event
118
+ @ephem = ephem
100
119
  @year = (year.to_i - 2000) / 1000.0
101
120
  uncorrected_time = compute
102
121
  @instant = Instant.from_time(uncorrected_time)
103
- @sun = Sun.new(ephem: ephem, instant: @instant)
104
122
  end
105
123
 
124
+ # @return [Time] the corrected UTC time of the event
106
125
  def time
107
126
  Instant.from_terrestrial_time(@instant.tt + corrected).to_time.round
108
127
  end
@@ -135,8 +154,12 @@ module Astronoby
135
154
  component[4] * @year**4
136
155
  end
137
156
 
157
+ def sun
158
+ @sun ||= Sun.new(ephem: @ephem, instant: @instant)
159
+ end
160
+
138
161
  def corrected
139
- longitude = @sun.apparent.ecliptic.longitude
162
+ longitude = sun.apparent.ecliptic.longitude
140
163
  58 * Angle.from_degrees(@event * 90 - longitude.degrees).sin
141
164
  end
142
165
  end
@@ -1,11 +1,22 @@
1
1
  module Astronoby
2
+ # Raised when arguments are mutually incompatible.
2
3
  class IncompatibleArgumentsError < ArgumentError; end
3
4
 
5
+ # Raised when an unsupported format is requested.
4
6
  class UnsupportedFormatError < ArgumentError; end
5
7
 
8
+ # Raised when an unsupported event type is requested.
6
9
  class UnsupportedEventError < ArgumentError; end
7
10
 
11
+ # Raised when an astronomical calculation fails.
8
12
  class CalculationError < StandardError; end
9
13
 
14
+ # Raised when there is an error with ephemeris data.
10
15
  class EphemerisError < StandardError; end
16
+
17
+ # Raised when an orientation kernel is not a supported orientation source.
18
+ class OrientationError < StandardError; end
19
+
20
+ # Raised when an orientation kernel does not cover the requested instant.
21
+ class OrientationOutOfRangeError < StandardError; end
11
22
  end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Astronoby
4
+ # A moment when a body's altitude passes through a given value.
5
+ class AltitudeCrossing
6
+ # @return [Astronoby::Instant] when the crossing happens, unrounded
7
+ attr_reader :instant
8
+
9
+ # @return [Symbol] +:rising+ when the altitude increases through the
10
+ # target, +:setting+ when it decreases
11
+ attr_reader :direction
12
+
13
+ # @param instant [Astronoby::Instant] when the crossing happens
14
+ # @param direction [Symbol] +:rising+ or +:setting+
15
+ # @param grazing [Boolean] whether the body only just reaches the target
16
+ def initialize(instant:, direction:, grazing: false)
17
+ @instant = instant
18
+ @direction = direction
19
+ @grazing = grazing
20
+ end
21
+
22
+ # @return [Boolean] true when the target is within a few hundredths of a
23
+ # degree of the body's highest or lowest altitude, so the crossing is
24
+ # nearly tangent and its instant is sensitive to small errors
25
+ def grazing?
26
+ @grazing
27
+ end
28
+ end
29
+ end