astronoby 0.7.0 → 0.9.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 (87) hide show
  1. checksums.yaml +4 -4
  2. data/.ruby-version +1 -1
  3. data/CHANGELOG.md +145 -3
  4. data/README.md +59 -33
  5. data/UPGRADING.md +75 -21
  6. data/docs/README.md +224 -0
  7. data/docs/angles.md +137 -0
  8. data/docs/configuration.md +98 -0
  9. data/docs/coordinates.md +167 -0
  10. data/docs/deep_sky_bodies.md +101 -0
  11. data/docs/ephem.md +85 -0
  12. data/docs/equinoxes_solstices_times.md +31 -0
  13. data/docs/glossary.md +152 -0
  14. data/docs/instant.md +139 -0
  15. data/docs/moon_phases.md +79 -0
  16. data/docs/observer.md +65 -0
  17. data/docs/reference_frames.md +138 -0
  18. data/docs/rise_transit_set_times.md +119 -0
  19. data/docs/solar_system_bodies.md +107 -0
  20. data/docs/twilight_times.md +123 -0
  21. data/lib/astronoby/angle.rb +6 -2
  22. data/lib/astronoby/angular_velocity.rb +76 -0
  23. data/lib/astronoby/bodies/deep_sky_object.rb +44 -0
  24. data/lib/astronoby/bodies/deep_sky_object_position.rb +127 -0
  25. data/lib/astronoby/bodies/earth.rb +12 -2
  26. data/lib/astronoby/bodies/jupiter.rb +17 -0
  27. data/lib/astronoby/bodies/mars.rb +17 -0
  28. data/lib/astronoby/bodies/mercury.rb +21 -0
  29. data/lib/astronoby/bodies/moon.rb +50 -36
  30. data/lib/astronoby/bodies/neptune.rb +21 -0
  31. data/lib/astronoby/bodies/saturn.rb +26 -0
  32. data/lib/astronoby/bodies/solar_system_body.rb +162 -27
  33. data/lib/astronoby/bodies/sun.rb +25 -2
  34. data/lib/astronoby/bodies/uranus.rb +5 -0
  35. data/lib/astronoby/bodies/venus.rb +25 -0
  36. data/lib/astronoby/cache.rb +189 -0
  37. data/lib/astronoby/configuration.rb +92 -0
  38. data/lib/astronoby/constants.rb +11 -3
  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/equatorial.rb +5 -8
  44. data/lib/astronoby/data/constellations/constellation_names.dat +88 -0
  45. data/lib/astronoby/data/constellations/indexed_abbreviations.dat +88 -0
  46. data/lib/astronoby/data/constellations/radec_to_index.dat +238 -0
  47. data/lib/astronoby/data/constellations/sorted_declinations.dat +202 -0
  48. data/lib/astronoby/data/constellations/sorted_right_ascensions.dat +237 -0
  49. data/lib/astronoby/distance.rb +6 -0
  50. data/lib/astronoby/equinox_solstice.rb +2 -2
  51. data/lib/astronoby/events/extremum_calculator.rb +233 -0
  52. data/lib/astronoby/events/extremum_event.rb +15 -0
  53. data/lib/astronoby/events/moon_phases.rb +15 -14
  54. data/lib/astronoby/events/rise_transit_set_calculator.rb +39 -12
  55. data/lib/astronoby/events/twilight_calculator.rb +116 -61
  56. data/lib/astronoby/events/twilight_events.rb +28 -0
  57. data/lib/astronoby/instant.rb +34 -6
  58. data/lib/astronoby/julian_date.rb +78 -0
  59. data/lib/astronoby/mean_obliquity.rb +8 -10
  60. data/lib/astronoby/nutation.rb +11 -3
  61. data/lib/astronoby/observer.rb +1 -1
  62. data/lib/astronoby/precession.rb +48 -38
  63. data/lib/astronoby/reference_frame.rb +2 -1
  64. data/lib/astronoby/reference_frames/apparent.rb +1 -11
  65. data/lib/astronoby/reference_frames/mean_of_date.rb +1 -1
  66. data/lib/astronoby/reference_frames/topocentric.rb +2 -12
  67. data/lib/astronoby/stellar_propagation.rb +162 -0
  68. data/lib/astronoby/time/greenwich_apparent_sidereal_time.rb +22 -0
  69. data/lib/astronoby/time/greenwich_mean_sidereal_time.rb +64 -0
  70. data/lib/astronoby/time/greenwich_sidereal_time.rb +20 -58
  71. data/lib/astronoby/time/local_apparent_sidereal_time.rb +42 -0
  72. data/lib/astronoby/time/local_mean_sidereal_time.rb +42 -0
  73. data/lib/astronoby/time/local_sidereal_time.rb +35 -26
  74. data/lib/astronoby/time/sidereal_time.rb +42 -0
  75. data/lib/astronoby/true_obliquity.rb +2 -3
  76. data/lib/astronoby/util/time.rb +62 -44
  77. data/lib/astronoby/velocity.rb +5 -0
  78. data/lib/astronoby/version.rb +1 -1
  79. data/lib/astronoby.rb +19 -1
  80. metadata +71 -11
  81. data/Gemfile +0 -5
  82. data/Gemfile.lock +0 -102
  83. data/benchmark/README.md +0 -131
  84. data/benchmark/benchmark.rb +0 -259
  85. data/benchmark/data/imcce.csv.zip +0 -0
  86. data/benchmark/data/sun_calc.csv.zip +0 -0
  87. data/lib/astronoby/epoch.rb +0 -22
