Skip to content

Commit

Permalink
Dedicated constants class (#62)
Browse files Browse the repository at this point in the history
This creates a new `Astronoby::Constants` where are stored constants used across the library.

Fixes #59
  • Loading branch information
rhannequin committed Apr 16, 2024
1 parent c5eb2b8 commit 26b69c8
Show file tree
Hide file tree
Showing 19 changed files with 148 additions and 91 deletions.
1 change: 1 addition & 0 deletions lib/astronoby.rb
@@ -1,5 +1,6 @@
# frozen_string_literal: true

require "astronoby/constants"
require "astronoby/angle"
require "astronoby/angles/dms"
require "astronoby/angles/hms"
Expand Down
10 changes: 6 additions & 4 deletions lib/astronoby/aberration.rb
Expand Up @@ -2,6 +2,8 @@

module Astronoby
class Aberration
MAXIMUM_SHIFT = Angle.from_degrees(20.5)

def self.for_ecliptic_coordinates(coordinates:, epoch:)
new(coordinates, epoch).apply
end
Expand All @@ -18,15 +20,15 @@ def initialize(coordinates, epoch)
# Chapter: 36 - Aberration
def apply
delta_longitude = Angle.from_degrees(
-20.5 * (
-MAXIMUM_SHIFT.degrees * (
sun_longitude - @coordinates.longitude
).cos / @coordinates.latitude.cos / 3600
).cos / @coordinates.latitude.cos / Constants::SECONDS_PER_DEGREE
)

delta_latitude = Angle.from_degrees(
-20.5 *
-MAXIMUM_SHIFT.degrees *
(sun_longitude - @coordinates.longitude).sin *
@coordinates.latitude.sin / 3600
@coordinates.latitude.sin / Constants::SECONDS_PER_DEGREE
)

Coordinates::Ecliptic.new(
Expand Down
41 changes: 18 additions & 23 deletions lib/astronoby/angle.rb
Expand Up @@ -5,16 +5,6 @@ class Angle
include Comparable

MIN_PRECISION = 10
PI_IN_DEGREES = 180.0

FULL_CIRCLE_IN_RADIANS = (2 * Math::PI)

RADIAN_PER_HOUR = Math::PI / 12.0
MINUTES_PER_DEGREE = 60.0
MINUTES_PER_HOUR = 60.0
SECONDS_PER_MINUTE = 60.0
SECONDS_PER_HOUR = MINUTES_PER_HOUR * SECONDS_PER_MINUTE

FORMATS = %i[dms hms].freeze

class << self
Expand All @@ -23,28 +13,32 @@ def zero
end

def from_radians(radians)
normalized_radians = radians.remainder(FULL_CIRCLE_IN_RADIANS)
normalized_radians = radians.remainder(Constants::RADIANS_PER_CIRCLE)
new(normalized_radians)
end

def from_degrees(degrees)
radians = degrees / PI_IN_DEGREES * Math::PI
radians = degrees / Constants::PI_IN_DEGREES * Math::PI
from_radians(radians)
end

def from_hours(hours)
radians = hours * RADIAN_PER_HOUR
radians = hours * Constants::RADIAN_PER_HOUR
from_radians(radians)
end

def from_hms(hour, minute, second)
hours = hour + minute / MINUTES_PER_HOUR + second / SECONDS_PER_HOUR
hours = hour +
minute / Constants::MINUTES_PER_HOUR +
second / Constants::SECONDS_PER_HOUR
from_hours(hours)
end

def from_dms(degree, minute, second)
sign = degree.negative? ? -1 : 1
degrees = degree.abs + minute / MINUTES_PER_HOUR + second / SECONDS_PER_HOUR
degrees = degree.abs +
minute / Constants::MINUTES_PER_HOUR +
second / Constants::SECONDS_PER_HOUR
from_degrees(sign * degrees)
end

Expand Down Expand Up @@ -72,11 +66,11 @@ def initialize(radians)
end

def degrees
@radians * PI_IN_DEGREES / Math::PI
@radians * Constants::PI_IN_DEGREES / Math::PI
end

def hours
@radians / RADIAN_PER_HOUR
@radians / Constants::RADIAN_PER_HOUR
end

def +(other)
Expand Down Expand Up @@ -141,12 +135,13 @@ def to_dms(deg)
sign = deg.negative? ? "-" : "+"
absolute_degrees = deg.abs
degrees = absolute_degrees.floor
decimal_minutes = MINUTES_PER_DEGREE * (absolute_degrees - degrees)
decimal_minutes = Constants::MINUTES_PER_DEGREE *
(absolute_degrees - degrees)
absolute_decimal_minutes = (
MINUTES_PER_DEGREE * (absolute_degrees - degrees)
Constants::MINUTES_PER_DEGREE * (absolute_degrees - degrees)
).abs
minutes = decimal_minutes.floor
seconds = SECONDS_PER_MINUTE * (
seconds = Constants::SECONDS_PER_MINUTE * (
absolute_decimal_minutes - absolute_decimal_minutes.floor
)

Expand All @@ -156,12 +151,12 @@ def to_dms(deg)
def to_hms(hrs)
absolute_hours = hrs.abs
hours = absolute_hours.floor
decimal_minutes = MINUTES_PER_HOUR * (absolute_hours - hours)
decimal_minutes = Constants::MINUTES_PER_HOUR * (absolute_hours - hours)
absolute_decimal_minutes = (
MINUTES_PER_HOUR * (absolute_hours - hours)
Constants::MINUTES_PER_HOUR * (absolute_hours - hours)
).abs
minutes = decimal_minutes.floor
seconds = SECONDS_PER_MINUTE * (
seconds = Constants::SECONDS_PER_MINUTE * (
absolute_decimal_minutes - absolute_decimal_minutes.floor
)

Expand Down
21 changes: 14 additions & 7 deletions lib/astronoby/bodies/sun.rb
Expand Up @@ -153,34 +153,40 @@ def true_anomaly
(1 + orbital_eccentricity.degrees) / (1 - orbital_eccentricity.degrees)
) * Math.tan(eccentric_anomaly.radians / 2)

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

# @return [Astronoby::Angle] Sun's longitude at perigee
def longitude_at_perigee
Angle.from_degrees(
(281.2208444 + 1.719175 * centuries + 0.000452778 * centuries**2) % 360
(281.2208444 + 1.719175 * centuries + 0.000452778 * centuries**2) %
Constants::DEGREES_PER_CIRCLE
)
end

# @return [Astronoby::Angle] Sun's orbital eccentricity
def orbital_eccentricity
Angle.from_degrees(
(0.01675104 - 0.0000418 * centuries - 0.000000126 * centuries**2) % 360
(0.01675104 - 0.0000418 * centuries - 0.000000126 * centuries**2) %
Constants::DEGREES_PER_CIRCLE
)
end

private

def true_longitude
Angle.from_degrees(
(true_anomaly + longitude_at_perigee).degrees % 360
(true_anomaly + longitude_at_perigee).degrees %
Constants::DEGREES_PER_CIRCLE
)
end

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

Expand All @@ -189,12 +195,13 @@ def days_since_epoch
end

def centuries
@centuries ||= (@epoch - Epoch::J1900) / Epoch::DAYS_PER_JULIAN_CENTURY
@centuries ||= (@epoch - Epoch::J1900) / Constants::DAYS_PER_JULIAN_CENTURY
end

def longitude_at_base_epoch
Angle.from_degrees(
(279.6966778 + 36000.76892 * centuries + 0.0003025 * centuries**2) % 360
(279.6966778 + 36000.76892 * centuries + 0.0003025 * centuries**2) %
Constants::DEGREES_PER_CIRCLE
)
end

Expand Down
22 changes: 22 additions & 0 deletions lib/astronoby/constants.rb
@@ -0,0 +1,22 @@
# frozen_string_literal: true

module Astronoby
class Constants
DAYS_PER_JULIAN_CENTURY = 36525.0

HOURS_PER_DAY = 24.0
DEGREES_PER_CIRCLE = 360.0
RADIANS_PER_CIRCLE = 2 * Math::PI

SECONDS_PER_MINUTE = 60.0
MINUTES_PER_HOUR = 60.0
MINUTES_PER_DEGREE = 60.0

SECONDS_PER_HOUR = SECONDS_PER_MINUTE * MINUTES_PER_HOUR
SECONDS_PER_DAY = SECONDS_PER_HOUR * HOURS_PER_DAY
SECONDS_PER_DEGREE = SECONDS_PER_MINUTE * MINUTES_PER_DEGREE
RADIAN_PER_HOUR = Math::PI / 12.0

PI_IN_DEGREES = 180.0
end
end
5 changes: 3 additions & 2 deletions lib/astronoby/coordinates/equatorial.rb
Expand Up @@ -23,7 +23,7 @@ def compute_hour_angle(time:, longitude:)
.to_lst(longitude: longitude)

ha = (lst.time - @right_ascension.hours)
ha += 24 if ha.negative?
ha += Constants::HOURS_PER_DAY if ha.negative?

Angle.from_hours(ha)
end
Expand All @@ -39,7 +39,8 @@ def to_horizontal(time:, latitude:, longitude:)
azimuth = Angle.acos(t2)

if ha.sin.positive?
azimuth = Angle.from_degrees(360 - azimuth.degrees)
azimuth =
Angle.from_degrees(Constants::DEGREES_PER_CIRCLE - azimuth.degrees)
end

Horizontal.new(
Expand Down
8 changes: 6 additions & 2 deletions lib/astronoby/coordinates/horizontal.rb
Expand Up @@ -31,7 +31,7 @@ def to_equatorial(time:)

if @azimuth.sin.positive?
hour_angle_degrees = Angle
.from_degrees(360 - hour_angle_degrees)
.from_degrees(Constants::DEGREES_PER_CIRCLE - hour_angle_degrees)
.degrees
end

Expand All @@ -40,7 +40,11 @@ def to_equatorial(time:)
.from_utc(time.utc)
.to_lst(longitude: @longitude)
right_ascension_decimal = lst.time - hour_angle_hours
right_ascension_decimal += 24 if right_ascension_decimal.negative?

if right_ascension_decimal.negative?
right_ascension_decimal += Constants::HOURS_PER_DAY
end

right_ascension = Angle.from_hours(right_ascension_decimal)

Equatorial.new(
Expand Down
2 changes: 0 additions & 2 deletions lib/astronoby/epoch.rb
Expand Up @@ -9,8 +9,6 @@ class Epoch
J2000 = 2451545.0

DEFAULT_EPOCH = J2000
DAYS_PER_JULIAN_CENTURY = 36525.0

JULIAN_DAY_NUMBER_OFFSET = 0.5

def self.from_time(time)
Expand Down
2 changes: 1 addition & 1 deletion lib/astronoby/equinox_solstice.rb
Expand Up @@ -101,7 +101,7 @@ def initialize(year, event)
end

def compute
t = (julian_day - Epoch::J2000) / Epoch::DAYS_PER_JULIAN_CENTURY
t = (julian_day - Epoch::J2000) / Constants::DAYS_PER_JULIAN_CENTURY
w = Angle.from_degrees(35999.373 * t) - Angle.from_degrees(2.47)
delta = 1 +
0.0334 * w.cos +
Expand Down
48 changes: 31 additions & 17 deletions lib/astronoby/events/observation_events.rb
Expand Up @@ -5,7 +5,6 @@ module Events
class ObservationEvents
STANDARD_ALTITUDE = Angle.from_dms(0, -34, 0)
RISING_SETTING_HOUR_ANGLE_RATIO_RANGE = (-1..1)
SECONDS_IN_A_DAY = 86_400
EARTH_SIDEREAL_ROTATION_RATE = 360.98564736629

attr_reader :rising_time,
Expand Down Expand Up @@ -58,19 +57,28 @@ def compute
return if h0.nil?

delta_m_rising = (local_horizontal_altitude_rising - shift).degrees./(
360 * declination_rising.cos * @observer.latitude.cos * local_hour_angle_rising.sin
Constants::DEGREES_PER_CIRCLE *
declination_rising.cos *
@observer.latitude.cos *
local_hour_angle_rising.sin
)
delta_m_transit = - local_hour_angle_transit.degrees / 360
delta_m_transit = -local_hour_angle_transit.degrees / Constants::DEGREES_PER_CIRCLE
delta_m_setting = (local_horizontal_altitude_setting - shift).degrees./(
360 * declination_setting.cos * @observer.latitude.cos * local_hour_angle_setting.sin
Constants::DEGREES_PER_CIRCLE *
declination_setting.cos *
@observer.latitude.cos *
local_hour_angle_setting.sin
)

corrected_rising =
rationalize_decimal_hours(24 * (initial_rising + delta_m_rising))
corrected_transit =
rationalize_decimal_hours(24 * (initial_transit + delta_m_transit))
corrected_setting =
rationalize_decimal_hours(24 * (initial_setting + delta_m_setting))
corrected_rising = rationalize_decimal_hours(
Constants::HOURS_PER_DAY * (initial_rising + delta_m_rising)
)
corrected_transit = rationalize_decimal_hours(
Constants::HOURS_PER_DAY * (initial_transit + delta_m_transit)
)
corrected_setting = rationalize_decimal_hours(
Constants::HOURS_PER_DAY * (initial_setting + delta_m_setting)
)

@rising_time = Util::Time.decimal_hour_to_time(@date, corrected_rising)
@rising_azimuth = local_horizontal_azimuth_rising
Expand Down Expand Up @@ -111,18 +119,22 @@ def initial_transit
@coordinates_of_the_day.right_ascension.degrees +
observer_longitude.degrees -
apparent_gst_at_midnight.degrees
) / 360.0
) / Constants::DEGREES_PER_CIRCLE
)
end

def initial_rising
@initial_rising ||=
rationalize_decimal_time(initial_transit - h0.degrees / 360)
rationalize_decimal_time(
initial_transit - h0.degrees / Constants::DEGREES_PER_CIRCLE
)
end

def initial_setting
@initial_setting ||=
rationalize_decimal_time(initial_transit + h0.degrees / 360)
rationalize_decimal_time(
initial_transit + h0.degrees / Constants::DEGREES_PER_CIRCLE
)
end

def gst_rising
Expand All @@ -149,7 +161,7 @@ def gst_setting
def leap_day_portion
@leap_day_portion ||= begin
leap_seconds = Util::Time.terrestrial_universal_time_delta(@date)
leap_seconds / SECONDS_IN_A_DAY
leap_seconds / Constants::SECONDS_PER_DAY
end
end

Expand Down Expand Up @@ -204,7 +216,9 @@ def local_horizontal_azimuth_setting
term1 = declination_setting.sin + shift.sin * @observer.latitude.cos
term2 = shift.cos * @observer.latitude.cos
angle = term1 / term2
Angle.from_degrees(360 - Angle.acos(angle).degrees)
Angle.from_degrees(
Constants::DEGREES_PER_CIRCLE - Angle.acos(angle).degrees
)
end

def rationalize_decimal_time(decimal_time)
Expand All @@ -214,8 +228,8 @@ def rationalize_decimal_time(decimal_time)
end

def rationalize_decimal_hours(decimal_hours)
decimal_hours += 24 if decimal_hours.negative?
decimal_hours -= 24 if decimal_hours > 24
decimal_hours += Constants::HOURS_PER_DAY if decimal_hours.negative?
decimal_hours -= Constants::HOURS_PER_DAY if decimal_hours > Constants::HOURS_PER_DAY
decimal_hours
end

Expand Down

0 comments on commit 26b69c8

Please sign in to comment.