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:



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

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_distanceNumeric

Returns Earth-Sun distance in meters.

Returns:

  • (Numeric)

    Earth-Sun distance in meters



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

def earth_distance
  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(latitude:, longitude:) ⇒ Astronoby::Coordinates::Horizontal

Computes the Sun’s horizontal coordinates

Parameters:

Returns:



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

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

#longitude_at_perigeeAstronoby::Angle

Returns Sun’s longitude at perigee.

Returns:



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

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

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

Returns Sun’s observation events.

Parameters:

Returns:



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
151
# File 'lib/astronoby/bodies/sun.rb', line 115

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:



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

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:



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

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:



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

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