astronoby 0.3.0 → 0.5.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 (38) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +132 -0
  3. data/Gemfile.lock +19 -17
  4. data/README.md +195 -25
  5. data/UPGRADING.md +72 -0
  6. data/lib/astronoby/aberration.rb +7 -5
  7. data/lib/astronoby/angle.rb +26 -34
  8. data/lib/astronoby/astronomical_models/ephemeride_lunaire_parisienne.rb +143 -0
  9. data/lib/astronoby/astronomical_models/moon_phases_periodic_terms.rb +249 -0
  10. data/lib/astronoby/bodies/moon.rb +335 -0
  11. data/lib/astronoby/bodies/sun.rb +129 -132
  12. data/lib/astronoby/constants.rb +31 -0
  13. data/lib/astronoby/coordinates/ecliptic.rb +4 -4
  14. data/lib/astronoby/coordinates/equatorial.rb +7 -5
  15. data/lib/astronoby/coordinates/horizontal.rb +24 -12
  16. data/lib/astronoby/distance.rb +83 -0
  17. data/lib/astronoby/epoch.rb +0 -2
  18. data/lib/astronoby/equinox_solstice.rb +3 -2
  19. data/lib/astronoby/events/moon_phases.rb +143 -0
  20. data/lib/astronoby/events/observation_events.rb +259 -0
  21. data/lib/astronoby/events/rise_transit_set_iteration.rb +215 -0
  22. data/lib/astronoby/events/twilight_events.rb +121 -0
  23. data/lib/astronoby/geocentric_parallax.rb +36 -56
  24. data/lib/astronoby/mean_obliquity.rb +2 -2
  25. data/lib/astronoby/moon_phase.rb +43 -0
  26. data/lib/astronoby/nutation.rb +5 -3
  27. data/lib/astronoby/observer.rb +39 -18
  28. data/lib/astronoby/precession.rb +1 -1
  29. data/lib/astronoby/refraction.rb +8 -10
  30. data/lib/astronoby/time/greenwich_sidereal_time.rb +18 -29
  31. data/lib/astronoby/time/local_sidereal_time.rb +4 -4
  32. data/lib/astronoby/util/maths.rb +72 -0
  33. data/lib/astronoby/util/time.rb +88 -0
  34. data/lib/astronoby/util/trigonometry.rb +4 -4
  35. data/lib/astronoby/version.rb +1 -1
  36. data/lib/astronoby.rb +12 -1
  37. metadata +15 -4
  38. data/lib/astronoby/body.rb +0 -155
@@ -5,17 +5,16 @@ module Astronoby
5
5
  LOW_ALTITUDE_BODY_ANGLE = Angle.from_degrees(15)
6
6
  ZENITH = Angle.from_degrees(90)
7
7
 
8
- def self.angle(coordinates:, observer:)
9
- new(coordinates, observer).refraction_angle
8
+ def self.angle(coordinates:)
9
+ new(coordinates).refraction_angle
10
10
  end
11
11
 
12
- def self.correct_horizontal_coordinates(coordinates:, observer:)
13
- new(coordinates, observer).refract
12
+ def self.correct_horizontal_coordinates(coordinates:)
13
+ new(coordinates).refract
14
14
  end
15
15
 
16
- def initialize(coordinates, observer)
16
+ def initialize(coordinates)
17
17
  @coordinates = coordinates
18
- @observer = observer
19
18
  end
20
19
 
21
20
  # Source:
@@ -27,8 +26,7 @@ module Astronoby
27
26
  Coordinates::Horizontal.new(
28
27
  azimuth: @coordinates.azimuth,
29
28
  altitude: @coordinates.altitude + refraction_angle,
30
- latitude: @coordinates.latitude,
31
- longitude: @coordinates.longitude
29
+ observer: @coordinates.observer
32
30
  )
33
31
  end
34
32
 
@@ -43,11 +41,11 @@ module Astronoby
43
41
  private
