/* * astro.cpp written by nickolas * * this is a utility to display the astrological configuration for a specific * date, time, and set of lat- and longitudinal coordinates. * * this application uses the astrodienst swisseph library and swiss ephemeris, * and must be built on the system that this is being compiled on. if you have * this utility you probably have it as well as the necessary ephemeride files * to compute charts for the dates you desire. if not, see here: * * if you're doing computation for dates between 1800 AD and 2399 AD, you only * need these ephemeride files: * * sepl_18.se1 (planets file) * semo_18.se1 (moon file) * seas_18.se1 (asteroid file) * * ... each of which i have in the current working directory. * * in regards to the command-line options, there are only a couple things that * should be noted; most else should be self-explanitory if you're using this. * * * when you're providing a time value to the '-u' flag, you're providing a * 24-hour value in _universal time_. so, if you live in the EST time zone, * and you would like to calculate a chart for noon time, you would provide * 17:00, because UTC is 5 hours in front of EST, and 17:00 is the 24-hour * equivalent of 5 PM. * * * although the '-c' flag should also be pretty self-explanitory, an example * for the coordinates of Boston, MA, which is 42.37 north latitude and * 71.05 west longitude, the topo value would be '-c 42.37N,71.05W'. also, * if you don't use capital letters, you might get some errors spat out at * you if you don't get any erratic behavior. about the lingering '0' after * the latitude and longitude values, that is the altitude. if you don't know * the correct altitude for the coordinates you're providing, you can just * leave it at 0. it most likely won't make that much of a difference to * any part of your chart (except by maybe a degree or two or three). * * * $ 8/20/2009: currently no real checks for the proper formatting of the * date and time strings, so take care to use them properly! * i.e. two digits for day, month, minutes and hours, and four * for the year (same for topo). i'll fix this in the next update. * * $ 8/21/2009: added checks for dates/times/topo. quicker than i thought that * i would! * * that's all, enjoy! * */ #include #include #include #include #include #include using namespace std; struct options { bool sidereal; bool tropical; bool deg_to_sign; double timeval; double geo_long; double geo_lati; double geo_alti; char londir; char latdir; int jd_day; int jd_month; int jd_year; }; // set the date void set_date(options op, char *arg) { string date; string delim; vector date_res; int cutmark; char *a = "/"; date = arg; delim = a; while ((cutmark = date.find_first_of(delim)) != date.npos) { if (cutmark > 0) date_res.push_back(date.substr(0, cutmark)); date = date.substr(cutmark + 1); } if (date.length() > 0) date_res.push_back(date); op.jd_month = atoi(date_res[0].c_str()); op.jd_day = atoi(date_res[1].c_str()); op.jd_year = atoi(date_res[2].c_str()); } // set the time void set_time(options op, char *arg) { string time; string lconv, ldelm, delim; vector time_res; int cutmark; char *a = ".", *b = ":"; time = arg; ldelm = a; delim = b; while ((cutmark = time.find_first_of(delim)) != time.npos) { if (cutmark > 0) time_res.push_back(time.substr(0, cutmark)); time = time.substr(cutmark + 1); } if (time.length() > 0) time_res.push_back(time); lconv = time_res[0] + ldelm + time_res[1]; op.timeval = strtod(lconv.c_str(), NULL); } // set the geographic positions (latitude, longitude, altitude) void set_topo(options op, char *arg) { string coord; string lldelim; string altit; vector ll_res; int cutmark; char *a = ","; coord = arg; lldelim = a; while ((cutmark = coord.find_first_of(lldelim)) != coord.npos) { if (cutmark > 0) ll_res.push_back(coord.substr(0, cutmark)); coord = coord.substr(cutmark + 1); } if (coord.length() > 0) ll_res.push_back(coord); char tmp_a[sizeof(coord[0]) - 1]; char tmp_b[sizeof(coord[1]) - 1]; string a_tmp, b_tmp; a_tmp = coord[0]; b_tmp = coord[1]; if (a_tmp[strlen(a_tmp.c_str()) - 1] == 'S') { snprintf(tmp_a, sizeof(tmp_a) + 2, "-%s", coord[0]); op.latdir = 'S'; } else { snprintf(tmp_a, sizeof(tmp_a) + 1, "%s", coord[0]); op.latdir = 'N'; } if (b_tmp[strlen(b_tmp.c_str()) - 1] == 'W') { snprintf(tmp_b, sizeof(tmp_b) + 2, "-%s", coord[1]); op.londir = 'W'; } else { snprintf(tmp_b, sizeof(tmp_b) + 1, "%s", coord[1]); op.londir = 'E'; } altit = coord[2]; op.geo_lati = strtod(tmp_a, NULL); op.geo_long = strtod(tmp_b, NULL); op.geo_alti = strtod(altit.c_str(), NULL); } // print the chart to stdout void print_chart(options op) { double comp_jdate; double comp_jtime; double parray[6]; int32 iflag = SEFLG_SPEED, iflag_ret; char error[AS_MAXCH]; char pname[40]; int i; comp_jdate = swe_julday(op.jd_year, op.jd_month, op.jd_day, op.timeval, SE_GREG_CAL); comp_jtime = comp_jdate + swe_deltat(comp_jdate); swe_set_topo(op.geo_long, op.geo_lati, op.geo_alti); cout << "* at " << op.timeval << " on " << op.jd_month << "/" << op.jd_day << "/" << op.jd_year << endl; cout << "* latitude: " << op.geo_lati << op.latdir << " " << "longitude: " << op.geo_long << op.londir << " " << "altitude: " << op.geo_alti << endl; iflag |= SEFLG_TOPOCTR; for (i = SE_SUN; i <= SE_CHIRON; i++) { if (i == SE_EARTH) continue; iflag_ret = swe_calc(comp_jtime, i, iflag, parray, error); if (iflag_ret < 0) cout << "# error: " << error << endl; else if (iflag_ret != iflag) cout << "# warning: iflag_ret != iflag: " << error << endl; swe_get_planet_name(i, pname); cout << pname << "\t" << parray[0] << "\t" << parray[1]; cout << "\t" << parray[2] << "\t" << parray[3] << endl; } } // show the help/usage screen void help_screen(char *name) { cout << "* utility to display astrological configurations" << endl; cout << "* written by nickolas, using astrodienst swisseph" << endl; cout << endl; cout << "usage: " << name << " [-hjst] [-d date] [-u time] [-c topo]" << endl; cout << "-h\tdisplay this intro/help message screen." << endl; cout << "-j\t(requires either -s or -t flags) translate" << endl; cout << " \tconstellation degrees to signs, based on the" << endl; cout << " \tsidereal or tropical assigments." << endl; cout << "-s\t(requires -j flag) display sidereal flavor chart, with" << endl; cout << " \tpisces at zero degrees." << endl; cout << "-t\t(requires -j flag) display tropical flavor chart, with" << endl; cout << " \taries at zero degrees." << endl; cout << "-d date\tcalculate chart for the date (on a gregorian calendar)" << endl; cout << " \tprovided by 'date' (format mm/dd/yyyy)" << endl; cout << "-u time\tcalculate chart for the time (universal time)" << endl; cout << " \tprovided by 'time' (format hh:mm)" << endl; cout << "-c topo\tcalculate chart for the lat- and longitudinal" << endl; cout << " \tcoordinates provided by 'topo' (format 00.00N,00.00W,0)" << endl; cout << endl; cout << "see the comments in the source file for extra (more detailed) help" << endl; cout << "with these options and the general usage of this application; it" << endl; cout << "is much, much easier to use than this help screen will have you believe." << endl; } // the main routine int main(int argc, char **argv) { options op; int c; while ((c = getopt(argc, argv, "hjstd:u:c:")) != -1) { switch(c) { case 'h': help_screen(argv[0]); return EXIT_FAILURE; case 'j': cout << "* converting degrees to constellation names" << endl; op.deg_to_sign = true; break; case 's': cout << "* using sidereal flavor chart (pisces at 0 degrees)" << endl; if (op.deg_to_sign == true) { op.sidereal = true; op.tropical = false; } break; case 't': cout << "* using tropical flavor chart (aries at 0 degrees)" << endl; if (op.deg_to_sign == true) { op.sidereal = false; op.tropical = true; } break; case 'd': set_date(op, optarg); if (op.jd_day > 31 or op.jd_month > 12) { cout << argv[0] << ": error: invalid date string. quitting." << endl; return EXIT_FAILURE; } break; case 'u': set_time(op, optarg); if (op.timeval > 24.59) { cout << argv[0] << ": error: invalid time string. quitting." << endl; return EXIT_FAILURE; } break; case 'c': set_topo(op, optarg); break; default: help_screen(argv[0]); return EXIT_FAILURE; } } if (op.deg_to_sign == true and (op.sidereal == false and op.tropical == false)) { help_screen(argv[0]); return EXIT_FAILURE; } print_chart(op); return EXIT_SUCCESS; }