Class: Astronoby::Sun

Inherits:
Object
  • Object
show all
Defined in:
lib/astronoby/bodies/sun.rb

Constant Summary collapse

SEMI_MAJOR_AXIS_IN_METERS =
149_598_500_000
ANGULAR_DIAMETER =
Angle.from_degrees(0.533128)
INTERPOLATION_FACTOR =
24.07
TWILIGHTS =
[
  CIVIL = :civil,
  NAUTICAL = :nautical,
  ASTRONOMICAL = :astronomical
].freeze
TWILIGHT_ANGLES =
{
  CIVIL => Angle.from_degrees(96),
  NAUTICAL => Angle.from_degrees(102),
  ASTRONOMICAL => Angle.from_degrees(108)
}.freeze
PERIODS_OF_THE_DAY =
[
  MORNING = :morning,
  EVENING = :evening
].freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(time:) ⇒ Sun

Returns a new instance of Sun.

Parameters:

  • time (Time)

    Considered time



73
74
75
# File 'lib/astronoby/bodies/sun.rb', line 73

def initialize(time:)
  @time = time
end

Instance Attribute Details

#timeObject (readonly)

Returns the value of attribute time.



26
27
28
# File 'lib/astronoby/bodies/sun.rb', line 26

def time
  @time
end

Class Method Details

.equation_of_time(date_or_time:) ⇒ Integer

Returns Equation of time in seconds.

Parameters:

  • date_or_time (Date, Time)

    Requested date

Returns:

  • (Integer)

    Equation of time in seconds



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/astronoby/bodies/sun.rb', line 36

def self.equation_of_time(date_or_time:)
  noon = Time.utc(date_or_time.year, date_or_time.month, date_or_time.day, 12)
  time = date_or_time.is_a?(Time) ? date_or_time : noon
  epoch = Epoch.from_time(time)
  sun = new(time: time)
  right_ascension = sun
    .apparent_ecliptic_coordinates
    .to_apparent_equatorial(epoch: epoch)
    .right_ascension
  t = (epoch - Epoch::J2000) / Constants::DAYS_PER_JULIAN_MILLENIA
  l0 = (280.4664567 +
    360_007.6982779 * t +
    0.03032028 * t**2 +
    t**3 / 49_931 -
    t**4 / 15_300 -
    t**5 / 2_000_000) % Constants::DEGREES_PER_CIRCLE
  nutation = Nutation.for_ecliptic_longitude(epoch: epoch)
  obliquity = TrueObliquity.for_epoch(epoch)

  (
    Angle
     .from_degrees(
       l0 -
       Constants::EQUATION_OF_TIME_CONSTANT -
       right_ascension.degrees +
       nutation.degrees * obliquity.cos
     ).hours * Constants::SECONDS_PER_HOUR
  ).round
end

Instance Method Details

#angular_sizeAstronoby::Angle

Returns Apparent Sun’s angular size.

Returns:



166
167
168
169
170
# File 'lib/astronoby/bodies/sun.rb', line 166

def angular_size
  Angle.from_degrees(
    ANGULAR_DIAMETER.degrees * distance_angular_size_factor
  )
end

#apparent_ecliptic_coordinatesObject



88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/astronoby/bodies/sun.rb', line 88

def apparent_ecliptic_coordinates
  nutation = Nutation.for_ecliptic_longitude(epoch: epoch)
  longitude_with_aberration = Aberration.for_ecliptic_coordinates(
    coordinates: true_ecliptic_coordinates,
    epoch: epoch
  ).longitude
  apparent_longitude = nutation + longitude_with_aberration

  Coordinates::Ecliptic.new(
    latitude: Angle.zero,
    longitude: apparent_longitude
  )
end

#earth_distanceAstronoby::Distance

Returns Earth-Sun distance.

Returns:



159
160
161
162
163
# File 'lib/astronoby/bodies/sun.rb', line 159

def earth_distance
  Distance.from_meters(
    SEMI_MAJOR_AXIS_IN_METERS / distance_angular_size_factor
  )
end

#epochObject



77
78
79
# File 'lib/astronoby/bodies/sun.rb', line 77

def epoch
  @epoch ||= Epoch.from_time(@time)
end

#horizontal_coordinates(observer:) ⇒ Astronoby::Coordinates::Horizontal

Computes the Sun’s horizontal coordinates

Parameters:

Returns:



106
107
108
109
110
# File 'lib/astronoby/bodies/sun.rb', line 106

def horizontal_coordinates(observer:)
  apparent_ecliptic_coordinates
    .to_apparent_equatorial(epoch: epoch)
    .to_horizontal(time: @time, observer: observer)