@@ -16,41 +16,43 @@ module Astronoby
16
16
  # https://syrte.obspm.fr/iau2006/aa03_412_P03.pdf
17
17
  # P(t) = R3(χA) R1(−ωA) R3(−ψA) R1(ϵ0)
18
18
 
19
- # Precession in right ascension
20
- psi_a = ((((
21
- -0.0000000951 * t +
22
- +0.000132851) * t +
23
- -0.00114045) * t +
24
- -1.0790069) * t +
25
- +5038.481507) * t
26
-
27
- # Precession in declination
28
- omega_a = ((((
29
- +0.0000003337 * t +
30
- -0.000000467) * t +
31
- -0.00772503) * t +
32
- +0.0512623) * t +
33
- -0.025754) * t +
34
- eps0
35
-
36
- # Precession of the ecliptic
37
- chi_a = ((((
38
- -0.0000000560 * t +
39
- +0.000170663) * t +
40
- -0.00121197) * t +
41
- -2.3814292) * t +
42
- +10.556403) * t
43
-
44
- psi_a = Angle.from_degree_arcseconds(psi_a)
45
- omega_a = Angle.from_degree_arcseconds(omega_a)
46
- chi_a = Angle.from_degree_arcseconds(chi_a)
47
-
48
- r3_psi = rotation_z(-psi_a)
49
- r1_omega = rotation_x(-omega_a)
50
- r3_chi = rotation_z(chi_a)
51
- r1_eps0 = rotation_x(MeanObliquity.obliquity_of_reference)
52
-
53
- r3_chi * r1_omega * r3_psi * r1_eps0
19
+ cache.fetch(cache_key) do
20
+ # Precession in right ascension
21
+ psi_a = ((((
22
+ -0.0000000951 * t +
23
+ +0.000132851) * t +
24
+ -0.00114045) * t +
25
+ -1.0790069) * t +
26
+ +5038.481507) * t
27
+
28
+ # Precession in declination
29
+ omega_a = ((((
30
+ +0.0000003337 * t +
31
+ -0.000000467) * t +
32
+ -0.00772503) * t +
33
+ +0.0512623) * t +
34
+ -0.025754) * t +
35
+ eps0
36
+
37
+ # Precession of the ecliptic
38
+ chi_a = ((((
39
+ -0.0000000560 * t +
40
+ +0.000170663) * t +
41
+ -0.00121197) * t +
42
+ -2.3814292) * t +
43
+ +10.556403) * t
44
+
45
+ psi_a = Angle.from_degree_arcseconds(psi_a)
46
+ omega_a = Angle.from_degree_arcseconds(omega_a)
47
+ chi_a = Angle.from_degree_arcseconds(chi_a)
48
+
49
+ r3_psi = rotation_z(-psi_a)
50
+ r1_omega = rotation_x(-omega_a)
51
+ r3_chi = rotation_z(chi_a)
52
+ r1_eps0 = rotation_x(MeanObliquity.obliquity_of_reference)
53
+
54
+ r3_chi * r1_omega * r3_psi * r1_eps0
55
+ end
54
56
  end
55
57
 
56
58
  def rotation_x(angle)
@@ -106,7 +108,7 @@ module Astronoby
106
108
  end
