Class: Astronoby::SolarSystemBody
- Inherits:
-
Object
- Object
- Astronoby::SolarSystemBody
- Extended by:
- Body
- Includes:
- Position
- Defined in:
- lib/astronoby/bodies/solar_system_body.rb
Overview
Base class for solar system bodies. Provides the reference frame chain (geometric -> astrometric -> mean-of-date -> apparent -> topocentric) and common observational properties (phase angle, magnitude, etc.).
Constant Summary collapse
- SOLAR_SYSTEM_BARYCENTER =
0- SUN =
10- MERCURY_BARYCENTER =
1- MERCURY =
199- VENUS_BARYCENTER =
2- VENUS =
299- EARTH_MOON_BARYCENTER =
3- EARTH =
399- MOON =
301- MARS_BARYCENTER =
4- JUPITER_BARYCENTER =
5- SATURN_BARYCENTER =
6- URANUS_BARYCENTER =
7- NEPTUNE_BARYCENTER =
8
Instance Attribute Summary collapse
-
#ephem ⇒ ::Ephem::SPK
readonly
The ephemeris data source.
-
#instant ⇒ Astronoby::Instant
readonly
The time instant.
-
#orientation ⇒ Astronoby::Orientation?
readonly
The orientation kernel, if provided.
Class Method Summary collapse
-
.absolute_magnitude ⇒ Float?
Absolute magnitude of the body.
-
.at(instant, ephem:, orientation: nil) ⇒ Astronoby::SolarSystemBody
Creates a new body instance at the given instant.
-
.compute_geometric(ephem:, instant:) ⇒ Astronoby::Geometric
The geometric frame.
-
.conjunction_events(ephem:, start_time:, end_time:, samples_per_period: 60) ⇒ Array<Astronoby::Conjunction>
Conjunctions with the Sun.
-
.ephemeris_segments(_ephem_source) ⇒ Array<Array>
Ephemeris segment identifiers.
-
.geometric(ephem:, instant:) ⇒ Astronoby::Geometric
Computes the geometric reference frame for this body.
-
.greatest_elongation_events(ephem:, start_time:, end_time:, samples_per_period: 60) ⇒ Array<Astronoby::GreatestElongation>
Greatest elongations.
-
.inferior_planet? ⇒ Boolean
True for an inferior planet (Mercury, Venus).
-
.opposition_events(ephem:, start_time:, end_time:, samples_per_period: 60) ⇒ Array<Astronoby::Opposition>
Oppositions with the Sun.
-
.planet? ⇒ Boolean
True for a planet (excludes the Sun, Earth and Moon).
-
.rise_transit_set_events(observer:, ephem:, date: nil, start_time: nil, end_time: nil, utc_offset: 0) ⇒ Astronoby::RiseTransitSetEvent+
Rise, transit, and set events for the given date or time range.
-
.superior_planet? ⇒ Boolean
True for a superior planet (Mars through Neptune).
Instance Method Summary collapse
-
#angular_diameter ⇒ Astronoby::Angle
Angular diameter of the body, as seen from Earth.
-
#apparent ⇒ Astronoby::Apparent
The apparent reference frame.
-
#apparent_magnitude ⇒ Float?
Source: Title: Astronomical Algorithms Author: Jean Meeus Edition: 2nd edition Chapter: 48 - Illuminated Fraction of the Moon’s Disk Apparent magnitude of the body, as seen from Earth.
-
#approaching_primary? ⇒ Boolean
True if the body is approaching its primary body, false otherwise.
-
#astrometric ⇒ Astronoby::Astrometric
The astrometric reference frame (GCRS).
-
#body ⇒ Astronoby::Body
The body definition (the class itself).
-
#constellation ⇒ Astronoby::Constellation?
Returns the constellation of the body.
-
#earth_geometric ⇒ Astronoby::Geometric
Earth’s geometric reference frame.
-
#eastern? ⇒ Boolean
True when the body is east of the Sun.
-
#elongation ⇒ Astronoby::Angle?
Apparent geocentric Sun-Earth-body angle.
-
#geometric ⇒ Astronoby::Geometric
The geometric reference frame (BCRS).
-
#illuminated_fraction ⇒ Float?
Fraction between 0 and 1 of the body’s disk that is illuminated.
-
#initialize(ephem:, instant:, orientation: nil) ⇒ SolarSystemBody
constructor
A new instance of SolarSystemBody.
-
#mean_of_date ⇒ Astronoby::MeanOfDate
The mean-of-date reference frame.
-
#phase_angle ⇒ Astronoby::Angle?
Source: Title: Astronomical Algorithms Author: Jean Meeus Edition: 2nd edition Chapter: 48 - Illuminated Fraction of the Moon’s Disk.
-
#receding_from_primary? ⇒ Boolean
True if the body is receding from its primary body, false otherwise.
-
#western? ⇒ Boolean
True when the body is west of the Sun.
Methods included from Position
Constructor Details
#initialize(ephem:, instant:, orientation: nil) ⇒ SolarSystemBody
Returns a new instance of SolarSystemBody.
233 234 235 236 237 |
# File 'lib/astronoby/bodies/solar_system_body.rb', line 233 def initialize(ephem:, instant:, orientation: nil) @ephem = ephem @instant = instant @orientation = orientation end |
Instance Attribute Details
#ephem ⇒ ::Ephem::SPK (readonly)
Returns the ephemeris data source.
30 31 32 |
# File 'lib/astronoby/bodies/solar_system_body.rb', line 30 def ephem @ephem end |
#instant ⇒ Astronoby::Instant (readonly)
Returns the time instant.
27 28 29 |
# File 'lib/astronoby/bodies/solar_system_body.rb', line 27 def instant @instant end |
#orientation ⇒ Astronoby::Orientation? (readonly)
Returns the orientation kernel, if provided.
33 34 35 |
# File 'lib/astronoby/bodies/solar_system_body.rb', line 33 def orientation @orientation end |
Class Method Details
.absolute_magnitude ⇒ Float?
Returns absolute magnitude of the body.
104 105 106 |
# File 'lib/astronoby/bodies/solar_system_body.rb', line 104 def self.absolute_magnitude nil end |
.at(instant, ephem:, orientation: nil) ⇒ Astronoby::SolarSystemBody
Creates a new body instance at the given instant.
41 42 43 |
# File 'lib/astronoby/bodies/solar_system_body.rb', line 41 def self.at(instant, ephem:, orientation: nil) new(ephem: ephem, instant: instant, orientation: orientation) end |
.compute_geometric(ephem:, instant:) ⇒ Astronoby::Geometric
Returns the geometric frame.
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
# File 'lib/astronoby/bodies/solar_system_body.rb', line 57 def self.compute_geometric(ephem:, instant:) segments = ephemeris_segments(ephem.type) segment1 = segments[0] segment2 = segments[1] if segments.size == 2 cache_key = CacheKey.generate(:geometric, instant, segment1, segment2) Astronoby.cache.fetch(cache_key) do state1 = ephem[*segment1].state_at(instant.tt) if segment2 state2 = ephem[*segment2].state_at(instant.tt) position = state1.position + state2.position velocity = state1.velocity + state2.velocity else position = state1.position velocity = state1.velocity end position_vector = Vector[ Distance.from_kilometers(position.x), Distance.from_kilometers(position.y), Distance.from_kilometers(position.z) ] velocity_vector = Vector[ Velocity.from_kilometers_per_day(velocity.x), Velocity.from_kilometers_per_day(velocity.y), Velocity.from_kilometers_per_day(velocity.z) ] Geometric.new( position: position_vector, velocity: velocity_vector, instant: instant, target_body: self ) end end |
.conjunction_events(ephem:, start_time:, end_time:, samples_per_period: 60) ⇒ Array<Astronoby::Conjunction>
Returns conjunctions with the Sun.
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 |
# File 'lib/astronoby/bodies/solar_system_body.rb', line 162 def self.conjunction_events( ephem:, start_time:, end_time:, samples_per_period: 60 ) unless planet? raise UnsupportedEventError, "#{self} has no conjunctions with the Sun" end ConjunctionOppositionCalculator.new( body: self, ephem: ephem, samples_per_period: samples_per_period ).conjunction_events_between(start_time, end_time) end |
.ephemeris_segments(_ephem_source) ⇒ Array<Array>
Returns ephemeris segment identifiers.
99 100 101 |
# File 'lib/astronoby/bodies/solar_system_body.rb', line 99 def self.ephemeris_segments(_ephem_source) raise NotImplementedError end |
.geometric(ephem:, instant:) ⇒ Astronoby::Geometric
Computes the geometric reference frame for this body.
50 51 52 |
# File 'lib/astronoby/bodies/solar_system_body.rb', line 50 def self.geometric(ephem:, instant:) compute_geometric(ephem: ephem, instant: instant) end |
.greatest_elongation_events(ephem:, start_time:, end_time:, samples_per_period: 60) ⇒ Array<Astronoby::GreatestElongation>
Returns greatest elongations.
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 |
# File 'lib/astronoby/bodies/solar_system_body.rb', line 210 def self.greatest_elongation_events( ephem:, start_time:, end_time:, samples_per_period: 60 ) unless inferior_planet? raise UnsupportedEventError, "#{self} has no greatest elongations from the Sun" end GreatestElongationCalculator.new( body: self, ephem: ephem, samples_per_period: samples_per_period ).greatest_elongation_events_between(start_time, end_time) end |
.inferior_planet? ⇒ Boolean
Returns true for an inferior planet (Mercury, Venus).
109 110 111 |
# File 'lib/astronoby/bodies/solar_system_body.rb', line 109 def self.inferior_planet? false end |
.opposition_events(ephem:, start_time:, end_time:, samples_per_period: 60) ⇒ Array<Astronoby::Opposition>
Returns oppositions with the Sun.
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 |
# File 'lib/astronoby/bodies/solar_system_body.rb', line 186 def self.opposition_events( ephem:, start_time:, end_time:, samples_per_period: 60 ) unless superior_planet? raise UnsupportedEventError, "#{self} has no oppositions with the Sun" end ConjunctionOppositionCalculator.new( body: self, ephem: ephem, samples_per_period: samples_per_period ).opposition_events_between(start_time, end_time) end |
.planet? ⇒ Boolean
Returns true for a planet (excludes the Sun, Earth and Moon).
119 120 121 |
# File 'lib/astronoby/bodies/solar_system_body.rb', line 119 def self.planet? inferior_planet? || superior_planet? end |
.rise_transit_set_events(observer:, ephem:, date: nil, start_time: nil, end_time: nil, utc_offset: 0) ⇒ Astronoby::RiseTransitSetEvent+
Returns Rise, transit, and set events for the given date or time range.
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
# File 'lib/astronoby/bodies/solar_system_body.rb', line 136 def self.rise_transit_set_events( observer:, ephem:, date: nil, start_time: nil, end_time: nil, utc_offset: 0 ) calculator = RiseTransitSetCalculator.new( body: self, observer: observer, ephem: ephem ) if date calculator.events_on(date, utc_offset: utc_offset) else calculator.events_between(start_time, end_time) end end |
.superior_planet? ⇒ Boolean
Returns true for a superior planet (Mars through Neptune).
114 115 116 |
# File 'lib/astronoby/bodies/solar_system_body.rb', line 114 def self.superior_planet? false end |
Instance Method Details
#angular_diameter ⇒ Astronoby::Angle
Angular diameter of the body, as seen from Earth. Based on the apparent
position of the body.
367 368 369 370 371 372 373 374 375 |
# File 'lib/astronoby/bodies/solar_system_body.rb', line 367 def angular_diameter @angular_radius ||= begin return if apparent.position.zero? Angle.from_radians( Math.asin(self.class::EQUATORIAL_RADIUS.m / apparent.distance.m) * 2 ) end end |
#apparent ⇒ Astronoby::Apparent
Returns the apparent reference frame.
274 275 276 277 278 279 280 281 |
# File 'lib/astronoby/bodies/solar_system_body.rb', line 274 def apparent @apparent ||= Apparent.build_from_astrometric( instant: @instant, target_astrometric: astrometric, earth_geometric: earth_geometric, target_body: body ) end |
#apparent_magnitude ⇒ Float?
Source:
Title: Astronomical Algorithms
Author: Jean Meeus
Edition: 2nd edition
Chapter: 48 - Illuminated Fraction of the Moon's Disk
Apparent magnitude of the body, as seen from Earth.
352 353 354 355 356 357 358 359 360 361 362 |
# File 'lib/astronoby/bodies/solar_system_body.rb', line 352 def apparent_magnitude return unless self.class.absolute_magnitude @apparent_magnitude ||= begin body_sun_distance = (astrometric.position - sun.astrometric.position).magnitude self.class.absolute_magnitude + 5 * Math.log10(body_sun_distance.au * astrometric.distance.au) + magnitude_correction_term end end |
#approaching_primary? ⇒ Boolean
Returns True if the body is approaching its primary body, false otherwise.
379 380 381 382 383 384 385 386 387 388 389 390 |
# File 'lib/astronoby/bodies/solar_system_body.rb', line 379 def approaching_primary? relative_position = (geometric.position - primary_body_geometric.position).map(&:m) relative_velocity = (geometric.velocity - primary_body_geometric.velocity).map(&:mps) radial_velocity_component = Astronoby::Util::Maths .dot_product(relative_position, relative_velocity) distance = Math.sqrt( Astronoby::Util::Maths.dot_product(relative_position, relative_position) ) radial_velocity_component / distance < 0 end |
#astrometric ⇒ Astronoby::Astrometric
Returns the astrometric reference frame (GCRS).
253 254 255 256 257 258 259 260 261 |
# File 'lib/astronoby/bodies/solar_system_body.rb', line 253 def astrometric @astrometric ||= Astrometric.build_from_geometric( instant: @instant, earth_geometric: earth_geometric, light_time_corrected_position: light_time_corrected_position, light_time_corrected_velocity: light_time_corrected_velocity, target_body: body ) end |
#body ⇒ Astronoby::Body
Returns the body definition (the class itself).
284 285 286 |
# File 'lib/astronoby/bodies/solar_system_body.rb', line 284 def body self.class end |
#constellation ⇒ Astronoby::Constellation?
Returns the constellation of the body
290 291 292 293 294 295 296 297 |
# File 'lib/astronoby/bodies/solar_system_body.rb', line 290 def constellation @constellation ||= Constellations::Finder.find( Precession.for_equatorial_coordinates( coordinates: astrometric.equatorial, epoch: JulianDate::B1875 ) ) end |
#earth_geometric ⇒ Astronoby::Geometric
Returns Earth’s geometric reference frame.
248 249 250 |
# File 'lib/astronoby/bodies/solar_system_body.rb', line 248 def earth_geometric @earth_geometric ||= Earth.geometric(ephem: @ephem, instant: @instant) end |
#eastern? ⇒ Boolean
Returns true when the body is east of the Sun.
308 309 310 311 |
# File 'lib/astronoby/bodies/solar_system_body.rb', line 308 def eastern? (apparent.ecliptic.longitude - sun.apparent.ecliptic.longitude) .sin.positive? end |
#elongation ⇒ Astronoby::Angle?
Apparent geocentric Sun-Earth-body angle
301 302 303 304 305 |
# File 'lib/astronoby/bodies/solar_system_body.rb', line 301 def elongation return unless sun @elongation ||= sun.apparent.separation_from(apparent) end |
#geometric ⇒ Astronoby::Geometric
Returns the geometric reference frame (BCRS).
240 241 242 243 244 245 |
# File 'lib/astronoby/bodies/solar_system_body.rb', line 240 def geometric @geometric ||= self.class.compute_geometric( ephem: @ephem, instant: @instant ) end |
#illuminated_fraction ⇒ Float?
Fraction between 0 and 1 of the body’s disk that is illuminated.
339 340 341 342 343 |
# File 'lib/astronoby/bodies/solar_system_body.rb', line 339 def illuminated_fraction return unless phase_angle @illuminated_fraction ||= (1 + phase_angle.cos) / 2.0 end |
#mean_of_date ⇒ Astronoby::MeanOfDate
Returns the mean-of-date reference frame.
264 265 266 267 268 269 270 271 |
# File 'lib/astronoby/bodies/solar_system_body.rb', line 264 def mean_of_date @mean_of_date ||= MeanOfDate.build_from_geometric( instant: @instant, target_geometric: geometric, earth_geometric: earth_geometric, target_body: body ) end |
#phase_angle ⇒ Astronoby::Angle?
Source:
Title: Astronomical Algorithms
Author: Jean Meeus
Edition: 2nd edition
Chapter: 48 - Illuminated Fraction of the Moon's Disk
324 325 326 327 328 329 330 331 332 333 334 335 |
# File 'lib/astronoby/bodies/solar_system_body.rb', line 324 def phase_angle return unless sun @phase_angle ||= begin term1 = sun.astrometric.distance.km * elongation.sin term2 = astrometric.distance.km - sun.astrometric.distance.km * elongation.cos angle = Angle.atan(term1 / term2) Astronoby::Util::Trigonometry .adjustement_for_arctangent(term1, term2, angle) end end |
#receding_from_primary? ⇒ Boolean
Returns True if the body is receding from its primary body, false otherwise.
394 395 396 |
# File 'lib/astronoby/bodies/solar_system_body.rb', line 394 def receding_from_primary? !approaching_primary? end |
#western? ⇒ Boolean
Returns true when the body is west of the Sun.
314 315 316 |
# File 'lib/astronoby/bodies/solar_system_body.rb', line 314 def western? !eastern? end |