44
42
 
45
43
  def pressure
46
- @_pressure ||= @observer.pressure
44
+ @_pressure ||= @coordinates.observer.pressure
47
45
  end
48
46
 
49
47
  def temperature
50
- @_temperature ||= @observer.temperature
48
+ @_temperature ||= @coordinates.observer.temperature
51
49
  end
52
50
 
53
51
  def altitude_in_degrees
@@ -3,11 +3,13 @@
3
3
  module Astronoby
4
4
  class GreenwichSiderealTime
5
5
  JULIAN_CENTURIES_EXPONENTS = [
6
- BigDecimal("6.697374558"),
7
- BigDecimal("2400.051336"),
8
- BigDecimal("0.000025862")
6
+ 6.697374558,
7
+ 2400.051336,
8
+ 0.000025862
9
9
  ].freeze
10
10
 
11
+ SIDEREAL_MINUTE_IN_UT_MINUTE = 0.9972695663
12
+
11
13
  attr_reader :date, :time
12
14
 
13
15
  # Source:
@@ -18,20 +20,20 @@ module Astronoby
18
20
  def self.from_utc(utc)
19
21
  date = utc.to_date
20
22
  julian_day = utc.to_date.ajd
21
- t = (julian_day - Epoch::J2000) / Epoch::DAYS_PER_JULIAN_CENTURY
23
+ t = (julian_day - Epoch::J2000) / Constants::DAYS_PER_JULIAN_CENTURY
22
24
  t0 = (
23
25
  (JULIAN_CENTURIES_EXPONENTS[0] +
24
26
  (JULIAN_CENTURIES_EXPONENTS[1] * t) +
25
- (JULIAN_CENTURIES_EXPONENTS[2] * t * t)) % 24
27
+ (JULIAN_CENTURIES_EXPONENTS[2] * t * t)) % Constants::HOURS_PER_DAY
26
28
  ).abs
27
29
 
28
30
  ut_in_hours = utc.hour +
29
- utc.min / 60.0 +
30
- (utc.sec + utc.subsec) / 3600.0
31
+ utc.min / Constants::MINUTES_PER_HOUR +
32
+ (utc.sec + utc.subsec) / Constants::SECONDS_PER_HOUR
31
33
 
32
- gmst = BigDecimal("1.002737909") * ut_in_hours + t0
33
- gmst += 24 if gmst.negative?
34
- gmst -= 24 if gmst > 24
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
35
37
 
36
38
  new(date: date, time: gmst)
37
39
  end
@@ -49,38 +51,25 @@ module Astronoby
49
51
  def to_utc
50
52
  date = @date
51
53
  julian_day = @date.ajd
52
- t = (julian_day - Epoch::J2000) / Epoch::DAYS_PER_JULIAN_CENTURY
54
+ t = (julian_day - Epoch::J2000) / Constants::DAYS_PER_JULIAN_CENTURY
53
55
 
54
56
  t0 = (
55
57
  (JULIAN_CENTURIES_EXPONENTS[0] +
56
58
  (JULIAN_CENTURIES_EXPONENTS[1] * t) +
57
- (JULIAN_CENTURIES_EXPONENTS[2] * t * t)) % 24
59
+ (JULIAN_CENTURIES_EXPONENTS[2] * t * t)) % Constants::HOURS_PER_DAY
58
60
  ).abs
59
61
 
60
62
  a = @time - t0
61
- a += 24 if a.negative?
62
- a -= 24 if a > 24
63
+ a += Constants::HOURS_PER_DAY if a.negative?
64
+ a -= Constants::HOURS_PER_DAY if a > Constants::HOURS_PER_DAY
63
65
 
64
- utc = BigDecimal("0.9972695663") * a
66
+ utc = SIDEREAL_MINUTE_IN_UT_MINUTE * a
65
67
 
