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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +132 -0
- data/Gemfile.lock +19 -17
- data/README.md +195 -25
- data/UPGRADING.md +72 -0
- data/lib/astronoby/aberration.rb +7 -5
- data/lib/astronoby/angle.rb +26 -34
- data/lib/astronoby/astronomical_models/ephemeride_lunaire_parisienne.rb +143 -0
- data/lib/astronoby/astronomical_models/moon_phases_periodic_terms.rb +249 -0
- data/lib/astronoby/bodies/moon.rb +335 -0
- data/lib/astronoby/bodies/sun.rb +129 -132
- data/lib/astronoby/constants.rb +31 -0
- data/lib/astronoby/coordinates/ecliptic.rb +4 -4
- data/lib/astronoby/coordinates/equatorial.rb +7 -5
- data/lib/astronoby/coordinates/horizontal.rb +24 -12
- data/lib/astronoby/distance.rb +83 -0
- data/lib/astronoby/epoch.rb +0 -2
- data/lib/astronoby/equinox_solstice.rb +3 -2
- data/lib/astronoby/events/moon_phases.rb +143 -0
- data/lib/astronoby/events/observation_events.rb +259 -0
- data/lib/astronoby/events/rise_transit_set_iteration.rb +215 -0
- data/lib/astronoby/events/twilight_events.rb +121 -0
- data/lib/astronoby/geocentric_parallax.rb +36 -56
- data/lib/astronoby/mean_obliquity.rb +2 -2
- data/lib/astronoby/moon_phase.rb +43 -0
- data/lib/astronoby/nutation.rb +5 -3
- data/lib/astronoby/observer.rb +39 -18
- data/lib/astronoby/precession.rb +1 -1
- data/lib/astronoby/refraction.rb +8 -10
- data/lib/astronoby/time/greenwich_sidereal_time.rb +18 -29
- data/lib/astronoby/time/local_sidereal_time.rb +4 -4
- data/lib/astronoby/util/maths.rb +72 -0
- data/lib/astronoby/util/time.rb +88 -0
- data/lib/astronoby/util/trigonometry.rb +4 -4
- data/lib/astronoby/version.rb +1 -1
- data/lib/astronoby.rb +12 -1
- metadata +15 -4
- data/lib/astronoby/body.rb +0 -155
data/lib/astronoby/refraction.rb
CHANGED
@@ -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
|
9
|
-
new(coordinates
|
8
|
+
def self.angle(coordinates:)
|
9
|
+
new(coordinates).refraction_angle
|
10
10
|
end
|
11
11
|
|
12
|
-
def self.correct_horizontal_coordinates(coordinates
|
13
|
-
new(coordinates
|
12
|
+
def self.correct_horizontal_coordinates(coordinates:)
|
13
|
+
new(coordinates).refract
|
14
14
|
end
|
15
15
|
|
16
|
-
def initialize(coordinates
|
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
|
-
|
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
|
-
|
7
|
-
|
8
|
-
|
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) /
|
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)) %
|
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 /
|
30
|
-
(utc.sec + utc.subsec) /
|
31
|
+
utc.min / Constants::MINUTES_PER_HOUR +
|
32
|
+
(utc.sec + utc.subsec) / Constants::SECONDS_PER_HOUR
|
31
33
|
|
32
|
-
gmst =
|
33
|
-
gmst +=
|
34
|
-
gmst -=
|
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) /
|
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)) %
|
59
|
+
(JULIAN_CENTURIES_EXPONENTS[2] * t * t)) % Constants::HOURS_PER_DAY
|
58
60
|
).abs
|
59
61
|
|
60
62
|
a = @time - t0
|
61
|
-
a +=
|
62
|
-
a -=
|
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 =
|
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 +=
|
16
|
-
time -=
|
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 +=
|
36
|
-
time -=
|
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(
|
16
|
+
return Angle.from_degrees(
|
17
|
+
angle.degrees + Constants::DEGREES_PER_CIRCLE
|
18
|
+
)
|
19
19
|
end
|
20
20
|
|
21
|
-
Angle.from_degrees(angle.degrees +
|
21
|
+
Angle.from_degrees(angle.degrees + Constants::DEGREES_PER_CIRCLE / 2)
|
22
22
|
end
|
23
23
|
end
|
24
24
|
end
|
data/lib/astronoby/version.rb
CHANGED
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/
|
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.
|
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-
|
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/
|
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.
|
140
|
+
version: 3.0.0
|
130
141
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
131
142
|
requirements:
|
132
143
|
- - ">="
|
data/lib/astronoby/body.rb
DELETED
@@ -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
|