107
109
 
108
110
  def self.matrix_for_epoch(epoch)
109
- t = (epoch - Epoch::DEFAULT_EPOCH) / Constants::DAYS_PER_JULIAN_CENTURY
111
+ t = (epoch - JulianDate::DEFAULT_EPOCH) / Constants::DAYS_PER_JULIAN_CENTURY
110
112
 
111
113
  zeta = Angle.from_degrees(
112
114
  0.6406161 * t + 0.0000839 * t * t + 0.000005 * t * t * t
@@ -146,15 +148,23 @@ module Astronoby
146
148
 
147
149
  private
148
150
 
151
+ def cache_key
152
+ @_cache_key ||= CacheKey.generate(:precession, @instant)
153
+ end
154
+
155
+ def cache
156
+ Astronoby.cache
157
+ end
158
+
149
159
  def t
150
160
  @t ||= Rational(
151
- @instant.tdb - Epoch::DEFAULT_EPOCH,
161
+ @instant.tdb - JulianDate::DEFAULT_EPOCH,
152
162
  Constants::DAYS_PER_JULIAN_CENTURY
153
163
  )
154
164
  end
155
165
 
156
166
  def eps0
157
- @eps0 ||= MeanObliquity.obliquity_of_reference_in_milliarcseconds
167
+ @eps0 ||= MeanObliquity.obliquity_of_reference_in_arcseconds
158
168
  end
159
169
  end
160
170
  end
@@ -34,7 +34,8 @@ module Astronoby
34
34
  @ecliptic ||= begin
35
35
  return Coordinates::Ecliptic.zero if distance.zero?
36
36
 
37
- equatorial.to_ecliptic(epoch: Epoch::J2000)
37
+ j2000 = Instant.from_terrestrial_time(JulianDate::J2000)
38
+ equatorial.to_ecliptic(instant: j2000)
38
39
  end
39
40
  end
40
41
 
@@ -43,17 +43,7 @@ module Astronoby
43
43
  @ecliptic ||= begin
44
44
  return Coordinates::Ecliptic.zero if distance.zero?
45
45
 
46
- equatorial.to_ecliptic(epoch: @instant.tdb)
47
- end
48
- end
49
-
50
- def angular_diameter
51
- @angular_radius ||= begin
52
- return Angle.zero if @position.zero?
53
-
54
- Angle.from_radians(
55
- Math.atan(@target_body.class::EQUATORIAL_RADIUS.m / distance.m) * 2
56
- )
46
+ equatorial.to_ecliptic(instant: @instant)
57
47
  end
58
48
  end
59
49
  end
@@ -31,7 +31,7 @@ module Astronoby
31
31
  @ecliptic ||= begin
32
32
  return Coordinates::Ecliptic.zero if distance.zero?
33
33
 
34
- equatorial.to_ecliptic(epoch: @instant.tdb)
34
+ equatorial.to_ecliptic(instant: @instant)
35
35
  end
36
36
  end
37
37
  end
@@ -14,7 +14,7 @@ module Astronoby
14
14
  matrix * observer.geocentric_position.map(&:m)
15
15
  )
16
16
  observer_velocity = Velocity.vector_from_mps(
17
- matrix * observer.geocentric_velocity.map(&:kmps)
17
+ matrix * observer.geocentric_velocity.map(&:mps)
18
18
  )
19
19
 
20
20
  position = apparent.position - observer_position
@@ -48,21 +48,11 @@ module Astronoby
48
48
  @observer = observer
49
49
  end
50
50
 
51
- def angular_diameter
52
- @angular_radius ||= begin
53
- return Angle.zero if @position.zero?
54
-
55
- Angle.from_radians(
56
- Math.atan(@target_body.class::EQUATORIAL_RADIUS.m / distance.m) * 2
57
- )
58
- end
59
- end
60
-
61
51
  def ecliptic
62
52
  @ecliptic ||= begin
63
53
  return Coordinates::Ecliptic.zero if distance.zero?
64
54
 
65
- equatorial.to_ecliptic(epoch: @instant.tdb)
55
+ equatorial.to_ecliptic(instant: @instant)
66
56
  end
67
57
  end
68
58
 
