astronoby 0.10.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 (45) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +134 -0
  3. data/README.md +13 -0
  4. data/UPGRADING.md +186 -0
  5. data/docs/README.md +32 -8
  6. data/docs/altitude_crossings.md +92 -0
  7. data/docs/configuration.md +8 -0
  8. data/docs/deep_sky_bodies.md +45 -0
  9. data/docs/glossary.md +2 -0
  10. data/docs/instant.md +14 -7
  11. data/docs/lunar_eclipses.md +128 -13
  12. data/docs/twilight_times.md +26 -11
  13. data/lib/astronoby/bodies/deep_sky_object_position.rb +6 -24
  14. data/lib/astronoby/cache.rb +13 -0
  15. data/lib/astronoby/constants.rb +1 -2
  16. data/lib/astronoby/constellations/data.rb +1 -1
  17. data/lib/astronoby/coordinates/equatorial.rb +15 -5
  18. data/lib/astronoby/delta_t.rb +44 -0
  19. data/lib/astronoby/events/altitude_crossing.rb +29 -0
  20. data/lib/astronoby/events/altitude_crossing_calculator.rb +511 -0
  21. data/lib/astronoby/events/altitude_extreme.rb +31 -0
  22. data/lib/astronoby/events/lunar_eclipse.rb +49 -37
  23. data/lib/astronoby/events/lunar_eclipse_calculator.rb +143 -31
  24. data/lib/astronoby/events/lunar_eclipse_geometry.rb +115 -0
  25. data/lib/astronoby/events/lunar_eclipse_phase.rb +45 -0
  26. data/lib/astronoby/events/lunar_eclipse_visibility.rb +296 -0
  27. data/lib/astronoby/events/rise_transit_set_calculator.rb +9 -13
  28. data/lib/astronoby/events/twilight_calculator.rb +37 -147
  29. data/lib/astronoby/horizon.rb +40 -0
  30. data/lib/astronoby/horizontal_transformation.rb +112 -0
  31. data/lib/astronoby/instant.rb +50 -13
  32. data/lib/astronoby/precession.rb +1 -1
  33. data/lib/astronoby/reference_frame.rb +8 -3
  34. data/lib/astronoby/reference_frames/apparent.rb +20 -8
  35. data/lib/astronoby/reference_frames/mean_of_date.rb +6 -0
  36. data/lib/astronoby/reference_frames/teme.rb +6 -0
  37. data/lib/astronoby/reference_frames/topocentric.rb +6 -0
  38. data/lib/astronoby/root_finder.rb +16 -9
  39. data/lib/astronoby/time/greenwich_apparent_sidereal_time.rb +10 -8
  40. data/lib/astronoby/time/greenwich_mean_sidereal_time.rb +11 -9
  41. data/lib/astronoby/util/time.rb +0 -22
  42. data/lib/astronoby/version.rb +1 -1
  43. data/lib/astronoby.rb +9 -1
  44. metadata +40 -5
  45. data/lib/astronoby/events/eclipse_phase.rb +0 -27