66
- decimal_hour_to_time(date, utc)
68
+ Util::Time.decimal_hour_to_time(date, utc)
67
69
  end
68
70
 
69
71
  def to_lst(longitude:)
70
72
  LocalSiderealTime.from_gst(gst: self, longitude: longitude)
71
73
  end
72
-
73
- private
74
-
75
- def decimal_hour_to_time(date, decimal)
76
- absolute_hour = decimal.abs
77
- hour = absolute_hour.floor
78
- decimal_minute = 60 * (absolute_hour - hour)
79
- absolute_decimal_minute = (60 * (absolute_hour - hour)).abs
80
- minute = decimal_minute.floor
81
- second = 60 * (absolute_decimal_minute - absolute_decimal_minute.floor)
82
-
83
- ::Time.utc(date.year, date.month, date.day, hour, minute, second).round
84
- end
85
74
  end
86
75
  end
@@ -12,8 +12,8 @@ module Astronoby
12
12
  def self.from_gst(gst:, longitude:)
13
13
  date = gst.date
14
14
  time = gst.time + longitude.hours
15
- time += 24 if time.negative?
16
- time -= 24 if time > 24
15
+ time += Constants::HOURS_PER_DAY if time.negative?
16
+ time -= Constants::HOURS_PER_DAY if time > Constants::HOURS_PER_DAY
17
17
 
18
18
  new(date: date, time: time, longitude: longitude)
19
19
  end
@@ -32,8 +32,8 @@ module Astronoby
32
32
  def to_gst
33
33
  date = @date
34
34
  time = @time - @longitude.hours
35
- time += 24 if time.negative?
36
- time -= 24 if time > 24
35
+ time += Constants::HOURS_PER_DAY if time.negative?
36
+ time -= Constants::HOURS_PER_DAY if time > Constants::HOURS_PER_DAY
37
37
 
38
38
  GreenwichSiderealTime.new(date: date, time: time)
