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:
@@ -10,8 +10,9 @@ use std::time::Instant;
|
||||
|
||||
use eternal_astrology::{
|
||||
all_lots, composite, find_aspects, find_synastry_aspects, next_return, secondary_progression,
|
||||
solar_arc_true, Aspect, AspectKind as EAspectKind, BirthData, BodySet, ChartConfig,
|
||||
HouseSystem as EHouseSystem, NatalChart, OrbTable, Zodiac as EZodiac,
|
||||
solar_arc_true, topocentric_ecliptic, Aspect, AspectKind as EAspectKind, BirthData, BodySet,
|
||||
ChartConfig, HouseSystem as EHouseSystem, Houses as EHouses, NatalChart, OrbTable,
|
||||
Zodiac as EZodiac,
|
||||
};
|
||||
use eternal_sky::{Ayanamsha, Body, EphemerisSession, Instant as ESInstant, Observer, SessionConfig};
|
||||
|
||||
@@ -380,6 +381,14 @@ pub fn compose(
|
||||
format!("Estrellas fijas · {}", count),
|
||||
);
|
||||
}
|
||||
crate::PipelineRequest::Topocentric => {
|
||||
build_topocentric_overlay(&natal, &mut render)?;
|
||||
push_overlay_meta(
|
||||
&mut render,
|
||||
"topocentric",
|
||||
"Topocéntrico (Polich-Page)".into(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -462,6 +471,93 @@ fn build_transit_overlay(
|
||||
/// secundaria. La carta progresada se computa con el mismo observer y
|
||||
/// config que la natal pero al instante natal+(age_years/period_years)
|
||||
/// días.
|
||||
/// Overlay topocéntrico: re-proyecta cada placement natal a longitud
|
||||
/// topocéntrica (con paralaje horizontal) y recalcula las casas con
|
||||
/// Polich-Page. Los dos quedan emparentados al mismo `module_id =
|
||||
/// "topocentric"` para que el canvas los pinte con un visual
|
||||
/// consistente. La capa convive con la natal geocéntrica — ambas se
|
||||
/// ven simultáneamente.
|
||||
fn build_topocentric_overlay(
|
||||
natal: &NatalChart,
|
||||
render: &mut RenderModel,
|
||||
) -> Result<(), EngineError> {
|
||||
const KM_PER_AU: f64 = 149_597_870.7;
|
||||
let lst = natal.local_apparent_sidereal_time_rad;
|
||||
let eps = natal.obliquity_rad;
|
||||
let obs_lat = natal.birth.observer.lat_rad;
|
||||
|
||||
// 1) Planetas topocéntricos. Para puntos sin distancia (nodos,
|
||||
// Lilith calculada) `topocentric_ecliptic` retorna la entrada sin
|
||||
// cambios — geocéntrico y topocéntrico coinciden ahí.
|
||||
let body_glyphs: Vec<Glyph> = natal
|
||||
.placements
|
||||
.iter()
|
||||
.map(|p| {
|
||||
let dist_au = p.distance_km / KM_PER_AU;
|
||||
let (lon_topo, _) = topocentric_ecliptic(
|
||||
p.longitude.longitude_rad(),
|
||||
p.latitude_rad,
|
||||
dist_au,
|
||||
obs_lat,
|
||||
lst,
|
||||
eps,
|
||||
);
|
||||
let lon_topo_deg = lon_topo.to_degrees() as f32;
|
||||
Glyph {
|
||||
deg: lon_topo_deg,
|
||||
symbol: body_symbol(p.body).into(),
|
||||
annotation: Some(format!("{:.2}° topo", lon_topo_deg)),
|
||||
retrograde: p.longitude_rate_rad_per_day < 0.0,
|
||||
house: None,
|
||||
dignity_marker: None,
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
render.layers.push(Layer {
|
||||
module_id: "topocentric".into(),
|
||||
kind: LayerKind::Bodies,
|
||||
ring: 0.50,
|
||||
z: 8,
|
||||
geometry: Geometry::GlyphsOnly,
|
||||
glyphs: body_glyphs,
|
||||
});
|
||||
|
||||
// 2) Casas Polich-Page. Si la latitud cae en el círculo polar el
|
||||
// sistema diverge — devolvemos un error parcial pero conservamos
|
||||
// la capa de planetas topocéntricos (que sí es válida).
|
||||
match EHouses::compute(EHouseSystem::PolichPage, lst, obs_lat, eps) {
|
||||
Ok(houses_pp) => {
|
||||
let cusps_deg: Vec<f32> =
|
||||
houses_pp.cusps.iter().map(|c| c.to_degrees() as f32).collect();
|
||||
let house_glyphs: Vec<Glyph> = (0..12)
|
||||
.map(|i| Glyph {
|
||||
deg: cusps_deg[i] + 4.0,
|
||||
symbol: format!("h{}", i + 1),
|
||||
annotation: None,
|
||||
retrograde: false,
|
||||
house: Some((i as u8) + 1),
|
||||
dignity_marker: None,
|
||||
})
|
||||
.collect();
|
||||
render.layers.push(Layer {
|
||||
module_id: "topocentric".into(),
|
||||
kind: LayerKind::Houses,
|
||||
ring: 0.78,
|
||||
z: 9,
|
||||
geometry: Geometry::Ring { cusps_deg },
|
||||
glyphs: house_glyphs,
|
||||
});
|
||||
}
|
||||
Err(e) => {
|
||||
// Polo: el visual se queda solo con planetas topocéntricos.
|
||||
eprintln!("[bridge] PolichPage no disponible en lat polar: {:?}", e);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn build_progression_overlay(
|
||||
natal: &NatalChart,
|
||||
target_age_years: f64,
|
||||
|
||||
@@ -326,6 +326,13 @@ pub enum PipelineRequest {
|
||||
/// aproximadas + precesión simple (~50.29″/año). Renderea como
|
||||
/// marcadores chicos justo afuera del sign dial.
|
||||
FixedStars,
|
||||
/// `module_id = "topocentric"` — capa "ascensional": planetas
|
||||
/// re-proyectados a longitud eclíptica topocéntrica (con paralaje
|
||||
/// horizontal aplicada por cuerpo) + casas Polich-Page (sistema
|
||||
/// topocéntrico de domificación). Visible sobre todo en la Luna
|
||||
/// (~1° de shift); imperceptible en planetas exteriores. La capa
|
||||
/// convive con la natal geocéntrica como overlay comparativo.
|
||||
Topocentric,
|
||||
}
|
||||
|
||||
/// Opciones que afectan la pasada natal (qué aspectos pintar, qué
|
||||
|
||||
Reference in New Issue
Block a user