/** @brief Find next direction changing of object ** ** This function tries to find when and where a planet in direct or ** retrograde motion goes retrograde or direct (respectively). ** ** @attention If step is set to 0, use a predefined step (recommended); it must ** be inferior to the planet's minimum retrogradation time. ** ** @remarks 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. ** Flag must include SEFLG_SPEED, and SEFLG_NOGDEFL to avoid bad surprises; ** alternatively use true positions. ** ** @see swh_min_retro_time() ** ** @param planet Planet number (SE_*, etc) ** @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 posret Planet's positions found ** @param err Buffer for error, declared as char[256] ** @return 0 on success, 1 if time limit reached, -1 on error */ int swh_next_retro(int planet, double jdstart, double step, int backw, double dayspan, int flag, double *jdret, double *posret, char *err) { int res, direct[3]; double jdstop = 0; /* dummy assign */ direct[2] = 0; /* dummy assign */ /* set limit */ dayspan = fabs(dayspan); if (dayspan) { jdstop = (backw) ? jdstart-dayspan : jdstart+dayspan; direct[2] = (backw) ? 0 : 1; } /* find step if 0 */ if (step == 0) { step = swh_min_retro_time(planet, err); if (step < 0) { return -1; } /* never retro */ } else { step = fabs(step); } /* find current direction */ res = swe_calc_ut(jdstart, planet, flag, posret, err); if (res < 0) { return -1; } direct[1] = direct[0] = (posret[3] > 0) ? 1 : 0; /* step till direction changes */ *jdret = jdstart; while (step > swh_precision) { *jdret = (backw) ? *jdret-step : *jdret+step; res = swe_calc_ut(*jdret, planet, flag, posret, err); if (res < 0) { return -1; } direct[0] = (posret[3] > 0) ? 1 : 0; if (direct[0] != direct[1]) /* invert step */ { if (dayspan && backw == direct[2]) { if (direct[2]) { if (*jdret > jdstop) return 1; } else { if (*jdret < jdstop) return 1; } } step = step/2; backw = (backw) ? 0 : 1; direct[1] = direct[0]; } else if (dayspan && backw != direct[2]) { if (direct[2]) { if (*jdret > jdstop) return 1; } else { if (*jdret < jdstop) return 1; } } } return 0; }
double SweWrapper::body_pos(body b, double julian_day) { /* target address for 6 position values: longitude, latitude, distance, long. speed, lat. speed, dist. speed */ static double coords[6]; static char swe_error_msg[AS_MAXCH]; static long calc_flag = 0; int swe_body = static_cast<int>(body_to_swe_body(b)); long swe_result = swe_calc_ut(julian_day, swe_body, calc_flag, coords, swe_error_msg); if(calc_flag != swe_result) { throw runtime_error{ (string("Swiss ephemeris error: '") + swe_error_msg + "'\n").c_str() }; } if(b == body::earth || b == body::snode) { coords[0] += 180.; if(coords[0] > 360.) coords[0] -= 360.; } // return ecliptic longitude of the body (in degrees [0..365), counting from the vernal equinox of the date as 0 degrees) return coords[0]; }
/** @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 Get number of years difference between two julian days ** ** One exact "astrological" year can be considered as one solar return. ** Then is it varying with the type of zodiac in use. ** ** @param jd1 First Julian day ** @param jd2 Second Julian day ** @param flag Calculation flag ** @param years Result, declared as double ** @param err Buffer for errors, declared as char[256] ** @return 0 on success, else -1 **/ int swh_years_diff(double jd1, double jd2, int flag, double *years, char *err) { double pos1[6], pos2[6], dec; double corr = 2 * swh_precision; int res; res = swe_calc_ut(jd1, SE_SUN, flag, pos1, err); if (res < 0) { return -1; } res = swe_calc_ut(jd2, SE_SUN, flag, pos2, err); if (res < 0) { return -1; } *years = 0; if (jd1 < jd2) /* forward search */ { dec = swe_difdegn(pos2[0], pos1[0]) / 360.0; while (1) { res = swh_next_aspect(SE_SUN, 0, pos1[0], jd1+corr, 120, 0, 0, flag, &jd1, pos2, err); if (res < 0) { return -1; } if (jd1+corr < jd2) { *years += 1; } else { break; } } *years += dec; } else if (jd1 > jd2) /* backward search */ { dec = swe_difdegn(pos1[0], pos2[0]) / 360.0; while (1) { res = swh_next_aspect(SE_SUN, 0, pos1[0], jd1-corr, 120, 1, 0, flag, &jd1, pos2, err); if (res < 0) { return -1; } if (jd1-corr > jd2) { *years -= 1; } else { break; } } *years -= dec; } /* else equal julian days */ return 0; }
static PyObject* astrology_swe_calc_ut(PyObject *self, PyObject *args) { double tjd_ut; int ipl; int iflag; if (!PyArg_ParseTuple(args, "dii", &tjd_ut, &ipl, &iflag)) return NULL; double xx[6]; char serr[AS_MAXCH]; int ret = swe_calc_ut(tjd_ut, ipl, iflag, xx, serr); return Py_BuildValue("(l)(dddddd)(s)", ret, xx[0], xx[1], xx[2], xx[3], xx[4], xx[5], serr); }
/* * Calculation of planets, moon, asteroids, lunar nodes, apogees, fictitious bodies * http://www.astro.com/swisseph/swephprg.htm#_Toc283735419 long swe_calc_ut( double tjd_ut, // Julian day number, Universal Time int ipl, // planet number long iflag, // flag bits double *xx, // target address for 6 position values: longitude, latitude, distance, long.speed, lat.speed, dist.speed char *serr // 256 bytes for error string ); */ static VALUE t_swe_calc_ut(VALUE self, VALUE julian_ut, VALUE body, VALUE iflag) { double results[6]; char serr[AS_MAXCH]; VALUE arr = rb_ary_new(); int id_push = rb_intern("push"); int i=0; if ( swe_calc_ut(NUM2DBL(julian_ut), NUM2INT(body), NUM2LONG(iflag), results, serr) < 0 ) rb_raise (rb_eRuntimeError, serr); for ( i = 0; i < 6; i++) rb_funcall(arr, id_push, 1, rb_float_new(results[i])); return arr; }
/** @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; }