end

#longitude_at_perigeeAstronoby::Angle

Returns Sun’s longitude at perigee.

Returns:



199
200
201
202
203
204
# File 'lib/astronoby/bodies/sun.rb', line 199

def longitude_at_perigee
  Angle.from_degrees(
    (281.2208444 + 1.719175 * centuries + 0.000452778 * centuries**2) %
      Constants::DEGREES_PER_CIRCLE
  )
end

#mean_anomalyAstronoby::Angle

Returns Sun’s mean anomaly.

Returns:



191
192
193
194
195
196
# File 'lib/astronoby/bodies/sun.rb', line 191

def mean_anomaly
  Angle.from_degrees(
    (longitude_at_base_epoch - longitude_at_perigee).degrees %
      Constants::DEGREES_PER_CIRCLE
  )
end

#observation_events(observer:) ⇒ Astronoby::Events::ObservationEvents

Returns Sun’s observation events.

Parameters:

Returns:



114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/astronoby/bodies/sun.rb', line 114

def observation_events(observer:)
  today = @time.to_date
  leap_seconds = Util::Time.terrestrial_universal_time_delta(today)
  yesterday = today.prev_day
  yesterday_midnight_terrestrial_time =
    Time.utc(yesterday.year, yesterday.month, yesterday.day) - leap_seconds
  yesterday_epoch = Epoch.from_time(yesterday_midnight_terrestrial_time)
  today_midnight_terrestrial_time =
    Time.utc(today.year, today.month, today.day) - leap_seconds
  today_epoch = Epoch.from_time(today_midnight_terrestrial_time)
  tomorrow = today.next_day
  tomorrow_midnight_terrestrial_time =
    Time.utc(tomorrow.year, tomorrow.month, tomorrow.day) - leap_seconds
  tomorrow_epoch = Epoch.from_time(tomorrow_midnight_terrestrial_time)

  coordinates_of_the_previous_day = self.class
    .new(time: yesterday_midnight_terrestrial_time)
    .apparent_ecliptic_coordinates
    .to_apparent_equatorial(epoch: yesterday_epoch)
  coordinates_of_the_day = self.class
    .new(time: today_midnight_terrestrial_time)
    .apparent_ecliptic_coordinates
    .to_apparent_equatorial(epoch: today_epoch)
  coordinates_of_the_next_day = self.class
    .new(time: tomorrow_midnight_terrestrial_time)
    .apparent_ecliptic_coordinates
    .to_apparent_equatorial(epoch: tomorrow_epoch)

  Events::ObservationEvents.new(
    observer: observer,
    date: today,
    coordinates_of_the_previous_day: coordinates_of_the_previous_day,
    coordinates_of_the_day: coordinates_of_the_day,
    coordinates_of_the_next_day: coordinates_of_the_next_day,
    additional_altitude: Angle.from_degrees(angular_size.degrees / 2)
  )
end

#orbital_eccentricityAstronoby::Angle

Returns Sun’s orbital eccentricity.

Returns:



207
208
209
210
211
212
# File 'lib/astronoby/bodies/sun.rb', line 207

def orbital_eccentricity
  Angle.from_degrees(
    (0.01675104 - 0.0000418 * centuries - 0.000000126 * centuries**2) %
      Constants::DEGREES_PER_CIRCLE
  )
end

#true_anomalyAstronoby::Angle

Returns Sun’s true anomaly.

Returns:



173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
# File 'lib/astronoby/bodies/sun.rb', line 173

def true_anomaly
  eccentric_anomaly = Util::Astrodynamics.eccentric_anomaly_newton_raphson(
    mean_anomaly,
    orbital_eccentricity.degrees,
    2e-06,
    10
  )

  tan = Math.sqrt(
    (1 + orbital_eccentricity.degrees) / (1 - orbital_eccentricity.degrees)
  ) * Math.tan(eccentric_anomaly.radians / 2)

  Angle.from_degrees(
    (Angle.atan(tan).degrees * 2) % Constants::DEGREES_PER_CIRCLE
  )
end

#true_ecliptic_coordinatesObject



81
82
83
84
85
86
# File 'lib/astronoby/bodies/sun.rb', line 81

def true_ecliptic_coordinates
  Coordinates::Ecliptic.new(
    latitude: Angle.zero,
    longitude: true_longitude
  )
end

#twilight_events(observer:) ⇒ Astronoby::Events::TwilightEvents

Returns Sun’s twilight events.

Parameters:

Returns:



154
155
156
# File 'lib/astronoby/bodies/sun.rb', line 154

def twilight_events(observer:)
  Events::TwilightEvents.new(sun: self, observer: observer)
end