Module: AstroChart::Pure::Houses
- Defined in:
- lib/astro_chart/pure/houses.rb
Overview
Houses — MIT-safe 純 Ruby Placidus 宮位(ASC / MC / 12 宮頭)。
零外部依賴、不參考 Swiss Ephemeris C 原始碼,僅使用公開文獻公式:
- 視恆星時 / 章動 / 黃赤交角:見 Core(Meeus Ch. 12 / 22)
- ASC / MC:標準球面天文公式(Meeus Ch. 13 座標轉換推得)
- Placidus 宮頭:古典半弧迭代法(半日弧 SA = arccos(-tanφ·tanδ), 宮頭 11/12 位於 RAMC 東側 1/3、2/3 半日弧處;宮頭 2/3 以半夜弧對應)
公開 API: Houses.calc(jd_ut, lat, lon, hsys = "P") -> { "cusps" => [12 floats], "ascendant" => Float, "mc" => Float } 欄位與 AstroChart::Ext.houses(jd, lat, lon, hsys.ord) 相同。
宮位制: "P" — Placidus(預設)。適用範圍 |lat| < ~66°(極圈內無定義), 超出範圍或迭代未收斂時 raise Core::DomainError(顯性失敗,不靜默 clamp)。 "W" — 整宮制(Whole Sign)。宮頭 1 = ASC 所在星座起點(floor(asc/30)*30), 其後每宮 +30°。ASC / MC 計算與 Placidus 相同(整宮制只改宮頭), 唯極圈內(|lat| > 90° − ε ≈ 66.56°)另套用東昇點修正(見 east_ascendant)——標準公式在該區可能傳回差 180° 的西方交點。 於 |lat| < 90° 皆有定義(lat = ±90° 時 tanφ 發散,ASC 本身無定義)。
Constant Summary collapse
Class Method Summary collapse
-
.asc_longitude(armc_deg, eps, phi) ⇒ Object
--- ASC:標準公式 --- λ_ASC = atan2( cos ARMC, -(sin ARMC · cos ε + tan φ · sin ε) ).
-
.calc(jd_ut, lat, lon, hsys = "P") ⇒ Object
jd_ut: UT 儒略日;lat: 地理緯度(北正);lon: 地理經度(東正) hsys: "P"(Placidus,預設)或 "W"(整宮制).
-
.east_ascendant(asc, mc) ⇒ Object
--- 東昇點修正 --- ASC 依定義位於 MC 東側半圓:(asc − mc) mod 360 ∈ (0°, 180°)。 極圈內原始公式可能落在西側半圓(實為降點),此時加 180°。 與 Swiss Ephemeris 極區行為一致(tmp/explore_polar_asc.rb 驗證 400 例全符)。.
-
.equal_cusps(asc) ⇒ Object
--- 等宮制 12 宮頭 --- 宮頭 1 = ASC 本身,其後每宮 +30°(模 360)。MC 仍照常算出並回傳, 但等宮制的第 10 宮頭為 ASC+270°,不等於 MC(MC 在宮內浮動)。.
-
.mc_longitude(armc_deg, eps) ⇒ Object
--- MC:天頂赤經 → 黃道經度 --- tan λ_MC = tan(ARMC) / cos ε,以 atan2 處理象限.
-
.placidus_cusp(armc_deg, eps, phi, offset_deg, frac, mode) ⇒ Object
--- Placidus 宮頭半弧迭代 --- 定義:黃道上一點 (α, δ),半日弧 SA_d = arccos(-tanφ·tanδ)、半夜弧 SA_n = arccos(tanφ·tanδ)。 宮頭 11:α = RAMC + (1/3)·SA_d 宮頭 12:α = RAMC + (2/3)·SA_d 宮頭 2 :α = RAMC + 180 - (2/3)·SA_n 宮頭 3 :α = RAMC + 180 - (1/3)·SA_n 黃道點的赤緯由 tan δ = tan ε · sin α 得出,固定點迭代至收斂。 offset_deg:初值偏移(赤道情形的精確解);frac:半弧比例;mode:地平上/下。.
-
.placidus_cusps(armc, eps, phi, asc, mc) ⇒ Object
--- Placidus 12 宮頭 ---.
-
.porphyry_cusps(asc, mc) ⇒ Object
--- Porphyry 12 宮頭 --- 依黃道經度遞增,四大軸順序為 ASC(1) → IC(4) → DSC(7) → MC(10)。每個 象限的黃道弧三等分,得中間兩個宮頭: 1→4:ASC..IC 弧 → 宮頭 2、3 4→7:IC..DSC 弧 → 宮頭 5、6 7→10:DSC..MC 弧 → 宮頭 8、9 10→1:MC..ASC 弧 → 宮頭 11、12.
-
.whole_sign_cusps(asc) ⇒ Object
--- 整宮制 12 宮頭 --- 宮頭 1 = ASC 所在星座 0°,其後每宮 +30°(模 360)。.
Class Method Details
.asc_longitude(armc_deg, eps, phi) ⇒ Object
--- ASC:標準公式 --- λ_ASC = atan2( cos ARMC, -(sin ARMC · cos ε + tan φ · sin ε) )
156 157 158 159 160 161 162 163 164 |
# File 'lib/astro_chart/pure/houses.rb', line 156 def asc_longitude(armc_deg, eps, phi) ra = armc_deg * DEG2RAD Core.norm360( Math.atan2( Math.cos(ra), -(Math.sin(ra) * Math.cos(eps) + Math.tan(phi) * Math.sin(eps)) ) * RAD2DEG ) end |
.calc(jd_ut, lat, lon, hsys = "P") ⇒ Object
jd_ut: UT 儒略日;lat: 地理緯度(北正);lon: 地理經度(東正) hsys: "P"(Placidus,預設)或 "W"(整宮制)
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
# File 'lib/astro_chart/pure/houses.rb', line 36 def calc(jd_ut, lat, lon, hsys = "P") tt = Core.jd_tt(jd_ut) eps = Core.true_obliquity(tt) * DEG2RAD # 真黃赤交角(弧度) ast_deg = Core.apparent_sidereal_deg(jd_ut) # 視恆星時(度) armc = Core.norm360(ast_deg + lon) # 天頂赤經 RAMC phi = lat * DEG2RAD mc = mc_longitude(armc, eps) asc = asc_longitude(armc, eps, phi) cusps = case hsys when "W" # 極圈內(|lat| > 90° − ε ≈ 66.56°)標準 atan2 公式可能傳回西方 # 交點(差 180°);整宮制在極圈內仍有定義,故此處修正為東昇點。 # 極圈外此修正恆為 no-op;Placidus 路徑不套用(維持原輸出)。 asc = east_ascendant(asc, mc) whole_sign_cusps(asc) when "E" # 等宮制:宮頭 1 = ASC,其後每宮 +30°。與整宮制同樣在 |lat| < 90° # 皆有定義,故一併套用東昇點修正。 asc = east_ascendant(asc, mc) equal_cusps(asc) when "O" # Porphyry:四大軸(ASC/IC/DSC/MC)之間的黃道弧各三等分。純幾何, # 不需半弧迭代,於 |lat| < 90° 皆有定義。 asc = east_ascendant(asc, mc) porphyry_cusps(asc, mc) else placidus_cusps(armc, eps, phi, asc, mc) end { "cusps" => cusps, "ascendant" => asc, "mc" => mc } end |
.east_ascendant(asc, mc) ⇒ Object
--- 東昇點修正 --- ASC 依定義位於 MC 東側半圓:(asc − mc) mod 360 ∈ (0°, 180°)。 極圈內原始公式可能落在西側半圓(實為降點),此時加 180°。 與 Swiss Ephemeris 極區行為一致(tmp/explore_polar_asc.rb 驗證 400 例全符)。
99 100 101 |
# File 'lib/astro_chart/pure/houses.rb', line 99 def east_ascendant(asc, mc) ((asc - mc) % 360.0) < 180.0 ? asc : Core.norm360(asc + 180.0) end |
.equal_cusps(asc) ⇒ Object
--- 等宮制 12 宮頭 --- 宮頭 1 = ASC 本身,其後每宮 +30°(模 360)。MC 仍照常算出並回傳, 但等宮制的第 10 宮頭為 ASC+270°,不等於 MC(MC 在宮內浮動)。
113 114 115 |
# File 'lib/astro_chart/pure/houses.rb', line 113 def equal_cusps(asc) Array.new(12) { |i| (asc + 30.0 * i) % 360.0 } end |
.mc_longitude(armc_deg, eps) ⇒ Object
--- MC:天頂赤經 → 黃道經度 --- tan λ_MC = tan(ARMC) / cos ε,以 atan2 處理象限
149 150 151 152 |
# File 'lib/astro_chart/pure/houses.rb', line 149 def mc_longitude(armc_deg, eps) ra = armc_deg * DEG2RAD Core.norm360(Math.atan2(Math.sin(ra), Math.cos(ra) * Math.cos(eps)) * RAD2DEG) end |
.placidus_cusp(armc_deg, eps, phi, offset_deg, frac, mode) ⇒ Object
--- Placidus 宮頭半弧迭代 --- 定義:黃道上一點 (α, δ),半日弧 SA_d = arccos(-tanφ·tanδ)、半夜弧 SA_n = arccos(tanφ·tanδ)。 宮頭 11:α = RAMC + (1/3)·SA_d 宮頭 12:α = RAMC + (2/3)·SA_d 宮頭 2 :α = RAMC + 180 - (2/3)·SA_n 宮頭 3 :α = RAMC + 180 - (1/3)·SA_n 黃道點的赤緯由 tan δ = tan ε · sin α 得出,固定點迭代至收斂。 offset_deg:初值偏移(赤道情形的精確解);frac:半弧比例;mode:地平上/下。
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 |
# File 'lib/astro_chart/pure/houses.rb', line 172 def placidus_cusp(armc_deg, eps, phi, offset_deg, frac, mode) tan_phi = Math.tan(phi) tan_eps = Math.tan(eps) ra = (armc_deg + offset_deg) * DEG2RAD armc_rad = armc_deg * DEG2RAD converged = false 60.times do dec = Math.atan(tan_eps * Math.sin(ra)) # 黃道點赤緯 x = tan_phi * Math.tan(dec) if x.abs > 1.0 # 極圈內該點無升落,Placidus 無定義。顯性失敗,不靜默 clamp。 raise Core::DomainError, "Placidus 在此緯度無定義(|tanφ·tanδ| = #{x.abs.round(4)} > 1,lat=#{(phi * RAD2DEG).round(4)}°)" end new_ra = if mode == :diurnal armc_rad + frac * Math.acos(-x) else armc_rad + Math::PI - frac * Math.acos(x) end step = (new_ra - ra).abs ra = new_ra # 先採納本次結果,收斂時回傳的才是最終值 if step < 1e-9 * DEG2RAD converged = true break end end raise Core::DomainError, "Placidus 宮頭迭代 60 次未收斂" unless converged # 赤經 → 黃道經度:tan λ = tan α / cos ε Core.norm360(Math.atan2(Math.sin(ra), Math.cos(ra) * Math.cos(eps)) * RAD2DEG) end |
.placidus_cusps(armc, eps, phi, asc, mc) ⇒ Object
--- Placidus 12 宮頭 ---
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
# File 'lib/astro_chart/pure/houses.rb', line 72 def placidus_cusps(armc, eps, phi, asc, mc) # Placidus 半弧迭代:宮頭 11、12(地平上,RAMC 東側)與 2、3(地平下) c11 = placidus_cusp(armc, eps, phi, 30.0, 1.0 / 3.0, :diurnal) c12 = placidus_cusp(armc, eps, phi, 60.0, 2.0 / 3.0, :diurnal) c2 = placidus_cusp(armc, eps, phi, 120.0, 2.0 / 3.0, :nocturnal) c3 = placidus_cusp(armc, eps, phi, 150.0, 1.0 / 3.0, :nocturnal) cusps = Array.new(12) cusps[0] = asc # 第 1 宮 = ASC cusps[1] = c2 cusps[2] = c3 cusps[3] = Core.norm360(mc + 180.0) # 第 4 宮 = MC 對沖 cusps[4] = Core.norm360(c11 + 180.0) cusps[5] = Core.norm360(c12 + 180.0) cusps[6] = Core.norm360(asc + 180.0) # 第 7 宮 = ASC 對沖 cusps[7] = Core.norm360(c2 + 180.0) cusps[8] = Core.norm360(c3 + 180.0) cusps[9] = mc # 第 10 宮 = MC cusps[10] = c11 cusps[11] = c12 cusps end |
.porphyry_cusps(asc, mc) ⇒ Object
--- Porphyry 12 宮頭 --- 依黃道經度遞增,四大軸順序為 ASC(1) → IC(4) → DSC(7) → MC(10)。每個 象限的黃道弧三等分,得中間兩個宮頭: 1→4:ASC..IC 弧 → 宮頭 2、3 4→7:IC..DSC 弧 → 宮頭 5、6 7→10:DSC..MC 弧 → 宮頭 8、9 10→1:MC..ASC 弧 → 宮頭 11、12
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
# File 'lib/astro_chart/pure/houses.rb', line 122 def porphyry_cusps(asc, mc) ic = Core.norm360(mc + 180.0) # 第 4 宮 = MC 對沖 dsc = Core.norm360(asc + 180.0) # 第 7 宮 = ASC 對沖 q1 = (ic - asc) % 360.0 # ASC → IC q2 = (dsc - ic) % 360.0 # IC → DSC q3 = (mc - dsc) % 360.0 # DSC → MC q4 = (asc - mc) % 360.0 # MC → ASC cusps = Array.new(12) cusps[0] = asc cusps[1] = Core.norm360(asc + q1 / 3.0) cusps[2] = Core.norm360(asc + 2.0 * q1 / 3.0) cusps[3] = ic cusps[4] = Core.norm360(ic + q2 / 3.0) cusps[5] = Core.norm360(ic + 2.0 * q2 / 3.0) cusps[6] = dsc cusps[7] = Core.norm360(dsc + q3 / 3.0) cusps[8] = Core.norm360(dsc + 2.0 * q3 / 3.0) cusps[9] = mc cusps[10] = Core.norm360(mc + q4 / 3.0) cusps[11] = Core.norm360(mc + 2.0 * q4 / 3.0) cusps end |
.whole_sign_cusps(asc) ⇒ Object
--- 整宮制 12 宮頭 --- 宮頭 1 = ASC 所在星座 0°,其後每宮 +30°(模 360)。
105 106 107 108 |
# File 'lib/astro_chart/pure/houses.rb', line 105 def whole_sign_cusps(asc) base = (asc / 30.0).floor * 30.0 Array.new(12) { |i| (base + 30.0 * i) % 360.0 } end |