Module: AstroChart::Ephemeris
- Defined in:
- lib/astro_chart/ephemeris.rb
Overview
Backend-agnostic ephemeris facade. All public callers go through this module so the backend (:pure / :swiss) can be swapped without touching the rest of the code.
Constant Summary collapse
- PLANETS =
SE-convention planet ids (numeric literals so the :pure default works without the C extension loaded; values match AstroChart::Ext constants when the extension is present).
{ "太陽" => 0, # SUN "月亮" => 1, # MOON "水星" => 2, # MERCURY "金星" => 3, # VENUS "火星" => 4, # MARS "木星" => 5, # JUPITER "土星" => 6, # SATURN "天王星" => 7, # URANUS "海王星" => 8, # NEPTUNE "冥王星" => 9, # PLUTO "北交點" => 11, # TRUE_NODE }.freeze
Class Method Summary collapse
-
.backend ⇒ Object
Current ephemeris backend (:pure or :swiss).
-
.backend=(name) ⇒ Object
Selecting :swiss loads the C extension on demand; a missing/uncompiled extension raises LoadError with an explicit message instead of failing silently at call time.
-
.calc_ut(jd, planet_id) ⇒ Object
Calculate planet apparent ecliptic longitude (degrees 0-360).
-
.ecliptic_latlon(jd, planet_id) ⇒ Object
Apparent geocentric ecliptic [longitude, latitude] in degrees.
-
.houses(jd, latitude, longitude, system = "P") ⇒ Object
Calculate house cusps + ascendant.
-
.julday(year, month, day, hour) ⇒ Object
Convert date/time to Julian Day number.
- .load_swiss_extension! ⇒ Object
-
.retrograde?(jd, planet_id) ⇒ Boolean
Whether the body is retrograde (moving backwards in longitude) at jd.
-
.speed(jd, planet_id) ⇒ Object
Apparent daily motion in ecliptic longitude (degrees/day), via central difference of calc_ut at jd ± 0.5 day.
Class Method Details
.backend ⇒ Object
Current ephemeris backend (:pure or :swiss). Defaults to :pure.
37 38 39 |
# File 'lib/astro_chart/ephemeris.rb', line 37 def backend @backend ||= DEFAULT_BACKEND end |
.backend=(name) ⇒ Object
Selecting :swiss loads the C extension on demand; a missing/uncompiled extension raises LoadError with an explicit message instead of failing silently at call time.
44 45 46 47 48 49 50 51 52 53 54 55 |
# File 'lib/astro_chart/ephemeris.rb', line 44 def backend=(name) case name when :pure @backend = :pure when :swiss load_swiss_extension! @backend = :swiss else raise ArgumentError, "unknown backend #{name.inspect} (expected :pure or :swiss)" end end |
.calc_ut(jd, planet_id) ⇒ Object
Calculate planet apparent ecliptic longitude (degrees 0-360).
98 99 100 101 102 103 |
# File 'lib/astro_chart/ephemeris.rb', line 98 def self.calc_ut(jd, planet_id) case backend when :swiss then Ext.calc_ut(jd, planet_id) else Pure.calc_ut(jd, planet_id) end end |
.ecliptic_latlon(jd, planet_id) ⇒ Object
Apparent geocentric ecliptic [longitude, latitude] in degrees. Pure backend only (the Swiss extension exposes latitude via its own API).
107 108 109 |
# File 'lib/astro_chart/ephemeris.rb', line 107 def self.ecliptic_latlon(jd, planet_id) Pure.ecliptic_latlon(jd, planet_id) end |
.houses(jd, latitude, longitude, system = "P") ⇒ Object
Calculate house cusps + ascendant. Returns { "cusps" => [12 floats], "ascendant" => float, "mc" => float }
142 143 144 145 146 147 |
# File 'lib/astro_chart/ephemeris.rb', line 142 def self.houses(jd, latitude, longitude, system = "P") case backend when :swiss then Ext.houses(jd, latitude, longitude, system.ord) else Pure.houses(jd, latitude, longitude, system) end end |
.julday(year, month, day, hour) ⇒ Object
Convert date/time to Julian Day number.
90 91 92 93 94 95 |
# File 'lib/astro_chart/ephemeris.rb', line 90 def self.julday(year, month, day, hour) case backend when :swiss then Ext.julday(year, month, day, hour) else Pure.julday(year, month, day, hour) end end |
.load_swiss_extension! ⇒ Object
57 58 59 60 61 62 63 64 65 66 67 68 69 |
# File 'lib/astro_chart/ephemeris.rb', line 57 def load_swiss_extension! return if defined?(Ext) begin require_relative "astro_chart_ext" rescue LoadError => e raise LoadError, "AstroChart :swiss backend requires the compiled Swiss Ephemeris C extension " \ "(astro_chart_ext). Build it with `rake compile` (or `ruby ext/astro_chart/extconf.rb && make`), " \ "or use the default pure-Ruby backend (AstroChart.backend = :pure). " \ "Original error: #{e.}" end end |
.retrograde?(jd, planet_id) ⇒ Boolean
Whether the body is retrograde (moving backwards in longitude) at jd.
136 137 138 |
# File 'lib/astro_chart/ephemeris.rb', line 136 def self.retrograde?(jd, planet_id) speed(jd, planet_id) < 0 end |
.speed(jd, planet_id) ⇒ Object
Apparent daily motion in ecliptic longitude (degrees/day), via central difference of calc_ut at jd ± 0.5 day. The difference is folded into (-180, 180] so the 0°/360° wraparound never produces a spurious value. Negative speed = retrograde motion.
When jd ± 0.5 falls outside a body's valid ephemeris window (e.g. the pure Pluto series' 1885-2099 range) while jd itself is inside, the stencil falls back to a one-sided difference over half a day, so charts at the very edges of the documented range still work. A jd that is itself out of range still raises Pure::Core::DomainError.
121 122 123 124 125 126 127 128 129 130 131 132 133 |
# File 'lib/astro_chart/ephemeris.rb', line 121 def self.speed(jd, planet_id) a, b, days = begin [calc_ut(jd - 0.5, planet_id), calc_ut(jd + 0.5, planet_id), 1.0] rescue Pure::Core::DomainError begin [calc_ut(jd, planet_id), calc_ut(jd + 0.5, planet_id), 0.5] rescue Pure::Core::DomainError [calc_ut(jd - 0.5, planet_id), calc_ut(jd, planet_id), 0.5] end end (((b - a + 540.0) % 360.0) - 180.0) / days end |