@@ -0,0 +1,112 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Astronoby
4
+ # Transforms equatorial coordinates at J2000.0 into horizontal coordinates
5
+ # for one observer at one instant.
6
+ #
7
+ # Everything that depends only on the observer and the instant is computed
8
+ # once at construction: the rotation from the ICRS to the true equator and
9
+ # equinox of date (nutation * precession, with the ICRS frame bias), and the
10
+ # local apparent sidereal time. Converting a point then costs a matrix
11
+ # product and a few trigonometric functions, instead of rebuilding the
12
+ # reference frame chain for each point. It is meant for converting many
13
+ # points for the same observer and instant, such as the stars of a catalogue
14
+ # for a sky chart.
15
+ #
16
+ # It plays the role of the "star-independent astrometry parameters" of SOFA
17
+ # and ERFA, restricted to what Astronoby applies without an ephemeris. The
18
+ # result is the same as
19
+ # `DeepSkyObject#at(instant).observed_by(observer).horizontal`, but the
20
+ # points are treated as fixed directions: no aberration, no proper motion and
21
+ # no parallax. The topocentric correction is not applied either, as it is
22
+ # nil for objects at stellar distances. Atmospheric refraction is optional.
23
+ #
24
+ # @example Convert the stars of a catalogue for one observer and instant
25
+ # transformation = Astronoby::HorizontalTransformation.new(
26
+ # observer: observer,
27
+ # instant: instant
28
+ # )
29
+ # horizontals = catalogue.map { |star| transformation.apply(star) }
30
+ class HorizontalTransformation
31
+ # @return [Astronoby::Observer] the observer
32
+ attr_reader :observer
33
+
34
+ # @return [Astronoby::Instant] the instant
35
+ attr_reader :instant
36
+
37
+ # @param observer [Astronoby::Observer] the observer
38
+ # @param instant [Astronoby::Instant] the instant of the observation
39
+ def initialize(observer:, instant:)
40
+ @observer = observer
41
+ @instant = instant
42
+ @rotation_rows = (
43
+ Nutation.matrix_for(instant) * Precession.matrix_for(instant)
44
+ ).to_a.freeze
45
+ @local_apparent_sidereal_time = LocalApparentSiderealTime.from_utc(
46
+ instant.to_time,
47
+ longitude: observer.longitude
48
+ ).time
49
+ freeze
50
+ end
51
+
52
+ # @param equatorial_coordinates [Astronoby::Coordinates::Equatorial]
53
+ # equatorial coordinates at epoch J2000.0
54
+ # @param refraction [Boolean] whether to apply atmospheric refraction
55
+ # correction (default: false)
56
+ # @return [Astronoby::Coordinates::Horizontal] horizontal coordinates
57
+ # @raise [Astronoby::IncompatibleArgumentsError] if the coordinates are not
58
+ # referred to epoch J2000.0
59
+ def apply(equatorial_coordinates, refraction: false)
60
+ ensure_j2000!(equatorial_coordinates)
61
+
62
+ horizontal = apparent_equatorial(equatorial_coordinates).to_horizontal(
63
+ time: @instant.to_time,
64
+ observer: @observer
65
+ )
66
+
67
+ if refraction
68
+ Refraction.correct_horizontal_coordinates(coordinates: horizontal)
69
+ else
70
+ horizontal
71
+ end
72
+ end
73
+
74
+ private
75
+
76
+ # Equatorial coordinates of date, with the hour angle already known so that
77
+ # the sidereal time is not computed again.
78
+ def apparent_equatorial(coordinates)
79
+ declination = coordinates.declination
80
+ right_ascension = coordinates.right_ascension
81
+ cos_declination = declination.cos
82
+ x = cos_declination * right_ascension.cos
83
+ y = cos_declination * right_ascension.sin
84
+ z = declination.sin
85
+
86
+ row_x, row_y, row_z = @rotation_rows
87
+ apparent_x = row_x[0] * x + row_x[1] * y + row_x[2] * z
88
+ apparent_y = row_y[0] * x + row_y[1] * y + row_y[2] * z
89
+ apparent_z = row_z[0] * x + row_z[1] * y + row_z[2] * z
90
+
91
+ apparent_right_ascension =
92
+ Angle.from_radians(Math.atan2(apparent_y, apparent_x))
93
+
94
+ Coordinates::Equatorial.new(
95
+ right_ascension: apparent_right_ascension,
96
+ declination: Angle.asin(apparent_z.clamp(-1.0, 1.0)),
97
+ hour_angle:
98
+ Angle.from_hours(@local_apparent_sidereal_time) -
99
+ apparent_right_ascension,
100
+ epoch: @instant.tt
101
+ )
102
+ end
103
+
104
+ def ensure_j2000!(coordinates)
105
+ return if coordinates.epoch == JulianDate::J2000
106
+
107
+ raise IncompatibleArgumentsError,
108
+ "Expected equatorial coordinates at epoch J2000.0, got epoch " \
109
+ "#{coordinates.epoch}"
110
+ end
111
+ end
112
+ end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "date"
4
+ require "horologium"
4
5
 