@@ -0,0 +1,162 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Astronoby
4
+ class StellarPropagation
5
+ # @return [Astronoby::Vector] Propagated position vector of
6
+ # Astronoby::Distance components
7
+ def self.position_for(**kwargs)
8
+ new(**kwargs).position
9
+ end
10
+
11
+ # @return [Astronoby::Vector] Propagated position vector of
12
+ # Astronoby::Velocity components
13
+ def self.velocity_vector_for(**kwargs)
14
+ new(**kwargs).velocity_vector
15
+ end
16
+
17
+ # @return [Astronoby::Coordinates::Equatorial] Propagated equatorial
18
+ # coordinates
19
+ def self.equatorial_coordinates_for(**kwargs)
20
+ new(**kwargs).equatorial_coordinates
21
+ end
22
+
23
+ # @param instant [Astronoby::Instant] Instant of the observation
24
+ # @param equatorial_coordinates [Astronoby::Coordinates::Equatorial]
25
+ # Equatorial coordinates at epoch J2000.0
26
+ # @param proper_motion_ra [Astronoby::AngularVelocity] Proper motion in
27
+ # right ascension
28
+ # @param proper_motion_dec [Astronoby::AngularVelocity] Proper motion in
29
+ # declination
30
+ # @param parallax [Astronoby::Angle] Parallax angle
31
+ # @param radial_velocity [Astronoby::Velocity] Radial velocity
32
+ # @param earth_geometric [Astronoby::ReferenceFrame::Geometric, nil]
33
+ # Geometric reference frame of the Earth
34
+ def initialize(
35
+ instant:,
36
+ equatorial_coordinates:,
37
+ proper_motion_ra:,
38
+ proper_motion_dec:,
39
+ parallax:,
40
+ radial_velocity:,
41
+ earth_geometric: nil
42
+ )
43
+ @instant = instant
44
+ @right_ascension = equatorial_coordinates.right_ascension
45
+ @declination = equatorial_coordinates.declination
46
+ @initial_epoch = equatorial_coordinates.epoch
47
+ @proper_motion_ra = proper_motion_ra
48
+ @proper_motion_dec = proper_motion_dec
49
+ @parallax = parallax
50
+ @radial_velocity = radial_velocity
51
+ @earth_geometric = earth_geometric
52
+ end
53
+
54
+ # @return [Astronoby::Vector] Propagated position vector of
55
+ # Astronoby::Distance components
56
+ def position
57
+ @position ||= Distance.vector_from_meters(
58
+ initial_position_vector +
59
+ tangential_velocity.map(&:mps) * time_elapsed_seconds
60
+ )
61
+ end
62
+
63
+ # @return [Astronoby::Vector] Propagated position vector of
64
+ # Astronoby::Velocity components
65
+ def velocity_vector
66
+ @velocity_vector ||= if @earth_geometric
67
+ @earth_geometric.velocity - tangential_velocity
68
+ else
69
+ tangential_velocity
70
+ end
71
+ end
72
+
73
+ # @return [Astronoby::Coordinates::Equatorial] Propagated equatorial
74
+ # coordinates
75
+ def equatorial_coordinates
76
+ @equatorial_coordinates ||= begin
77
+ right_ascension = Util::Trigonometry.adjustement_for_arctangent(
78
+ position.y.m,
79
+ position.x.m,
80
+ Angle.atan(position.y.m / position.x.m)
81
+ )
82
+ declination = Angle.asin(position.z.m / position.magnitude.m)
83
+
84
+ Coordinates::Equatorial.new(
85
+ right_ascension: right_ascension,
86
+ declination: declination,
87
+ epoch: @instant.tt
88
+ )
89
+ end
90
+ end
91
+
92
+ private
93
+
94
+ def distance
95
+ @distance ||= Distance.from_parsecs(
96
+ 1 / (@parallax.degrees * Constants::ARCSECONDS_PER_DEGREE)
97
+ )
98
+ end
99
+
100
+ def unit_position_vector
101
+ @unit_position_vector ||= Vector[
102
+ @right_ascension.cos * @declination.cos,
103
+ @right_ascension.sin * @declination.cos,
104
+ @declination.sin
105
+ ]
106
+ end
107
+
108
+ def right_ascension_unit_vector
109
+ @right_ascension_unit_vector ||= Vector[
110
+ -@right_ascension.sin,
111
+ @right_ascension.cos,
112
+ 0.0
113
+ ]
114
+ end
115
+
116
+ def declination_unit_vector
117
+ @declination_unit_vector ||= Vector[
118
+ -@right_ascension.cos * @declination.sin,
119
+ -@right_ascension.sin * @declination.sin,
120
+ @declination.cos
121
+ ]
122
+ end
123
+
124
+ def initial_position_vector
125
+ @initial_position_vector ||= unit_position_vector * distance.meters
126
+ end
127
+
128
+ def tangential_velocity
129
+ @tangential_velocity ||= begin
130
+ # Doppler factor for light travel time correction
131
+ k = 1.0 / (1.0 - @radial_velocity.kmps / Velocity.light_speed.kmps)
132
+
133
+ proper_motion_ra_component =
134
+ @proper_motion_ra.mas_per_year / (
135
+ @parallax.degree_milliarcseconds * Constants::DAYS_PER_JULIAN_YEAR
136
+ ) * k
137
+ proper_motion_dec_component =
138
+ @proper_motion_dec.mas_per_year / (
139
+ @parallax.degree_milliarcseconds * Constants::DAYS_PER_JULIAN_YEAR
140
+ ) * k
141
+ radial_velocity_component = Velocity
142
+ .from_kmps(@radial_velocity.kmps * k)
143
+
144
+ Velocity.vector_from_astronomical_units_per_day([
145
+ -proper_motion_ra_component * @right_ascension.sin -
146
+ proper_motion_dec_component * @declination.sin * @right_ascension.cos +
147
+ radial_velocity_component.aupd * @declination.cos * @right_ascension.cos,
148
+ proper_motion_ra_component * @right_ascension.cos -
149
+ proper_motion_dec_component * @declination.sin * @right_ascension.sin +
150
+ radial_velocity_component.aupd * @declination.cos * @right_ascension.sin,
151
+ proper_motion_dec_component * @declination.cos +
152
+ radial_velocity_component.aupd * @declination.sin
153
+ ])
154
+ end
155
+ end
156
+
157
+ def time_elapsed_seconds
158
+ @time_elapsed_seconds ||=
159
+ (@instant.tt - @initial_epoch) * Constants::SECONDS_PER_DAY
160
+ end
161
+ end
162
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Astronoby
4
+ class GreenwichApparentSiderealTime < GreenwichSiderealTime
5
+ def self.from_utc(utc)
6
+ gmst = GreenwichMeanSiderealTime.from_utc(utc)
7
+ instant = Instant.from_time(utc)
8
+ nutation = Nutation.new(instant: instant)
9
+ mean_obliquity = MeanObliquity.at(instant)
10
+
11
+ equation_of_equinoxes = nutation.nutation_in_longitude.hours *
12
+ mean_obliquity.cos
13
+ gast_time = normalize_time(gmst.time + equation_of_equinoxes)
14
+
15
+ new(date: gmst.date, time: gast_time)
16
+ end
17
+
18
+ def initialize(date:, time:)
19
+ super(date: date, time: time, type: APPARENT)
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Astronoby
4
+ class GreenwichMeanSiderealTime < GreenwichSiderealTime
5
+ JULIAN_CENTURIES_EXPONENTS = [
6
+ 6.697374558,
7
+ 2400.051336,
8
+ 0.000025862
9
+ ].freeze
10
+
11
+ SIDEREAL_MINUTE_IN_UT_MINUTE = 0.9972695663
12
+
13
+ # Source:
14
+ # Title: Practical Astronomy with your Calculator or Spreadsheet
15
+ # Authors: Peter Duffett-Smith and Jonathan Zwart
16
+ # Edition: Cambridge University Press
17
+ # Chapter: 12 - Conversion of UT to Greenwich sidereal time (GST)
18
+ def self.from_utc(utc)
19
+ date = utc.to_date
20
+ julian_day = utc.to_date.ajd
21
+ t = (julian_day - JulianDate::J2000) / Constants::DAYS_PER_JULIAN_CENTURY
22
+ t0 = (
23
+ (JULIAN_CENTURIES_EXPONENTS[0] +
24
+ (JULIAN_CENTURIES_EXPONENTS[1] * t) +
25
+ (JULIAN_CENTURIES_EXPONENTS[2] * t * t)) % Constants::HOURS_PER_DAY
26
+ ).abs
27
+
28
+ ut_in_hours = utc.hour +
29
+ utc.min / Constants::MINUTES_PER_HOUR +
30
+ (utc.sec + utc.subsec) / Constants::SECONDS_PER_HOUR
31
+
32
+ gmst = normalize_time(1.002737909 * ut_in_hours + t0)
33
+
34
+ new(date: date, time: gmst)
35
+ end
36
+
37
+ def initialize(date:, time:)
38
+ super(date: date, time: time, type: MEAN)
39
+ end
40
+
41
+ # Source:
42
+ # Title: Practical Astronomy with your Calculator or Spreadsheet
43
+ # Authors: Peter Duffett-Smith and Jonathan Zwart
44
+ # Edition: Cambridge University Press
45
+ # Chapter: 13 - Conversion of GST to UT
46
+ def to_utc
47
+ date = @date
48
+ julian_day = @date.ajd
49
+ t = (julian_day - JulianDate::J2000) / Constants::DAYS_PER_JULIAN_CENTURY
50
+
51
+ t0 = (
52
+ (JULIAN_CENTURIES_EXPONENTS[0] +
53
+ (JULIAN_CENTURIES_EXPONENTS[1] * t) +
54
+ (JULIAN_CENTURIES_EXPONENTS[2] * t * t)) % Constants::HOURS_PER_DAY
55
+ ).abs
56
+
57
+ a = normalize_time(@time - t0)
58
+
59
+ utc = SIDEREAL_MINUTE_IN_UT_MINUTE * a
60
+
61
+ Util::Time.decimal_hour_to_time(date, 0, utc)
62
+ end
63
+ end
64
+ end
@@ -1,71 +1,33 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Astronoby
4
- class GreenwichSiderealTime
5
- JULIAN_CENTURIES_EXPONENTS = [
6
- 6.697374558,
7
- 2400.051336,
8
- 0.000025862
9
- ].freeze
10
-
11
- SIDEREAL_MINUTE_IN_UT_MINUTE = 0.9972695663
12
-
13
- attr_reader :date, :time
14
-
15
- # Source:
16
- # Title: Practical Astronomy with your Calculator or Spreadsheet
17
- # Authors: Peter Duffett-Smith and Jonathan Zwart
18
- # Edition: Cambridge University Press
19
- # Chapter: 12 - Conversion of UT to Greenwich sidereal time (GST)
20
- def self.from_utc(utc)
21
- date = utc.to_date
22
- julian_day = utc.to_date.ajd
23
- t = (julian_day - Epoch::J2000) / Constants::DAYS_PER_JULIAN_CENTURY
24
- t0 = (
25
- (JULIAN_CENTURIES_EXPONENTS[0] +
26
- (JULIAN_CENTURIES_EXPONENTS[1] * t) +
27
- (JULIAN_CENTURIES_EXPONENTS[2] * t * t)) % Constants::HOURS_PER_DAY
28
- ).abs
29
-
30
- ut_in_hours = utc.hour +
31
- utc.min / Constants::MINUTES_PER_HOUR +
32
- (utc.sec + utc.subsec) / Constants::SECONDS_PER_HOUR
33
-
34
- gmst = 1.002737909 * ut_in_hours + t0
35
- gmst += Constants::HOURS_PER_DAY if gmst.negative?
36
- gmst -= Constants::HOURS_PER_DAY if gmst > Constants::HOURS_PER_DAY
4
+ class GreenwichSiderealTime < SiderealTime
5
+ def self.from_utc(utc, type: MEAN)
6
+ validate_type!(type)
7
+ case type
8
+ when MEAN
9
+ GreenwichMeanSiderealTime.from_utc(utc)
10
+ when APPARENT
11
+ GreenwichApparentSiderealTime.from_utc(utc)
12
+ end
13
+ end
37
14
 
