Class: Astronoby::Angle

Inherits:
Object
  • Object
show all
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.



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

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.



68
69
70
# File 'lib/astronoby/angle.rb', line 68

def radians
  @radians
end

Class Method Details

.acos(ratio) ⇒ Object



57
58
59
60
# File 'lib/astronoby/angle.rb', line 57

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

.as_degrees(degrees) ⇒ Object



31
32
33
34
# File 'lib/astronoby/angle.rb', line 31

def as_degrees(degrees)
  radians = degrees / PI_IN_DEGREES * PI
  as_radians(radians)
end

.as_dms(degree, minute, second) ⇒ Object



46
47
48
49
50
# File 'lib/astronoby/angle.rb', line 46

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

.as_hms(hour, minute, second) ⇒ Object



41
42
43
44
# File 'lib/astronoby/angle.rb', line 41

def as_hms(hour, minute, second)
  hours = hour + minute / MINUTES_PER_HOUR + second / SECONDS_PER_HOUR
  as_hours(hours)
end

.as_hours(hours) ⇒ Object



36
37
38
39
# File 'lib/astronoby/angle.rb', line 36

def as_hours(hours)
  radians = hours * RADIAN_PER_HOUR
  as_radians(radians)
end

.as_radians(radians) ⇒ Object



26
27
28
29
# File 'lib/astronoby/angle.rb', line 26

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

.asin(ratio) ⇒ Object



52
53
54
55
# File 'lib/astronoby/angle.rb', line 52

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

.atan(ratio) ⇒ Object



62
63
64
65
# File 'lib/astronoby/angle.rb', line 62

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

.zeroObject



22
23
24
# File 'lib/astronoby/angle.rb', line 22

def zero
  new(0)
end

Instance Method Details

#+(other) ⇒ Object



87
88
89
# File 'lib/astronoby/angle.rb', line 87

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

#-(other) ⇒ Object



91
92
93
# File 'lib/astronoby/angle.rb', line 91

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

#<=>(other) ⇒ Object



128
129
130
131
132
# File 'lib/astronoby/angle.rb', line 128

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

  radians <=> other.radians
end

#==(other) ⇒ Object Also known as: eql?



119
120
121
# File 'lib/astronoby/angle.rb', line 119

def ==(other)
  other.is_a?(self.class) && radians == other.radians
end

#cosObject



99
100
101
# File 'lib/astronoby/angle.rb', line 99

def cos
  Math.cos(radians)
end

#degreesObject



79
80
81
# File 'lib/astronoby/angle.rb', line 79

def degrees
  @radians * PI_IN_DEGREES / PI
end

#hashObject



124
125
126
# File 'lib/astronoby/angle.rb', line 124

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

#hoursObject



83
84
85
# File 'lib/astronoby/angle.rb', line 83

def hours
  @radians / RADIAN_PER_HOUR
end

#negative?Boolean

Returns:

  • (Boolean)


111
112
113
# File 'lib/astronoby/angle.rb', line 111

def negative?
  radians < 0
end

#positive?Boolean

Returns:

  • (Boolean)


107
108
109
# File 'lib/astronoby/angle.rb', line 107

def positive?
  radians > 0
end

#sinObject



95
96
97
# File 'lib/astronoby/angle.rb', line 95

def sin
  Math.sin(radians)
end

#str(format) ⇒ Object



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

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



103
104
105
# File 'lib/astronoby/angle.rb', line 103

def tan
  Math.tan(radians)
end

#to_dms(deg) ⇒ Object



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

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



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

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)


115
116
117
# File 'lib/astronoby/angle.rb', line 115

def zero?
  radians.zero?
end