5
6
  module Astronoby
6
7
  # Represents a specific instant in time using Terrestrial Time (TT) as its
@@ -8,9 +9,15 @@ module Astronoby
8
9
  # time scales commonly used in astronomy:
9
10
  # - Terrestrial Time (TT)
10
11
  # - International Atomic Time (TAI)
12
+ # - Barycentric Dynamical Time (TDB)
11
13
  # - Universal Time Coordinated (UTC)
12
14
  # - Greenwich Mean Sidereal Time (GMST)
13
15
  #
16
+ # TAI and TDB are delegated to the horologium gem, which owns the scales
17
+ # that convert by definition or by model. UT1 is not: it rests on
18
+ # observations of the rotation of the Earth, and comes from
19
+ # {Astronoby::DeltaT}.
20
+ #
14
21
  # @example Create an instant from the current time
15
22
  # instant = Astronoby::Instant.from_time(Time.now)
16
23
  # instant.tai # Get International Atomic Time
@@ -28,6 +35,16 @@ module Astronoby
28
35
  # midnight. This constant adds 0.5 days (12 hours) to make the conversion.
29
36
  DATETIME_JD_EPOCH_ADJUSTMENT = 0.5
30
37
 
38
+ # Astronoby pins the precision it asks horologium for rather than reading
39
+ # horologium's global default, so a host application configuring
40
+ # horologium for itself cannot change what Astronoby computes.
41
+ #
42
+ # Exact rather than standard: standard would round the Julian Date into a
43
+ # two-part float on the way in, and TAI is a fixed offset from TT, so
44
+ # there is nothing to round it for. It is also the cheaper of the two
45
+ # here, having no conversion to make in either direction.
46
+ PRECISION = :exact
47
+
31
48
  class << self
32
49
  # Creates a new Instant from a Terrestrial Time value
33
50
  #
@@ -44,7 +61,7 @@ module Astronoby
44
61
  # @param time [Time] a Time object to convert
45
62
  # @return [Astronoby::Instant] a new Instant object
46
63
  def from_time(time)
47
- delta_t = Util::Time.terrestrial_universal_time_delta(time)
64
+ delta_t = DeltaT.at(time)
48
65
  terrestrial_time = time.utc.to_datetime.ajd +
49
66
  Rational(delta_t, Constants::SECONDS_PER_DAY)
50
67
  from_terrestrial_time(terrestrial_time)
@@ -55,7 +72,7 @@ module Astronoby
55
72
  # @param julian_date [Numeric] the Julian Date in UTC
56
73
  # @return [Astronoby::Instant] a new Instant object
57
74
  def from_utc_julian_date(julian_date)
58
- delta_t = Util::Time.terrestrial_universal_time_delta(julian_date)
75
+ delta_t = DeltaT.at(julian_date)
59
76
  terrestrial_time = julian_date +
60
77
  Rational(delta_t, Constants::SECONDS_PER_DAY)
61
78
  from_terrestrial_time(terrestrial_time)
@@ -120,8 +137,7 @@ module Astronoby
120
137
  #
121
138
  # @return [Numeric] Delta T in seconds
122
139
  def delta_t
123
- @memo[:delta_t] ||=
124
- Util::Time.terrestrial_universal_time_delta(@terrestrial_time)
140
+ @memo[:delta_t] ||= DeltaT.at(@terrestrial_time)
125
141
  end
126
142
 
127
143
  # Get the Greenwich Mean Sidereal Time
@@ -156,21 +172,26 @@ module Astronoby
156
172
 
157
173
  # Get the International Atomic Time (TAI)
158
174
  #
159
- # @return [Numeric] TAI as Julian Date
175
+ # Read as a Rational rather than a Float. A Julian Date is around 2.46
176
+ # million, so a single Float rounds to about 47 microseconds of the day,
177
+ # which would coarsen an instant that TT carries exactly.
178
+ #
179
+ # @return [Rational] TAI as Julian Date
160
180
  def tai