38
- new(date: date, time: gmst)
15
+ def self.mean_from_utc(utc)
16
+ GreenwichMeanSiderealTime.from_utc(utc)
39
17
  end
40
18
 
41
- def initialize(date:, time:)
42
- @date = date
43
- @time = time
19
+ def self.apparent_from_utc(utc)
20
+ GreenwichApparentSiderealTime.from_utc(utc)
44
21
  end
45
22
 
46
- # Source:
47
- # Title: Practical Astronomy with your Calculator or Spreadsheet
48
- # Authors: Peter Duffett-Smith and Jonathan Zwart
49
- # Edition: Cambridge University Press
50
- # Chapter: 13 - Conversion of GST to UT
51
23
  def to_utc
52
- date = @date
53
- julian_day = @date.ajd
54
- t = (julian_day - Epoch::J2000) / Constants::DAYS_PER_JULIAN_CENTURY
55
-
56
- t0 = (
57
- (JULIAN_CENTURIES_EXPONENTS[0] +
58
- (JULIAN_CENTURIES_EXPONENTS[1] * t) +
59
- (JULIAN_CENTURIES_EXPONENTS[2] * t * t)) % Constants::HOURS_PER_DAY
60
- ).abs
61
-
62
- a = @time - t0
63
- a += Constants::HOURS_PER_DAY if a.negative?
64
- a -= Constants::HOURS_PER_DAY if a > Constants::HOURS_PER_DAY
65
-
66
- utc = SIDEREAL_MINUTE_IN_UT_MINUTE * a
24
+ unless mean?
25
+ raise NotImplementedError,
26
+ "UTC conversion only supported for mean sidereal time"
27
+ end
67
28
 
