astronoby 0.7.0 → 0.8.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 +87 -3
- data/README.md +56 -32
- data/UPGRADING.md +50 -21
- data/docs/README.md +196 -0
- data/docs/angles.md +137 -0
- data/docs/celestial_bodies.md +107 -0
- data/docs/configuration.md +98 -0
- data/docs/coordinates.md +167 -0
- data/docs/ephem.md +85 -0
- data/docs/equinoxes_solstices_times.md +31 -0
- data/docs/glossary.md +152 -0
- data/docs/instant.md +139 -0
- data/docs/moon_phases.md +79 -0
- data/docs/observer.md +65 -0
- data/docs/reference_frames.md +138 -0
- data/docs/rise_transit_set_times.md +119 -0
- data/docs/twilight_times.md +123 -0
- data/lib/astronoby/bodies/earth.rb +8 -2
- data/lib/astronoby/bodies/jupiter.rb +17 -0
- data/lib/astronoby/bodies/mars.rb +17 -0
- data/lib/astronoby/bodies/mercury.rb +21 -0
- data/lib/astronoby/bodies/moon.rb +29 -36
- data/lib/astronoby/bodies/neptune.rb +21 -0
- data/lib/astronoby/bodies/saturn.rb +26 -0
- data/lib/astronoby/bodies/solar_system_body.rb +139 -29
- data/lib/astronoby/bodies/sun.rb +25 -2
- data/lib/astronoby/bodies/uranus.rb +5 -0
- data/lib/astronoby/bodies/venus.rb +25 -0
- data/lib/astronoby/cache.rb +188 -0
- data/lib/astronoby/configuration.rb +92 -0
- data/lib/astronoby/constants.rb +4 -1
- data/lib/astronoby/constellation.rb +12 -0
- data/lib/astronoby/constellations/data.rb +42 -0
- data/lib/astronoby/constellations/finder.rb +35 -0
- data/lib/astronoby/constellations/repository.rb +20 -0
- data/lib/astronoby/coordinates/equatorial.rb +3 -3
- data/lib/astronoby/data/constellations/constellation_names.dat +88 -0
- data/lib/astronoby/data/constellations/indexed_abbreviations.dat +88 -0
- data/lib/astronoby/data/constellations/radec_to_index.dat +238 -0
- data/lib/astronoby/data/constellations/sorted_declinations.dat +202 -0
- data/lib/astronoby/data/constellations/sorted_right_ascensions.dat +237 -0
- data/lib/astronoby/equinox_solstice.rb +2 -2
- data/lib/astronoby/events/moon_phases.rb +15 -14
- data/lib/astronoby/events/rise_transit_set_calculator.rb +32 -8
- data/lib/astronoby/events/twilight_calculator.rb +115 -60
- data/lib/astronoby/events/twilight_events.rb +28 -0
- data/lib/astronoby/instant.rb +7 -2
- data/lib/astronoby/julian_date.rb +78 -0
- data/lib/astronoby/mean_obliquity.rb +8 -10
- data/lib/astronoby/nutation.rb +11 -3
- data/lib/astronoby/observer.rb +1 -1
- data/lib/astronoby/precession.rb +48 -38
- data/lib/astronoby/reference_frame.rb +2 -1
- data/lib/astronoby/reference_frames/apparent.rb +1 -1
- data/lib/astronoby/reference_frames/mean_of_date.rb +1 -1
- data/lib/astronoby/reference_frames/topocentric.rb +1 -11
- data/lib/astronoby/time/greenwich_sidereal_time.rb +2 -2
- data/lib/astronoby/true_obliquity.rb +2 -3
- data/lib/astronoby/util/time.rb +1 -1
- data/lib/astronoby/version.rb +1 -1
- data/lib/astronoby.rb +8 -1
- metadata +59 -11
- data/Gemfile +0 -5
- data/Gemfile.lock +0 -102
- data/benchmark/README.md +0 -131
- data/benchmark/benchmark.rb +0 -259
- data/benchmark/data/imcce.csv.zip +0 -0
- data/benchmark/data/sun_calc.csv.zip +0 -0
- data/lib/astronoby/epoch.rb +0 -22
@@ -24,72 +24,114 @@ module Astronoby
|
|
24
24
|
@ephem = ephem
|
25
25
|
end
|
26
26
|
|
27
|
-
def event_on(date)
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
morning_civil = compute_twilight_time(
|
34
|
-
MORNING,
|
35
|
-
TWILIGHT_ANGLES[CIVIL],
|
36
|
-
observation_events,
|
37
|
-
equatorial_coordinates
|
38
|
-
)
|
39
|
-
|
40
|
-
evening_civil = compute_twilight_time(
|
41
|
-
EVENING,
|
42
|
-
TWILIGHT_ANGLES[CIVIL],
|
43
|
-
observation_events,
|
44
|
-
equatorial_coordinates
|
45
|
-
)
|
27
|
+
def event_on(date, utc_offset: 0)
|
28
|
+
start_time = Time
|
29
|
+
.new(date.year, date.month, date.day, 0, 0, 0, utc_offset)
|
30
|
+
end_time = Time
|
31
|
+
.new(date.year, date.month, date.day, 23, 59, 59, utc_offset)
|
32
|
+
events = events_between(start_time, end_time)
|
46
33
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
34
|
+
TwilightEvent.new(
|
35
|
+
morning_civil_twilight_time:
|
36
|
+
events.morning_civil_twilight_times.first,
|
37
|
+
evening_civil_twilight_time:
|
38
|
+
events.evening_civil_twilight_times.first,
|
39
|
+
morning_nautical_twilight_time:
|
40
|
+
events.morning_nautical_twilight_times.first,
|
41
|
+
evening_nautical_twilight_time:
|
42
|
+
events.evening_nautical_twilight_times.first,
|
43
|
+
morning_astronomical_twilight_time:
|
44
|
+
events.morning_astronomical_twilight_times.first,
|
45
|
+
evening_astronomical_twilight_time:
|
46
|
+
events.evening_astronomical_twilight_times.first
|
59
47
|
)
|
48
|
+
end
|
60
49
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
)
|
50
|
+
def events_between(start_time, end_time)
|
51
|
+
rts_events = Astronoby::RiseTransitSetCalculator.new(
|
52
|
+
body: Sun,
|
53
|
+
observer: @observer,
|
54
|
+
ephem: @ephem
|
55
|
+
).events_between(start_time, end_time)
|
56
|
+
|
57
|
+
equatorial_by_time = {}
|
58
|
+
|
59
|
+
(rts_events.rising_times + rts_events.setting_times)
|
60
|
+
.compact
|
61
|
+
.each do |event_time|
|
62
|
+
rounded_time = event_time.round
|
63
|
+
next if equatorial_by_time.key?(rounded_time)
|
64
|
+
|
65
|
+
instant = Instant.from_time(rounded_time)
|
66
|
+
sun_at_time = Sun.new(instant: instant, ephem: @ephem)
|
67
|
+
equatorial_by_time[rounded_time] = sun_at_time.apparent.equatorial
|
68
|
+
end
|
69
|
+
|
70
|
+
morning_civil = []
|
71
|
+
evening_civil = []
|
72
|
+
morning_nautical = []
|
73
|
+
evening_nautical = []
|
74
|
+
morning_astronomical = []
|
75
|
+
evening_astronomical = []
|
76
|
+
|
77
|
+
arrays_by_period = {
|
78
|
+
MORNING => {
|
79
|
+
CIVIL => morning_civil,
|
80
|
+
NAUTICAL => morning_nautical,
|
81
|
+
ASTRONOMICAL => morning_astronomical
|
82
|
+
},
|
83
|
+
EVENING => {
|
84
|
+
CIVIL => evening_civil,
|
85
|
+
NAUTICAL => evening_nautical,
|
86
|
+
ASTRONOMICAL => evening_astronomical
|
87
|
+
}
|
88
|
+
}
|
89
|
+
|
90
|
+
[
|
91
|
+
[rts_events.rising_times, MORNING],
|
92
|
+
[rts_events.setting_times, EVENING]
|
93
|
+
].each do |times, period|
|
94
|
+
times.each do |event_time|
|
95
|
+
next unless event_time
|
96
|
+
|
97
|
+
equatorial_coordinates = equatorial_by_time[event_time.round]
|
98
|
+
TWILIGHT_ANGLES.each do |twilight, angle|
|
99
|
+
arrays_by_period[period][twilight] << compute_twilight_time_from(
|
100
|
+
period,
|
101
|
+
angle,
|
102
|
+
event_time,
|
103
|
+
equatorial_coordinates
|
104
|
+
)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
67
108
|
|
68
|
-
|
69
|
-
EVENING,
|
70
|
-
TWILIGHT_ANGLES[ASTRONOMICAL],
|
71
|
-
observation_events,
|
72
|
-
equatorial_coordinates
|
73
|
-
)
|
109
|
+
within_range = ->(time) { time && time >= start_time && time <= end_time }
|
74
110
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
111
|
+
TwilightEvents.new(
|
112
|
+
morning_civil.select(&within_range),
|
113
|
+
evening_civil.select(&within_range),
|
114
|
+
morning_nautical.select(&within_range),
|
115
|
+
evening_nautical.select(&within_range),
|
116
|
+
morning_astronomical.select(&within_range),
|
117
|
+
evening_astronomical.select(&within_range)
|
82
118
|
)
|
83
119
|
end
|
84
120
|
|
85
|
-
def time_for_zenith_angle(
|
121
|
+
def time_for_zenith_angle(
|
122
|
+
date:,
|
123
|
+
period_of_the_day:,
|
124
|
+
zenith_angle:,
|
125
|
+
utc_offset: 0
|
126
|
+
)
|
86
127
|
unless PERIODS_OF_THE_DAY.include?(period_of_the_day)
|
87
128
|
raise IncompatibleArgumentsError,
|
88
|
-
"Only #{PERIODS_OF_THE_DAY.join(" or ")} are allowed as
|
129
|
+
"Only #{PERIODS_OF_THE_DAY.join(" or ")} are allowed as " \
|
130
|
+
"period_of_the_day, got #{period_of_the_day}"
|
89
131
|
end
|
90
132
|
|
91
|
-
observation_events = get_observation_events(date)
|
92
|
-
midday_instant = create_midday_instant(date)
|
133
|
+
observation_events = get_observation_events(date, utc_offset: utc_offset)
|
134
|
+
midday_instant = create_midday_instant(date, utc_offset: utc_offset)
|
93
135
|
sun_at_midday = Sun.new(instant: midday_instant, ephem: @ephem)
|
94
136
|
equatorial_coordinates = sun_at_midday.apparent.equatorial
|
95
137
|
|
@@ -103,17 +145,17 @@ module Astronoby
|
|
103
145
|
|
104
146
|
private
|
105
147
|
|
106
|
-
def create_midday_instant(date)
|
107
|
-
time = Time.
|
148
|
+
def create_midday_instant(date, utc_offset: 0)
|
149
|
+
time = Time.new(date.year, date.month, date.day, 12, 0, 0, utc_offset)
|
108
150
|
Instant.from_time(time)
|
109
151
|
end
|
110
152
|
|
111
|
-
def get_observation_events(date)
|
153
|
+
def get_observation_events(date, utc_offset: 0)
|
112
154
|
Astronoby::RiseTransitSetCalculator.new(
|
113
155
|
body: Sun,
|
114
156
|
observer: @observer,
|
115
157
|
ephem: @ephem
|
116
|
-
).event_on(date)
|
158
|
+
).event_on(date, utc_offset: utc_offset)
|
117
159
|
end
|
118
160
|
|
119
161
|
def compute_twilight_time(
|
@@ -128,8 +170,21 @@ module Astronoby
|
|
128
170
|
observation_events.setting_time
|
129
171
|
end
|
130
172
|
|
131
|
-
|
132
|
-
|
173
|
+
compute_twilight_time_from(
|
174
|
+
period_of_the_day,
|
175
|
+
zenith_angle,
|
176
|
+
period_time,
|
177
|
+
equatorial_coordinates
|
178
|
+
)
|
179
|
+
end
|
180
|
+
|
181
|
+
def compute_twilight_time_from(
|
182
|
+
period_of_the_day,
|
183
|
+
zenith_angle,
|
184
|
+
period_time,
|
185
|
+
equatorial_coordinates
|
186
|
+
)
|
187
|
+
# If the sun doesn't rise or set on this day, we can't calculate twilight
|
133
188
|
return nil unless period_time
|
134
189
|
|
135
190
|
hour_angle_at_period = equatorial_coordinates
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Astronoby
|
4
|
+
class TwilightEvents
|
5
|
+
attr_reader :morning_civil_twilight_times,
|
6
|
+
:evening_civil_twilight_times,
|
7
|
+
:morning_nautical_twilight_times,
|
8
|
+
:evening_nautical_twilight_times,
|
9
|
+
:morning_astronomical_twilight_times,
|
10
|
+
:evening_astronomical_twilight_times
|
11
|
+
|
12
|
+
def initialize(
|
13
|
+
morning_civil,
|
14
|
+
evening_civil,
|
15
|
+
morning_nautical,
|
16
|
+
evening_nautical,
|
17
|
+
morning_astronomical,
|
18
|
+
evening_astronomical
|
19
|
+
)
|
20
|
+
@morning_civil_twilight_times = morning_civil
|
21
|
+
@evening_civil_twilight_times = evening_civil
|
22
|
+
@morning_nautical_twilight_times = morning_nautical
|
23
|
+
@evening_nautical_twilight_times = evening_nautical
|
24
|
+
@morning_astronomical_twilight_times = morning_astronomical
|
25
|
+
@evening_astronomical_twilight_times = evening_astronomical
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/astronoby/instant.rb
CHANGED
@@ -21,7 +21,12 @@ module Astronoby
|
|
21
21
|
class Instant
|
22
22
|
include Comparable
|
23
23
|
|
24
|
-
|
24
|
+
# The adjustment value to align our noon-based Julian Date with the
|
25
|
+
# midnight-based epoch required by Ruby's `DateTime.jd` constructor.
|
26
|
+
# Our internal time values are standard astronomical Julian Dates, which
|
27
|
+
# start at noon. `DateTime.jd` expects a day that starts at the preceding
|
28
|
+
# midnight. This constant adds 0.5 days (12 hours) to make the conversion.
|
29
|
+
DATETIME_JD_EPOCH_ADJUSTMENT = 0.5
|
25
30
|
|
26
31
|
class << self
|
27
32
|
# Creates a new Instant from a Terrestrial Time value
|
@@ -90,7 +95,7 @@ module Astronoby
|
|
90
95
|
DateTime.jd(
|
91
96
|
@terrestrial_time -
|
92
97
|
Rational(delta_t / Constants::SECONDS_PER_DAY) +
|
93
|
-
|
98
|
+
DATETIME_JD_EPOCH_ADJUSTMENT
|
94
99
|
)
|
95
100
|
end
|
96
101
|
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Astronoby
|
4
|
+
# @see https://en.wikipedia.org/wiki/Julian_day
|
5
|
+
# @see https://en.wikipedia.org/wiki/Epoch_(astronomy)
|
6
|
+
class JulianDate
|
7
|
+
# Starting year for Besselian epoch calculations
|
8
|
+
# @return [Integer] 1900
|
9
|
+
BESSELIAN_EPOCH_STARTING_YEAR = 1900
|
10
|
+
|
11
|
+
# Starting year for Julian epoch calculations
|
12
|
+
# @return [Integer] 2000
|
13
|
+
JULIAN_EPOCH_STARTING_YEAR = 2000
|
14
|
+
|
15
|
+
# Julian Date for Besselian epoch 1875.0
|
16
|
+
# @return [Float] 2405889.258550475
|
17
|
+
B1875 = 2405889.258550475
|
18
|
+
|
19
|
+
# Julian Date for Besselian epoch 1900.0
|
20
|
+
# @return [Float] 2415020.31352
|
21
|
+
B1900 = 2415020.31352
|
22
|
+
|
23
|
+
# Julian Date for Julian epoch 1950.0
|
24
|
+
# @return [Float] 2433282.5
|
25
|
+
J1950 = 2433282.5
|
26
|
+
|
27
|
+
# Julian Date for Julian epoch 2000.0 (current standard)
|
28
|
+
# @return [Float] 2451545.0
|
29
|
+
J2000 = 2451545.0
|
30
|
+
|
31
|
+
# Default epoch used by the library
|
32
|
+
# @return [Float] 2451545.0
|
33
|
+
DEFAULT_EPOCH = J2000
|
34
|
+
|
35
|
+
# Converts a Time object to Julian Date
|
36
|
+
#
|
37
|
+
# @param time [Time] the time to convert
|
38
|
+
# @return [Rational] the Julian Date
|
39
|
+
#
|
40
|
+
# @example
|
41
|
+
# JulianDate.from_time(Time.utc(2000, 1, 1, 12, 0, 0))
|
42
|
+
# # => 2451545.0
|
43
|
+
def self.from_time(time)
|
44
|
+
time.to_datetime.ajd
|
45
|
+
end
|
46
|
+
|
47
|
+
# Converts a Julian year to Julian Date
|
48
|
+
#
|
49
|
+
# Uses the formula: JD = J2000 + 365.25 * (year - 2000)
|
50
|
+
#
|
51
|
+
# @param julian_year [Float] the Julian year
|
52
|
+
# @return [Float] the Julian Date
|
53
|
+
#
|
54
|
+
# @example
|
55
|
+
# JulianDate.from_julian_year(2025.0)
|
56
|
+
# # => 2460676.25
|
57
|
+
def self.from_julian_year(julian_year)
|
58
|
+
J2000 + Constants::DAYS_PER_JULIAN_YEAR *
|
59
|
+
(julian_year - JULIAN_EPOCH_STARTING_YEAR)
|
60
|
+
end
|
61
|
+
|
62
|
+
# Converts a Besselian year to Julian Date
|
63
|
+
#
|
64
|
+
# Uses the formula: JD = B1900 + 365.242198781 * (year - 1900)
|
65
|
+
# where 365.242198781 is the tropical year length at B1900.
|
66
|
+
#
|
67
|
+
# @param besselian_year [Float] the Besselian year
|
68
|
+
# @return [Float] the Julian Date
|
69
|
+
#
|
70
|
+
# @example
|
71
|
+
# JulianDate.from_besselian_year(1875.0)
|
72
|
+
# # => 2405889.258550475
|
73
|
+
def self.from_besselian_year(besselian_year)
|
74
|
+
B1900 + Constants::TROPICAL_YEAR_AT_B1900 *
|
75
|
+
(besselian_year - BESSELIAN_EPOCH_STARTING_YEAR)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -9,36 +9,34 @@ module Astronoby
|
|
9
9
|
# IAU resolution in 2006 in favor of the P03 astronomical model
|
10
10
|
# https://syrte.obspm.fr/iau2006/aa03_412_P03.pdf
|
11
11
|
|
12
|
-
EPOCH_OF_REFERENCE =
|
12
|
+
EPOCH_OF_REFERENCE = JulianDate::DEFAULT_EPOCH
|
13
13
|
OBLIQUITY_OF_REFERENCE = 23.4392794
|
14
14
|
|
15
|
-
def self.
|
16
|
-
return obliquity_of_reference if
|
15
|
+
def self.at(instant)
|
16
|
+
return obliquity_of_reference if instant.julian_date == EPOCH_OF_REFERENCE
|
17
17
|
|
18
18
|
t = Rational(
|
19
|
-
|
19
|
+
instant.julian_date - EPOCH_OF_REFERENCE,
|
20
20
|
Constants::DAYS_PER_JULIAN_CENTURY
|
21
21
|
)
|
22
22
|
|
23
|
-
epsilon0 =
|
23
|
+
epsilon0 = obliquity_of_reference_in_arcseconds
|
24
24
|
c1 = -46.836769
|
25
25
|
c2 = -0.0001831
|
26
26
|
c3 = 0.00200340
|
27
27
|
c4 = -0.000000576
|
28
28
|
c5 = -0.0000000434
|
29
29
|
|
30
|
-
Angle.
|
31
|
-
0,
|
32
|
-
0,
|
30
|
+
Angle.from_degree_arcseconds(
|
33
31
|
epsilon0 + t * (c1 + t * (c2 + t * (c3 + t * (c4 + t * c5))))
|
34
32
|
)
|
35
33
|
end
|
36
34
|
|
37
35
|
def self.obliquity_of_reference
|
38
|
-
Angle.
|
36
|
+
Angle.from_degree_arcseconds(obliquity_of_reference_in_arcseconds)
|
39
37
|
end
|
40
38
|
|
41
|
-
def self.
|
39
|
+
def self.obliquity_of_reference_in_arcseconds
|
42
40
|
84381.406
|
43
41
|
end
|
44
42
|
end
|
data/lib/astronoby/nutation.rb
CHANGED
@@ -104,7 +104,7 @@ module Astronoby
|
|
104
104
|
|
105
105
|
# @return [Matrix] The nutation matrix
|
106
106
|
def matrix
|
107
|
-
mean_obliquity = MeanObliquity.
|
107
|
+
mean_obliquity = MeanObliquity.at(@instant)
|
108
108
|
true_obliquity = mean_obliquity + nutation_in_obliquity
|
109
109
|
build_nutation_matrix(
|
110
110
|
mean_obliquity: mean_obliquity,
|
@@ -125,6 +125,14 @@ module Astronoby
|
|
125
125
|
|
126
126
|
private
|
127
127
|
|
128
|
+
def cache_key
|
129
|
+
@_cache_key ||= CacheKey.generate(:nutation, @instant)
|
130
|
+
end
|
131
|
+
|
132
|
+
def cache
|
133
|
+
Astronoby.cache
|
134
|
+
end
|
135
|
+
|
128
136
|
def iau2000a
|
129
137
|
a = fundamental_arguments
|
130
138
|
|
@@ -172,7 +180,7 @@ module Astronoby
|
|
172
180
|
end
|
173
181
|
|
174
182
|
def iau2000b_angles
|
175
|
-
|
183
|
+
cache.fetch(cache_key) do
|
176
184
|
dpsi, deps = iau2000b
|
177
185
|
dpsi = Angle.from_degree_arcseconds(dpsi / 1e7)
|
178
186
|
deps = Angle.from_degree_arcseconds(deps / 1e7)
|
@@ -206,7 +214,7 @@ module Astronoby
|
|
206
214
|
|
207
215
|
def julian_centuries
|
208
216
|
@julian_centuries ||=
|
209
|
-
(@instant.tt -
|
217
|
+
(@instant.tt - JulianDate::J2000) / Constants::DAYS_PER_JULIAN_CENTURY
|
210
218
|
end
|
211
219
|
|
212
220
|
# IAU 2006/2000A formula for the mean anomaly of the Moon
|
data/lib/astronoby/observer.rb
CHANGED
@@ -62,7 +62,7 @@ module Astronoby
|
|
62
62
|
def earth_fixed_rotation_matrix_for(instant)
|
63
63
|
dpsi = Nutation.new(instant: instant).nutation_in_longitude
|
64
64
|
|
65
|
-
mean_obliquity = MeanObliquity.
|
65
|
+
mean_obliquity = MeanObliquity.at(instant)
|
66
66
|
|
67
67
|
gast = Angle.from_radians(
|
68
68
|
Angle.from_hours(instant.gmst).radians +
|
data/lib/astronoby/precession.rb
CHANGED
@@ -16,41 +16,43 @@ module Astronoby
|
|
16
16
|
# https://syrte.obspm.fr/iau2006/aa03_412_P03.pdf
|
17
17
|
# P(t) = R3(χA) R1(−ωA) R3(−ψA) R1(ϵ0)
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
19
|
+
cache.fetch(cache_key) do
|
20
|
+
# Precession in right ascension
|
21
|
+
psi_a = ((((
|
22
|
+
-0.0000000951 * t +
|
23
|
+
+0.000132851) * t +
|
24
|
+
-0.00114045) * t +
|
25
|
+
-1.0790069) * t +
|
26
|
+
+5038.481507) * t
|
27
|
+
|
28
|
+
# Precession in declination
|
29
|
+
omega_a = ((((
|
30
|
+
+0.0000003337 * t +
|
31
|
+
-0.000000467) * t +
|
32
|
+
-0.00772503) * t +
|
33
|
+
+0.0512623) * t +
|
34
|
+
-0.025754) * t +
|
35
|
+
eps0
|
36
|
+
|
37
|
+
# Precession of the ecliptic
|
38
|
+
chi_a = ((((
|
39
|
+
-0.0000000560 * t +
|
40
|
+
+0.000170663) * t +
|
41
|
+
-0.00121197) * t +
|
42
|
+
-2.3814292) * t +
|
43
|
+
+10.556403) * t
|
44
|
+
|
45
|
+
psi_a = Angle.from_degree_arcseconds(psi_a)
|
46
|
+
omega_a = Angle.from_degree_arcseconds(omega_a)
|
47
|
+
chi_a = Angle.from_degree_arcseconds(chi_a)
|
48
|
+
|
49
|
+
r3_psi = rotation_z(-psi_a)
|
50
|
+
r1_omega = rotation_x(-omega_a)
|
51
|
+
r3_chi = rotation_z(chi_a)
|
52
|
+
r1_eps0 = rotation_x(MeanObliquity.obliquity_of_reference)
|
53
|
+
|
54
|
+
r3_chi * r1_omega * r3_psi * r1_eps0
|
55
|
+
end
|
54
56
|
end
|
55
57
|
|
56
58
|
def rotation_x(angle)
|
@@ -106,7 +108,7 @@ module Astronoby
|
|
106
108
|
end
|
107
109
|
|
108
110
|
def self.matrix_for_epoch(epoch)
|
109
|
-
t = (epoch -
|
111
|
+
t = (epoch - JulianDate::DEFAULT_EPOCH) / Constants::DAYS_PER_JULIAN_CENTURY
|
110
112
|
|
111
113
|
zeta = Angle.from_degrees(
|
112
114
|
0.6406161 * t + 0.0000839 * t * t + 0.000005 * t * t * t
|
@@ -146,15 +148,23 @@ module Astronoby
|
|
146
148
|
|
147
149
|
private
|
148
150
|
|
151
|
+
def cache_key
|
152
|
+
@_cache_key ||= CacheKey.generate(:precession, @instant)
|
153
|
+
end
|
154
|
+
|
155
|
+
def cache
|
156
|
+
Astronoby.cache
|
157
|
+
end
|
158
|
+
|
149
159
|
def t
|
150
160
|
@t ||= Rational(
|
151
|
-
@instant.tdb -
|
161
|
+
@instant.tdb - JulianDate::DEFAULT_EPOCH,
|
152
162
|
Constants::DAYS_PER_JULIAN_CENTURY
|
153
163
|
)
|
154
164
|
end
|
155
165
|
|
156
166
|
def eps0
|
157
|
-
@eps0 ||= MeanObliquity.
|
167
|
+
@eps0 ||= MeanObliquity.obliquity_of_reference_in_arcseconds
|
158
168
|
end
|
159
169
|
end
|
160
170
|
end
|
@@ -34,7 +34,8 @@ module Astronoby
|
|
34
34
|
@ecliptic ||= begin
|
35
35
|
return Coordinates::Ecliptic.zero if distance.zero?
|
36
36
|
|
37
|
-
|
37
|
+
j2000 = Instant.from_terrestrial_time(JulianDate::J2000)
|
38
|
+
equatorial.to_ecliptic(instant: j2000)
|
38
39
|
end
|
39
40
|
end
|
40
41
|
|
@@ -48,21 +48,11 @@ module Astronoby
|
|
48
48
|
@observer = observer
|
49
49
|
end
|
50
50
|
|
51
|
-
def angular_diameter
|
52
|
-
@angular_radius ||= begin
|
53
|
-
return Angle.zero if @position.zero?
|
54
|
-
|
55
|
-
Angle.from_radians(
|
56
|
-
Math.atan(@target_body.class::EQUATORIAL_RADIUS.m / distance.m) * 2
|
57
|
-
)
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
51
|
def ecliptic
|
62
52
|
@ecliptic ||= begin
|
63
53
|
return Coordinates::Ecliptic.zero if distance.zero?
|
64
54
|
|
65
|
-
equatorial.to_ecliptic(
|
55
|
+
equatorial.to_ecliptic(instant: @instant)
|
66
56
|
end
|
67
57
|
end
|
68
58
|
|
@@ -20,7 +20,7 @@ module Astronoby
|
|
20
20
|
def self.from_utc(utc)
|
21
21
|
date = utc.to_date
|
22
22
|
julian_day = utc.to_date.ajd
|
23
|
-
t = (julian_day -
|
23
|
+
t = (julian_day - JulianDate::J2000) / Constants::DAYS_PER_JULIAN_CENTURY
|
24
24
|
t0 = (
|
25
25
|
(JULIAN_CENTURIES_EXPONENTS[0] +
|
26
26
|
(JULIAN_CENTURIES_EXPONENTS[1] * t) +
|
@@ -51,7 +51,7 @@ module Astronoby
|
|
51
51
|
def to_utc
|
52
52
|
date = @date
|
53
53
|
julian_day = @date.ajd
|
54
|
-
t = (julian_day -
|
54
|
+
t = (julian_day - JulianDate::J2000) / Constants::DAYS_PER_JULIAN_CENTURY
|
55
55
|
|
56
56
|
t0 = (
|
57
57
|
(JULIAN_CENTURIES_EXPONENTS[0] +
|
@@ -2,9 +2,8 @@
|
|
2
2
|
|
3
3
|
module Astronoby
|
4
4
|
class TrueObliquity
|
5
|
-
def self.
|
6
|
-
|
7
|
-
mean_obliquity = MeanObliquity.for_epoch(epoch)
|
5
|
+
def self.at(instant)
|
6
|
+
mean_obliquity = MeanObliquity.at(instant)
|
8
7
|
nutation = Nutation.new(instant: instant).nutation_in_obliquity
|
9
8
|
|
10
9
|
mean_obliquity + nutation
|
data/lib/astronoby/util/time.rb
CHANGED
@@ -496,7 +496,7 @@ module Astronoby
|
|
496
496
|
when Numeric
|
497
497
|
instant
|
498
498
|
when ::Time, ::Date, ::DateTime
|
499
|
-
|
499
|
+
JulianDate.from_time(instant)
|
500
500
|
else
|
501
501
|
raise IncompatibleArgumentsError,
|
502
502
|
"Expected a Numeric, Time, Date or DateTime object, got #{instant.class}"
|
data/lib/astronoby/version.rb
CHANGED