161
- @memo[:tai] ||= @terrestrial_time -
162
- Rational(Constants::TAI_TT_OFFSET, Constants::SECONDS_PER_DAY)
181
+ @memo[:tai] ||= scale_free_instant
182
+ .as(:julian_date, scale: :tai, as: :rational)
163
183
  end
164
184
 
165
185
  # Get the Barycentric Dynamical Time (TDB)
166
- # Note: Currently approximated as equal to TT
167
186
  #
168
- # @return [Numeric] TDB as Julian Date
187
+ # TDB - TT comes from the Fairhead and Bretagnon series ERFA uses. It
188
+ # peaks around 1.7 milliseconds, so a Float Julian Date would quantise
189
+ # most of the correction away; see {#tai} on the shape.
190
+ #
191
+ # @return [Rational] TDB as Julian Date
169
192
  def tdb
170
- # This is technically false, there is a slight difference between TT and
171
- # TDB. However, this difference is so small that currenly Astronoby
172
- # doesn't support it and consider they are the same value.
173
- @memo[:tdb] ||= @terrestrial_time
193
+ @memo[:tdb] ||= scale_free_instant
194
+ .as(:julian_date, scale: :tdb, as: :rational)
174
195
  end
175
196
 
176
197
  # Get the offset between TT and UTC for this instant
@@ -198,5 +219,21 @@ module Astronoby
198
219
  @terrestrial_time <=> other.terrestrial_time
199
220
  end
200
221
  alias_method :eql?, :==
222
+
223
+ private
224
+
225
+ # The instant as horologium holds it: a point on the timeline with no
226
+ # scale of its own. Building it costs more than reading a Julian Date back
227
+ # out of it, so it is built on the first scale conversion that needs it
228
+ # and never on the paths that only want TT.
229
+ #
230
+ # @return [Horologium::Instant]
231
+ def scale_free_instant
232
+ @memo[:scale_free_instant] ||= Horologium::Instant.from_julian_date(
233
+ @terrestrial_time,
234
+ scale: :tt,
235
+ precision: PRECISION
236
+ )
237
+ end
201
238
  end
202
239
  end
@@ -163,7 +163,7 @@ module Astronoby
163
163
 
164
164
  def t
165
165
  @t ||= Rational(
166
- @instant.tdb - JulianDate::DEFAULT_EPOCH,
166
+ @instant.tt - JulianDate::DEFAULT_EPOCH,
167
167
  Constants::DAYS_PER_JULIAN_CENTURY
168
168
  )
169
169
  end
@@ -39,13 +39,18 @@ module Astronoby
39
39
  @target_body = target_body
40
40
  end
41
41
 
42
+ # @return [Numeric] Julian Date epoch
43
+ def epoch
44
+ JulianDate::DEFAULT_EPOCH
45
+ end
46
+
42
47
  # @return [Astronoby::Coordinates::Equatorial] equatorial coordinates
43
- # derived from the position vector
48
+ # derived from the position vector, referred to the frame's epoch
44
49
  def equatorial
45
50
  @equatorial ||= begin
46
- return Coordinates::Equatorial.zero if distance.zero?
51
+ return Coordinates::Equatorial.zero(epoch: epoch) if distance.zero?
47
52
 
48
- Coordinates::Equatorial.from_position_vector(@position)
53
+ Coordinates::Equatorial.from_position_vector(@position, epoch: epoch)
49
54
  end
50
55
  end
51
56
 
@@ -6,29 +6,35 @@ module Astronoby
6
6
  class Apparent < ReferenceFrame
7
7
  # Builds an apparent frame from an astrometric frame by applying
8
8
  # aberration in GCRS, then rotating by nutation * precession (with ICRS
9
- # frame bias).
9
+ # frame bias). Without Earth's geometric frame there is no observer
10
+ # velocity to derive the aberration from, so only the rotation is applied.
10
11
  #
11
12
  # @param instant [Astronoby::Instant] the time instant
12
13
  # @param target_astrometric [Astronoby::Astrometric] target's astrometric