68
- Util::Time.decimal_hour_to_time(date, 0, utc)
29
+ gmst = GreenwichMeanSiderealTime.new(date: @date, time: @time)
30
+ gmst.to_utc
69
31
  end
70
32
 
71
33
  def to_lst(longitude:)
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Astronoby
4
+ class LocalApparentSiderealTime < LocalSiderealTime
5
+ # Source:
6
+ # Title: Practical Astronomy with your Calculator or Spreadsheet
7
+ # Authors: Peter Duffett-Smith and Jonathan Zwart
8
+ # Edition: Cambridge University Press
9
+ # Chapter: 14 - Local sidereal time (LST)
10
+ def self.from_gst(gst:, longitude:)
11
+ unless gst.apparent?
12
+ raise ArgumentError, "GST must be apparent sidereal time"
13
+ end
14
+
15
+ date = gst.date
16
+ time = normalize_time(gst.time + longitude.hours)
17
+
18
+ new(date: date, time: time, longitude: longitude)
19
+ end
20
+
21
+ def self.from_utc(utc, longitude:)
22
+ gast = GreenwichApparentSiderealTime.from_utc(utc)
23
+ from_gst(gst: gast, longitude: longitude)
24
+ end
25
+
26
+ def initialize(date:, time:, longitude:)
27
+ super(date: date, time: time, longitude: longitude, type: APPARENT)
28
+ end
29
+
30
+ # Source:
31
+ # Title: Practical Astronomy with your Calculator or Spreadsheet
32
+ # Authors: Peter Duffett-Smith and Jonathan Zwart
33
+ # Edition: Cambridge University Press
34
+ # Chapter: 15 - Converting LST to GST
35
+ def to_gst
36
+ date = @date
37
+ time = normalize_time(@time - @longitude.hours)
38
+
39
+ GreenwichApparentSiderealTime.new(date: date, time: time)
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Astronoby
4
+ class LocalMeanSiderealTime < LocalSiderealTime
5
+ # Source:
6
+ # Title: Practical Astronomy with your Calculator or Spreadsheet
7
+ # Authors: Peter Duffett-Smith and Jonathan Zwart
8
+ # Edition: Cambridge University Press
9
+ # Chapter: 14 - Local sidereal time (LST)
10
+ def self.from_gst(gst:, longitude:)
11
+ unless gst.mean?
12
+ raise ArgumentError, "GST must be mean sidereal time"
13
+ end
14
+
15
+ date = gst.date
16
+ time = normalize_time(gst.time + longitude.hours)
17
+
18
+ new(date: date, time: time, longitude: longitude)
19
+ end
20
+
21
+ def self.from_utc(utc, longitude:)
22
+ gmst = GreenwichMeanSiderealTime.from_utc(utc)
23
+ from_gst(gst: gmst, longitude: longitude)
24
+ end
25
+
26
+ def initialize(date:, time:, longitude:)
27
+ super(date: date, time: time, longitude: longitude, type: MEAN)
28
+ end
29
+
30
+ # Source:
31
+ # Title: Practical Astronomy with your Calculator or Spreadsheet
32
+ # Authors: Peter Duffett-Smith and Jonathan Zwart
33
+ # Edition: Cambridge University Press
34
+ # Chapter: 15 - Converting LST to GST
35
+ def to_gst
36
+ date = @date
37
+ time = normalize_time(@time - @longitude.hours)
38
+
39
+ GreenwichMeanSiderealTime.new(date: date, time: time)
40
+ end
41
+ end
42
+ end