39
39
  end
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Astronoby
4
+ module Util
5
+ module Maths
6
+ class << self
7
+ # Source:
8
+ # Title: Astronomical Algorithms
9
+ # Author: Jean Meeus
10
+ # Edition: 2nd edition
11
+ # Chapter: 3 - Interpolation
12
+
13
+ # @param values [Array<Numeric>] First term
14
+ # @param factor [Numeric] Interpolation factor
15
+ # @return [Float] Interpolated value
16
+ def interpolate(values, factor)
17
+ unless factor.between?(0, 1)
18
+ raise IncompatibleArgumentsError,
19
+ "Interpolation factor must be between 0 and 1, got #{factor}"
20
+ end
21
+
22
+ if values.length == 3
23
+ return interpolate_3_terms(values, factor)
24
+ elsif values.length == 5
25
+ return interpolate_5_terms(values, factor)
26
+ end
27
+
28
+ raise IncompatibleArgumentsError,
29
+ "Only 3 or 5 terms are supported for interpolation"
30
+ end
31
+
32
+ private
33
+
34
+ # @return [Float] Interpolated value
35
+ def interpolate_3_terms(terms, factor)
36
+ y1, y2, y3 = terms
37
+
38
+ a = y2 - y1
39
+ b = y3 - y2
40
+ c = b - a
41
+
42
+ y2 + (factor / 2.0) * (a + b + factor * c)
43
+ end
44
+
45
+ # @return [Float] Interpolated value
46
+ def interpolate_5_terms(terms, factor)
47
+ y1, y2, y3, y4, y5 = terms
48
+
49
+ a = y2 - y1
50
+ b = y3 - y2
51
+ c = y4 - y3
52
+ d = y5 - y4
53
+
54
+ e = b - a
55
+ f = c - b
56
+ g = d - c
57
+
58
+ h = f - e
59
+ j = g - f
60
+
61
+ k = j - h
62
+
63
+ y3 +
64
+ factor * ((b + c) / 2.0 - (h + j) / 12.0) +
65
+ factor**2 * (f / 2.0 - k / 24.0) +
66
+ factor**3 * (h + j) / 12.0 +
67
+ factor**4 * k / 24.0
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Astronoby
4
+ module Util
5
+ module Time
6
+ # @param date [Date]
7
+ # @param decimal [Numeric] Hour of the day, in decimal hours
8
+ # @return [::Time] Date and time
9
+ def self.decimal_hour_to_time(date, decimal)
10
+ absolute_hour = decimal.abs
11
+ hour = absolute_hour.floor
12
+
13
+ unless hour.between?(0, Constants::HOURS_PER_DAY)
14
+ raise(
15
+ IncompatibleArgumentsError,
16
+ "Hour must be between 0 and #{Constants::HOURS_PER_DAY.to_i}, got #{hour}"
17
+ )
18
+ end
19
+
20
+ decimal_minute = Constants::MINUTES_PER_HOUR * (absolute_hour - hour)
21
+ absolute_decimal_minute = (
22
+ Constants::MINUTES_PER_HOUR * (absolute_hour - hour)
23
+ ).abs
24
+ minute = decimal_minute.floor
25
+ second = Constants::SECONDS_PER_MINUTE *
26
+ (absolute_decimal_minute - absolute_decimal_minute.floor)
27
+
28
+ ::Time.utc(date.year, date.month, date.day, hour, minute, second).round
29
+ end
30
+
31
+ # @param instant [Numeric, Time, Date, DateTime]
32
+ # @return [Integer, Float] Number of leap seconds for the given instant
33
+ def self.terrestrial_universal_time_delta(instant)
34
+ # Source:
35
+ # Title: Astronomical Algorithms
36
+ # Author: Jean Meeus
37
+ # Edition: 2nd edition
38
+ # Chapter: 10 - Dynamical Time and Universal Time
39
+
40
+ jd = case instant
41
+ when Numeric
42
+ instant
43
+ when ::Time, ::Date, ::DateTime
44
+ Epoch.from_time(instant)
45
+ else
46
+ raise IncompatibleArgumentsError,
47
+ "Expected a Numeric, Time, Date or DateTime object, got #{instant.class}"
48
+ end
49
+
50
+ return 69 if jd >= 2457754.5
51
+ return 68 if jd >= 2457204.5
52
+ return 67 if jd >= 2456109.5
53
+ return 66 if jd >= 2454832.5
54
+ return 65 if jd >= 2453736.5
55
+ return 64 if jd >= 2451179.5
56
+ return 63 if jd >= 2450814.5
57
+
58
+ theta = ((jd - Epoch::J1900) / 365.25) / 100.0
59
+ if (2415020.5...2450814.5).cover?(jd) # 1900 - 1997
60
+ return -2.44 +
61
+ 87.24 * theta +
62
+ 815.20 * theta**2 -
63
+ 2_637.80 * theta**3 -
64
+ 18_756.33 * theta**4 +
65
+ 124_906.15 * theta**5 -
66
+ 303_191.19 * theta**6 +
67
+ 372_919.88 * theta**7 -
68
+ 232_424.66 * theta**8 +
69
+ 58_353.42 * theta**9
70
+ elsif (2378496.5...2415020.5).cover?(jd) # 1800 - 1899
71
+ return -2.5 +
72
+ 228.95 * theta +
73
+ 5_218.61 * theta**2 +
74
+ 56_282.84 * theta**3 +
75
+ 324_011.78 * theta**4 +
76
+ 1_061_660.75 * theta**5 +
77
+ 2_087_298.89 * theta**6 +
78
+ 2_513_807.78 * theta**7 +
79
+ 1_818_961.41 * theta**8 +
80
+ 727_058.63 * theta**9 +
81
+ 123_563.95 * theta**10
82
+ end
83
+
84
+ 0.0
85
+ end
86
+ end
87
+ end
88
+ end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "bigdecimal/math"
4
-
5
3
  module Astronoby