13
14
  # frame
14
- # @param earth_geometric [Astronoby::Geometric] Earth's geometric frame
15
+ # @param earth_geometric [Astronoby::Geometric, nil] Earth's geometric
16
+ # frame
15
17
  # @param target_body [Astronoby::Body, nil] the target body
16
18
  # @return [Astronoby::Apparent] a new apparent frame
17
19
  def self.build_from_astrometric(
18
20
  instant:,
19
21
  target_astrometric:,
20
- earth_geometric:,
21
- target_body:
22
+ target_body:,
23
+ earth_geometric: nil
22
24
  )
23
25
  position = target_astrometric.position
24
26
  velocity = target_astrometric.velocity
25
27
  precession_matrix = Precession.matrix_for(instant)
26
28
  nutation_matrix = Nutation.matrix_for(instant)
27
29
 
28
- corrected_position = Aberration.new(
29
- astrometric_position: position,
30
- observer_velocity: earth_geometric.velocity
31
- ).corrected_position
30
+ corrected_position = if earth_geometric
31
+ Aberration.new(
32
+ astrometric_position: position,
33
+ observer_velocity: earth_geometric.velocity
34
+ ).corrected_position
35
+ else
36
+ position
37
+ end
32
38
 
33
39
  # In theory, here we should also apply light deflection. However, so far
34
40
  # the deflection algorithm hasn't shown any significant changes to the
@@ -53,6 +59,12 @@ module Astronoby
53
59
  )
54
60
  end
55
61
 
62
+ # @return [Numeric] Julian Date epoch of the frame's coordinates, which
63
+ # are referred to the true equator and equinox of date
64
+ def epoch
65
+ instant.tt
66
+ end
67
+
56
68
  # @return [Astronoby::Coordinates::Ecliptic] ecliptic coordinates at the
57
69
  # current instant (true ecliptic and equinox of date)
58
70
  def ecliptic
@@ -37,6 +37,12 @@ module Astronoby
37
37
  )
38
38
  end
39
39
 
40
+ # @return [Numeric] Julian Date epoch of the frame's coordinates, which
41
+ # are referred to the mean equator and equinox of date
42
+ def epoch
43
+ instant.tt
44
+ end
45
+
40
46
  # @return [Astronoby::Coordinates::Ecliptic] ecliptic coordinates at the
41
47
  # current instant (mean equinox of date)
42
48
  def ecliptic
@@ -43,6 +43,12 @@ module Astronoby
43
43
  )
44
44
  end
45
45
 
46
+ # @return [Numeric] Julian Date epoch of the frame's coordinates, which
47
+ # are referred to the true equator and mean equinox of date
48
+ def epoch
49
+ instant.tt
50
+ end
51
+
46
52
  # Converts TEME position and velocity to ECEF using the canonical
47
53
  # Vallado formulation with R₃(GMST).
48
54
  #
@@ -64,6 +64,12 @@ module Astronoby
64
64
  @observer = observer
65
65
  end
66
66
 
67
+ # @return [Numeric] Julian Date epoch of the frame's coordinates, which
68
+ # are referred to the true equator and equinox of date
69
+ def epoch
70
+ instant.tt
71
+ end
72
+
67
73
  # @return [Astronoby::Coordinates::Ecliptic] ecliptic coordinates at the
68
74
  # current instant (true ecliptic and equinox of date)
69
75
  def ecliptic
@@ -3,7 +3,7 @@
3
3
  module Astronoby
4
4
  class RootFinder
5
5
  MIN_SAMPLES_PER_PERIOD = 20
6
- BISECTION_TOLERANCE_DAYS = 1e-5
6
+ BISECTION_TOLERANCE_DAYS = 1e-8
7
7
 
8
8
  # @param value_at [#call] callable mapping a Julian Date (Terrestrial Time)
9
9
  # to a Float
@@ -22,21 +22,28 @@ module Astronoby
22
22
  # @return [Array<Float>] root times in Julian Date (Terrestrial Time),
23
23
  # sorted by time
