/** @brief Get an estimation of when a planet is gone past a fixed point ** ** Get Julian day number and positions when a celestial object is gone past ** a fixed point expressed in longitude degrees. This is not meant to be ** precise at all. Mainly used in swephelp search routines. ** ** @attention Same warning as in swh_next_retro. ** ** @remarks If step is set to 0, use a predefined step (recommended). ** ** @param planet Planet number (SE_*, etc) ** @param fixedpt Fixed pointed targeted [0;360[ ** @param jdstart Julian day number, when search is starting ** @param step Number of days used in the dichotomic search process ** @param backw Search before jdstart [1], or after [0] (boolean) ** @param flag Calculation flags, see swisseph docs ** @param jdret Julian day number found ** @param posret Planet's positions found ** @param err Buffer for errors, declared as char[256] ** @return 0 on success, -1 on error */ int swh_go_past(int planet, double fixedpt, double jdstart, double step, int backw, int flag, double *jdret, double *posret, char *err) { int res; double testjd, difdegn[2], difdeg2n[2]; /* find step if 0 */ if (step == 0) { step = swh_min_retro_time(planet, err); if (step < 0) { step = 10; } /* never retro, use default step */ } else { step = fabs(step); } /* get start position */ res = swe_calc_ut(jdstart, planet, flag, posret, err); if (res < 0) { return -1; } /* get difference between start pt and fixed pt */ difdegn[1] = swe_difdegn(posret[0], fixedpt); difdeg2n[1] = swe_difdeg2n(posret[0], fixedpt); *jdret = jdstart; while (1) { *jdret = (backw) ? *jdret-step : *jdret+step; res = swe_calc_ut(*jdret, planet, flag, posret, err); if (res < 0) { return -1; } if (posret[3] < 0) { res = swh_next_retro(planet, *jdret, step, (backw) ? 0 : 1, 0, flag, &testjd, posret, err); if (res < 0) { return -1; } } else { testjd = *jdret; } difdegn[0] = swe_difdegn(posret[0], fixedpt); difdeg2n[0] = swe_difdeg2n(posret[0], fixedpt); if (ISPOSITIVE(difdeg2n[1]) != ISPOSITIVE(difdeg2n[0]) && fabs(difdegn[1]-difdegn[0]) > 180) { *jdret = testjd; return 0; } difdegn[1] = difdegn[0]; difdeg2n[1] = difdeg2n[0]; } }
/** @brief Find next aspect between two moving objects ** ** Same as swh_next_aspect_with, but aspect in [0;180], instead of [0;360[. ** ** @see swh_next_aspect_with() ** ** @remarks If aspect is not 0 or 180, it will try two aspects [0;360[, and ** return the nearest from jdstart. It may then be faster to use ** swh_next_aspect_with several times, especially when scanning ** long periods of time. */ int swh_next_aspect_with2(int planet, double aspect, int other, char *star, double jdstart, double step, int backw, double dayspan, int flag, double *jdret, double *posret0, double *posret1, char *err) { int res, res2; double jdtmp, postmp0[6], postmp1[6]; aspect = fabs(swe_difdeg2n(0, aspect)); if (aspect == 0 || aspect == 180) { return swh_next_aspect_with(planet, aspect, other, star, jdstart, step, backw, dayspan, flag, jdret, posret0, posret1, err); } /* else try both */ res = swh_next_aspect_with(planet, aspect, other, star, jdstart, step, backw, dayspan, flag, jdret, posret0, posret1, err); if (res < 0) { return -1; } res2 = swh_next_aspect_with(planet, 0-aspect, other, star, jdstart, step, backw, dayspan, flag, &jdtmp, postmp0, postmp1, err); if (res2 < 0) { return -1; } if (res == 1 && res2 == 1) { return 1; } /* both reached time limit */ else if (res != res2) /* one reached limit */ { if (res2 == 0) { *jdret = jdtmp; for (res = 0; res < 6; res++) { posret0[res] = postmp0[res]; } for (res = 0; res < 6; res++) { posret1[res] = postmp1[res]; } } } else /* both found something */ { if (backw) { if (jdtmp > *jdret) { *jdret = jdtmp; for (res = 0; res < 6; res++) { posret0[res] = postmp0[res]; } for (res = 0; res < 6; res++) { posret1[res] = postmp1[res]; } } } else { if (jdtmp < *jdret) { *jdret = jdtmp; for (res = 0; res < 6; res++) { posret0[res] = postmp0[res]; } for (res = 0; res < 6; res++) { posret1[res] = postmp1[res]; } } } } return 0; }
/** @brief Find next aspect to a house cusp ** ** Same as swh_next_aspect_cusp, but aspect in [0;180], instead of [0;360[. ** ** @see swh_next_aspect_cusp() ** ** @remarks If aspect is not 0 or 180, it will try two aspects [0;360[, and ** return the nearest from jdstart. It may then be faster to use ** swh_next_aspect_cusp several times, especially when scanning ** long periods of time. */ int swh_next_aspect_cusp2(int planet, char *star, double aspect, int cusp, double jdstart, double lat, double lon, int hsys, double step, int backw, int flag, double *jdret, double *posret, double *cuspsret, double *ascmcret, char *err) { int res, res2; double jdtmp, postmp[6], cuspstmp[37], ascmctmp[10]; aspect = fabs(swe_difdeg2n(0, aspect)); if (aspect == 0 || aspect == 180) { return swh_next_aspect_cusp(planet, star, aspect, cusp, jdstart, lat, lon, hsys, step, backw, flag, jdret, posret, cuspsret, ascmcret, err); } /* else try both */ res = swh_next_aspect_cusp(planet, star, aspect, cusp, jdstart, lat, lon, hsys, step, backw, flag, jdret, posret, cuspsret, ascmcret, err); if (res < 0) { return -1; } res2 = swh_next_aspect_cusp(planet, star, aspect, cusp, jdstart, lat, lon, hsys, step, backw, flag, &jdtmp, postmp, cuspstmp, ascmctmp, err); if (res2 < 0) { return -1; } if (backw) { if (jdtmp > *jdret) { *jdret = jdtmp; for (res = 0; res < 6; res++) { posret[res] = postmp[res]; } for (res = 0; res < 37; res++) { cuspsret[res] = cuspstmp[res]; } for (res = 0; res < 10; res++) { ascmcret[res] = ascmctmp[res]; } } } else { if (jdtmp < *jdret) { *jdret = jdtmp; for (res = 0; res < 6; res++) { posret[res] = postmp[res]; } for (res = 0; res < 37; res++) { cuspsret[res] = cuspstmp[res]; } for (res = 0; res < 10; res++) { ascmcret[res] = ascmctmp[res]; } } } return 0; }
/** @brief Aspect matching ** ** Same as swh_match_aspect, but aspect in [0;180], instead of [0;360[ ** ** @see swh_match_aspect() */ int swh_match_aspect2(double pos0, double speed0, double pos1, double speed1, double aspect, double orb, double *diffret, int *applic, double *factor) { double difdeg2n = swe_difdeg2n(pos0, pos1); double diff = fabs(difdeg2n); aspect = fabs(aspect); orb = fabs(orb); if (difdeg2n > 0) { if (diff > aspect) { if (speed1 > speed0) { *applic = -1; } else if (speed1 < speed0) { *applic = 1; } else { *applic = 0; } *diffret = diff-aspect; } else if (diff < aspect) { if (speed1 > speed0) { *applic = 1; } else if (speed1 < speed0) { *applic = -1; } else { *applic = 0; } *diffret = aspect-diff; } else /* aspect exact */ { if (speed1 != speed0) { *applic = 1; } else { *applic = 0; } *diffret = 0; *factor = 0; return 0; } } else if (difdeg2n > -180) { if (diff > aspect) { if (speed1 > speed0) { *applic = 1; } else if (speed1 < speed0) { *applic = -1; } else { *applic = 0; } *diffret = diff-aspect; } else if (diff < aspect) { if (speed1 > speed0) { *applic = -1; } else if (speed1 < speed0) { *applic = 1; } else { *applic = 0; } *diffret = aspect-diff; } else /* aspect exact */ { if (speed1 != speed0) { *applic = 1; } else { *applic = 0; } *diffret = 0; *factor = 0; return 0; } } else /* exact conjunction or opposition */ { if (speed1 != speed0) { *applic = 1; } else { *applic = 0; } *diffret = 0; *factor = 0; return 0; } *factor = *diffret / orb; if (aspect-orb <= diff && diff <= aspect+orb) { return 0; } /* match */ else { return -1; } /* no match */ }
/** @brief Find next aspect to a house cusp ** ** Get Julian day number and positions, and houses cusps, when a ** celestial object makes longitudinal aspect to a house cusp. ** ** @attention Here, step may not be too high, or 0. Setting it to 0.2 is enough. ** ** @remarks If star != "", the planet is ignored. ** ** @see For risings, settings, meridian transits, see swe_rise_trans. ** ** @param planet Planet number (SE_*, etc) ** @param star Fixed star ** @param aspect Aspect, in degrees [0;360[ ** @param cusp House cusp number [1;12], or [1;36] for Gauquelin sectors ** @param jdstart Julian day number, when search is starting ** @param lat Latitude, in degrees (north is positive) ** @param lon Longitude, in degrees (east is positive) ** @param hsys House system, see swisseph docs ** @param step Number of days used in the dichotomic search process ** @param backw Search before jdstart [1], or after [0] (boolean) ** @param flag Calculation flags, see swisseph docs ** @param jdret Julian day number found ** @param posret Planet (or fixed star) positions found ** @param cuspsret House cusps positions found ** @param ascmcret Asc-Mc-etc found, see swisseph docs ** @param err Buffer for errors, declared as char[256] ** @return 0 on success, -1 on error */ int swh_next_aspect_cusp(int planet, char *star, double aspect, int cusp, double jdstart, double lat, double lon, int hsys, double step, int backw, int flag, double *jdret, double *posret, double *cuspsret, double *ascmcret, char *err) { int res, starflag; double diff[4]; char starbuf[41]; aspect = swe_degnorm(aspect); step = fabs(step); if (step == 0) { step = 0.2; } /* get start position */ if (strcmp("", star) != 0) { strcpy(starbuf, star); /* only first time */ res = swe_fixstar_ut(starbuf, jdstart, flag, posret, err); if (res < 0) { return -1; } starflag = 1; } else { res = swe_calc_ut(jdstart, planet, flag, posret, err); if (res < 0) { return -1; } starflag = 0; } res = swe_houses_ex(jdstart, flag, lat, lon, hsys, cuspsret, ascmcret); if (res < 0) { return -1; } /* compare */ diff[1] = swe_difdeg2n(posret[0], cuspsret[cusp] + aspect); diff[3] = swe_difdegn(posret[0], cuspsret[cusp] + aspect); *jdret = jdstart; while (step > swh_precision) { *jdret = (backw) ? *jdret-step : *jdret+step; /* get positions */ if (starflag) { res = swe_fixstar_ut(starbuf, *jdret, flag, posret, err); if (res < 0) { return -1; } } else { res = swe_calc_ut(*jdret, planet, flag, posret, err); if (res < 0) { return -1; } } res = swe_houses_ex(*jdret, flag, lat, lon, hsys, cuspsret, ascmcret); if (res < 0) { return -1; } /* compare */ diff[0] = swe_difdeg2n(posret[0], cuspsret[cusp] + aspect); diff[2] = swe_difdegn(posret[0], cuspsret[cusp] + aspect); if (ISPOSITIVE(diff[1]) != ISPOSITIVE(diff[0]) && fabs(diff[3]-diff[2]) > 180) { backw = (backw) ? 0 : 1; step = step/2; } diff[1] = diff[0]; diff[3] = diff[2]; } return 0; }
/** @brief Find next aspect between two moving objects ** ** Get Julian day number and positions when a celestial object makes a ** longitudinal aspect to another moving object. ** ** @attention Here, step may not be set to 0. If you estimate that the aspect ** is to occur in a very long time, you better set it to a high value, for ** faster results. In doubt, set it to 10. ** ** @remarks If star != "", the other planet is ignored. ** If dayspan is set to 0, the search is not limited in time. ** Otherwise, the function may return 1 when time limit has been reached. ** ** @param planet Planet number (SE_*, etc) ** @param aspect Aspect, in degrees [0;360[ ** @param other Other planet number ** @param star Fixed star ** @param jdstart Julian day number, when search is starting ** @param step Number of days used in the dichotomic search process ** @param backw Search before jdstart [1], or after [0] (boolean) ** @param dayspan Limit search to a certain time, expressed in days ** @param flag Calculation flags, see swisseph docs ** @param jdret Julian day number found ** @param posret0 Planet's positions found ** @param posret1 Other planet (or star) positions found ** @param err Buffer for errors, declared as char[256] ** @return 0 on success, 1 if time limit reached, -1 on error */ int swh_next_aspect_with(int planet, double aspect, int other, char *star, double jdstart, double step, int backw, double dayspan, int flag, double *jdret, double *posret0, double *posret1, char *err) { int res, starflag, direct = 0; /* dummy assign */ double jdstop = 0, diff[4]; /* dummy assign */ char starbuf[41]; aspect = swe_degnorm(aspect); step = fabs(step); if (step == 0) { step = 10; } dayspan = fabs(dayspan); if (dayspan) { jdstop = (backw) ? jdstart-dayspan : jdstart+dayspan; direct = (backw) ? 0 : 1; } /* get planets positions */ res = swe_calc_ut(jdstart, planet, flag, posret0, err); if (res < 0) { return -1; } if (strcmp("", star) != 0) { strcpy(starbuf, star); /* only first time */ res = swe_fixstar_ut(starbuf, jdstart, flag, posret1, err); if (res < 0) { return -1; } starflag = 1; } else { res = swe_calc_ut(jdstart, other, flag, posret1, err); if (res < 0) { return -1; } starflag = 0; } /* compare */ diff[1] = swe_difdeg2n(posret0[0], posret1[0] + aspect); diff[3] = swe_difdegn(posret0[0], posret1[0] + aspect); *jdret = jdstart; while (step > swh_precision) { *jdret = (backw) ? *jdret-step : *jdret+step; /* get planets positions */ res = swe_calc_ut(*jdret, planet, flag, posret0, err); if (res < 0) { return -1; } if (starflag) { res = swe_fixstar_ut(starbuf, *jdret, flag, posret1, err); if (res < 0) { return -1; } } else { res = swe_calc_ut(*jdret, other, flag, posret1, err); if (res < 0) { return -1; } } /* compare */ diff[0] = swe_difdeg2n(posret0[0], posret1[0] + aspect); diff[2] = swe_difdegn(posret0[0], posret1[0] + aspect); if (ISPOSITIVE(diff[1]) != ISPOSITIVE(diff[0]) && fabs(diff[3]-diff[2]) > 180) /* invert step */ { if (dayspan && backw == direct) { if (direct) { if (*jdret > jdstop) return 1; } else { if (*jdret < jdstop) return 1; } } backw = (backw) ? 0 : 1; step = step/2; } else if (dayspan && backw != direct) { if (direct) { if (*jdret > jdstop) return 1; } else { if (*jdret < jdstop) return 1; } } diff[1] = diff[0]; diff[3] = diff[2]; } return 0; }
int swh_saturn_4_stars( const double jd, const int flag, double* ret, char* err ) { char starbuf[50]; double xx[6]; double* stars[2] = {0,0}; /* dummy assign */ double midp, dist0, dist1, dist2; int i; /* Get bodies positions */ i = swe_calc_ut( jd, SE_SATURN, flag, xx, err ); if ( i < 0 ) return -1; ret[0] = xx[0]; strcpy( starbuf, "Aldebaran" ); i = swe_fixstar_ut( starbuf, jd, flag, xx, err ); if ( i < 0 ) return -1; ret[1] = xx[0]; strcpy( starbuf, "Regulus" ); i = swe_fixstar_ut( starbuf, jd, flag, xx, err ); if ( i < 0 ) return -1; ret[2] = xx[0]; strcpy( starbuf, "Antares" ); i = swe_fixstar_ut( starbuf, jd, flag, xx, err ); if ( i < 0 ) return -1; ret[3] = xx[0]; strcpy( starbuf, "Fomalhaut" ); i = swe_fixstar_ut( starbuf, jd, flag, xx, err ); if ( i < 0 ) return -1; ret[4] = xx[0]; /* Find nearest stars from Saturn */ if ( ret[0] <= ret[1] || ret[0] > ret[4] ) { stars[0] = &ret[4]; stars[1] = &ret[1]; } else if ( ret[0] <= ret[2] ) { stars[0] = &ret[1]; stars[1] = &ret[2]; } else if ( ret[0] <= ret[3] ) { stars[0] = &ret[2]; stars[1] = &ret[3]; } else if ( ret[0] <= ret[4] ) { stars[0] = &ret[3]; stars[1] = &ret[4]; } /* Find midpoint between stars */ midp = swe_deg_midp( *stars[0], *stars[1] ); /* Find distance Saturn/midpoint */ dist0 = fabs( swe_difdeg2n( ret[0], midp ) ); /* Find which star is closer from saturn and calculate the index */ dist1 = fabs( swe_difdeg2n( ret[0], *stars[0] ) ); dist2 = fabs( swe_difdeg2n( ret[0], *stars[1] ) ); if ( dist1 <= dist2 ) /* first is closer */ ret[5] = dist0 / ( fabs( swe_difdeg2n( midp, *stars[0] ) ) / 100.0 ); else /* second is closer */ ret[5] = dist0 / ( fabs( swe_difdeg2n( midp, *stars[1] ) ) / 100.0 ); return 0; }