astroceleste_engine/
fixed_stars.rs1use serde::Serialize;
4
5use crate::aspects::{Aspect, Point};
6use crate::catalog::FIXED_STARS;
7use crate::pyfloat;
8use crate::symbolic::symbolic_degree_number;
9use crate::zodiac::{determine_house, longitude_to_zodiac, PRECESSION_RATE_ARCSEC_YEAR};
10
11#[derive(Debug, Clone, PartialEq, Serialize)]
13pub struct FixedStarPosition {
14 pub name: &'static str,
16 pub symbol: &'static str,
18 pub sign: &'static str,
20 pub sign_symbol: &'static str,
22 pub degree: i64,
24 pub minute: i64,
26 pub ecliptic_longitude: f64,
28 pub ecliptic_latitude: f64,
30 pub house: u8,
32 pub magnitude: f64,
34 pub symbolic_degree: i64,
36}
37
38pub fn fixed_stars(
41 jd: f64,
42 cusps: &[f64],
43 points: &[Point],
44 max_orb: f64,
45 sidereal_shift: Option<f64>,
46) -> (Vec<FixedStarPosition>, Vec<Aspect>) {
47 let years = (jd - 2_451_545.0) / 365.25;
48 let precession_deg = (years * PRECESSION_RATE_ARCSEC_YEAR) / 3600.0;
49 let mut stars = Vec::new();
50 let mut aspects = Vec::new();
51
52 for star in &FIXED_STARS {
53 let mut lon = pyfloat::rem(star.j2000_lon + precession_deg, 360.0);
54 if let Some(ayanamsa) = sidereal_shift {
55 lon = pyfloat::rem(pyfloat::rem(lon - ayanamsa, 360.0) + 360.0, 360.0);
56 }
57 let mut conjunct = false;
58 for body in points {
59 let mut diff = pyfloat::rem((lon - body.longitude).abs(), 360.0);
60 if diff > 180.0 {
61 diff = 360.0 - diff;
62 }
63 let orb = (diff - 0.0).abs();
64 if orb <= max_orb {
65 conjunct = true;
66 aspects.push(Aspect {
67 body1: star.name.to_string(),
68 body2: body.name.to_string(),
69 aspect_type: "Conjunction",
70 symbol: "☌",
71 angle: 0.0,
72 orb: pyfloat::round(orb, 2),
73 max_orb: pyfloat::round(max_orb, 2),
74 is_major: None,
75 is_applying: true,
76 });
77 }
78 }
79 if conjunct {
80 let z = longitude_to_zodiac(lon);
81 stars.push(FixedStarPosition {
82 name: star.name,
83 symbol: star.symbol,
84 sign: z.sign.name,
85 sign_symbol: z.sign.symbol,
86 degree: z.degree,
87 minute: z.minute,
88 ecliptic_longitude: lon,
89 ecliptic_latitude: star.j2000_lat,
90 house: determine_house(lon, cusps),
91 magnitude: star.magnitude,
92 symbolic_degree: symbolic_degree_number(z.degree, z.minute),
93 });
94 }
95 }
96 (stars, aspects)
97}