astronoby 0.8.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.
- checksums.yaml +4 -4
- data/.ruby-version +1 -1
- data/CHANGELOG.md +159 -0
- data/README.md +12 -5
- data/UPGRADING.md +109 -0
- data/docs/README.md +109 -16
- data/docs/angles.md +2 -1
- data/docs/configuration.md +20 -17
- data/docs/coordinates.md +73 -13
- data/docs/deep_sky_bodies.md +101 -0
- data/docs/ephem.md +6 -3
- data/docs/equinoxes_solstices_times.md +4 -3
- data/docs/glossary.md +97 -1
- data/docs/iers.md +40 -0
- data/docs/instant.md +21 -16
- data/docs/lunar_eclipses.md +93 -0
- data/docs/lunar_observation.md +87 -0
- data/docs/moon_phases.md +5 -2
- data/docs/observer.md +21 -7
- data/docs/planetary_phenomena.md +78 -0
- data/docs/reference_frames.md +193 -35
- data/docs/rise_transit_set_times.md +10 -8
- data/docs/{celestial_bodies.md → solar_system_bodies.md} +27 -5
- data/docs/twilight_times.md +25 -21
- data/lib/astronoby/angle.rb +69 -4
- data/lib/astronoby/angles/dms.rb +18 -1
- data/lib/astronoby/angles/hms.rb +14 -1
- data/lib/astronoby/angular_velocity.rb +97 -0
- data/lib/astronoby/bodies/deep_sky_object.rb +49 -0
- data/lib/astronoby/bodies/deep_sky_object_position.rb +142 -0
- data/lib/astronoby/bodies/earth.rb +9 -42
- data/lib/astronoby/bodies/jupiter.rb +10 -0
- data/lib/astronoby/bodies/mars.rb +10 -0
- data/lib/astronoby/bodies/mercury.rb +10 -0
- data/lib/astronoby/bodies/moon.rb +162 -15
- data/lib/astronoby/bodies/neptune.rb +10 -0
- data/lib/astronoby/bodies/saturn.rb +10 -0
- data/lib/astronoby/bodies/solar_system_body.rb +257 -53
- data/lib/astronoby/bodies/sun.rb +79 -4
- data/lib/astronoby/bodies/uranus.rb +10 -0
- data/lib/astronoby/bodies/venus.rb +10 -0
- data/lib/astronoby/body.rb +6 -0
- data/lib/astronoby/cache.rb +1 -0
- data/lib/astronoby/center.rb +84 -0
- data/lib/astronoby/constants.rb +7 -2
- data/lib/astronoby/constellation.rb +9 -1
- data/lib/astronoby/coordinates/ecliptic.rb +10 -1
- data/lib/astronoby/coordinates/equatorial.rb +66 -13
- data/lib/astronoby/coordinates/geodetic.rb +102 -0
- data/lib/astronoby/coordinates/horizontal.rb +13 -1
- data/lib/astronoby/distance.rb +41 -0
- data/lib/astronoby/duration.rb +116 -0
- data/lib/astronoby/earth_rotation.rb +70 -0
- data/lib/astronoby/equinox_solstice.rb +31 -8
- data/lib/astronoby/errors.rb +11 -0
- data/lib/astronoby/events/conjunction.rb +51 -0
- data/lib/astronoby/events/conjunction_opposition_calculator.rb +84 -0
- data/lib/astronoby/events/eclipse_phase.rb +27 -0
- data/lib/astronoby/events/extremum_calculator.rb +80 -0
- data/lib/astronoby/events/extremum_event.rb +15 -0
- data/lib/astronoby/events/greatest_elongation.rb +58 -0
- data/lib/astronoby/events/greatest_elongation_calculator.rb +56 -0
- data/lib/astronoby/events/lunar_eclipse.rb +99 -0
- data/lib/astronoby/events/lunar_eclipse_calculator.rb +285 -0
- data/lib/astronoby/events/opposition.rb +19 -0
- data/lib/astronoby/events/rise_transit_set_calculator.rb +9 -6
- data/lib/astronoby/events/rise_transit_set_event.rb +12 -1
- data/lib/astronoby/events/rise_transit_set_events.rb +12 -1
- data/lib/astronoby/events/twilight_calculator.rb +1 -1
- data/lib/astronoby/events/twilight_event.rb +24 -6
- data/lib/astronoby/events/twilight_events.rb +26 -6
- data/lib/astronoby/extremum_finder.rb +148 -0
- data/lib/astronoby/instant.rb +35 -9
- data/lib/astronoby/libration.rb +25 -0
- data/lib/astronoby/mean_obliquity.rb +8 -0
- data/lib/astronoby/moon_orientation_ephemeris.rb +69 -0
- data/lib/astronoby/moon_physical_ephemeris.rb +263 -0
- data/lib/astronoby/nutation.rb +10 -20
- data/lib/astronoby/observer.rb +67 -49
- data/lib/astronoby/orientation.rb +107 -0
- data/lib/astronoby/position.rb +16 -0
- data/lib/astronoby/precession.rb +61 -60
- data/lib/astronoby/reference_frame.rb +73 -7
- data/lib/astronoby/reference_frames/apparent.rb +25 -16
- data/lib/astronoby/reference_frames/astrometric.rb +14 -1
- data/lib/astronoby/reference_frames/geometric.rb +7 -1
- data/lib/astronoby/reference_frames/mean_of_date.rb +13 -1
- data/lib/astronoby/reference_frames/teme.rb +153 -0
- data/lib/astronoby/reference_frames/topocentric.rb +31 -5
- data/lib/astronoby/refraction.rb +26 -5
- data/lib/astronoby/root_finder.rb +83 -0
- data/lib/astronoby/rotation.rb +49 -0
- data/lib/astronoby/stellar_propagation.rb +162 -0
- data/lib/astronoby/time/greenwich_apparent_sidereal_time.rb +31 -0
- data/lib/astronoby/time/greenwich_mean_sidereal_time.rb +101 -0
- data/lib/astronoby/time/greenwich_sidereal_time.rb +41 -58
- data/lib/astronoby/time/local_apparent_sidereal_time.rb +63 -0
- data/lib/astronoby/time/local_mean_sidereal_time.rb +63 -0
- data/lib/astronoby/time/local_sidereal_time.rb +59 -26
- data/lib/astronoby/time/sidereal_time.rb +64 -0
- data/lib/astronoby/true_obliquity.rb +4 -0
- data/lib/astronoby/util/maths.rb +8 -0
- data/lib/astronoby/util/time.rb +10 -467
- data/lib/astronoby/vector.rb +10 -0
- data/lib/astronoby/velocity.rb +44 -0
- data/lib/astronoby/version.rb +1 -1
- data/lib/astronoby.rb +33 -0
- metadata +58 -6
|
@@ -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,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Astronoby
|
|
4
|
+
# Greenwich Apparent Sidereal Time (GAST). Derived from GMST by applying
|
|
5
|
+
# the equation of the equinoxes (nutation correction).
|
|
6
|
+
class GreenwichApparentSiderealTime < GreenwichSiderealTime
|
|
7
|
+
# Creates GAST from UTC by computing GMST and applying the equation
|
|
8
|
+
# of the equinoxes.
|
|
9
|
+
#
|
|
10
|
+
# @param utc [Time] the UTC time
|
|
11
|
+
# @return [Astronoby::GreenwichApparentSiderealTime]
|
|
12
|
+
def self.from_utc(utc)
|
|
13
|
+
gmst = GreenwichMeanSiderealTime.from_utc(utc)
|
|
14
|
+
instant = Instant.from_time(utc)
|
|
15
|
+
nutation = Nutation.new(instant: instant)
|
|
16
|
+
mean_obliquity = MeanObliquity.at(instant)
|
|
17
|
+
|
|
18
|
+
equation_of_equinoxes = nutation.nutation_in_longitude.hours *
|
|
19
|
+
mean_obliquity.cos
|
|
20
|
+
gast_time = normalize_time(gmst.time + equation_of_equinoxes)
|
|
21
|
+
|
|
22
|
+
new(date: gmst.date, time: gast_time)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# @param date [Date] the calendar date
|
|
26
|
+
# @param time [Numeric] GAST in hours
|
|
27
|
+
def initialize(date:, time:)
|
|
28
|
+
super(date: date, time: time, type: APPARENT)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "iers"
|
|
4
|
+
|
|
5
|
+
module Astronoby
|
|
6
|
+
# Greenwich Mean Sidereal Time (GMST). Computed from UTC using the IERS
|
|
7
|
+
# Conventions 2010 ERA-based expression, with a polynomial fallback for
|
|
8
|
+
# dates outside the IERS EOP data range.
|
|
9
|
+
class GreenwichMeanSiderealTime < GreenwichSiderealTime
|
|
10
|
+
JULIAN_CENTURIES_EXPONENTS = [
|
|
11
|
+
6.697374558,
|
|
12
|
+
2400.051336,
|
|
13
|
+
0.000025862
|
|
14
|
+
].freeze
|
|
15
|
+
|
|
16
|
+
SIDEREAL_MINUTE_IN_UT_MINUTE = 0.9972695663
|
|
17
|
+
|
|
18
|
+
UT_TO_SIDEREAL_RATIO = 1.002737909
|
|
19
|
+
|
|
20
|
+
# Creates GMST from UTC using the IERS Conventions 2010 ERA-based
|
|
21
|
+
# expression.
|
|
22
|
+
#
|
|
23
|
+
# Source:
|
|
24
|
+
# Title: IERS Conventions (2010)
|
|
25
|
+
# Chapter: 5.5.7 - ERA based expressions for Greenwich Sidereal Time
|
|
26
|
+
#
|
|
27
|
+
# @param utc [Time] the UTC time
|
|
28
|
+
# @return [Astronoby::GreenwichMeanSiderealTime]
|
|
29
|
+
def self.from_utc(utc)
|
|
30
|
+
date = utc.to_date
|
|
31
|
+
gmst_hours = begin
|
|
32
|
+
gmst_radians = IERS::GMST.at(utc)
|
|
33
|
+
gmst_radians * 12.0 / Math::PI
|
|
34
|
+
rescue IERS::OutOfRangeError
|
|
35
|
+
from_utc_polynomial(utc)
|
|
36
|
+
end
|
|
37
|
+
gmst_hours = normalize_time(gmst_hours)
|
|
38
|
+
|
|
39
|
+
new(date: date, time: gmst_hours)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Polynomial fallback for dates outside the IERS EOP data range.
|
|
43
|
+
#
|
|
44
|
+
# Source:
|
|
45
|
+
# Title: Practical Astronomy with your Calculator or Spreadsheet
|
|
46
|
+
# Authors: Peter Duffett-Smith and Jonathan Zwart
|
|
47
|
+
# Edition: Cambridge University Press
|
|
48
|
+
# Chapter: 12 - Conversion of UT to Greenwich sidereal time (GST)
|
|
49
|
+
#
|
|
50
|
+
# @param utc [Time] the UTC time
|
|
51
|
+
# @return [Numeric] GMST in hours
|
|
52
|
+
def self.from_utc_polynomial(utc)
|
|
53
|
+
julian_day = utc.to_date.ajd
|
|
54
|
+
t = (julian_day - JulianDate::J2000) / Constants::DAYS_PER_JULIAN_CENTURY
|
|
55
|
+
t0 = (
|
|
56
|
+
(JULIAN_CENTURIES_EXPONENTS[0] +
|
|
57
|
+
(JULIAN_CENTURIES_EXPONENTS[1] * t) +
|
|
58
|
+
(JULIAN_CENTURIES_EXPONENTS[2] * t * t)) % Constants::HOURS_PER_DAY
|
|
59
|
+
).abs
|
|
60
|
+
|
|
61
|
+
ut_in_hours = utc.hour +
|
|
62
|
+
utc.min / Constants::MINUTES_PER_HOUR +
|
|
63
|
+
(utc.sec + utc.subsec) / Constants::SECONDS_PER_HOUR
|
|
64
|
+
|
|
65
|
+
UT_TO_SIDEREAL_RATIO * ut_in_hours + t0
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# @param date [Date] the calendar date
|
|
69
|
+
# @param time [Numeric] GMST in hours
|
|
70
|
+
def initialize(date:, time:)
|
|
71
|
+
super(date: date, time: time, type: MEAN)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Converts GMST back to UTC.
|
|
75
|
+
#
|
|
76
|
+
# Source:
|
|
77
|
+
# Title: Practical Astronomy with your Calculator or Spreadsheet
|
|
78
|
+
# Authors: Peter Duffett-Smith and Jonathan Zwart
|
|
79
|
+
# Edition: Cambridge University Press
|
|
80
|
+
# Chapter: 13 - Conversion of GST to UT
|
|
81
|
+
#
|
|
82
|
+
# @return [Time] the UTC time
|
|
83
|
+
def to_utc
|
|
84
|
+
date = @date
|
|
85
|
+
julian_day = @date.ajd
|
|
86
|
+
t = (julian_day - JulianDate::J2000) / Constants::DAYS_PER_JULIAN_CENTURY
|
|
87
|
+
|
|
88
|
+
t0 = (
|
|
89
|
+
(JULIAN_CENTURIES_EXPONENTS[0] +
|
|
90
|
+
(JULIAN_CENTURIES_EXPONENTS[1] * t) +
|
|
91
|
+
(JULIAN_CENTURIES_EXPONENTS[2] * t * t)) % Constants::HOURS_PER_DAY
|
|
92
|
+
).abs
|
|
93
|
+
|
|
94
|
+
a = normalize_time(@time - t0)
|
|
95
|
+
|
|
96
|
+
utc = SIDEREAL_MINUTE_IN_UT_MINUTE * a
|
|
97
|
+
|
|
98
|
+
Util::Time.decimal_hour_to_time(date, 0, utc)
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
@@ -1,73 +1,56 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Astronoby
|
|
4
|
-
class
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
]
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
julian_day = utc.to_date.ajd
|
|
23
|
-
t = (julian_day - JulianDate::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
|
+
# Greenwich Sidereal Time base class. Dispatches to mean or apparent
|
|
5
|
+
# subclasses.
|
|
6
|
+
class GreenwichSiderealTime < SiderealTime
|
|
7
|
+
# Creates a Greenwich Sidereal Time from UTC.
|
|
8
|
+
#
|
|
9
|
+
# @param utc [Time] the UTC time
|
|
10
|
+
# @param type [Symbol] :mean or :apparent
|
|
11
|
+
# @return [Astronoby::GreenwichMeanSiderealTime,
|
|
12
|
+
# Astronoby::GreenwichApparentSiderealTime]
|
|
13
|
+
def self.from_utc(utc, type: MEAN)
|
|
14
|
+
validate_type!(type)
|
|
15
|
+
case type
|
|
16
|
+
when MEAN
|
|
17
|
+
GreenwichMeanSiderealTime.from_utc(utc)
|
|
18
|
+
when APPARENT
|
|
19
|
+
GreenwichApparentSiderealTime.from_utc(utc)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
37
22
|
|
|
38
|
-
|
|
23
|
+
# @param utc [Time] the UTC time
|
|
24
|
+
# @return [Astronoby::GreenwichMeanSiderealTime]
|
|
25
|
+
def self.mean_from_utc(utc)
|
|
26
|
+
GreenwichMeanSiderealTime.from_utc(utc)
|
|
39
27
|
end
|
|
40
28
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
29
|
+
# @param utc [Time] the UTC time
|
|
30
|
+
# @return [Astronoby::GreenwichApparentSiderealTime]
|
|
31
|
+
def self.apparent_from_utc(utc)
|
|
32
|
+
GreenwichApparentSiderealTime.from_utc(utc)
|
|
44
33
|
end
|
|
45
34
|
|
|
46
|
-
#
|
|
47
|
-
#
|
|
48
|
-
#
|
|
49
|
-
#
|
|
50
|
-
# Chapter: 13 - Conversion of GST to UT
|
|
35
|
+
# Converts to UTC.
|
|
36
|
+
#
|
|
37
|
+
# @return [Time] the UTC time
|
|
38
|
+
# @raise [NotImplementedError] if this is apparent sidereal time
|
|
51
39
|
def to_utc
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
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
|
|
40
|
+
unless mean?
|
|
41
|
+
raise NotImplementedError,
|
|
42
|
+
"UTC conversion only supported for mean sidereal time"
|
|
43
|
+
end
|
|
67
44
|
|
|
68
|
-
|
|
45
|
+
gmst = GreenwichMeanSiderealTime.new(date: @date, time: @time)
|
|
46
|
+
gmst.to_utc
|
|
69
47
|
end
|
|
70
48
|
|
|
49
|
+
# Converts to Local Sidereal Time for a given longitude.
|
|
50
|
+
#
|
|
51
|
+
# @param longitude [Astronoby::Angle] the observer's longitude
|
|
52
|
+
# @return [Astronoby::LocalMeanSiderealTime,
|
|
53
|
+
# Astronoby::LocalApparentSiderealTime]
|
|
71
54
|
def to_lst(longitude:)
|
|
72
55
|
LocalSiderealTime.from_gst(gst: self, longitude: longitude)
|
|
73
56
|
end
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Astronoby
|
|
4
|
+
# Local Apparent Sidereal Time (LAST). Derived from GAST by adding the
|
|
5
|
+
# observer's longitude.
|
|
6
|
+
class LocalApparentSiderealTime < LocalSiderealTime
|
|
7
|
+
# Creates LAST from a Greenwich Apparent Sidereal Time and longitude.
|
|
8
|
+
#
|
|
9
|
+
# Source:
|
|
10
|
+
# Title: Practical Astronomy with your Calculator or Spreadsheet
|
|
11
|
+
# Authors: Peter Duffett-Smith and Jonathan Zwart
|
|
12
|
+
# Edition: Cambridge University Press
|
|
13
|
+
# Chapter: 14 - Local sidereal time (LST)
|
|
14
|
+
#
|
|
15
|
+
# @param gst [Astronoby::GreenwichApparentSiderealTime] GAST
|
|
16
|
+
# @param longitude [Astronoby::Angle] the observer's longitude
|
|
17
|
+
# @return [Astronoby::LocalApparentSiderealTime]
|
|
18
|
+
# @raise [ArgumentError] if gst is not apparent sidereal time
|
|
19
|
+
def self.from_gst(gst:, longitude:)
|
|
20
|
+
unless gst.apparent?
|
|
21
|
+
raise ArgumentError, "GST must be apparent sidereal time"
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
date = gst.date
|
|
25
|
+
time = normalize_time(gst.time + longitude.hours)
|
|
26
|
+
|
|
27
|
+
new(date: date, time: time, longitude: longitude)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Creates LAST from UTC and longitude.
|
|
31
|
+
#
|
|
32
|
+
# @param utc [Time] the UTC time
|
|
33
|
+
# @param longitude [Astronoby::Angle] the observer's longitude
|
|
34
|
+
# @return [Astronoby::LocalApparentSiderealTime]
|
|
35
|
+
def self.from_utc(utc, longitude:)
|
|
36
|
+
gast = GreenwichApparentSiderealTime.from_utc(utc)
|
|
37
|
+
from_gst(gst: gast, longitude: longitude)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# @param date [Date] the calendar date
|
|
41
|
+
# @param time [Numeric] LAST in hours
|
|
42
|
+
# @param longitude [Astronoby::Angle] the observer's longitude
|
|
43
|
+
def initialize(date:, time:, longitude:)
|
|
44
|
+
super(date: date, time: time, longitude: longitude, type: APPARENT)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Converts to Greenwich Apparent Sidereal Time.
|
|
48
|
+
#
|
|
49
|
+
# Source:
|
|
50
|
+
# Title: Practical Astronomy with your Calculator or Spreadsheet
|
|
51
|
+
# Authors: Peter Duffett-Smith and Jonathan Zwart
|
|
52
|
+
# Edition: Cambridge University Press
|
|
53
|
+
# Chapter: 15 - Converting LST to GST
|
|
54
|
+
#
|
|
55
|
+
# @return [Astronoby::GreenwichApparentSiderealTime]
|
|
56
|
+
def to_gst
|
|
57
|
+
date = @date
|
|
58
|
+
time = normalize_time(@time - @longitude.hours)
|
|
59
|
+
|
|
60
|
+
GreenwichApparentSiderealTime.new(date: date, time: time)
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Astronoby
|
|
4
|
+
# Local Mean Sidereal Time (LMST). Derived from GMST by adding the
|
|
5
|
+
# observer's longitude.
|
|
6
|
+
class LocalMeanSiderealTime < LocalSiderealTime
|
|
7
|
+
# Creates LMST from a Greenwich Mean Sidereal Time and longitude.
|
|
8
|
+
#
|
|
9
|
+
# Source:
|
|
10
|
+
# Title: Practical Astronomy with your Calculator or Spreadsheet
|
|
11
|
+
# Authors: Peter Duffett-Smith and Jonathan Zwart
|
|
12
|
+
# Edition: Cambridge University Press
|
|
13
|
+
# Chapter: 14 - Local sidereal time (LST)
|
|
14
|
+
#
|
|
15
|
+
# @param gst [Astronoby::GreenwichMeanSiderealTime] GMST
|
|
16
|
+
# @param longitude [Astronoby::Angle] the observer's longitude
|
|
17
|
+
# @return [Astronoby::LocalMeanSiderealTime]
|
|
18
|
+
# @raise [ArgumentError] if gst is not mean sidereal time
|
|
19
|
+
def self.from_gst(gst:, longitude:)
|
|
20
|
+
unless gst.mean?
|
|
21
|
+
raise ArgumentError, "GST must be mean sidereal time"
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
date = gst.date
|
|
25
|
+
time = normalize_time(gst.time + longitude.hours)
|
|
26
|
+
|
|
27
|
+
new(date: date, time: time, longitude: longitude)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Creates LMST from UTC and longitude.
|
|
31
|
+
#
|
|
32
|
+
# @param utc [Time] the UTC time
|
|
33
|
+
# @param longitude [Astronoby::Angle] the observer's longitude
|
|
34
|
+
# @return [Astronoby::LocalMeanSiderealTime]
|
|
35
|
+
def self.from_utc(utc, longitude:)
|
|
36
|
+
gmst = GreenwichMeanSiderealTime.from_utc(utc)
|
|
37
|
+
from_gst(gst: gmst, longitude: longitude)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# @param date [Date] the calendar date
|
|
41
|
+
# @param time [Numeric] LMST in hours
|
|
42
|
+
# @param longitude [Astronoby::Angle] the observer's longitude
|
|
43
|
+
def initialize(date:, time:, longitude:)
|
|
44
|
+
super(date: date, time: time, longitude: longitude, type: MEAN)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Converts to Greenwich Mean Sidereal Time.
|
|
48
|
+
#
|
|
49
|
+
# Source:
|
|
50
|
+
# Title: Practical Astronomy with your Calculator or Spreadsheet
|
|
51
|
+
# Authors: Peter Duffett-Smith and Jonathan Zwart
|
|
52
|
+
# Edition: Cambridge University Press
|
|
53
|
+
# Chapter: 15 - Converting LST to GST
|
|
54
|
+
#
|
|
55
|
+
# @return [Astronoby::GreenwichMeanSiderealTime]
|
|
56
|
+
def to_gst
|
|
57
|
+
date = @date
|
|
58
|
+
time = normalize_time(@time - @longitude.hours)
|
|
59
|
+
|
|
60
|
+
GreenwichMeanSiderealTime.new(date: date, time: time)
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
@@ -1,41 +1,74 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Astronoby
|
|
4
|
-
class
|
|
5
|
-
|
|
4
|
+
# Local Sidereal Time base class. Dispatches to mean or apparent subclasses
|
|
5
|
+
# based on the type of the source GST.
|
|
6
|
+
class LocalSiderealTime < SiderealTime
|
|
7
|
+
# @return [Astronoby::Angle] the observer's longitude
|
|
8
|
+
attr_reader :longitude
|
|
6
9
|
|
|
7
|
-
#
|
|
8
|
-
#
|
|
9
|
-
#
|
|
10
|
-
#
|
|
11
|
-
#
|
|
10
|
+
# Creates an LST from a Greenwich Sidereal Time and longitude.
|
|
11
|
+
#
|
|
12
|
+
# @param gst [Astronoby::GreenwichSiderealTime] Greenwich Sidereal Time
|
|
13
|
+
# @param longitude [Astronoby::Angle] the observer's longitude
|
|
14
|
+
# @return [Astronoby::LocalMeanSiderealTime,
|
|
15
|
+
# Astronoby::LocalApparentSiderealTime]
|
|
12
16
|
def self.from_gst(gst:, longitude:)
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
+
case gst.type
|
|
18
|
+
when MEAN
|
|
19
|
+
LocalMeanSiderealTime.from_gst(gst: gst, longitude: longitude)
|
|
20
|
+
when APPARENT
|
|
21
|
+
LocalApparentSiderealTime.from_gst(gst: gst, longitude: longitude)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
17
24
|
|
|
18
|
-
|
|
25
|
+
# Creates an LST from UTC and longitude.
|
|
26
|
+
#
|
|
27
|
+
# @param utc [Time] the UTC time
|
|
28
|
+
# @param longitude [Astronoby::Angle] the observer's longitude
|
|
29
|
+
# @param type [Symbol] :mean or :apparent
|
|
30
|
+
# @return [Astronoby::LocalMeanSiderealTime,
|
|
31
|
+
# Astronoby::LocalApparentSiderealTime]
|
|
32
|
+
def self.from_utc(utc, longitude:, type: MEAN)
|
|
33
|
+
validate_type!(type)
|
|
34
|
+
case type
|
|
35
|
+
when MEAN
|
|
36
|
+
LocalMeanSiderealTime.from_utc(utc, longitude: longitude)
|
|
37
|
+
when APPARENT
|
|
38
|
+
LocalApparentSiderealTime.from_utc(utc, longitude: longitude)
|
|
39
|
+
end
|
|
19
40
|
end
|
|
20
41
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
42
|
+
# @param date [Date] the calendar date
|
|
43
|
+
# @param time [Numeric] the sidereal time in hours
|
|
44
|
+
# @param longitude [Astronoby::Angle] the observer's longitude
|
|
45
|
+
# @param type [Symbol] :mean or :apparent
|
|
46
|
+
def initialize(date:, time:, longitude:, type: MEAN)
|
|
47
|
+
super(date: date, time: time, type: type)
|
|
24
48
|
@longitude = longitude
|
|
25
49
|
end
|
|
26
50
|
|
|
27
|
-
#
|
|
28
|
-
#
|
|
29
|
-
#
|
|
30
|
-
#
|
|
31
|
-
# Chapter: 15 - Converting LST to GST
|
|
51
|
+
# Converts to Greenwich Sidereal Time.
|
|
52
|
+
#
|
|
53
|
+
# @return [Astronoby::GreenwichMeanSiderealTime,
|
|
54
|
+
# Astronoby::GreenwichApparentSiderealTime]
|
|
32
55
|
def to_gst
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
56
|
+
case @type
|
|
57
|
+
when MEAN
|
|
58
|
+
lst = LocalMeanSiderealTime.new(
|
|
59
|
+
date: @date,
|
|
60
|
+
time: @time,
|
|
61
|
+
longitude: @longitude
|
|
62
|
+
)
|
|
63
|
+
lst.to_gst
|
|
64
|
+
when APPARENT
|
|
65
|
+
last = LocalApparentSiderealTime.new(
|
|
66
|
+
date: @date,
|
|
67
|
+
time: @time,
|
|
68
|
+
longitude: @longitude
|
|
69
|
+
)
|
|
70
|
+
last.to_gst
|
|
71
|
+
end
|
|
39
72
|
end
|
|
40
73
|
end
|
|
41
74
|
end
|