24
24
  def roots(start_jd, end_jd, accept: nil)
25
- brackets = find_brackets(start_jd, end_jd)
26
- located = brackets.map { |a, b| bisect(a, b) }
25
+ samples = collect_samples(start_jd, end_jd)
26
+ located = (
27
+ samples_on_root(samples) +
28
+ find_brackets(samples).map { |a, b, f_a| bisect(a, b, f_a) }
29
+ ).uniq.sort
27
30
  located.select { |jd| accept.nil? || accept.call(jd) }
28
31
  end
29
32
 
30
33
  private
31
34
 
32
- def find_brackets(start_jd, end_jd)
33
- samples = collect_samples(start_jd, end_jd)
35
+ def samples_on_root(samples)
36
+ samples.filter_map { |sample| sample[:jd] if sample[:value].zero? }
37
+ end
34
38
 
39
+ def find_brackets(samples)
35
40
  (0...samples.length - 1).filter_map do |i|
36
41
  current = samples[i]
37
42
  following = samples[i + 1]
38
43
 
39
- [current[:jd], following[:jd]] if sign_change?(current, following)
44
+ if sign_change?(current, following)
45
+ [current[:jd], following[:jd], current[:value]]
46
+ end
40
47
  end
41
48
  end
42
49
 
@@ -61,11 +68,11 @@ module Astronoby
61
68
  [base_samples, MIN_SAMPLES_PER_PERIOD].max
62
69
  end
63
70
 
64
- def bisect(a, b)
65
- f_a = @value_at.call(a)
66
-
71
+ def bisect(a, b, f_a)
67
72
  while (b - a).abs > BISECTION_TOLERANCE_DAYS
68
73
  midpoint = (a + b) / 2
74
+ break if midpoint == a || midpoint == b
75
+
69
76
  f_midpoint = @value_at.call(midpoint)
70
77
  return midpoint if f_midpoint.zero?
71
78
 
@@ -10,16 +10,18 @@ module Astronoby
10
10
  # @param utc [Time] the UTC time
11
11
  # @return [Astronoby::GreenwichApparentSiderealTime]
12
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)
13
+ Astronoby.cache.fetch(CacheKey.generate_for_utc(:gast, utc)) do
14
+ gmst = GreenwichMeanSiderealTime.from_utc(utc)
15
+ instant = Instant.from_time(utc)
16
+ nutation = Nutation.new(instant: instant)
17
+ mean_obliquity = MeanObliquity.at(instant)
17
18
 
18
- equation_of_equinoxes = nutation.nutation_in_longitude.hours *
19
- mean_obliquity.cos
20
- gast_time = normalize_time(gmst.time + equation_of_equinoxes)
19
+ equation_of_equinoxes = nutation.nutation_in_longitude.hours *
20
+ mean_obliquity.cos
21
+ gast_time = normalize_time(gmst.time + equation_of_equinoxes)
21
22
 
22
- new(date: gmst.date, time: gast_time)
23
+ new(date: gmst.date, time: gast_time)
24
+ end
23
25
  end
24
26
 
25
27
  # @param date [Date] the calendar date
@@ -27,16 +27,18 @@ module Astronoby
27
27
  # @param utc [Time] the UTC time
28
28
  # @return [Astronoby::GreenwichMeanSiderealTime]
29
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)
30
+ Astronoby.cache.fetch(CacheKey.generate_for_utc(:gmst, utc)) do
31
+ date = utc.to_date
32
+ gmst_hours = begin
33
+ gmst_radians = IERS::GMST.at(utc)
34
+ gmst_radians * 12.0 / Math::PI
35
+ rescue IERS::OutOfRangeError
36
+ from_utc_polynomial(utc)
37
+ end
38
+ gmst_hours = normalize_time(gmst_hours)
38
39
 
39
- new(date: date, time: gmst_hours)
40
+ new(date: date, time: gmst_hours)
41
+ end
40
42
  end
41
43
 
42
44
  # Polynomial fallback for dates outside the IERS EOP data range.
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "iers"
4
-
5
3
  module Astronoby
