diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..624d5cf --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,31 @@ +# Swephelp CMakeLists.txt + +cmake_minimum_required( VERSION 2.8 ) +project( swephelp ) + +message( STATUS "-- Configuring swephelp..." ) + +set( SOURCES + swhdatetime.c + swhformat.c + swhgeo.c + swhmisc.c + swhraman.c + swhsearch.c + swhutil.c + ) + +include_directories( BEFORE . ../libswe ) + +if ( MSVC ) + add_definitions( -D_CRT_SECURE_NO_WARNINGS ) +else() + add_definitions( -g -O9 -Wall ) + if ( NOT MINGW ) + add_definitions( -fPIC ) + endif() +endif() + +add_library( swephelp STATIC ${SOURCES} ) + +# vi: set fenc=utf-8 ff=unix et sw=4 ts=3 sts=4 : diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..86cdc86 --- /dev/null +++ b/Makefile @@ -0,0 +1,21 @@ +# Swephelp makefile + +CC = gcc +CFLAGS = -g -O9 -Wall -std=gnu99 +# path to swisseph +INCS = -I. -I./libswe + +SWHOBJ = swhdatetime.o swhformat.o swhgeo.o swhmisc.o swhraman.o swhsearch.o swhutil.o + +.c.o: + $(CC) -c $(CFLAGS) $(INCS) $< + +all: libswephelp.a + +libswephelp.a: $(SWHOBJ) + ar rcs libswephelp.a $(SWHOBJ) + +clean: + rm -f *.o libswephelp.a + +# vi: set fenc=utf-8 ff=unix sw=4 et=4 ts=4 sts=4 : diff --git a/README.TXT b/README.TXT new file mode 100644 index 0000000..bf37c97 --- /dev/null +++ b/README.TXT @@ -0,0 +1,15 @@ +=============== +Swephelp README +=============== + +Swephelp is a helper library based on (and for) the Swiss Ephemeris library. +It is not part of the Swiss Ephemeris library itself. + +It features a collection of functions frequently used in astrology applications. + +Functions for dates and time, geographical information, indian astrology, +transits search, constant values for aspects, signs, planets... + +Stanislas Marquis + +.. diff --git a/swephelp.h b/swephelp.h new file mode 100644 index 0000000..dbfb604 --- /dev/null +++ b/swephelp.h @@ -0,0 +1,53 @@ +/* + Swephelp + + Copyright 2007-2014 Stanislas Marquis + + Swephelp is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + Swephelp is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Swephelp. If not, see . +*/ + +/** @file swephelp.h +** @brief swephelp export header file +** +** Main swephelp header, imports all swephelp functions and defines. +*/ + +#ifndef SWEPHELP_H +#define SWEPHELP_H + +/* pollute namespace with fancy aliases */ +#ifndef SWH_USE_ALIASES +#define SWH_USE_ALIASES 1 +#endif + +/* use a global mutex to protect swisseph data */ +#ifndef SWH_USE_THREADS +#define SWH_USE_THREADS 1 +#endif + +/* include swisseph functions */ +#include + +/* swephelp headers */ +#include "swhdatetime.h" +#include "swhdef.h" +#include "swhformat.h" +#include "swhgeo.h" +#include "swhmisc.h" +#include "swhraman.h" +#include "swhsearch.h" +#include "swhutil.h" + +#endif /* SWEPHELP_H */ +/* vi: set fenc=utf-8 ff=unix et sw=4 ts=4 sts=4 : */ diff --git a/swhdatetime.c b/swhdatetime.c new file mode 100644 index 0000000..6c9348b --- /dev/null +++ b/swhdatetime.c @@ -0,0 +1,168 @@ +/* + Swephelp + + Copyright 2007-2014 Stanislas Marquis + + Swephelp is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + Swephelp is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Swephelp. If not, see . +*/ + +/** @file swhdatetime.c +** @brief swephelp date and time functions +*/ + +#include +#include +#include +#include +#include +#include + +#include + +#include "swhdatetime.h" +#include "swhwin.h" + +/** @brief Get current Julian day number, Gregorian calendar +** @return Julian day number +*/ +double swh_jdnow(void) +{ + time_t t = time(NULL); +#ifdef WIN32 /* has not gmtime_r ? */ + struct tm *tmp = gmtime(&t); + return swe_julday(tmp->tm_year+1900, tmp->tm_mon+1, tmp->tm_mday, + (tmp->tm_hour+(tmp->tm_min/60.0)+(tmp->tm_sec/3600.0)), SE_GREG_CAL); +#else + struct tm tmp; + gmtime_r(&t, &tmp); + return swe_julday(tmp.tm_year+1900, tmp.tm_mon+1, tmp.tm_mday, + (tmp.tm_hour+(tmp.tm_min/60.0)+(tmp.tm_sec/3600.0)), SE_GREG_CAL); +#endif +} + +/** @brief Reverse Julian day to date and time +** +** Similar to swe_revjul, but returns time with three integers instead +** of one double. (Also tries to avoid some floating points rounding errors.) +** +** @see swh_julday() +** +** @param jd Julian day +** @param flag Calendar type (SE_GREG_CAL|SE_JUL_CAL) +** @param dt Results, declared as int[6] (year, month, day, hour, min, sec) +** @return 0 +*/ +int swh_revjul(double jd, int flag, int *dt) +{ + double t; + assert(flag == SE_GREG_CAL || flag == SE_JUL_CAL); + swe_revjul(jd, flag, &dt[0], &dt[1], &dt[2], &t); + dt[3] = (int) floor(t); + t -= dt[3]; + dt[4] = (int) floor(t * 60); + t -= dt[4]/60.0; + dt[5] = (int) lround(t * 3600); + if (dt[5] == 60) /* rounding error */ + { + dt[5] = 0; + dt[4] += 1; + if (dt[4] == 60) + { + dt[4] = 0; + dt[3] += 1; + /* wont go further? */ + } + } + return 0; +} + +/** @brief Get integers from datetime representation +** +** As a habit we keep dates and times in a personal, yet +** unambiguous format: "{yyyy}/{mm}/{dd} {hh}:{mm}:{ss}". +** +** @param coord datetime string +** @param ret Returned integers declared as int[6] +** @return 0 on success, or -1 if string is invalid +*/ +int swh_dt2i(const char *dt, int *ret) +{ + char *ptr, buf[22]; +#ifndef WIN32 + char *saveptr; +#endif + strcpy(buf, dt); +#ifndef WIN32 + ptr = strtok_r(buf, "/", &saveptr); +#else + ptr = strtok(buf, "/"); +#endif + if (ptr == NULL || strspn(ptr, "-0123456789") != strlen(ptr)) + return -1; + else + ret[0] = atoi(ptr); /* year */ +#ifndef WIN32 + ptr = strtok_r(NULL, "/", &saveptr); +#else + ptr = strtok(NULL, "/"); +#endif + if (ptr == NULL || strspn(ptr, "0123456789") != strlen(ptr)) + return -1; + else + ret[1] = atoi(ptr); /* month */ + assert(ret[1] > 0 && ret[1] < 13); +#ifndef WIN32 + ptr = strtok_r(NULL, " ", &saveptr); +#else + ptr = strtok(NULL, " "); +#endif + if (ptr == NULL || strspn(ptr, "0123456789") != strlen(ptr)) + return -1; + else + ret[2] = atoi(ptr); /* mday */ + assert(ret[2] > 0 && ret[2] < 32); +#ifndef WIN32 + ptr = strtok_r(NULL, ":", &saveptr); +#else + ptr = strtok(NULL, ":"); +#endif + if (ptr == NULL || strspn(ptr, "0123456789") != strlen(ptr)) + return -1; + else + ret[3] = atoi(ptr); /* hour */ + assert(ret[3] > -1 && ret[3] < 24); +#ifndef WIN32 + ptr = strtok_r(NULL, ":", &saveptr); +#else + ptr = strtok(NULL, ":"); +#endif + if (ptr == NULL || strspn(ptr, "0123456789") != strlen(ptr)) + return -1; + else + ret[4] = atoi(ptr); /* minutes */ + assert(ret[4] > -1 && ret[4] < 60); +#ifndef WIN32 + ptr = strtok_r(NULL, ":", &saveptr); +#else + ptr = strtok(NULL, ":"); +#endif + if (ptr == NULL || strspn(ptr, "0123456789") != strlen(ptr)) + return -1; + else + ret[5] = atoi(ptr); /* seconds */ + assert(ret[5] > -1 && ret[5] < 60); + return 0; +} + +/* vi: set fenc=utf-8 ff=unix et sw=4 ts=4 sts=4 : */ diff --git a/swhdatetime.h b/swhdatetime.h new file mode 100644 index 0000000..01213cc --- /dev/null +++ b/swhdatetime.h @@ -0,0 +1,102 @@ +/* + Swephelp + + Copyright 2007-2014 Stanislas Marquis + + Swephelp is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + Swephelp is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Swephelp. If not, see . +*/ + +/** @file swhdatetime.h +** @brief swephelp date and time functions +*/ + +#ifndef SWHDATETIME_H +#define SWHDATETIME_H + +#ifndef SWH_USE_ALIASES +#define SWH_USE_ALIASES 1 +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include + +/** @brief Get current Julian day number, Gregorian calendar +** @return Julian day number +*/ +double swh_jdnow(void); + +/** @brief Get Julian day number from a date and time +** +** A conveniance function that, compared to swe_julday, does not require +** hour in decimal format, but accepts integers only. +** +** @attention Does not check date validity. See swe_date_conversion. +** +** @see swh_revjul() +** +** @param year Year (4 digits) +** @param mon Month [1;12] +** @param day Day [1;31] +** @param hour Hour [0;23] +** @param min Minutes [0;59] +** @param sec Seconds [0;59] +** @param flag Calendar type (SE_GREG_CAL|SE_JUL_CAL) +** @return Julian day number +*/ +#define swh_julday(year, mon, day, hour, min, sec, flag)\ + swe_julday(year, mon, day, ((hour)+((min)/60.0)+((sec)/3600.0)), flag) + +/** @brief Reverse Julian day to date and time +** +** Similar to swe_revjul, but returns time with three integers instead +** of one double. (Also tries to avoid some floating points rounding errors.) +** +** @see swh_julday() +** +** @param jd Julian day +** @param flag Calendar type (SE_GREG_CAL|SE_JUL_CAL) +** @param dt Results, declared as int[6] (year, month, day, hour, min, sec) +** @return 0 +*/ +int swh_revjul(double jd, int flag, int *dt); + +/** @brief Get integers from datetime representation +** +** As a habit we keep dates and times in a personal, yet +** unambiguous format: "{yyyy}/{mm}/{dd} {hh}:{mm}:{ss}". +** +** @param coord datetime string +** @param ret Returned integers declared as int[6] +** @return 0 on success, or -1 if string is invalid +*/ +int swh_dt2i(const char *dt, int *ret); + +#if SWH_USE_ALIASES + +/** @def DateTime_Split +*/ +#define DateTime_Split(dt, ret) swh_dt2i(dt, ret) + +#endif /* SWH_USE_ALIASES */ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* SWHDATETIME_H */ +/* vi: set fenc=utf-8 ff=unix et sw=4 ts=4 sts=4 : */ diff --git a/swhdef.h b/swhdef.h new file mode 100644 index 0000000..0b87d78 --- /dev/null +++ b/swhdef.h @@ -0,0 +1,144 @@ +/* + Swephelp + + Copyright 2007-2014 Stanislas Marquis + + Swephelp is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + Swephelp is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Swephelp. If not, see . +*/ + +/** @file swhdef.h +** @brief swephelp defines header file +** +** Contains various usefull defines. +*/ + +#ifndef SWHDEF_H +#define SWHDEF_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* Aspects */ +#define SWH_CONJUNCTION 0 +#define SWH_SQUISEXTILE 15 +#define SWH_SEMINOVILE 20 +#define SWH_SQUISQUARE 22.5 +#define SWH_UNDECILE (360/11.0) +#define SWH_SEMISEXTILE 30 +#define SWH_SEMIQUINTILE 36 +#define SWH_NOVILE 40 +#define SWH_SEMISQUARE 45 +#define SWH_SEPTILE (360/7.0) +#define SWH_SEXTILE 60 +#define SWH_BIUNDECILE ((360/11.0)*2) +#define SWH_QUINTILE 72 +#define SWH_BINOVILE 80 +#define SWH_SQUARE 90 +#define SWH_TRIUNDECILE ((360/11.0)*3) +#define SWH_BISEPTILE ((360/7.0)*2) +#define SWH_TRINE 120 +#define SWH_QUADUNDECILE ((360/11.0)*4) +#define SWH_SESQUISQUARE 135 +#define SWH_BIQUINTILE 144 +#define SWH_QUINCUNX 150 +#define SWH_TRISEPTILE ((360/7.0)*3) +#define SWH_QUATRONOVILE 160 +#define SWH_QUINUNDECILE ((360/11.0)*5) +#define SWH_OPPOSITION 180 + +/* Signs */ +#define SWH_ARIES 0 +#define SWH_TAURUS 1 +#define SWH_GEMINI 2 +#define SWH_CANCER 3 +#define SWH_LEO 4 +#define SWH_VIRGO 5 +#define SWH_LIBRA 6 +#define SWH_SCORPIO 7 +#define SWH_SAGITTARIUS 8 +#define SWH_CAPRICORN 9 +#define SWH_AQUARIUS 10 +#define SWH_PISCES 11 + +#define SWH_MESHA SWH_ARIES +#define SWH_VRISHABA SWH_TAURUS +#define SWH_MITHUNA SWH_GEMINI +#define SWH_KATAKA SWH_CANCER +#define SWH_SIMHA SWH_LEO +#define SWH_KANYA SWH_VIRGO +#define SWH_THULA SWH_LIBRA +#define SWH_VRISHIKA SWH_SCORPIO +#define SWH_DHANUS SWH_SAGITTARIUS +#define SWH_MAKARA SWH_CAPRICORN +#define SWH_KUMBHA SWH_AQUARIUS +#define SWH_MEENA SWH_PISCES + +/* Planets */ +#define SWH_RAVI 0 +#define SWH_CHANDRA 1 +#define SWH_BUDHA 2 +#define SWH_SUKRA 3 +#define SWH_KUJA 4 +#define SWH_GURU 5 +#define SWH_SANI 6 +#define SWH_RAHU 10 +#define SWH_KETU -10 + +#define SWH_SURYA SWH_RAVI +#define SWH_SOMA SWH_CHANDRA +#define SWH_SOUMYA SWH_BUDHA +#define SWH_BHARGAVA SWH_SUKRA +#define SWH_ANGARAKA SWH_KUJA +#define SWH_BRIHASPATI SWH_GURU +#define SWH_MANDA SWH_SANI +#define SWH_THAMA SWH_RAHU +#define SWH_SIKHI SWH_KETU + +/* Nakshatras */ +#define SWH_ASWINI 0 +#define SWH_BHARANI 1 +#define SWH_KRITHIKA 2 +#define SWH_ROHINI 3 +#define SWH_MRIGASIRA 4 +#define SWH_ARIDRA 5 +#define SWH_PUNARVASU 6 +#define SWH_PUSHYAMI 7 +#define SWH_ASLESHA 8 +#define SWH_MAKHA 9 +#define SWH_PUBBA 10 +#define SWH_UTTARA 11 +#define SWH_HASTA 12 +#define SWH_CHITTA 13 +#define SWH_SWATHI 14 +#define SWH_VISHAKA 15 +#define SWH_ANURADHA 16 +#define SWH_JYESTA 17 +#define SWH_MOOLA 18 +#define SWH_POORVASHADA 19 +#define SWH_UTTARASHADA 20 +#define SWH_SRAVANA 21 +#define SWH_DHANISHTA 22 +#define SWH_SATABISHA 23 +#define SWH_POORVABHADRA 24 +#define SWH_UTTARABHADRA 25 +#define SWH_REVATHI 26 + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* swhdef.h */ +/* vi: set fenc=utf-8 ff=unix et sw=4 ts=4 sts=4 : */ diff --git a/swhformat.c b/swhformat.c new file mode 100644 index 0000000..32f6e73 --- /dev/null +++ b/swhformat.c @@ -0,0 +1,189 @@ +/* + Swephelp + + Copyright 2007-2014 Stanislas Marquis + + Swephelp is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + Swephelp is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Swephelp. If not, see . +*/ + +/** @file swhformat.c +** @brief swephelp formating functions +*/ + +#include + +#include "swhformat.h" + +/** @brief Get degrees, sign number, minutes, seconds, from longitude position +** +** Split a longitude position to a more usual format. +** +** @param pos Longitude position [0;360[ +** @param ret Results, declared as int[4] (deg, sign, min, sec) +** @return 0 +*/ +int swh_degsplit(double pos, int *ret) +{ + pos = swe_degnorm(pos); + ret[1] = (int) floor(pos/30.0); + pos -= ret[1]*30; + ret[0] = (int) floor(pos); + pos -= ret[0]; + ret[2] = (int) floor(pos*60); + pos -= ret[2]/60.0; + ret[3] = (int) floor(pos*3600); + return 0; +} + +/** @brief Get the 3-letters string representing a sign number +** @param sign Sign number [0;11] +** @param str Returned string, declared as char[4] +** @return 0, or -1 if sign was invalid +*/ +int swh_signtostr(int sign, char *str) +{ + switch (sign) + { + case 0: strcpy(str, "Ari"); return 0; + case 1: strcpy(str, "Tau"); return 0; + case 2: strcpy(str, "Gem"); return 0; + case 3: strcpy(str, "Can"); return 0; + case 4: strcpy(str, "Leo"); return 0; + case 5: strcpy(str, "Vir"); return 0; + case 6: strcpy(str, "Lib"); return 0; + case 7: strcpy(str, "Sco"); return 0; + case 8: strcpy(str, "Sag"); return 0; + case 9: strcpy(str, "Cap"); return 0; + case 10: strcpy(str, "Aqu"); return 0; + case 11: strcpy(str, "Pis"); return 0; + default: return -1; + } +} + +/** @brief Get house system name +** @param hsys House system char [PKRCBOAEHVXGU] +** @param str Returned string, declared as char[25] +** @return 0, or -1 if house system is unknown +*/ +int swh_house_system_name(char hsys, char *str) +{ + switch (hsys) + { + case 'P': strcpy(str, "Placidus"); return 0; + case 'K': strcpy(str, "Koch"); return 0; + case 'R': strcpy(str, "Regiomontanus"); return 0; + case 'C': strcpy(str, "Campanus"); return 0; + case 'B': strcpy(str, "Alcabitius"); return 0; + case 'M': strcpy(str, "Morinus"); return 0; + case 'O': strcpy(str, "Porphyry"); return 0; + case 'A': strcpy(str, "Equal"); return 0; + case 'E': strcpy(str, "Equal"); return 0; + case 'H': strcpy(str, "Horizon/Azimuth"); return 0; + case 'V': strcpy(str, "Equal Vehlow"); return 0; + case 'X': strcpy(str, "Axial Rotation/Meridian"); return 0; + case 'G': strcpy(str, "Gauquelin"); return 0; + case 'T': strcpy(str, "Polich/Page"); return 0; + case 'U': strcpy(str, "Krusinski"); return 0; + case 'W': strcpy(str, "Whole Sign"); return 0; + case 'Y': strcpy(str, "APC Houses"); return 0; + default: return -1; + } +} + +/** @brief Get house system unique id +** @param hsys House system char identifier (see swisseph docs) +** @return A numerical identifier, or -1 if house system invalid +*/ +int swh_house_system_id(char hsys) +{ + switch (hsys) + { + case 'P': return 0; + case 'K': return 1; + case 'R': return 2; + case 'C': return 3; + case 'B': return 4; + case 'M': return 5; + case 'O': return 6; + case 'A': return 7; + case 'E': return 7; /* same */ + case 'H': return 8; + case 'V': return 9; + case 'X': return 10; + case 'G': return 11; + case 'T': return 12; + case 'U': return 13; + case 'W': return 14; + case 'Y': return 15; + default: return -1; + } +} + +/** @brief Get house system char +** @param hsys House system int identifier +** @return Identifier, or -1 if house system invalid +*/ +char swh_house_system_char(int hsys) +{ + switch (hsys) + { + case 0: return 'P'; + case 1: return 'K'; + case 2: return 'R'; + case 3: return 'C'; + case 4: return 'B'; + case 5: return 'M'; + case 6: return 'O'; + case 7: return 'A'; + /* case 7: return 'E'; / same */ + case 8: return 'H'; + case 9: return 'V'; + case 10: return 'X'; + case 11: return 'G'; + case 12: return 'T'; + case 13: return 'U'; + case 14: return 'W'; + case 15: return 'Y'; + default: return -1; + } +} + +/** @brief Get sidereal mode flag +** +** Return the swisseph sidereal mode flag from the given sidereal mode index. +** +** @param sidmode +** @return Flag, or -1 if invalid mode +*/ +int swh_sidereal_mode_flag(int sidmode) +{ + if (sidmode == 0) return 256; /* no western/tropical flag in swisseph */ + else if (sidmode == 22) return 255; /* user defined */ + else if (sidmode > 0 && sidmode < 22) return sidmode - 1; + else return -1; +} + +/** @brief Get sidereal mode unique identifier +** @param sidmode Sidereal mode identifier +** @return index [0:22] +*/ +int swh_sidereal_mode_id(int sidmode) +{ + if (sidmode == 256) return 0; /* western/tropical */ + else if (sidmode == 255) return 22; /* user-defined */ + else if (sidmode > -1 && sidmode < 21) return sidmode + 1; + else return -1; +} + +/* vi: set fenc=utf-8 ff=unix et sw=4 ts=4 sts=4 : */ diff --git a/swhformat.h b/swhformat.h new file mode 100644 index 0000000..0178dd1 --- /dev/null +++ b/swhformat.h @@ -0,0 +1,116 @@ +/* + Swephelp + + Copyright 2007-2014 Stanislas Marquis + + Swephelp is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + Swephelp is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Swephelp. If not, see . +*/ + +/** @file swhformat.h +** @brief swephelp formating functions +*/ + +#ifndef SWHFORMAT_H +#define SWHFORMAT_H + +#ifndef SWH_USE_ALIASES +#define SWH_USE_ALIASES 1 +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** @brief Get degrees, sign number, minutes, seconds, from longitude position +** +** Split a longitude position to a more usual format. +** +** @param pos Longitude position [0;360[ +** @param ret Results, declared as int[4] (deg, sign, min, sec) +** @return 0 +*/ +int swh_degsplit(double pos, int *ret); + +/** @brief Get the 3-letters string representing a sign number +** @param sign Sign number [0;11] +** @param str Returned string, declared as char[4] +** @return 0, or -1 if sign was invalid +*/ +int swh_signtostr(int sign, char *str); + +/** @brief Get house system name +** @param hsys House system char [PKRCBOAEHVXGU] +** @param str Returned string, declared as char[25] +** @return 0, or -1 if house system is unknown +*/ +int swh_house_system_name(char hsys, char *str); + +/** @brief Get house system unique id +** @param hsys House system char identifier (see swisseph docs) +** @return Identifier, or -1 if house system invalid +*/ +int swh_house_system_id(char hsys); + +/** @brief Get house system char +** @param hsys House system int identifier +** @return iIdentifier, or -1 if house system invalid +*/ +char swh_house_system_char(int hsys); + +/** @brief Get sidereal mode flag +** +** Return the swisseph sidereal mode flag from the given sidereal mode index. +** +** @param sidmode +** @return Flag, or -1 if invalid mode +*/ +int swh_sidereal_mode_flag(int sidmode); + +/** @brief Get sidereal mode unique identifier +** @param sidmode Sidereal mode identifier +** @return index [0:22] +*/ +int swh_sidereal_mode_id(int sidmode); + +#if SWH_USE_ALIASES + +/** @def HouseSystem_AsCharP +*/ +#define HouseSystem_AsCharP(x) swh_house_system_name(x) + +/** @def HouseSystem_AsChar +*/ +#define HouseSystem_AsChar(x) swh_house_system_char(x) + +/** @def HouseSystem_AsInt +*/ +#define HouseSystem_AsInt(x) swh_house_system_id(x) + +/** @def SiderealMode_AsFlag +*/ +#define SiderealMode_AsFlag(x) swh_sidereal_mode_flag(x) + +/** @def SiderealMode_AsInt +*/ +#define SiderealMode_AsInt(x) swh_sidereal_mode_id(x) + +#endif /* SWH_USE_ALIASES */ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* SWHFORMAT_H */ +/* vi: set fenc=utf-8 ff=unix et sw=4 ts=4 sts=4 : */ diff --git a/swhgeo.c b/swhgeo.c new file mode 100644 index 0000000..b82117f --- /dev/null +++ b/swhgeo.c @@ -0,0 +1,171 @@ +/* + Swephelp + + Copyright 2007-2014 Stanislas Marquis + + Swephelp is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + Swephelp is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Swephelp. If not, see . +*/ + +/** @file swhgeo.c +** @brief Geographical utilities (latitude, longitude, altitude) +*/ + +#include +#include +#include +#include +#include + +#include "swhgeo.h" +#include "swhwin.h" + +/** @brief Get double from latitude or longitude string +** +** Get a double from a longitude or latitude expressed as a string like +** "{degrees}:{direction}:{minutes}:{seconds}". +** Directions are given as a single char, 'N' for north, 'S' for south, +** 'E' for east, 'W' for west. +** +** @param coord Latitude or longitude string +** @param ret Returned double +** @return 0 on success, or -1 if string is invalid +*/ +int swh_geoc2d(const char *coord, double *ret) +{ + int deg, dir, min, sec; +#ifndef NDEBUG + int degmax; /* used in asserts only */ +#endif + char *ptr, buf[12]; + strcpy(buf, coord); +#ifndef WIN32 + char *saveptr; + ptr = strtok_r(buf, ":", &saveptr); +#else + ptr = strtok(buf, ":"); +#endif + if (ptr == NULL || strspn(ptr, "0123456789") != strlen(ptr)) + return -1; + else + deg = atoi(ptr); + assert(deg >= 0); +#ifndef WIN32 + ptr = strtok_r(NULL, ":", &saveptr); +#else + ptr = strtok(NULL, ":"); +#endif + if (ptr == NULL) + return -1; + else + { + if (strcmp(ptr, "N") == 0 || strcmp(ptr, "E") == 0) + { +#ifndef NDEBUG + degmax = 90; +#endif + dir = 1; + } + else if (strcmp(ptr, "S") == 0 || strcmp(ptr, "W") == 0) + { +#ifndef NDEBUG + degmax = 180; +#endif + dir = 0; + } + else + return -1; + } + assert(deg <= degmax); +#ifndef WIN32 + ptr = strtok_r(NULL, ":", &saveptr); +#else + ptr = strtok(NULL, ":"); +#endif + if (ptr == NULL || strspn(ptr, "0123456789") != strlen(ptr)) + return -1; + else + min = atoi(ptr); + assert(deg == degmax ? min == 0 : min >= 0 && min <= 59); +#ifndef WIN32 + ptr = strtok_r(NULL, ":", &saveptr); +#else + ptr = strtok(NULL, ":"); +#endif + if (ptr == NULL || strspn(ptr, "0123456789") != strlen(ptr)) + return -1; + else + sec = atoi(ptr); + assert(deg == degmax ? sec == 0 : sec >= 0 && sec <= 59); + *ret = (double) (dir ? + (deg + ((1.0/60) * min) + ((1.0/3600) * sec)) : + -(deg + ((1.0/60) * min) + ((1.0/3600) * sec))); + return 0; +} + +/** @brief Extract degrees, minutes and seconds from a geographical coordinate +** @param coord Latitude or Longitude +** @param ret Returned degrees, minutes, seconds, declared as int[3] +** @return 0 +*/ +int swh_geod2i(double coord, int *ret) +{ + coord = fabs(coord); + ret[0] = (int) floor(coord); + coord -= ret[0]; + ret[1] = (int) lround(coord * 60); + coord -= ret[1] / 60.0; + ret[2] = (int) lround(coord * 3600); + if (ret[2] < 0) ret[2] = 0; + return 0; +} + +/** @brief Get string from geographical coordinates +** +** Get formated string for a geographical coordinate, like +** "{degrees}:{N|S|E|W}:{minutes}:{seconds}". +** +** @remarks Use the defined macros swh_geolat2c swh_geolon2c instead. +** +** @param coord longitude as double +** @param ret Buffer for returned string, declared as char[12] +** @param maxdeg 90 for latitude, 180 for longitude +** @return 0 on success, or -1 if coord is invalid +*/ +int swh_geod2c(double coord, int maxdeg, char *ret) +{ + int deg, dir, min, sec; + if (coord < -(maxdeg) || coord > maxdeg) + return -1; + if (coord >= 0) + { + deg = (int) floor(coord); + dir = 1; + } + else + { + deg = (int) fabs(ceil(coord)); + dir = 0; + } + coord = fabs(coord) - deg; + min = (int) lround(coord * 60); + coord -= min / 60.0; + sec = (int) lround(coord * 3600); + if (maxdeg == 90) /* latitude */ + sprintf(ret, "%.2d:%s:%.2d:%.2d", deg, dir ? "N" : "S", min, sec); + else /* assuming longitude */ + sprintf(ret, "%.3d:%s:%.2d:%.2d", deg, dir ? "E" : "W", min, sec); + return 0; +} + +/* vi: set fenc=utf-8 ff=unix et sw=4 ts=4 sts=4 : */ diff --git a/swhgeo.h b/swhgeo.h new file mode 100644 index 0000000..7f46959 --- /dev/null +++ b/swhgeo.h @@ -0,0 +1,156 @@ +/* + Swephelp + + Copyright 2007-2014 Stanislas Marquis + + Swephelp is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + Swephelp is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Swephelp. If not, see . +*/ + +/** @file swhgeo.h +** @brief Geographical utilities (latitude, longitude, altitude) +*/ + +#ifndef SWHGEO_H +#define SWHGEO_H + +#ifndef SWH_USE_ALIASES +#define SWH_USE_ALIASES 1 +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** @brief Get double from latitude or longitude string +** +** Get a double from a longitude or latitude expressed as a string like +** "{degrees}:{direction}:{minutes}:{seconds}". +** Directions are given in a single char, 'N' for north, 'S' for south, +** 'E' for east, 'W' for west. +** +** @param coord Latitude or longitude string +** @param ret Returned double +** @return 0 on success, or -1 if string is invalid +*/ +int swh_geoc2d(const char *coord, double *ret); + +/** @brief Extract degrees, minutes and seconds from a geographical coordinate +** @param coord Latitude or Longitude +** @param ret Returned degrees, minutes, seconds, declared as int[3] +** @return 0 +*/ +int swh_geod2i(double coord, int *ret); + +/** @brief Get string from geographical coordinates +** +** Get formated string for a geographical coordinate, like +** "{degrees}:{N|S|E|W}:{minutes}:{seconds}". +** +** @remarks Use the defined macros swh_geolat2c swh_geolon2c instead. +** +** @param coord longitude as double +** @param ret Buffer for returned string, declared as char[12] +** @param maxdeg 90 for latitude, 180 for longitude +** @return 0 on success, or -1 if coord is invalid +*/ +int swh_geod2c(double coord, int maxdeg, char *ret); + +/** @brief Get string from geographical latitude +** +** Get formated string for a latitude, like +** "{degrees}:{N|S}:{minutes}:{seconds}". +** +** @param coord latitude as double +** @param ret Buffer for returned string, declared as char[11] +** @return 0 on success, or -1 if latitude is invalid +*/ +#define swh_geolat2c(coord, ret) swh_geod2c((coord), 90, (ret)) + +/** @brief Get string from geographical longitude +** +** Get formated string for a longitude, like +** "{degrees}:{E|W}:{minutes}:{seconds}". +** +** @param coord latitude as double +** @param ret Buffer for returned string, declared as char[12] +** @return 0 on success, or -1 if latitude is invalid +*/ +#define swh_geolon2c(coord, ret) swh_geod2c((coord), 180, (ret)) + +#if SWH_USE_ALIASES + +/** @def GeoLat +** @brief Latitude (as double) +*/ +#define GeoLat double + +/** @def GeoLon +** @brief Longitude (as double) +*/ +#define GeoLon double + +/** @def GeoCoord +** @brief Generic Geocoordinate (as double) +*/ +#define GeoCoord double + +/** @def GeoAlt +** @brief Altitude (as integer) +*/ +#define GeoAlt int + +/** @def GeoLat_Check +** @brief Check latitude validity +*/ +#define GeoLat_Check(x) (((x) < -90 || (x) > 90) ? (0) : (1)) + +/** @def GeoLon_Check +** @brief Check longitude validity +*/ +#define GeoLon_Check(x) (((x) < -180 || (x) > 180) ? (0) : (1)) + +/** @def GeoAlt_Check +** @brief Check altitude validity (must be >= 0, cf. swisseph doc) +*/ +#define GeoAlt_Check(x) (((x) < 0) ? (0) : (1)) + +/** @def GeoCoord_AsInt +** @brief Get degrees, minutes, seconds of a coordinate, in an int[3] +*/ +#define GeoCoord_AsInt(x, y) swh_geod2i((x), (y)) + +/** @def GeoCoord_AsDouble +** @brief Get a double from a geocoord char* representation +*/ +#define GeoCoord_AsDouble(x, y) swh_geoc2d((x), (y)) + +/** @def GeoLat_AsString +** @brief Get a char* representation of a latitude +*/ +#define GeoLat_AsString(coord, ret) swh_geolat2c((coord), (ret)) + +/** @def GeoLon_AsString +** @brief Get a char* representation of a longitude +*/ +#define GeoLon_AsString(coord, ret) swh_geolon2c((coord), (ret)) + +#endif /* SWH_USE_ALIASES */ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* SWHGEO_H */ +/* vi: set fenc=utf-8 ff=unix et sw=4 ts=4 sts=4 : */ diff --git a/swhmisc.c b/swhmisc.c new file mode 100644 index 0000000..5175409 --- /dev/null +++ b/swhmisc.c @@ -0,0 +1,105 @@ +/* + Swephelp + + Copyright 2007-2014 Stanislas Marquis + + Swephelp is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + Swephelp is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Swephelp. If not, see . +*/ + +/** @file swhmisc.c +** @brief Misc experimental stuff +*/ + +#include + +#include "swhmisc.h" + +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; +} + +/* vi: set fenc=utf-8 ff=unix et sw=4 ts=4 sts=4 : */ diff --git a/swhmisc.h b/swhmisc.h new file mode 100644 index 0000000..b7d7ab1 --- /dev/null +++ b/swhmisc.h @@ -0,0 +1,60 @@ +/* + Swephelp + + Copyright 2007-2014 Stanislas Marquis + + Swephelp is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + Swephelp is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Swephelp. If not, see . +*/ + +/** @file swhmisc.h +** @brief Misc experimental stuff +*/ + +#ifndef SWHMISC_H +#define SWHMISC_H + +#ifndef SWH_USE_ALIASES +#define SWH_USE_ALIASES 1 +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** @brief Calculate Halbronn's "Saturn 4 Stars" index value +** @param jd Julian day UT +** @param flag Calculation flags, see Swisseph docs +** @param ret Array for 6 double (longitude of Sat, Ald, Reg, Ant, Fom, and index value) +** @param err Buffer for error, declared as char[256] +** @return 0 on success, else -1 +** +** This is an attempt at defining an "index value" based on Jacques Halbronn's +** theory, known as the "Saturn 4 stars" system, or "Astrocyclon", or "Central +** Astrology", etc. +** +** The returned value (the index) represents, for a given time, the visual +** proximity of Saturn regarding its cycle along the path marked by the royal stars. +** The nearer of the stars Saturn is found, closer to 100 the index value is. +** Also, the index value is zero (0) exactly when saturn is at mid-point between +** the two nearest stars. +*/ +int swh_saturn_4_stars( const double jd, const int flag, double* ret, char* err ); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* SWHMISC_H */ +/* vi: set fenc=utf-8 ff=unix et sw=4 ts=4 sts=4 : */ diff --git a/swhraman.c b/swhraman.c new file mode 100644 index 0000000..32446ba --- /dev/null +++ b/swhraman.c @@ -0,0 +1,328 @@ +/* + Swephelp + + Copyright 2007-2014 Stanislas Marquis + + Swephelp is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + Swephelp is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Swephelp. If not, see . +*/ + +/** @file swhraman.c +*/ + +#include + +#include "swhdef.h" +#include "swhraman.h" + +/** @brief Get Raman houses cusps +** +** Get Raman houses cusps (bhavamadhya or arambhasandhi), given the ascendant +** and midheaven cusps. +** +** @param asc Udaya lagna +** @param mc Madhya lagna +** @param ret Returned sputhas, declared as double[12] +** @param sandhi Return bhavamadhya (0) or arambhasandhi (1), boolean +** @return 0 +*/ +int swh_raman_houses(double asc, double mc, double *ret, int sandhi) +{ + double arc; + if (sandhi == 0) /* we want bhavamadhya */ + { + ret[0] = swe_degnorm(asc); + ret[9] = swe_degnorm(mc); + } + else /* we want arambhasandhi */ + { + arc = fabs(swe_difdeg2n(asc, mc)) / 6.0; + ret[0] = swe_degnorm(asc - arc); + ret[9] = swe_degnorm(mc - arc); + } + ret[6] = swe_degnorm(ret[0] + 180); + ret[3] = swe_degnorm(ret[9] + 180); + arc = fabs(swe_difdeg2n(ret[0], ret[9])) / 3.0; + ret[11] = swe_degnorm(ret[0] - arc); + ret[10] = swe_degnorm(ret[9] + arc); + ret[4] = swe_degnorm(ret[10] + 180); + ret[5] = swe_degnorm(ret[11] + 180); + arc = fabs(swe_difdeg2n(ret[0], ret[3])) / 3.0; + ret[1] = swe_degnorm(ret[0] + arc); + ret[2] = swe_degnorm(ret[3] - arc); + ret[7] = swe_degnorm(ret[1] + 180); + ret[8] = swe_degnorm(ret[2] + 180); + return 0; +} + +/** @brief Get lord of sign +** +** Get planet number (lord of sign) for given sign number. +** +** @param sign Sign number [0:11] +** @return Planet number (SE_*), or -1 if sign is invalid +*/ +int swh_lord(int sign) +{ + switch (sign) + { + case SWH_ARIES: + case SWH_SCORPIO: return SE_MARS; + case SWH_TAURUS: + case SWH_LIBRA: return SE_VENUS; + case SWH_GEMINI: + case SWH_VIRGO: return SE_MERCURY; + case SWH_CANCER: return SE_MOON; + case SWH_LEO: return SE_SUN; + case SWH_SAGITTARIUS: + case SWH_PISCES: return SE_JUPITER; + case SWH_CAPRICORN: + case SWH_AQUARIUS: return SE_SATURN; + default: return -1; + } +} + +/** @brief Get Nakshatra and Pada from longitude +** +** Get Nakshatra number [0:26] and Pada [0:3] from longitude. +** +** @param longitude Longitude on ecliptic +** @param ret Returned Nakshatra and Pada, declared as int[2] +** @return 0 +*/ +int swh_long2nakshatra(double longitude, int *ret) +{ + longitude = swe_degnorm(longitude); + ret[0] = (int) (longitude / (40/3.0)); + ret[1] = (int) ((longitude - (ret[0] * (40/3.0))) / (10/3.0)); + return 0; +} + +/** @brief Get Nakshatra name +** +** Get Nakshatra name from Nakshatra number. +** +** @param nakshatra Nakshatra number [0:26] +** @param str Buffer for returned string, declared as char[15] +** @return 0 on success, or -1 if nakshatra is invalid +*/ +int swh_get_nakshatra_name(int nakshatra, char *str) +{ + switch (nakshatra) + { + case SWH_ASWINI: strcpy(str, "Aswini"); return 0; + case SWH_BHARANI: strcpy(str, "Bharani"); return 0; + case SWH_KRITHIKA: strcpy(str, "Krithika"); return 0; + case SWH_ROHINI: strcpy(str, "Rohini"); return 0; + case SWH_MRIGASIRA: strcpy(str, "Mrigasira"); return 0; + case SWH_ARIDRA: strcpy(str, "Aridra"); return 0; + case SWH_PUNARVASU: strcpy(str, "Punarvasu"); return 0; + case SWH_PUSHYAMI: strcpy(str, "Pushyami"); return 0; + case SWH_ASLESHA: strcpy(str, "Aslesha"); return 0; + case SWH_MAKHA: strcpy(str, "Makha"); return 0; + case SWH_PUBBA: strcpy(str, "Pubba"); return 0; + case SWH_UTTARA: strcpy(str, "Uttara"); return 0; + case SWH_HASTA: strcpy(str, "Hasta"); return 0; + case SWH_CHITTA: strcpy(str, "Chitta"); return 0; + case SWH_SWATHI: strcpy(str, "Swathi"); return 0; + case SWH_VISHAKA: strcpy(str, "Vishaka"); return 0; + case SWH_ANURADHA: strcpy(str, "Anuradha"); return 0; + case SWH_JYESTA: strcpy(str, "Jyesta"); return 0; + case SWH_MOOLA: strcpy(str, "Moola"); return 0; + case SWH_POORVASHADA: strcpy(str, "Poorvashada"); return 0; + case SWH_UTTARASHADA: strcpy(str, "Uttarashada"); return 0; + case SWH_SRAVANA: strcpy(str, "Sravana"); return 0; + case SWH_DHANISHTA: strcpy(str, "Dhanishta"); return 0; + case SWH_SATABISHA: strcpy(str, "Satabhisha"); return 0; + case SWH_POORVABHADRA: strcpy(str, "Poorvabhadra"); return 0; + case SWH_UTTARABHADRA: strcpy(str, "Uttarabhadra"); return 0; + case SWH_REVATHI: strcpy(str, "Revathi"); return 0; + default: return -1; + } +} + +/** @brief Get Rasi difference +** +** Get number of rasi between two rasis, from 0 to 11. +** That is used for drishti. +** +** @param r1 Rasi number [0:11] +** @param r2 Rasi number [0:11] +** @return Rasi difference [0:11] +*/ +int swh_rasi_dif(int r1, int r2) +{ + r1 = swh_rasinorm(r1); + r2 = swh_rasinorm(r2); + if (r1 == r2) return 0; + else if (r1 < r2) return 12 - (r2 - r1); + else return r1 - r2; +} + +/** @brief Get Rasi difference +** +** Get number of rasi between two rasis, from -5 to 6. +** +** @param r1 Rasi number [0:11] +** @param r2 Rasi number [0:11] +** @return Rasi difference [-5:6] +*/ +int swh_rasi_dif2(int r1, int r2) +{ + const int i = swh_rasi_dif(r1, r2); + return (i > 6) ? (-6 + (i - 6)) : (i); +} + +/** @brief Get Naisargika relation between planets +** +** Get naisargika relation between planets. +** +** @param gr1 Planet number +** @param gr2 Planet number +** @param ret Relation returned Satru (-1) Sama (0) or Mitra (1) +** @return 0 on success, or -1 if a planet is invalid +*/ +int swh_naisargika_relation(int gr1, int gr2, int *ret) +{ + switch (gr1) + { + case SE_SUN: + switch (gr2) + { + case SE_MOON: case SE_MARS: case SE_JUPITER: goto mitra; + case SE_MERCURY: goto sama; + case SE_VENUS: case SE_SATURN: goto satru; + } + case SE_MOON: + switch (gr2) + { + case SE_SUN: case SE_MERCURY: goto mitra; + case SE_MARS: case SE_JUPITER: case SE_VENUS: case SE_SATURN: goto sama; + } + case SE_MERCURY: + switch (gr2) + { + case SE_SUN: case SE_VENUS: goto mitra; + case SE_MARS: case SE_JUPITER: case SE_SATURN: goto sama; + case SE_MOON: goto satru; + } + case SE_VENUS: + switch (gr2) + { + case SE_MERCURY: case SE_SATURN: goto mitra; + case SE_MARS: case SE_JUPITER: goto sama; + case SE_SUN: case SE_MOON: goto satru; + } + case SE_MARS: + switch (gr2) + { + case SE_SUN: case SE_MOON: case SE_JUPITER: goto mitra; + case SE_VENUS: case SE_SATURN: goto sama; + case SE_MERCURY: goto satru; + } + case SE_JUPITER: + switch (gr2) + { + case SE_SUN: case SE_MOON: case SE_MARS: goto mitra; + case SE_SATURN: goto sama; + case SE_MERCURY: case SE_VENUS: goto satru; + } + case SE_SATURN: + switch (gr2) + { + case SE_MERCURY: case SE_VENUS: goto mitra; + case SE_JUPITER: goto sama; + case SE_SUN: case SE_MOON: case SE_MARS: goto satru; + } + } + return -1; + mitra: *ret = 1; return 0; + sama: *ret = 0; return 0; + satru: *ret = -1; return 0; +} + +/** @brief Get residential strength of a planet +** +** Get the residential strength of a planet, given the bhavamadhya longitudes. +** +** @param graha Graha longitude +** @param bm 12 Bhavamadhya longitudes +** @param ret Residential strength returned +** @return 0 on success, or -1 on error +*/ +int swh_residential_strength(double graha, const double *bm, double *ret) +{ + int i; + double s, arc1, arc2; + static const int idx[] = {0,1,2,3,4,5,6,7,8,9,10,11,0}; + for (i = 0; i < 12; ++i) + { + if (graha == bm[idx[i]] || graha == bm[idx[i+1]]) + { + *ret = 0; return 0; + } + arc1 = swe_difdeg2n(bm[idx[i]], graha); + arc2 = swe_difdeg2n(bm[idx[i+1]], graha); + if ((arc1 >= 0 ? 1 : 0) != + (arc2 >= 0 ? 1 : 0) + && fabs(arc1) + fabs(arc2) < 180) + { + s = swe_deg_midp(bm[idx[i]], bm[idx[i+1]]); + if (graha == s) + { + *ret = 1.0; return 0; + } + arc1 = fabs(arc1); + arc2 = fabs(arc2); + if (arc1 < arc2) + { + *ret = (arc1 / fabs(swe_difdeg2n(s, bm[idx[i]]))); + } + else + { + *ret = (arc2 / fabs(swe_difdeg2n(s, bm[idx[i+1]]))); + } + return 0; + } + } + return -1; +} + +/* *** Sthanabala ***/ + +/** @brief Get Ochchabala +** +** Get the exaltation strength of a planet. +** +** @param graha Planet number (SE_*) +** @param sputha Planet longitude on ecliptic [0:360[ +** @return Ochchabala in shashtiamsa, or -1 if planet is invalid +*/ +double swh_ochchabala(int graha, double sputha) +{ + int x; + switch (graha) + { + case SE_SUN: x = 190; break; + case SE_MOON: x = 213; break; + case SE_MERCURY: x = 345; break; + case SE_VENUS: x = 177; break; + case SE_MARS: x = 118; break; + case SE_JUPITER: x = 275; break; + case SE_SATURN: x = 20; break; + default: return -1; + } + return fabs(swe_difdeg2n(sputha, x)) / 3.0; +} + +/* vi: set fenc=utf-8 ff=unix et sw=4 ts=4 sts=4 : */ diff --git a/swhraman.h b/swhraman.h new file mode 100644 index 0000000..15aba0c --- /dev/null +++ b/swhraman.h @@ -0,0 +1,176 @@ +/* + Swephelp + + Copyright 2007-2014 Stanislas Marquis + + Swephelp is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + Swephelp is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Swephelp. If not, see . +*/ + +/** @file swhraman.h +** @brief B.V.Raman's astrology +*/ + +#ifndef SWHRAMAN_H +#define SWHRAMAN_H + +#ifndef SWH_USE_ALIASES +#define SWH_USE_ALIASES 1 +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include + +/** @brief Get Raman houses cusps +** +** Get Raman houses cusps (bhavamadhya or arambhasandhi), given the ascendant +** and midheaven cusps. +** +** @param asc Udaya lagna +** @param mc Madhya lagna +** @param ret Returned sputhas, declared as double[12] +** @param sandhi Return bhavamadhya (0) or arambhasandhi (1), boolean +** @return 0 +*/ +int swh_raman_houses(double asc, double mc, double *ret, int sandhi); + +/** @brief Get lord of sign +** +** Get planet number (lord of sign) for given sign number. +** +** @param sign Sign number [0:11] +** @return Planet number (SE_*), or -1 if sign is invalid +*/ +int swh_lord(int sign); + +/** @brief Get Rasi from longitude +** +** Get Rasi number [0:11] from longitude. +** +** @param longitude Longitude on ecliptic (double) +** @return Rasi number [0:11] +*/ +#define swh_long2rasi(longitude) ((int) (swe_degnorm(longitude) / 30.0)) + +/** @brief Get Navamsa from longitude +** +** Get Navamsa number [0:11] from longitude. +** +** @param longitude Longitude on ecliptic (double) +** @return Navamsa number [0:11] +*/ +#define swh_long2navamsa(longitude) ((int) (swe_degnorm(longitude) / (10/3.0)) % 12) + +/** @brief Get Nakshatra and Pada from longitude +** +** Get Nakshatra number [0:26] and Pada [0:3] from longitude. +** +** @param longitude Longitude on ecliptic +** @param ret Returned Nakshatra and Pada, declared as int[2] +** @return 0 +*/ +int swh_long2nakshatra(double longitude, int *ret); + +/** @brief Get Nakshatra name +** +** Get Nakshatra name from Nakshatra number. +** +** @param nakshatra Nakshatra number [0:26] +** @param str Buffer for returned string, declared as char[15] +** @return 0 on success, or -1 if nakshatra is invalid +*/ +int swh_get_nakshatra_name(int nakshatra, char *str); + +/** @brief Get normalized rasi number +** +** Get a normalized rasi number between 0 and 11. +** +** @param rasi Rasi number (int) +** @return Normalized rasi number [0:11] +*/ +#define swh_rasinorm(rasi) ((rasi) < 0 ?\ + ((rasi) + (12 * (1 + (int) ((rasi) / -12)))) % 12 : (rasi) % 12) + +/** @brief Get Rasi difference +** +** Get number of rasi between two rasis, from 0 to 11. +** That is used for drishti. +** +** @param r1 Rasi number [0:11] +** @param r2 Rasi number [0:11] +** @return Rasi difference [0:11] +*/ +int swh_rasi_dif(int r1, int r2); + +/** @brief Get Rasi difference +** +** Get number of rasi between two rasis, from -5 to 6. +** +** @param r1 Rasi number [0:11] +** @param r2 Rasi number [0:11] +** @return Rasi difference [-5:6] +*/ +int swh_rasi_dif2(int r1, int r2); + +/** @brief Get Tatkalika relation between planets +** +** Get tatkalika relation between two planets. +** +** @param r1 Rasi number of graha (int) [0:11] +** @param r2 Rasi number of graha (int) [0:11] +** @return Tatkalika relation Satru (-1) or Mitra (1) +*/ +#define swh_tatkalika_relation(r1, r2) (abs(swh_rasi_dif2((r1), (r2))) <= 3 ? 1 : -1) + +/** @brief Get Naisargika relation between planets +** +** Get naisargika relation between planets. +** +** @param gr1 Planet number +** @param gr2 Planet number +** @param ret Relation returned Satru (-1) Sama (0) or Mitra (1) +** @return 0 on success, or -1 if a planet is invalid +*/ +int swh_naisargika_relation(int gr1, int gr2, int *ret); + +/** @brief Get residential strength of a planet +** +** Get the residential strength of a planet, given the bhavamadhya longitudes. +** +** @param graha Graha longitude +** @param bm 12 Bhavamadhya longitudes +** @param ret Residential strength returned +** @return 0 on success, or -1 on error +*/ +int swh_residential_strength(double graha, const double *bm, double *ret); + +/** @brief Get Ochchabala +** +** Get the exaltation strength of a planet. +** +** @param graha Planet number (SE_*) +** @param sputha Planet longitude on ecliptic [0:360[ +** @return Ochchabala in shashtiamsa, or -1 if planet is invalid +*/ +double swh_ochchabala(int graha, double sputha); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* SWHRAMAN_H */ +/* vi: set fenc=utf-8 ff=unix et sw=4 ts=4 sts=4 : */ diff --git a/swhsearch.c b/swhsearch.c new file mode 100644 index 0000000..720aadf --- /dev/null +++ b/swhsearch.c @@ -0,0 +1,1044 @@ +/* + Swephelp + + Copyright 2007-2014 Stanislas Marquis + + Swephelp is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + Swephelp is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Swephelp. If not, see . +*/ + +/** @file swhsearch.c +** @brief swephelp search functions +*/ + +#include "swhsearch.h" + +#include + +/** @brief Half a second of time (expressed in day) +** Used to set the precision of search functions. +*/ +static double swh_precision = ((1.0/86400)/2); + +/** @def ISPOSITIVE +** @brief Return 1 if x is greater than 0, else return 0 (!) +*/ +#define ISPOSITIVE(x) ((x) > 0 ? 1 : 0) + +/** @brief Get the minimum retrogradation time of a planet, in days +** +** This function is mainly used in swephelp search routines. +** +** The returned value is ~3 days inferior to the "real" minimum +** retrogradation time (tested from 1.1.-3000 to 1.1.3000 when possible). +** +** @remarks May return 10 (default) if the planet is not implemented. +** This may be the case if you want some unusual asteroid. If you need to +** speed search routines, you may try to compute the retrogradation time +** using the minretro.py script, add one line to the source code, and recompile. +** +** @todo Implement more planets, main asteroids... +** +** @param planet Planet number (SE_*, etc) +** @param err Buffer for errors, declared as char[32] (or more) +** @return Number of days, or -1 if planet is never retrograde. +*/ +int swh_min_retro_time(int planet, char *err) +{ + int days; + switch (planet) + { /* days MUST be inferior to the minimum retrogradation time + tested from 1.1.-3000 to 1.1.3000 when possible */ + case SE_SUN: strcpy(err, "Sun retro?"); return -1; + case SE_MOON: strcpy(err, "Moon retro?"); return -1; + case SE_MERCURY: days = 16; break; /* ~19 days */ + case SE_VENUS: days = 37; break; /* ~40 days */ + case SE_MARS: days = 56; break; /* ~59 days */ + case SE_JUPITER: days = 114; break; /* ~117 days */ + case SE_SATURN: days = 129; break; /* ~132 days */ + case SE_URANUS: days = 145; break; /* ~148 days */ + case SE_NEPTUNE: days = 153; break; /* ~156 days */ + case SE_PLUTO: days = 153; break; /* ~156 days */ + case SE_MEAN_NODE: strcpy(err, "Mean node retro?"); return -1; + case SE_TRUE_NODE: strcpy(err, "True node retro?"); return -1; + case SE_MEAN_APOG: strcpy(err, "Mean apogee retro?"); return -1; + case SE_OSCU_APOG: strcpy(err, "Oscul. apogee retro?"); return -1; + case SE_EARTH: strcpy(err, "Earth retro?"); return -1; + case SE_CHIRON: days = 125; break; /* ~128 days */ + case SE_PHOLUS: days = 125; break; /* ~128 days */ + case SE_CERES: days = 85; break; /* ~88 days */ + case SE_PALLAS: days = 46; break; /* ~49 days */ + case SE_JUNO: days = 68; break; /* ~71 days */ + case SE_VESTA: days = 81; break; /* ~84 days */ + /* TODO more planets */ + default: days = 10; /* default... */ + } + return days; +} + +/** @brief Get the maximum retrogradation time of a planet, in days +** +** Thought this function would be usefull in search routines, but +** seems like it is not (?). +** +** @remarks The returned value is ~2 days superior to the "real" maximum +** retrogradation time (tested from 1.1.-3000 to 1.1.3000 when possible). +** +** @deprecated This function is not usefull. May disappear one day +** +** @param planet Planet number (SE_*, etc) +** @param err Buffer for errors, declared as char[32] (or more) +** @return Number of days, or -1 if planet is never retrograde. +*/ +int swh_max_retro_time(int planet, char *err) +{ + int days; + switch (planet) + { /* days MUST be superior to maximum retrogradation time + tested from 1.1.-3000 to 1.1.3000 when possible */ + case SE_SUN: strcpy(err, "Sun retro?"); return -1; + case SE_MOON: strcpy(err, "Moon retro?"); return -1; + case SE_MERCURY: days = 27; break; /* ~25 days */ + case SE_VENUS: days = 46; break; /* ~44 days */ + case SE_MARS: days = 84; break; /* ~84 days */ + case SE_JUPITER: days = 126; break; /* ~124 days */ + case SE_SATURN: days = 145; break; /* ~143 days */ + case SE_URANUS: days = 157; break; /* ~155 days */ + case SE_NEPTUNE: days = 163; break; /* ~161 days */ + case SE_PLUTO: days = 168; break; /* ~166 days */ + case SE_MEAN_NODE: strcpy(err, "Mean node retro?"); return -1; + case SE_TRUE_NODE: strcpy(err, "True node retro?"); return -1; + case SE_MEAN_APOG: strcpy(err, "Mean apogee retro?"); return -1; + case SE_OSCU_APOG: strcpy(err, "Oscul. apogee retro?"); return -1; + case SE_EARTH: strcpy(err, "Earth retro?"); return -1; + case SE_CHIRON: days = 160; break; /* ~158 days */ + case SE_PHOLUS: days = 172; break; /* ~170 days */ + case SE_CERES: days = 109; break; /* ~107 days */ + case SE_PALLAS: days = 123; break; /* ~121 days */ + case SE_JUNO: days = 116; break; /* ~114 days */ + case SE_VESTA: days = 100; break; /* ~98 days */ + /* TODO more planets */ + default: days = 150; /* default... */ + } + return days; +} + +/** @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; +} + +/** @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 exact aspect to a fixed point +** +** Get Julian day number and positions when a celestial object makes a +** longitudinal aspect to a fixed point expressed in longitude degrees. +** +** @attention Same warning as in swh_next_retro. +** +** @remarks If step is set to 0, use a predefined step (recommended). +** 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 fixedpt Fixed point 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 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 errors, declared as char[256] +** @return 0 on success, 1 if time limit reached, -1 on error +*/ +int swh_next_aspect(int planet, double aspect, double fixedpt, double jdstart, + double step, int backw, double dayspan, int flag, double *jdret, + double *posret, char *err) +{ + int res, direct = 0; /* dummy assign */ + double jdstop = 0; /* dummy assign */ + dayspan = fabs(dayspan); + if (dayspan) + { + jdstop = (backw) ? jdstart-dayspan : jdstart+dayspan; + direct = (backw) ? 0 : 1; + } + if (step == 0) + { + step = swh_min_retro_time(planet, err); + if (step < 0) { step = 10; } /* default step */ + } else { step = fabs(step); } + fixedpt = swe_degnorm(fixedpt + aspect); + *jdret = jdstart; + while (step > swh_precision) + { + res = swh_go_past(planet, fixedpt, *jdret, step, backw, flag, + jdret, posret, err); + if (res < 0) { return -1; } + if (dayspan && backw == direct) + { + if (direct) { if (*jdret > jdstop) return 1; } + else { if (*jdret < jdstop) return 1; } + } + backw = (backw) ? 0 : 1; + step = step/2; + } + return 0; +} + +/** @brief Find next exact aspect to a fixed point +** +** Same as swh_next_aspect but with aspect in [0;180], instead of [0;360[. +** +** @see swh_next_aspect() +** +** @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 several times, especially when scanning long periods of time. +*/ +int swh_next_aspect2(int planet, double aspect, double fixedpt, double jdstart, + double step, int backw, double dayspan, int flag, double *jdret, + double *posret, char *err) +{ + int res, res2; + double jdtmp, postmp[6]; + aspect = fabs(swe_difdeg2n(0, aspect)); + if (aspect == 0 || aspect == 180) + { + return swh_next_aspect(planet, aspect, fixedpt, jdstart, step, backw, + dayspan, flag, jdret, posret, err); + } + /* else try both */ + res = swh_next_aspect(planet, aspect, fixedpt, jdstart, step, backw, + dayspan, flag, jdret, posret, err); + if (res < 0) { return -1; } + res2 = swh_next_aspect(planet, 0-aspect, fixedpt, jdstart, step, backw, + dayspan, flag, &jdtmp, postmp, 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++) { posret[res] = postmp[res]; } + } + } + else /* both found something */ + { + if (backw) + { + if (jdtmp > *jdret) + { + *jdret = jdtmp; + for (res = 0; res < 6; res++) { posret[res] = postmp[res]; } + } + } + else + { + if (jdtmp < *jdret) + { + *jdret = jdtmp; + for (res = 0; res < 6; res++) { posret[res] = postmp[res]; } + } + } + } + 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; +} + +/** @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 +** +** 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 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 +** +** Check if the two given positions match the aspect within the given orb. +** This also calculates the difference between targeted aspect and distance +** between objects, and if aspect is applicating or separating, or stable due +** to equal speeds. +** +** @param pos0 First object longitude, in degrees [0;360[ +** @param speed0 First object longitude speed, in degrees per day +** @param pos1 Second object longitude, in degrees [0;360[ +** @param speed1 Second object longitude speed, in degrees per day +** @param aspect Aspect targeted, in degrees [0;360[ +** @param orb Orb allowed, in degrees +** @param diffret Difference between aspect and objects distance, in degrees +** @param applic Aspect applicating [-1], separating [1], or stable [0] +** @param factor Aspect strength, compared to orb +** @return 0 if aspect match, else -1 +*/ +int swh_match_aspect(double pos0, double speed0, double pos1, double speed1, + double aspect, double orb, double *diffret, int *applic, double *factor) +{ + double diff = swe_difdegn(pos0, pos1); + aspect = fabs(aspect); + orb = fabs(orb); + 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 is exact, cannot applic */ + { + 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 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 Aspect matching +** +** Same as swh_match_aspect, but with a different orb in case aspect is +** applying, separating, or stable. +** +** @see swh_match_aspect() +*/ +int swh_match_aspect3(double pos0, double speed0, double pos1, double speed1, + double aspect, double app_orb, double sep_orb, double def_orb, + double *diffret, int *applic, double *factor) +{ + app_orb = fabs(app_orb); + sep_orb = fabs(sep_orb); + def_orb = fabs(def_orb); + if (speed0 == speed1) + { /* stable aspect */ + return swh_match_aspect(pos0, speed0, pos1, speed1, aspect, + def_orb, diffret, applic, factor); + } + if (app_orb == sep_orb) + { + return swh_match_aspect(pos0, speed0, pos1, speed1, aspect, app_orb, + diffret, applic, factor); + } + if (app_orb > sep_orb) + { + int i = swh_match_aspect(pos0, speed0, pos1, speed1, aspect, app_orb, + diffret, applic, factor); + if (i == 0) + { + if (*applic == -1) + { + return 0; + } + else if (*diffret <= sep_orb) + { + *factor = *diffret / sep_orb; + return 0; + } + else + { + return -1; + } + } + else + { + return -1; + } + } + else + { + int i = swh_match_aspect(pos0, speed0, pos1, speed1, aspect, sep_orb, + diffret, applic, factor); + if (i == 0) + { + if (*applic == 1) + { + return 0; + } + else if (*diffret <= app_orb) + { + *factor = *diffret / app_orb; + return 0; + } + else + { + return -1; + } + } + else + { + return -1; + } + } +} + +/** @brief Aspect matching +** +** Same as swh_match_aspect2, but with a different orb in case aspect is +** applying, separating, or stable. +** +** @see swh_match_aspect2() +*/ +int swh_match_aspect4(double pos0, double speed0, double pos1, double speed1, + double aspect, double app_orb, double sep_orb, double def_orb, + double *diffret, int *applic, double *factor) +{ + app_orb = fabs(app_orb); + sep_orb = fabs(sep_orb); + def_orb = fabs(def_orb); + if (speed0 == speed1) + { /* stable aspect */ + return swh_match_aspect2(pos0, speed0, pos1, speed1, aspect, + def_orb, diffret, applic, factor); + } + if (app_orb == sep_orb) + { + return swh_match_aspect2(pos0, speed0, pos1, speed1, aspect, app_orb, + diffret, applic, factor); + } + if (app_orb > sep_orb) + { + int i = swh_match_aspect2(pos0, speed0, pos1, speed1, aspect, app_orb, + diffret, applic, factor); + if (i == 0) + { + if (*applic == -1) + { + return 0; + } + else if (*diffret <= sep_orb) + { + *factor = *diffret / sep_orb; + return 0; + } + else + { + return -1; + } + } + else + { + return -1; + } + } + else + { + int i = swh_match_aspect2(pos0, speed0, pos1, speed1, aspect, sep_orb, + diffret, applic, factor); + if (i == 0) + { + if (*applic == 1) + { + return 0; + } + else if (*diffret <= app_orb) + { + *factor = *diffret / app_orb; + return 0; + } + else + { + return -1; + } + } + else + { + return -1; + } + } +} + +/** @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; +} + +/* vi: set fenc=utf-8 ff=unix et sw=4 ts=4 sts=4 : */ diff --git a/swhsearch.h b/swhsearch.h new file mode 100644 index 0000000..b515384 --- /dev/null +++ b/swhsearch.h @@ -0,0 +1,335 @@ +/* + Swephelp + + Copyright 2007-2014 Stanislas Marquis + + Swephelp is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + Swephelp is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Swephelp. If not, see . +*/ + +/** @file swhsearch.h +** @brief swephelp search functions +*/ + +#ifndef SWHSEARCH_H +#define SWHSEARCH_H + +#ifndef SWH_USE_ALIASES +#define SWH_USE_ALIASES 1 +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** @brief Get the minimum retrogradation time of a planet, in days +** +** This function is mainly used in swephelp search routines. +** +** The returned value is ~3 days inferior to the "real" minimum +** retrogradation time (tested from 1.1.-3000 to 1.1.3000 when possible). +** +** @remarks May return 10 (default) if the planet is not implemented. +** This may be the case if you want some unusual asteroid. If you need to +** speed search routines, you may try to compute the retrogradation time +** using the minretro.py script, add one line to the source code, and recompile. +** +** @todo Implement more planets, main asteroids... +** +** @param planet Planet number (SE_*, etc) +** @param err Buffer for errors, declared as char[32] (or more) +** @return Number of days, or -1 if planet is never retrograde. +*/ +int swh_min_retro_time(int planet, char *err); + +/** @brief Get the maximum retrogradation time of a planet, in days +** +** Thought this function would be usefull in search routines, but +** seems like it is not (?). +** +** @remarks The returned value is ~2 days superior to the "real" maximum +** retrogradation time (tested from 1.1.-3000 to 1.1.3000 when possible). +** +** @deprecated This function is not usefull. May disappear one day +** +** @param planet Planet number (SE_*, etc) +** @param err Buffer for errors, declared as char[32] (or more) +** @return Number of days, or -1 if planet is never retrograde. +*/ +int swh_max_retro_time(int planet, char *err); + +/** @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); + +/** @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); + +/** @brief Find next exact aspect to a fixed point +** +** Get Julian day number and positions when a celestial object makes a +** longitudinal aspect to a fixed point expressed in longitude degrees. +** +** @attention Same warning as in swh_next_retro. +** +** @remarks If step is set to 0, use a predefined step (recommended). +** 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 fixedpt Fixed point 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 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 errors, declared as char[256] +** @return 0 on success, 1 if time limit reached, -1 on error +*/ +int swh_next_aspect(int planet, double aspect, double fixedpt, double jdstart, + double step, int backw, double dayspan, int flag, double *jdret, + double *posret, char *err); + +/** @brief Find next exact aspect to a fixed point +** +** Same as swh_next_aspect but with aspect in [0;180], instead of [0;360[. +** +** @see swh_next_aspect() +** +** @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 several times, especially when scanning long periods of time. +*/ +int swh_next_aspect2(int planet, double aspect, double fixedpt, double jdstart, + double step, int backw, double dayspan, int flag, double *jdret, + double *posret, char *err); + +/** @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); + +/** @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); + +/** @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); + +/** @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); + +/** @brief Aspect matching +** +** Check if the two given positions match the aspect within the given orb. +** This also calculates the difference between targeted aspect and distance +** between objects, and if aspect is applicating or separating, or stable due +** to equal speeds. +** +** @param pos0 First object longitude, in degrees [0;360[ +** @param speed0 First object longitude speed, in degrees per day +** @param pos1 Second object longitude, in degrees [0;360[ +** @param speed1 Second object longitude speed, in degrees per day +** @param aspect Aspect targeted, in degrees [0;360[ +** @param orb Orb allowed, in degrees +** @param diffret Difference between aspect and objects distance, in degrees +** @param applic Aspect applicating [-1], separating [1], or stable [0] +** @param factor Aspect strength, compared to orb +** @return 0 if aspect match, else -1 +*/ +int swh_match_aspect(double pos0, double speed0, double pos1, double speed1, + double aspect, double orb, double *diffret, int *applic, double *factor); + +/** @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); + +/** @brief Aspect matching +** +** Same as swh_match_aspect, but with a different orb in case aspect is +** applying, separating, or stable. +** +** @see swh_match_aspect() +*/ +int swh_match_aspect3(double pos0, double speed0, double pos1, double speed1, + double aspect, double app_orb, double sep_orb, double def_orb, + double *diffret, int *applic, double *factor); + +/** @brief Aspect matching +** +** Same as swh_match_aspect2, but with a different orb in case aspect is +** applying, separating, or stable. +** +** @see swh_match_aspect2() +*/ +int swh_match_aspect4(double pos0, double speed0, double pos1, double speed1, + double aspect, double app_orb, double sep_orb, double def_orb, + double *diffret, int *applic, double *factor); + +/** @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); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* SWHSEARCH_H */ +/* vi: set fenc=utf-8 ff=unix et sw=4 ts=4 sts=4 : */ diff --git a/swhutil.c b/swhutil.c new file mode 100644 index 0000000..d4d6cc0 --- /dev/null +++ b/swhutil.c @@ -0,0 +1,103 @@ +/* + Swephelp + + Copyright 2007-2014 Stanislas Marquis + + Swephelp is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + Swephelp is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Swephelp. If not, see . +*/ + +/** @file swhutil.c +** @brief swephelp utilities +*/ + +#include "swhutil.h" + +#include +#include + +#include + +#if SWH_USE_THREADS + +#ifdef _MSC_VER +#include + +static HANDLE swh_mutex = NULL; + +void swh_lock(void) +{ + if ( swh_mutex == NULL ) + { + swh_mutex = CreateMutex( NULL, FALSE, NULL ); + assert( swh_mutex ); + } + WaitForSingleObject( swh_mutex, INFINITE ); +} + +void swh_unlock(void) +{ + assert( swh_mutex ); + ReleaseMutex( swh_mutex ); +} + +int swh_trylock(void) +{ + assert( swh_mutex ); + return WaitForSingleObject( swh_mutex, 0 ); +} + +#else /* not MSVC */ +#include + +static pthread_mutex_t swh_mutex = PTHREAD_MUTEX_INITIALIZER; + +void swh_lock(void) +{ + pthread_mutex_lock(&swh_mutex); +} + +void swh_unlock(void) +{ + pthread_mutex_unlock(&swh_mutex); +} + +int swh_trylock(void) +{ + return pthread_mutex_trylock(&swh_mutex); +} + +#endif /* _MSC_VER */ + +void swh_globals_init(swh_Globals *glob) +{ + memset(glob, 0, sizeof(swh_Globals)); +} + +int swh_set_globals(swh_Globals *glob) +{ + if (glob->ephe_path[0] != '\0') + swe_set_ephe_path(glob->ephe_path); + if (glob->jpl_path[0] != '\0') + swe_set_jpl_file(glob->jpl_path); + if (!(glob->topo_lon > 180 || glob->topo_lon < -180 || + glob->topo_lat > 90 || glob->topo_lat < -90 || + glob->topo_alt < 0)) + swe_set_topo(glob->topo_lon, glob->topo_lat, glob->topo_alt); + if (glob->sidmode > -1 && glob->sidmode < 256) + swe_set_sid_mode(glob->sidmode, glob->t0, glob->ayant0); + return 0; +} + +#endif /* SWH_USE_THREADS */ +/* vi: set fenc=utf-8 ff=unix et sw=4 ts=4 sts=4 : */ diff --git a/swhutil.h b/swhutil.h new file mode 100644 index 0000000..05ff631 --- /dev/null +++ b/swhutil.h @@ -0,0 +1,78 @@ +/* + Swephelp + + Copyright 2007-2014 Stanislas Marquis + + Swephelp is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + Swephelp is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Swephelp. If not, see . +*/ + +/** @file swhutil.h +** @brief swephelp utilities +*/ + +#ifndef SWHUTIL_H +#define SWHUTIL_H + +#ifndef SWH_USE_THREADS +#define SWH_USE_THREADS 1 +#endif + +#ifndef SWH_USE_ALIASES +#define SWH_USE_ALIASES 1 +#endif + +#if SWH_USE_THREADS + +#ifdef __cplusplus +extern "C" +{ +#endif + +void swh_lock(void); + +void swh_unlock(void); + +int swh_trylock(void); + +typedef struct +{ + char ephe_path[64]; /* swiss eph files path */ + char jpl_path[64]; /* jpl file path */ + double topo_lon; /* longitude. set to invalid value disables checking topo */ + double topo_lat; /* latitude */ + int topo_alt; /* altitude */ + int sidmode; /* sidereal mode */ + double t0; /* sidmode param */ + double ayant0; /* sidmode param */ +} swh_Globals; + +void swh_globals_init(swh_Globals *glob); + +int swh_set_globals(swh_Globals *glob); + +#if SWH_USE_ALIASES + +#define SWH_LOCK() swh_lock() +#define SWH_UNLOCK() swh_unlock() +#define SWH_TRYLOCK() swh_trylock() + +#endif /* SWH_USE_ALIASES */ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* SWH_USE_THREADS */ +#endif /* SWHUTIL_H */ +/* vi: set fenc=utf-8 ff=unix sw=4 ts=4 sts=4 : */ diff --git a/swhwin.h b/swhwin.h new file mode 100644 index 0000000..088ae0f --- /dev/null +++ b/swhwin.h @@ -0,0 +1,34 @@ +/* + Swephelp + + Copyright 2007-2014 Stanislas Marquis + + Swephelp is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + Swephelp is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Swephelp. If not, see . +*/ + +/** @file swhwin.h +** @brief swephelp windowz specific header +*/ + +#ifndef SWHWIN_H +#define SWHWIN_H + +#ifdef WIN32 + +#define lround(num) \ + ((long)(num > 0 ? num + 0.5 : ceil(num - 0.5))) + +#endif /* WIN32 */ +#endif /* SWHWIN_H */ +/* vi: set fenc=utf8 ff=unix et sw=4 ts=4 sts=4 : */