6
4
  module Util
7
5
  module Trigonometry
@@ -15,10 +13,12 @@ module Astronoby
15
13
  return angle if y.positive? && x.positive?
16
14
 
17
15
  if y.negative? && x.positive?
18
- return Angle.from_degrees(angle.degrees + 360)
16
+ return Angle.from_degrees(
17
+ angle.degrees + Constants::DEGREES_PER_CIRCLE
18
+ )
19
19
  end
20
20
 
21
- Angle.from_degrees(angle.degrees + 180)
21
+ Angle.from_degrees(angle.degrees + Constants::DEGREES_PER_CIRCLE / 2)
22
22
  end
23
23
  end
24
24
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Astronoby
4
- VERSION = "0.3.0"
4
+ VERSION = "0.5.0"
5
5
  end
data/lib/astronoby.rb CHANGED
@@ -1,10 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "astronoby/constants"
3
4
  require "astronoby/angle"
4
5
  require "astronoby/angles/dms"
5
6
  require "astronoby/angles/hms"
7
+ require "astronoby/distance"
6
8
  require "astronoby/epoch"
7
- require "astronoby/body"
9
+ require "astronoby/astronomical_models/ephemeride_lunaire_parisienne"
10
+ require "astronoby/astronomical_models/moon_phases_periodic_terms"
11
+ require "astronoby/bodies/moon"
8
12
  require "astronoby/bodies/sun"
9
13
  require "astronoby/coordinates/ecliptic"
10
14
  require "astronoby/coordinates/equatorial"
@@ -12,8 +16,13 @@ require "astronoby/coordinates/horizontal"
12
16
  require "astronoby/aberration"
13
17
  require "astronoby/equinox_solstice"
14
18
  require "astronoby/errors"
19
+ require "astronoby/events/moon_phases"
20
+ require "astronoby/events/observation_events"
21
+ require "astronoby/events/rise_transit_set_iteration"
22
+ require "astronoby/events/twilight_events"
15
23
  require "astronoby/geocentric_parallax"
16
24
  require "astronoby/mean_obliquity"
25
+ require "astronoby/moon_phase"
17
26
  require "astronoby/nutation"
18
27
  require "astronoby/observer"
19
28
  require "astronoby/precession"
@@ -21,6 +30,8 @@ require "astronoby/refraction"
21
30
  require "astronoby/time/greenwich_sidereal_time"
22
31
  require "astronoby/time/local_sidereal_time"
23
32
  require "astronoby/util/astrodynamics"
33
+ require "astronoby/util/maths"
34
+ require "astronoby/util/time"
24
35
  require "astronoby/util/trigonometry"
25
36
  require "astronoby/true_obliquity"
26
37
  require "astronoby/version"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: astronoby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rémy Hannequin
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-03-29 00:00:00.000000000 Z
11
+ date: 2024-06-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: matrix
@@ -91,16 +91,25 @@ files:
91
91
  - lib/astronoby/angle.rb
92
92
  - lib/astronoby/angles/dms.rb
93
93
  - lib/astronoby/angles/hms.rb
94
+ - lib/astronoby/astronomical_models/ephemeride_lunaire_parisienne.rb
95
+ - lib/astronoby/astronomical_models/moon_phases_periodic_terms.rb
96
+ - lib/astronoby/bodies/moon.rb
94
97
  - lib/astronoby/bodies/sun.rb
95
- - lib/astronoby/body.rb
98
+ - lib/astronoby/constants.rb
96
99
  - lib/astronoby/coordinates/ecliptic.rb
97
100
  - lib/astronoby/coordinates/equatorial.rb
98
101
  - lib/astronoby/coordinates/horizontal.rb
102
+ - lib/astronoby/distance.rb
99
103
  - lib/astronoby/epoch.rb
