Add astrological houses to natal chart and daily transits
Every planet position now carries its whole-sign house (1-12); transits report the natal house each transiting planet currently occupies rather than a fresh "houses for right now" chart, matching how transits are normally read. Surfaced in both text and HTML output, fully translated.
This commit is contained in:
@@ -86,6 +86,20 @@ static void compute_body_positions(astro_time_t time, PlanetPosition out[NUM_BOD
|
||||
}
|
||||
}
|
||||
|
||||
/* Whole-sign house number (1-12) for `sign`, counting from `ascendant_sign`
|
||||
* as house 1. Used both for the natal chart's own placements and (with the
|
||||
* natal ascendant) for today's transiting planets - see the `house` field
|
||||
* comment in astro.h for why transits use the natal houses, not their own. */
|
||||
static int whole_sign_house(ZodiacSign sign, ZodiacSign ascendant_sign) {
|
||||
return ((int)sign - (int)ascendant_sign + 12) % 12 + 1;
|
||||
}
|
||||
|
||||
static void assign_houses(PlanetPosition bodies[NUM_BODIES], ZodiacSign ascendant_sign) {
|
||||
for (int b = 0; b < NUM_BODIES; b++) {
|
||||
bodies[b].house = whole_sign_house(bodies[b].sign, ascendant_sign);
|
||||
}
|
||||
}
|
||||
|
||||
void astro_compute_natal_chart(const BirthData *birth, NatalChart *out) {
|
||||
astro_time_t time = time_from_birth(birth);
|
||||
|
||||
@@ -96,6 +110,8 @@ void astro_compute_natal_chart(const BirthData *birth, NatalChart *out) {
|
||||
for (int house = 0; house < 12; house++) {
|
||||
out->houses[house] = (ZodiacSign)((ascendant_sign + house) % 12);
|
||||
}
|
||||
|
||||
assign_houses(out->bodies, out->houses[0]);
|
||||
}
|
||||
|
||||
static MoonPhaseName moon_phase_from_angle(double angle_deg) {
|
||||
@@ -129,6 +145,7 @@ void astro_compute_daily_transits(time_t utc_moment, const NatalChart *natal,
|
||||
astro_time_t time = time_from_unix(utc_moment);
|
||||
|
||||
compute_body_positions(time, out->bodies);
|
||||
assign_houses(out->bodies, natal->houses[0]);
|
||||
|
||||
astro_angle_result_t phase = Astronomy_MoonPhase(time);
|
||||
out->moon_phase = moon_phase_from_angle(phase.angle);
|
||||
|
||||
@@ -60,6 +60,11 @@ typedef struct {
|
||||
double ecliptic_longitude; /* geocentric, degrees, [0, 360) */
|
||||
ZodiacSign sign;
|
||||
double degree_in_sign; /* [0, 30) */
|
||||
int house; /* 1-12, whole-sign, always relative to the natal Ascendant -
|
||||
* for DailyTransits.bodies this places today's transiting
|
||||
* planets in the natal chart's own houses (the standard,
|
||||
* personalized way to read transits), not a fresh "houses
|
||||
* for right now" chart. */
|
||||
} PlanetPosition;
|
||||
|
||||
typedef struct {
|
||||
|
||||
@@ -18,7 +18,8 @@ void reading_generate(const char *tarot_seed, const BirthData *birth,
|
||||
}
|
||||
|
||||
static void print_position_deg(FILE *out, const PlanetPosition *p) {
|
||||
fprintf(out, "%5.1f%s %s", p->degree_in_sign, "\xc2\xb0", astro_sign_name(p->sign));
|
||||
fprintf(out, "%5.1f%s %-11s (%s %d)", p->degree_in_sign, "\xc2\xb0",
|
||||
astro_sign_name(p->sign), ui("ui.house", "House"), p->house);
|
||||
}
|
||||
|
||||
void reading_print_text(const DailyReading *r, FILE *out) {
|
||||
@@ -68,8 +69,8 @@ void reading_print_text(const DailyReading *r, FILE *out) {
|
||||
}
|
||||
|
||||
static void print_body_row_html(FILE *out, const char *label, const PlanetPosition *p) {
|
||||
fprintf(out, "<tr><td>%s</td><td>%.1f° %s</td></tr>\n", label,
|
||||
p->degree_in_sign, astro_sign_name(p->sign));
|
||||
fprintf(out, "<tr><td>%s</td><td>%.1f° %s</td><td>%s %d</td></tr>\n", label,
|
||||
p->degree_in_sign, astro_sign_name(p->sign), ui("ui.house", "House"), p->house);
|
||||
}
|
||||
|
||||
void reading_print_html(const DailyReading *r, FILE *out) {
|
||||
|
||||
Reference in New Issue
Block a user