Class: Astronoby::Angle
- Inherits:
-
Object
- Object
- Astronoby::Angle
- Includes:
- Comparable
- Defined in:
- lib/astronoby/angle.rb
Overview
Represents an angle with radians as its internal representation. Provides conversions between radians, degrees, hours, and sexagesimal formats (DMS and HMS), as well as trigonometric operations.
Constant Summary collapse
- MIN_PRECISION =
10- FORMATS =
%i[dms hms].freeze
Instance Attribute Summary collapse
-
#radians ⇒ Numeric
readonly
The angle in radians.
Class Method Summary collapse
-
.acos(ratio) ⇒ Astronoby::Angle
The arccosine.
-
.asin(ratio) ⇒ Astronoby::Angle
The arcsine.
-
.atan(ratio) ⇒ Astronoby::Angle
The arctangent.
-
.from_degree_arcseconds(arcseconds) ⇒ Astronoby::Angle
A new Angle.
-
.from_degrees(degrees) ⇒ Astronoby::Angle
A new Angle.
-
.from_dms(degree, minute, second) ⇒ Astronoby::Angle
A new Angle.
-
.from_hms(hour, minute, second) ⇒ Astronoby::Angle
A new Angle.
-
.from_hours(hours) ⇒ Astronoby::Angle
A new Angle.
-
.from_radians(radians) ⇒ Astronoby::Angle
A new Angle, normalized to (-2π, 2π).
-
.zero ⇒ Astronoby::Angle
A zero angle.
Instance Method Summary collapse
-
#+(other) ⇒ Astronoby::Angle
The sum.
-
#-(other) ⇒ Astronoby::Angle
The difference.
-
#-@ ⇒ Astronoby::Angle
The negated angle.
-
#<=>(other) ⇒ Integer?
-1, 0, or 1; nil if not comparable.
-
#cos ⇒ Float
The cosine of the angle.
-
#degree_milliarcseconds ⇒ Float
The angle in milliarcseconds.
-
#degrees ⇒ Float
The angle in degrees.
-
#hash ⇒ Integer
Hash value.
-
#hours ⇒ Float
The angle in hour-angle hours.
-
#initialize(radians) ⇒ Angle
constructor
A new instance of Angle.
-
#negative? ⇒ Boolean
True if the angle is negative.
-
#positive? ⇒ Boolean
True if the angle is positive.
-
#sin ⇒ Float
The sine of the angle.
-
#str(format, precision: 4) ⇒ String
Formats the angle as a string in the given format.
-
#tan ⇒ Float
The tangent of the angle.
-
#to_dms ⇒ Astronoby::Dms
The angle in degrees, arcminutes, arcseconds.
-
#to_hms ⇒ Astronoby::Hms
The angle in hours, minutes, seconds.
-
#zero? ⇒ Boolean
True if the angle is zero.
Constructor Details
#initialize(radians) ⇒ Angle
Returns a new instance of Angle.
103 104 105 106 |
# File 'lib/astronoby/angle.rb', line 103 def initialize(radians) @radians = radians freeze end |
Instance Attribute Details
#radians ⇒ Numeric (readonly)
Returns the angle in radians.
100 101 102 |
# File 'lib/astronoby/angle.rb', line 100 def radians @radians end |
Class Method Details
.acos(ratio) ⇒ Astronoby::Angle
Returns the arccosine.
86 87 88 89 |
# File 'lib/astronoby/angle.rb', line 86 def acos(ratio) radians = Math.acos(ratio) from_radians(radians) end |
.asin(ratio) ⇒ Astronoby::Angle
Returns the arcsine.
79 80 81 82 |
# File 'lib/astronoby/angle.rb', line 79 def asin(ratio) radians = Math.asin(ratio) from_radians(radians) end |
.atan(ratio) ⇒ Astronoby::Angle
Returns the arctangent.
93 94 95 96 |
# File 'lib/astronoby/angle.rb', line 93 def atan(ratio) radians = Math.atan(ratio) from_radians(radians) end |
.from_degree_arcseconds(arcseconds) ⇒ Astronoby::Angle
Returns a new Angle.
43 44 45 |
# File 'lib/astronoby/angle.rb', line 43 def from_degree_arcseconds(arcseconds) from_dms(0, 0, arcseconds) end |
.from_degrees(degrees) ⇒ Astronoby::Angle
Returns a new Angle.
36 37 38 39 |
# File 'lib/astronoby/angle.rb', line 36 def from_degrees(degrees) radians = degrees / Constants::PI_IN_DEGREES * Math::PI from_radians(radians) end |
.from_dms(degree, minute, second) ⇒ Astronoby::Angle
Returns a new Angle.
69 70 71 72 73 74 75 |
# File 'lib/astronoby/angle.rb', line 69 def from_dms(degree, minute, second) sign = degree.negative? ? -1 : 1 degrees = degree.abs + minute / Constants::ARCMINUTES_PER_DEGREE + second / Constants::ARCSECONDS_PER_DEGREE from_degrees(sign * degrees) end |
.from_hms(hour, minute, second) ⇒ Astronoby::Angle
Returns a new Angle.
58 59 60 61 62 63 |
# File 'lib/astronoby/angle.rb', line 58 def from_hms(hour, minute, second) hours = hour + minute / Constants::MINUTES_PER_HOUR + second / Constants::SECONDS_PER_HOUR from_hours(hours) end |
.from_hours(hours) ⇒ Astronoby::Angle
Returns a new Angle.
49 50 51 52 |
# File 'lib/astronoby/angle.rb', line 49 def from_hours(hours) radians = hours * Constants::RADIAN_PER_HOUR from_radians(radians) end |
.from_radians(radians) ⇒ Astronoby::Angle
Returns a new Angle, normalized to (-2π, 2π).
29 30 31 32 |
# File 'lib/astronoby/angle.rb', line 29 def from_radians(radians) normalized_radians = radians.remainder(Constants::RADIANS_PER_CIRCLE) new(normalized_radians) end |
.zero ⇒ Astronoby::Angle
Returns a zero angle.
23 24 25 |
# File 'lib/astronoby/angle.rb', line 23 def zero new(0) end |
Instance Method Details
#+(other) ⇒ Astronoby::Angle
Returns the sum.
125 126 127 |
# File 'lib/astronoby/angle.rb', line 125 def +(other) self.class.from_radians(radians + other.radians) end |
#-(other) ⇒ Astronoby::Angle
Returns the difference.
131 132 133 |
# File 'lib/astronoby/angle.rb', line 131 def -(other) self.class.from_radians(@radians - other.radians) end |
#-@ ⇒ Astronoby::Angle
Returns the negated angle.
136 137 138 |
# File 'lib/astronoby/angle.rb', line 136 def -@ self.class.from_radians(-@radians) end |
#<=>(other) ⇒ Integer?
Returns -1, 0, or 1; nil if not comparable.
177 178 179 180 181 |
# File 'lib/astronoby/angle.rb', line 177 def <=>(other) return unless other.is_a?(self.class) radians <=> other.radians end |
#cos ⇒ Float
Returns the cosine of the angle.
146 147 148 |
# File 'lib/astronoby/angle.rb', line 146 def cos Math.cos(radians) end |
#degree_milliarcseconds ⇒ Float
Returns the angle in milliarcseconds.
114 115 116 |
# File 'lib/astronoby/angle.rb', line 114 def degree_milliarcseconds degrees * Constants::MILLIARCSECONDS_PER_DEGREE end |
#degrees ⇒ Float
Returns the angle in degrees.
109 110 111 |
# File 'lib/astronoby/angle.rb', line 109 def degrees @radians * Constants::PI_IN_DEGREES / Math::PI end |
#hash ⇒ Integer
Returns hash value.
171 172 173 |
# File 'lib/astronoby/angle.rb', line 171 def hash [radians, self.class].hash end |
#hours ⇒ Float
Returns the angle in hour-angle hours.
119 120 121 |
# File 'lib/astronoby/angle.rb', line 119 def hours @radians / Constants::RADIAN_PER_HOUR end |
#negative? ⇒ Boolean
Returns true if the angle is negative.
161 162 163 |
# File 'lib/astronoby/angle.rb', line 161 def negative? radians < 0 end |
#positive? ⇒ Boolean
Returns true if the angle is positive.
156 157 158 |
# File 'lib/astronoby/angle.rb', line 156 def positive? radians > 0 end |
#sin ⇒ Float
Returns the sine of the angle.
141 142 143 |
# File 'lib/astronoby/angle.rb', line 141 def sin Math.sin(radians) end |
#str(format, precision: 4) ⇒ String
Formats the angle as a string in the given format.
190 191 192 193 194 195 196 197 198 199 |
# File 'lib/astronoby/angle.rb', line 190 def str(format, precision: 4) case format when :dms then to_dms.format(precision: precision) when :hms then to_hms.format(precision: precision) else raise UnsupportedFormatError.new( "Expected a format between #{FORMATS.join(", ")}, got #{format}" ) end end |
#tan ⇒ Float
Returns the tangent of the angle.
151 152 153 |
# File 'lib/astronoby/angle.rb', line 151 def tan Math.tan(radians) end |
#to_dms ⇒ Astronoby::Dms
Returns the angle in degrees, arcminutes, arcseconds.
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 |
# File 'lib/astronoby/angle.rb', line 202 def to_dms sign = degrees.negative? ? "-" : "+" absolute_degrees = degrees.abs deg = absolute_degrees.floor decimal_minutes = Constants::ARCMINUTES_PER_DEGREE * (absolute_degrees - deg) absolute_decimal_minutes = ( Constants::ARCMINUTES_PER_DEGREE * (absolute_degrees - deg) ).abs minutes = decimal_minutes.floor seconds = Constants::SECONDS_PER_MINUTE * ( absolute_decimal_minutes - absolute_decimal_minutes.floor ) Dms.new(sign, deg, minutes, seconds) end |
#to_hms ⇒ Astronoby::Hms
Returns the angle in hours, minutes, seconds.
220 221 222 223 224 225 226 227 228 229 230 231 232 233 |
# File 'lib/astronoby/angle.rb', line 220 def to_hms absolute_hours = hours.abs hrs = absolute_hours.floor decimal_minutes = Constants::MINUTES_PER_HOUR * (absolute_hours - hrs) absolute_decimal_minutes = ( Constants::MINUTES_PER_HOUR * (absolute_hours - hrs) ).abs minutes = decimal_minutes.floor seconds = Constants::SECONDS_PER_MINUTE * ( absolute_decimal_minutes - absolute_decimal_minutes.floor ) Hms.new(hrs, minutes, seconds) end |
#zero? ⇒ Boolean
Returns true if the angle is zero.
166 167 168 |
# File 'lib/astronoby/angle.rb', line 166 def zero? radians.zero? end |