6
4
  module Util
7
5
  module Time
@@ -40,26 +38,6 @@ module Astronoby
40
38
 
41
39
  ::Time.utc(date.year, date.month, date.day, hour, minute, second).round
42
40
  end
43
-
44
- # @param instant [Numeric, Time, Date, DateTime]
45
- # @return [Numeric] Delta T (TT - UT1) in seconds for the given instant
46
- def self.terrestrial_universal_time_delta(instant)
47
- case instant
48
- when Numeric
49
- IERS::DeltaT.at(jd: instant).delta_t
50
- when ::Time, ::Date, ::DateTime
51
- IERS::DeltaT.at(instant).delta_t
52
- else
53
- raise IncompatibleArgumentsError,
54
- "Expected a Numeric, Time, Date or DateTime object, got #{instant.class}"
55
- end
56
- rescue IERS::OutOfRangeError => e
57
- if e.available_range
58
- IERS::DeltaT.at(mjd: e.available_range.end).delta_t
59
- else
60
- 0
61
- end
62
- end
63
41
  end
64
42
  end
65
43
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Astronoby
4
- VERSION = "0.10.0"
4
+ VERSION = "0.11.0"
5
5
  end
data/lib/astronoby.rb CHANGED
@@ -18,6 +18,7 @@ require "astronoby/body"
18
18
  require "astronoby/position"
19
19
  require "astronoby/ephem"
20
20
  require "astronoby/julian_date"
21
+ require "astronoby/delta_t"
21
22
  require "astronoby/instant"
22
23
  require "astronoby/vector"
23
24
  require "astronoby/velocity"
@@ -47,6 +48,8 @@ require "astronoby/equinox_solstice"
47
48
  require "astronoby/errors"
48
49
  require "astronoby/extremum_finder"
49
50
  require "astronoby/root_finder"
51
+ require "astronoby/horizon"
52
+ require "astronoby/horizontal_transformation"
50
53
  require "astronoby/events/conjunction"
51
54
  require "astronoby/events/opposition"
52
55
  require "astronoby/events/greatest_elongation"
@@ -55,15 +58,20 @@ require "astronoby/events/greatest_elongation_calculator"
55
58
  require "astronoby/events/extremum_event"
56
59
  require "astronoby/events/extremum_calculator"
57
60
  require "astronoby/events/moon_phases"
61
+ require "astronoby/events/altitude_crossing"
62
+ require "astronoby/events/altitude_extreme"
63
+ require "astronoby/events/altitude_crossing_calculator"
58
64
  require "astronoby/events/rise_transit_set_event"
59
65
  require "astronoby/events/rise_transit_set_events"
60
66
  require "astronoby/events/rise_transit_set_calculator"
61
67
  require "astronoby/events/twilight_event"
62
68
  require "astronoby/events/twilight_events"
63
69
  require "astronoby/events/twilight_calculator"
64
- require "astronoby/events/eclipse_phase"
70
+ require "astronoby/events/lunar_eclipse_phase"
71
+ require "astronoby/events/lunar_eclipse_geometry"
65
72
  require "astronoby/events/lunar_eclipse"
66
73
  require "astronoby/events/lunar_eclipse_calculator"
74
+ require "astronoby/events/lunar_eclipse_visibility"
67
75
  require "astronoby/geocentric_parallax"
68
76
  require "astronoby/libration"
69
77
  require "astronoby/mean_obliquity"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: astronoby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.0
4
+ version: 0.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rémy Hannequin
@@ -24,7 +24,7 @@ dependencies:
24
24
  - !ruby/object:Gem::Version
25
25
  version: '0.5'
26
26
  - !ruby/object:Gem::Dependency
27
- name: iers
27
+ name: horologium
28
28
  requirement: !ruby/object:Gem::Requirement
29
29
  requirements:
30
30
  - - "~>"
@@ -37,6 +37,26 @@ dependencies:
37
37
  - - "~>"
38
38
  - !ruby/object:Gem::Version
39
39
  version: '0.1'
