feat(tahuantinsuyu): capa "ascensional" topocéntrica completa

5 fases que cierran el sistema topocéntrico end-to-end, conviviendo
con el cómputo geocéntrico tradicional sin reemplazarlo:

T3 — Pipeline en tahuantinsuyu-engine:
- Nuevo `PipelineRequest::Topocentric`.
- `build_topocentric_overlay(natal, render)`: para cada placement
  natal aplica `topocentric_ecliptic` (paralaje horizontal con
  `distance_km/AU` + observer.lat_rad + LST + obliquidad), emite
  Layer Bodies en ring=0.50 con `module_id="topocentric"`.
  Recalcula cusps con `Houses::compute(PolichPage, ...)` y emite
  Layer Houses asociado. Si la latitud cae en el círculo polar y
  Polich-Page diverge, sigue con planetas topocéntricos solos.

T4 — Render overlay en canvas:
- Nuevo `Radii.topocentric = 0.555·r` (justo bajo el carril natal
  bodies=0.60). `body_ring("topocentric")` lo mapea.
- Glyphs topocéntricos con disco más chico (22→22*s) y alpha 0.75
  (vs 1.0 natal) — se distinguen como "el sutil debajo del
  fuerte". En Luna el shift natal↔topo es visible; en Saturno los
  dos glyphs casi se superponen.
- Cusps Polich-Page pintadas como línea punteada (dash 3/2.5px)
  en un anillo interior al de casas geocéntricas, color
  `house_cusp` α=0.55 — claramente sistema secundario sin
  esconderse.

T5 — Módulo TopocentricModule:
- Nuevo módulo en tahuantinsuyu-modules con id="topocentric",
  label "Topocéntrico (ascensional)". Toggle "Activar" default
  OFF (es overlay opcional). Registrado en `Registry::with_builtins`.
- Shell traduce `module_configs["topocentric"]["enabled"] = true`
  → `PipelineRequest::Topocentric` en `build_requests`. Persiste
  por carta vía el mismo mecanismo de `persist_module`.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
sergio
2026-05-18 17:56:40 +00:00
parent 86c5fd8653
commit 1d49b9ff88
5 changed files with 239 additions and 19 deletions
@@ -142,6 +142,7 @@ impl Registry {
r.register(Box::new(uranian::UranianModule));
r.register(Box::new(lots::LotsModule));
r.register(Box::new(fixed_stars::FixedStarsModule));
r.register(Box::new(topocentric::TopocentricModule));
r
}
@@ -808,3 +809,49 @@ pub mod uranian {
}
}
}
// =====================================================================
// TopocentricModule — capa "ascensional" (paralaje + Polich-Page)
// =====================================================================
pub mod topocentric {
use super::*;
/// Capa topocéntrica que convive con la natal geocéntrica: cada
/// planeta se re-proyecta a longitud eclíptica topocéntrica (con
/// paralaje horizontal por cuerpo) y las casas se calculan con el
/// sistema Polich-Page. El shift es visible en la Luna (~1°),
/// modesto en interiores cerca de oposición, e imperceptible en
/// exteriores. La engine despacha al pipeline
/// `PipelineRequest::Topocentric` cuando este módulo está activo.
pub struct TopocentricModule;
impl Module for TopocentricModule {
fn id(&self) -> &'static str {
"topocentric"
}
fn label(&self) -> &'static str {
"Topocéntrico (ascensional)"
}
fn description(&self) -> &'static str {
"Paralaje horizontal por cuerpo + casas Polich-Page."
}
fn applies_to(&self, kind: ChartKind) -> bool {
matches!(kind, ChartKind::Natal)
}
fn enabled_by_default(&self) -> bool {
false
}
fn controls(&self) -> Vec<Control> {
vec![Control::Toggle {
key: "enabled".into(),
label: "Activar".into(),
default: false,
hotkey: None,
}]
}
fn compute_layers(&self, _chart: &Chart, _cfg: &serde_json::Value) -> Vec<Layer> {
Vec::new()
}
}
}