Class: Astronoby::Angle

Inherits:
Object
  • Object
show all
Includes:
Comparable
Defined in:
lib/astronoby/angle.rb

Constant Summary collapse

PRECISION =
14
PI =
BigMath.PI(PRECISION)
PI_IN_DEGREES =
BigDecimal("180")
FULL_CIRCLE_IN_RADIANS =
(2 * PI)
RADIAN_PER_HOUR =
PI / BigDecimal("12")
MINUTES_PER_DEGREE =
BigDecimal("60")
MINUTES_PER_HOUR =
BigDecimal("60")
SECONDS_PER_MINUTE =
BigDecimal("60")
SECONDS_PER_HOUR =
MINUTES_PER_HOUR * SECONDS_PER_MINUTE
FORMATS =
%i[dms hms].freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(radians) ⇒ Angle

Returns a new instance of Angle.



72
73
74
75
76
77
78
79
# File 'lib/astronoby/angle.rb', line 72

def initialize(radians)
  @radians = if radians.is_a?(Integer) || radians.is_a?(BigDecimal)
    BigDecimal(radians)
  else
    BigDecimal(radians, PRECISION)
  end
  freeze
end

Instance Attribute Details

#radiansObject (readonly)

Returns the value of attribute radians.



70
71
72
# File 'lib/astronoby/angle.rb', line 70

def radians
  @radians
end

Class Method Details

.acos(ratio) ⇒ Object



59
60
61
62
# File 'lib/astronoby/angle.rb', line 59

def acos(ratio)
  radians = Math.acos(ratio)
  from_radians(radians)
end

.asin(ratio) ⇒ Object



54
55
56
57
# File 'lib/astronoby/angle.rb', line 54

def asin(ratio)
  radians = Math.asin(ratio)
  from_radians(radians)
end

.atan(ratio) ⇒ Object



64
65
66
67
# File 'lib/astronoby/angle.rb', line 64

def atan(ratio)
  radians = Math.atan(ratio)
  from_radians(radians)
end

.from_degrees(degrees) ⇒ Object



33
34
35
36
# File 'lib/astronoby/angle.rb', line 33

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

.from_dms(degree, minute, second) ⇒ Object



48
49
50
51
52
# File 'lib/astronoby/angle.rb', line 48

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

.from_hms(hour, minute, second) ⇒ Object



43
44
45
46
# File 'lib/astronoby/angle.rb', line 43

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

.from_hours(hours) ⇒ Object



38
39
40
41
# File 'lib/astronoby/angle.rb', line 38

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

.from_radians(radians) ⇒ Object



28
29
30
31
# File 'lib/astronoby/angle.rb', line 28

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

.zeroObject



24
25
26
# File 'lib/astronoby/angle.rb', line 24

def zero
  new(0)
end

Instance Method Details

#+(other) ⇒ Object



89
90
91
# File 'lib/astronoby/angle.rb', line 89

def +(other)
  self.class.from_radians(radians + other.radians)
end

#-(other) ⇒ Object



93
94
95
# File 'lib/astronoby/angle.rb', line 93

def -(other)
  self.class.from_radians(@radians - other.radians)
end

#<=>(other) ⇒ Object



125
126
127
128
129
# File 'lib/astronoby/angle.rb', line 125

def <=>(other)
  return unless other.is_a?(self.class)

  radians <=> other.radians
end

#cosObject



101
102
103
# File 'lib/astronoby/angle.rb', line 101

def cos
  Math.cos(radians)
end

#degreesObject



81
82
83
# File 'lib/astronoby/angle.rb', line 81

def degrees
  @radians * PI_IN_DEGREES / PI
end

#hashObject



121
122
123
# File 'lib/astronoby/angle.rb', line 121

def hash
  [radians, self.class].hash
end

#hoursObject



85
86
87
# File 'lib/astronoby/angle.rb', line 85

def hours
  @radians / RADIAN_PER_HOUR
end

#negative?Boolean

Returns:

  • (Boolean)


113
114
115
# File 'lib/astronoby/angle.rb', line 113

def negative?
  radians < 0
end

#positive?Boolean

Returns:

  • (Boolean)


109
110
111
# File 'lib/astronoby/angle.rb', line 109

def positive?
  radians > 0
end

#sinObject



97
98
99
# File 'lib/astronoby/angle.rb', line 97

def sin
  Math.sin(radians)
end

#str(format) ⇒ Object



132
133
134
135
136
137
138
139
140
141
# File 'lib/astronoby/angle.rb', line 132

def str(format)
  case format
  when :dms then to_dms(degrees).format
  when :hms then to_hms(hours).format
  else
    raise UnsupportedFormatError.new(
      "Expected a format between #{FORMATS.join(", ")}, got #{format}"
    )
  end
end

#tanObject



105
106
107
# File 'lib/astronoby/angle.rb', line 105

def tan
  Math.tan(radians)
end

#to_dms(deg) ⇒ Object



143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
# File 'lib/astronoby/angle.rb', line 143

def to_dms(deg)
  sign = deg.negative? ? "-" : "+"
  absolute_degrees = deg.abs
  degrees = absolute_degrees.floor
  decimal_minutes = MINUTES_PER_DEGREE * (absolute_degrees - degrees)
  absolute_decimal_minutes = (
    MINUTES_PER_DEGREE * (absolute_degrees - degrees)
  ).abs
  minutes = decimal_minutes.floor
  seconds = SECONDS_PER_MINUTE * (
    absolute_decimal_minutes - absolute_decimal_minutes.floor
  )

  Dms.new(sign, degrees, minutes, seconds.to_f.floor(4))
end

#to_hms(hrs) ⇒ Object



159
160
161
162
163
164
165
166
167
168
169
170
171
172
# File 'lib/astronoby/angle.rb', line 159

def to_hms(hrs)
  absolute_hours = hrs.abs
  hours = absolute_hours.floor
  decimal_minutes = MINUTES_PER_HOUR * (absolute_hours - hours)
  absolute_decimal_minutes = (
    MINUTES_PER_HOUR * (absolute_hours - hours)
  ).abs
  minutes = decimal_minutes.floor
  seconds = SECONDS_PER_MINUTE * (
    absolute_decimal_minutes - absolute_decimal_minutes.floor
  )

  Hms.new(hours, minutes, seconds.to_f.floor(4))
end

#zero?Boolean

Returns:

  • (Boolean)


117
118
119
# File 'lib/astronoby/angle.rb', line 117

def zero?
  radians.zero?
end