100
104
  - lib/astronoby/equinox_solstice.rb
101
105
  - lib/astronoby/errors.rb
106
+ - lib/astronoby/events/moon_phases.rb
107
+ - lib/astronoby/events/observation_events.rb
108
+ - lib/astronoby/events/rise_transit_set_iteration.rb
109
+ - lib/astronoby/events/twilight_events.rb
102
110
  - lib/astronoby/geocentric_parallax.rb
103
111
  - lib/astronoby/mean_obliquity.rb
112
+ - lib/astronoby/moon_phase.rb
104
113
  - lib/astronoby/nutation.rb
105
114
  - lib/astronoby/observer.rb
106
115
  - lib/astronoby/precession.rb
@@ -109,6 +118,8 @@ files:
109
118
  - lib/astronoby/time/local_sidereal_time.rb
110
119
  - lib/astronoby/true_obliquity.rb
111
120
  - lib/astronoby/util/astrodynamics.rb
121
+ - lib/astronoby/util/maths.rb
122
+ - lib/astronoby/util/time.rb
112
123
  - lib/astronoby/util/trigonometry.rb
113
124
  - lib/astronoby/version.rb
114
125
  homepage: https://github.com/rhannequin/astronoby
@@ -126,7 +137,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
126
137
  requirements:
127
138
  - - ">="
128
139
  - !ruby/object:Gem::Version
129
- version: 3.2.0
140
+ version: 3.0.0
130
141
  required_rubygems_version: !ruby/object:Gem::Requirement
131
142
  requirements:
132
143
  - - ">="