40
+ - !ruby/object:Gem::Dependency
41
+ name: iers
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '0.3'
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: 0.3.1
50
+ type: :runtime
51
+ prerelease: false
52
+ version_requirements: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - "~>"
55
+ - !ruby/object:Gem::Version
56
+ version: '0.3'
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: 0.3.1
40
60
  - !ruby/object:Gem::Dependency
41
61
  name: matrix
42
62
  requirement: !ruby/object:Gem::Requirement
@@ -127,14 +147,20 @@ dependencies:
127
147
  requirements:
128
148
  - - "~>"
129
149
  - !ruby/object:Gem::Version
130
- version: '0.22'
150
+ version: '1.0'
151
+ - - "<"
152
+ - !ruby/object:Gem::Version
153
+ version: '1.2'
131
154
  type: :development
132
155
  prerelease: false
133
156
  version_requirements: !ruby/object:Gem::Requirement
134
157
  requirements:
135
158
  - - "~>"
136
159
  - !ruby/object:Gem::Version
137
- version: '0.22'
160
+ version: '1.0'
161
+ - - "<"
162
+ - !ruby/object:Gem::Version
163
+ version: '1.2'
138
164
  - !ruby/object:Gem::Dependency
139
165
  name: standard
140
166
  requirement: !ruby/object:Gem::Requirement
@@ -167,6 +193,7 @@ files:
167
193
  - Rakefile
168
194
  - UPGRADING.md
169
195
  - docs/README.md
196
+ - docs/altitude_crossings.md
170
197
  - docs/angles.md
171
198
  - docs/configuration.md
172
199
  - docs/coordinates.md
@@ -225,21 +252,27 @@ files:
225
252
  - lib/astronoby/data/constellations/sorted_declinations.dat
226
253
  - lib/astronoby/data/constellations/sorted_right_ascensions.dat
227
254
  - lib/astronoby/deflection.rb
255
+ - lib/astronoby/delta_t.rb
228
256
  - lib/astronoby/distance.rb
229
257
  - lib/astronoby/duration.rb
230
258
  - lib/astronoby/earth_rotation.rb
231
259
  - lib/astronoby/ephem.rb
232
260
  - lib/astronoby/equinox_solstice.rb
233
261
  - lib/astronoby/errors.rb
262
+ - lib/astronoby/events/altitude_crossing.rb
263
+ - lib/astronoby/events/altitude_crossing_calculator.rb
264
+ - lib/astronoby/events/altitude_extreme.rb
234
265
  - lib/astronoby/events/conjunction.rb
235
266
  - lib/astronoby/events/conjunction_opposition_calculator.rb
236
- - lib/astronoby/events/eclipse_phase.rb
237
267
  - lib/astronoby/events/extremum_calculator.rb
238
268
  - lib/astronoby/events/extremum_event.rb
239
269
  - lib/astronoby/events/greatest_elongation.rb
240
270
  - lib/astronoby/events/greatest_elongation_calculator.rb
241
271
  - lib/astronoby/events/lunar_eclipse.rb
242
272
  - lib/astronoby/events/lunar_eclipse_calculator.rb
273
+ - lib/astronoby/events/lunar_eclipse_geometry.rb
274
+ - lib/astronoby/events/lunar_eclipse_phase.rb
275
+ - lib/astronoby/events/lunar_eclipse_visibility.rb
243
276
  - lib/astronoby/events/moon_phases.rb
244
277
  - lib/astronoby/events/opposition.rb
245
278
  - lib/astronoby/events/rise_transit_set_calculator.rb
@@ -250,6 +283,8 @@ files:
250
283
  - lib/astronoby/events/twilight_events.rb
251
284
  - lib/astronoby/extremum_finder.rb
252
285
  - lib/astronoby/geocentric_parallax.rb
286
+ - lib/astronoby/horizon.rb
287
+ - lib/astronoby/horizontal_transformation.rb
253
288
  - lib/astronoby/instant.rb
254
289
  - lib/astronoby/julian_date.rb
255
290
  - lib/astronoby/libration.rb