@@ -1,155 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Astronoby
4
- class Body
5
- DEFAULT_REFRACTION_VERTICAL_SHIFT = Angle.from_dms(0, 34, 0)
6
- RISING_SETTING_HOUR_ANGLE_RATIO_RANGE = (-1..1)
7
-
8
- def initialize(equatorial_coordinates)
9
- @equatorial_coordinates = equatorial_coordinates
10
- end
11
-
12
- # Source:
13
- # Title: Practical Astronomy with your Calculator or Spreadsheet
14
- # Authors: Peter Duffett-Smith and Jonathan Zwart
15
- # Edition: Cambridge University Press
16
- # Chapter: 33 - Rising and setting
17
-
18
- # @param latitude [Astronoby::Angle] Latitude of the observer
19
- # @param longitude [Astronoby::Angle] Longitude of the observer
20
- # @param date [Date] Date of the event
21
- # @param apparent [Boolean] Compute apparent or true data
22
- # @param vertical_shift [Astronoby::Angle] Vertical shift correction angle
23
- # @return [Time, nil] Sunrise time
24
- def rising_time(
25
- latitude:,
26
- longitude:,
27
- date:,
28
- apparent: true,
29
- vertical_shift: nil
30
- )
31
- time_ratio = time_ratio(latitude, apparent, vertical_shift)
32
- return nil unless RISING_SETTING_HOUR_ANGLE_RATIO_RANGE.cover?(time_ratio)
33
-
34
- hour_angle = Angle.acos(time_ratio)
35
- local_sidereal_time = LocalSiderealTime.new(
36
- date: date,
37
- time: right_ascension.hours - hour_angle.hours,
38
- longitude: longitude
39
- )
40
-
41
- local_sidereal_time.to_gst.to_utc
42
- end
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: 33 - Rising and setting
49
-
50
- # @param latitude [Astronoby::Angle] Latitude of the observer
51
- # @param apparent [Boolean] Compute apparent or true data
52
- # @param vertical_shift [Astronoby::Angle] Vertical shift correction angle
53
- # @return [Astronoby::Angle, nil] Sunrise azimuth
54
- def rising_azimuth(latitude:, apparent: true, vertical_shift: nil)
55
- time_ratio = time_ratio(latitude, apparent, vertical_shift)
56
- return nil unless RISING_SETTING_HOUR_ANGLE_RATIO_RANGE.cover?(time_ratio)
57
-
58
- azimuth_ratio = azimuth_ratio(latitude, apparent, vertical_shift)
59
-
60
- Angle.acos(azimuth_ratio)
61
- end
62
-
63
- # Source:
64
- # Title: Practical Astronomy with your Calculator or Spreadsheet
65
- # Authors: Peter Duffett-Smith and Jonathan Zwart
66
- # Edition: Cambridge University Press
67
- # Chapter: 33 - Rising and setting
68
-
69
- # @param latitude [Astronoby::Angle] Latitude of the observer
70
- # @param longitude [Astronoby::Angle] Longitude of the observer
71
- # @param date [Date] Date of the event
72
- # @param apparent [Boolean] Compute apparent or true data
73
- # @param vertical_shift [Astronoby::Angle] Vertical shift correction angle
74
- # @return [Time, nil] Sunset time
75
- def setting_time(
76
- latitude:,
77
- longitude:,
78
- date:,
79
- apparent: true,
80
- vertical_shift: nil
81
- )
82
- time_ratio = time_ratio(latitude, apparent, vertical_shift)
83
- return unless RISING_SETTING_HOUR_ANGLE_RATIO_RANGE.cover?(time_ratio)
84
-
85
- hour_angle = Angle.acos(time_ratio)
86
- local_sidereal_time = LocalSiderealTime.new(
87
- date: date,
88
- time: right_ascension.hours + hour_angle.hours,
89
- longitude: longitude
90
- )
91
-
92
- local_sidereal_time.to_gst.to_utc
93
- end
94
-
95
- # Source:
96
- # Title: Practical Astronomy with your Calculator or Spreadsheet
97
- # Authors: Peter Duffett-Smith and Jonathan Zwart
98
- # Edition: Cambridge University Press
99
- # Chapter: 33 - Rising and setting
100
-
101
- # @param latitude [Astronoby::Angle] Latitude of the observer
102
- # @param apparent [Boolean] Compute apparent or true data
103
- # @param vertical_shift [Astronoby::Angle] Vertical shift correction angle
104
- # @return [Astronoby::Angle, nil] Sunset azimuth
105
- def setting_azimuth(latitude:, apparent: true, vertical_shift: nil)
106
- time_ratio = time_ratio(latitude, apparent, vertical_shift)
107
- return nil unless RISING_SETTING_HOUR_ANGLE_RATIO_RANGE.cover?(time_ratio)
108
-
109
- azimuth_ratio = azimuth_ratio(latitude, apparent, vertical_shift)
110
-
111
- Angle.from_degrees(360 - Angle.acos(azimuth_ratio).degrees)
112
- end
113
-
114
- private
115
-
116
- def time_ratio(latitude, apparent, vertical_shift)
117
- shift = if vertical_shift
118
- vertical_shift
119
- elsif apparent
120
- DEFAULT_REFRACTION_VERTICAL_SHIFT
121
- else
122
- Angle.zero
123
- end
124
-
125
- term1 = shift.sin + latitude.sin * declination.sin
126
- term2 = latitude.cos * declination.cos
127
-
128
- -term1 / term2
129
- end
130
-
131
- def azimuth_ratio(latitude, apparent, vertical_shift)
132
- shift = if vertical_shift
133
- vertical_shift
134
- elsif apparent
135
- DEFAULT_REFRACTION_VERTICAL_SHIFT
136
- else
137
- Angle.zero
138
- end
139
-
140
- (declination.sin + shift.sin * latitude.cos) / (shift.cos * latitude.cos)
141
- end
142
-
143
- def azimuth_component(latitude)
144
- declination.sin / latitude.cos
145
- end
146
-
147
- def right_ascension
148
- @equatorial_coordinates.right_ascension
149
- end
150
-
151
- def declination
152
- @equatorial_coordinates.declination
153
- end
154
- end
155
- end