This is options.c in view mode; [Download] [Up]
/* ** Astrolog (Version 4.10) File: options.c ** ** IMPORTANT NOTICE: the graphics database and chart display routines ** used in this program are Copyright (C) 1991-1994 by Walter D. Pullen ** (cruiser1@stein.u.washington.edu). Permission is granted to freely ** use and distribute these routines provided one doesn't sell, ** restrict, or profit from them in any way. Modification is allowed ** provided these notices remain with any altered or edited versions of ** the program. ** ** The main planetary calculation routines used in this program have ** been Copyrighted and the core of this program is basically a ** conversion to C of the routines created by James Neely as listed in ** Michael Erlewine's 'Manual of Computer Programming for Astrologers', ** available from Matrix Software. The copyright gives us permission to ** use the routines for personal use but not to sell them or profit from ** them in any way. ** ** The PostScript code within the core graphics routines are programmed ** and Copyright (C) 1992-1993 by Brian D. Willoughby ** (brianw@sounds.wa.com). Conditions are identical to those above. ** ** The extended accurate ephemeris databases and formulas are from the ** calculation routines in the program "Placalc" and are programmed and ** Copyright (C) 1989,1991,1993 by Astrodienst AG and Alois Treindl ** (alois@azur.ch). The use of that source code is subject to ** regulations made by Astrodienst Zurich, and the code is not in the ** public domain. This copyright notice must not be changed or removed ** by any user of this program. ** ** Initial programming 8/28,30, 9/10,13,16,20,23, 10/3,6,7, 11/7,10,21/1991. ** X Window graphics initially programmed 10/23-29/1991. ** PostScript graphics initially programmed 11/29-30/1992. ** Last code change made 3/19/1994. */ #include "astrolog.h" /* ****************************************************************************** ** Display Subroutines. ****************************************************************************** */ /* This is a subprocedure of CreateGrid() and CreateGridRelation(). Given */ /* two planets, determine what aspect, if any, is present between them, */ /* and save the aspect name and orb in the specified grid cell. */ void GetAspect(planet1, planet2, ret1, ret2, i, j) real *planet1, *planet2, *ret1, *ret2; int i, j; { int k; real l, m; grid->v[i][j] = grid->n[i][j] = 0; l = MinDistance(planet2[i], planet1[j]); for (k = aspects; k >= 1; k--) { m = l-aspectangle[k]; if (dabs(m) < Orb(i, j, k)) { grid->n[i][j] = k; /* If -ga switch in effect, then change the sign of the orb to */ /* correspond to whether the aspect is applying or separating. */ /* To do this, we check the velocity vectors to see if the */ /* planets are moving toward, away, or are overtaking each other. */ if (exdisplay & DASHga) m = SGN2(ret1[j]-ret2[i])* SGN2(MinDifference(planet2[i], planet1[j]))*SGN2(m)*dabs(m); grid->v[i][j] = (int) (m*60.0); } } } /* Set up the aspect/midpoint grid. Allocate memory for this array, if not */ /* already done. Allocation is only done once, first time this is called. */ bool EnsureGrid() { char string[STRING]; if (grid != NULL) return TRUE; Allocate(grid, sizeof(gridstruct), gridstruct PTR); if (grid == NULL #ifdef PC /* For PC's the grid better not cross a segment boundary. */ || HIWORD(LOWORD(grid) + sizeof(gridstruct)) > 0 #endif ) { sprintf(string, "Not enough memory for grid (%d bytes).", sizeof(gridstruct)); PrintError(string); return FALSE; } return TRUE; } /* Fill in the aspect grid based on the aspects taking place among the */ /* planets in the present chart. Also fill in the midpoint grid. */ void CreateGrid(acc) int acc; { int i, j, k; real l; if (!EnsureGrid()) return; for (j = 1; j <= total; j++) if (!ignore[j]) for (i = 1; i <= total; i++) if (!ignore[i]) /* The parameter 'acc' determine what half of the grid is filled in */ /* with the aspects and what half is filled in with the midpoints. */ if (acc ? i > j : i < j) GetAspect(planet, planet, ret, ret, i, j); else if (acc ? i < j : i > j) { l = Mod(Midpoint(planet[i], planet[j])); k = (int)l; /* Calculate */ grid->n[i][j] = k/30+1; /* midpoint. */ grid->v[i][j] = (int)((l-(real)(k/30)*30.0)*60.0); } else { grid->n[i][j] = ZTOS(planet[j]); grid->v[i][j] = (int)(planet[j]-(real)(grid->n[i][j]-1)*30.0); } } /* This is similar to the previous function; however, this time fill in the */ /* grid based on the aspects (or midpoints if 'acc' set) taking place among */ /* the planets in two different charts, as in the -g -r0 combination. */ void CreateGridRelation(acc) int acc; { int i, j, k; real l; if (!EnsureGrid()) return; for (j = 1; j <= total; j++) if (!ignore[j]) for (i = 1; i <= total; i++) if (!ignore[i]) if (!acc) GetAspect(planet1, planet2, ret1, ret2, i, j); else { l = Mod(Midpoint(planet2[i], planet1[j])); k = (int)l; /* Calculate */ grid->n[i][j] = k/30+1; /* midpoint. */ grid->v[i][j] = (int)((l-(real)(k/30)*30.0)*60.0); } } /* ****************************************************************************** ** Multiple Chart Display Subprograms. ****************************************************************************** */ /* Print out an aspect (or midpoint if -g0 switch in effect) grid of a */ /* relationship chart. This is similar to the ChartGrid() routine; however, */ /* here we have both axes labeled with the planets for the two charts in */ /* question, instead of just a diagonal down the center for only one chart. */ void DisplayGridRelation() { int i, j, k, tot = total, temp; #ifdef INTERPRET if (interpret && !(exdisplay & DASHg0)) { InterpretGridRelation(); return; } #endif fprintf(S, " 2>"); for (temp = 0, i = 1; i <= total; i++) if (!ignore[i]) { printc(BOXV); AnsiColor(objectansi[i]); fprintf(S, "%c%c%c", OBJNAM(i)); AnsiColor(DEFAULT); temp++; if (column80 && temp >= 19) { tot = i; i = total; } } fprintf(S, "\n1 "); for (i = 1; i <= tot; i++) if (!ignore[i]) { printc(BOXV); AnsiColor(signansi(ZTOS(planet2[i]))); fprintf(S, "%2d%c", (int)planet2[i] % 30, DEGR0); AnsiColor(DEFAULT); } fprintf(S, "\nV "); for (i = 1; i <= tot; i++) if (!ignore[i]) { printc(BOXV); temp = ZTOS(planet2[i]); AnsiColor(signansi(temp)); fprintf(S, "%c%c%c", SIGNAM(temp)); AnsiColor(DEFAULT); } printl(); for (j = 1; j <= total; j++) if (!ignore[j]) for (k = 1; k <= 4; k++) { if (k < 2) PrintTab(BOXH, 3); else if (k == 2) { AnsiColor(objectansi[j]); fprintf(S, "%c%c%c", OBJNAM(j)); } else { temp = ZTOS(planet1[j]); AnsiColor(signansi(temp)); if (k == 3) fprintf(S, "%2d%c", (int)planet1[j] - (temp-1)*30, DEGR0); else fprintf(S, "%c%c%c", SIGNAM(temp)); } if (k > 1) AnsiColor(DEFAULT); for (i = 1; i <= tot; i++) if (!ignore[i]) { printc(k < 2 ? BOXC : BOXV); temp = grid->n[i][j]; if (k > 1) { if (i == j) AnsiColor(REVERSE); AnsiColor(exdisplay & DASHg0 ? signansi(temp) : aspectansi[temp]); } if (k < 2) PrintTab(BOXH, 3); else if (k == 2) { if (exdisplay & DASHg0) fprintf(S, "%c%c%c", SIGNAM(temp)); else fprintf(S, "%s", temp ? aspectabbrev[temp] : " "); } else if (k == 3) { if (exdisplay & DASHg0) fprintf(S, "%2d%c", grid->v[i][j]/60, DEGR0); else if (grid->n[i][j]) { if (grid->v[i][j] < 6000) fprintf(S, "%c%2d", exdisplay & DASHga ? (grid->v[i][j] < 0 ? 'a' : 's') : (grid->v[i][j] < 0 ? '-' : '+'), abs(grid->v[i][j])/60); else fprintf(S, "%3d", abs(temp)/60); } else fprintf(S, " "); } else { if (grid->n[i][j]) fprintf(S, "%02d'", abs(grid->v[i][j])%60); else fprintf(S, " "); } AnsiColor(DEFAULT); } printl(); } } /* Display all aspects between objects in the relationship comparison chart, */ /* one per line, in sorted order based on the total "power" of the aspects, */ /* as specified with the -r0 -m0 switch combination. */ void DisplayAspectRelation() { int pcut = 30000, icut, jcut, phi, ihi, jhi, ahi, p, i, j, k, count = 0; real ip, jp; loop { phi = -1; /* Search for the next most powerful aspect in the aspect grid. */ for (i = 1; i <= total; i++) if (!ignore[i]) for (j = 1; j <= total; j++) if (!ignore[j]) if (k = grid->n[i][j]) { ip = i <= OBJECTS ? objectinf[i] : 2.5; jp = j <= OBJECTS ? objectinf[j] : 2.5; p = (int) (aspectinf[k]*(ip+jp)/2.0* (1.0-dabs((real)(grid->v[i][j]))/60.0/aspectorb[k])*1000.0); if ((p < pcut || (p == pcut && (i > icut || (i == icut && j > jcut)))) && p > phi) { ihi = i; jhi = j; phi = p; ahi = k; } } if (phi < 0) /* Exit when no less powerful aspect found. */ break; pcut = phi; icut = ihi; jcut = jhi; count++; /* Display the current aspect. */ #ifdef INTERPRET if (interpret) { /* Interpret it if -I in effect. */ InterpretAspectRelation(jhi, ihi); continue; } #endif fprintf(S, "%3d: ", count); PrintAspect(jhi, ZTOS(planet1[jhi]), (int)Sgn(ret1[jhi]), ahi, ihi, ZTOS(planet2[ihi]), (int)Sgn(ret2[ihi]), 'A'); k = grid->v[ihi][jhi]; AnsiColor(k < 0 ? WHITE : LTGRAY); fprintf(S, "- orb: %c%d,%02d'", exdisplay & DASHga ? (k < 0 ? 'a' : 's') : (k < 0 ? '-' : '+'), abs(k)/60, abs(k)%60); AnsiColor(DKGREEN); fprintf(S, " - power:%6.2f\n", (real) phi/1000.0); AnsiColor(DEFAULT); } } /* Display locations of all midpoints between objects in the relationship */ /* comparison chart, one per line, in sorted zodiac order from zero Aries */ /* onward, as specified with the -r0 -m switch combination. */ void DisplayMidpointRelation() { int mcut = -1, icut, jcut, mlo, ilo, jlo, m, i, j, count = 0; loop { mlo = 21600; /* Search for the next closest midpoint farther down in the zodiac. */ for (i = 1; i <= total; i++) if (!ignore[i]) for (j = 1; j <= total; j++) if (!ignore[j]) { m = (grid->n[j][i]-1)*30*60 + grid->v[j][i]; if ((m > mcut || (m == mcut && (i > icut || (i == icut && j > jcut)))) && m < mlo) { ilo = i; jlo = j; mlo = m; } } if (mlo >= 21600) /* Exit when no midpoint farther in zodiac found. */ break; mcut = mlo; icut = ilo; jcut = jlo; count++; /* Display the current midpoint. */ #ifdef INTERPRET if (interpret) { /* Interpret it if -I in effect. */ InterpretMidpointRelation(ilo, jlo); continue; } #endif fprintf(S, "%4d: ", count); PrintZodiac((real) mlo/60.0); printc(' '); PrintAspect(ilo, ZTOS(planet1[ilo]), (int)Sgn(ret1[ilo]), 0, jlo, ZTOS(planet2[jlo]), (int)Sgn(ret2[jlo]), 'M'); AnsiColor(DEFAULT); m = (int)(MinDistance(planet1[ilo], planet2[jlo])*60.0); fprintf(S, "-%4d%c%02d' degree span.\n", m/60, DEGR1, m%60); } } /* Calculate any of the various kinds of relationship charts. This involves */ /* reading in and storing the planet and house positions for both charts, */ /* and then combining them in the main single chart in the proper manner. */ /* If the parameter 'var' is set, then we read the info for the two charts */ /* from files, otherwise use the info in preset "core" and "second" charts. */ void CastRelation(var) int var; { int mon, day, yea, i; real tim, zon, lon, lat, ratio, t1, t2, t; /* Read in and cast the first chart. */ if (var) InputData(filename); mon = MM; day = DD; yea = YY; tim = TT; zon = ZZ; lon = OO; lat = AA; if (var) { SetTwin(MM, DD, YY, TT, ZZ, OO, AA); } else { SetCore(Mon2, Day2, Yea2, Tim2, Zon2, Lon2, Lat2); } t1 = CastChart(TRUE); for (i = 1; i <= SIGNS; i++) { house1[i] = house[i]; inhouse1[i] = inhouse[i]; } for (i = 1; i <= total; i++) { planet1[i] = planet[i]; planetalt1[i] = planetalt[i]; ret1[i] = ret[i]; } /* Read in the second chart. */ if (var) { InputData(filename2); if (relation == DASHrp) { progress = TRUE; Jdp = (real)MdyToJulian(MM, DD, YY) + TT / 24.0; SetCore(mon, day, yea, tim, zon, lon, lat); } } else { SetCore(mon, day, yea, tim, zon, lon, lat); } SetMain(MM, DD, YY, TT, ZZ, OO, AA); t2 = CastChart(TRUE); for (i = 1; i <= SIGNS; i++) { house2[i] = house[i]; inhouse2[i] = inhouse[i]; } for (i = 1; i <= total; i++) { planet2[i] = planet[i]; planetalt2[i] = planetalt[i]; ret2[i] = ret[i]; } /* Now combine the two charts based on what relation we are doing. */ /* For the standard -r synastry chart, use the house cusps of chart1 */ /* and the planets positions of chart2. */ ratio = (real)ratio1 / ((real)(ratio1 + ratio2)); if (relation <= DASHr) for (i = 1; i <= SIGNS; i++) house[i] = house1[i]; /* For the -rc composite chart, take the midpoints of the planets/houses. */ else if (relation == DASHrc) { for (i = 1; i <= total; i++) { planet[i] = RATIO(planet1[i], planet2[i], ratio); if (dabs(planet2[i] - planet1[i]) > DEGHALF) planet[i] = Mod(planet[i] + DEGREES*ratio); planetalt[i] = RATIO(planetalt1[i], planetalt2[i], ratio); ret[i] = RATIO(ret1[i], ret2[i], ratio); } for (i = 1; i <= SIGNS; i++) { house[i] = RATIO(house1[i], house2[i], ratio); if (dabs(house2[i] - house1[i]) > DEGHALF) house[i] = Mod(house[i] + DEGREES*ratio); } /* Make sure we don't have any 180 degree errors in house cusp */ /* complement pairs, which may happen if the cusps are far apart. */ for (i = 1; i <= SIGNS; i++) if (MinDistance(house[_CAP], Mod(house[i]-STOZ(i+3))) > DEGQUAD) house[i] = Mod(house[i]+DEGHALF); if (dabs(DEGHALF - MinDistance(house[_ARI], planet[_ASC])) < SMALL) planet[_ASC] = Mod(planet[_ASC]+DEGHALF); /* For the -rm time space midpoint chart, calculate the midpoint time and */ /* place between the two charts and then recast for the new chart info. */ } else if (relation == DASHrm) { T = RATIO(t1, t2, ratio); t = (T*36525.0)+ROUND; JD = floor(t)+2415020.0; TT = FRACT(t)*24.0; ZZ = RATIO(DecToDeg(zon), DecToDeg(Zon), ratio); ZZ = DegToDec(ZZ); TT = DecToDeg(TT)-DecToDeg(ZZ); TT = DegToDec(TT); if (TT < 0.0) { TT = DecToDeg(TT)+24.0; TT = DegToDec(TT); JD -= 1.0; } JulianToMdy(JD, &MM, &DD, &YY); OO = RATIO(DecToDeg(lon), DecToDeg(Lon), ratio); if (dabs(Lon-lon) > DEGHALF) OO = Mod(OO+DEGREES*ratio); OO = DegToDec(OO); AA = RATIO(DecToDeg(lat), DecToDeg(Lat), ratio); AA = DegToDec(AA); SetMain(MM, DD, YY, TT, ZZ, OO, AA); CastChart(FALSE); /* There are a couple of non-astrological charts, which only require the */ /* number of days that have passed between the two charts to be done. */ } else JD = dabs(t2-t1)*36525.0; HousePlace(); } /* Given two objects and an aspect between them, or an object and a sign */ /* that it's entering, print if this is a "major" event, such as a season */ /* change or major lunar phase. This is called from the DisplayInDay */ /* searching and influence routines. Go an interpretation if need be too. */ void PrintInDay(source, aspect, dest) int source, aspect, dest; { if (aspect == _SIG) { if (source == _SUN) { AnsiColor(WHITE); if (dest == 1) fprintf(S, " (Vernal Equinox)"); /* If the Sun changes sign, */ else if (dest == 4) /* then print out if this */ fprintf(S, " (Summer Solstice)"); /* is a season change. */ else if (dest == 7) fprintf(S, " (Autumnal Equinox)"); else if (dest == 10) fprintf(S, " (Winter Solstice)"); } } else if (aspect > 0) { if (source == _SUN && dest == _MOO) { if (aspect <= _SQU) AnsiColor(WHITE); if (aspect == _CON) fprintf(S, " (New Moon)"); /* Print out if the present */ else if (aspect == _OPP) /* aspect is a New, Full, */ fprintf(S, " (Full Moon)"); /* or Half Moon. */ else if (aspect == _SQU) fprintf(S, " (Half Moon)"); } } printl(); #ifdef INTERPRET if (interpret) InterpretInDay(source, aspect, dest); #endif AnsiColor(DEFAULT); } /* Given two objects and an aspect (or one object, and an event such as a */ /* sign or direction change) display the configuration in question. This */ /* is called by the many charts which list aspects among items, such as */ /* the -m0 aspect lists, -m midpoint lists, -d aspect in day search and */ /* influence charts, and -t transit search and influence charts. */ void PrintAspect(obj1, sign1, ret1, asp, obj2, sign2, ret2, chart) int obj1, sign1, ret1, asp, obj2, sign2, ret2; char chart; { int smart, a, s2; smart = smartcusp && IsCusp(obj2) && asp == _OPP; a = smart ? _CON : asp; s2 = smart ? sign1 : sign2; AnsiColor(objectansi[obj1]); if (chart == 't' || chart == 'T') fprintf(S, "trans "); else if (chart == 'e' || chart == 'u' || chart == 'U') fprintf(S, "progr "); fprintf(S, "%7.7s", objectname[obj1]); AnsiColor(signansi(sign1)); fprintf(S, " %c%c%c%c%c", ret1 > 0 ? '(' : (ret1 < 0 ? '[' : '<'), SIGNAM(sign1), ret1 > 0 ? ')' : (ret1 < 0 ? ']' : '>')); AnsiColor(a > 0 ? aspectansi[a] : WHITE); printc(' '); if (a == _SIG) fprintf(S, "-->"); /* Print a sign change. */ else if (a == _DIR) fprintf(S, "S/%c", obj2 ? 'R' : 'D'); /* Print a direction change. */ else if (a == 0) fprintf(S, chart == 'm' ? "&" : "with"); else fprintf(S, "%s", aspectabbrev[a]); /* Print an aspect. */ printc(' '); if (chart == 'A') fprintf(S, "with "); if (a == _SIG) { AnsiColor(signansi(obj2)); fprintf(S, "%s", signname[obj2]); } else if (a >= 0) { AnsiColor(signansi(s2)); if (chart == 't' || chart == 'u' || chart == 'T' || chart == 'U') fprintf(S, "natal "); fprintf(S, "%c%c%c%c%c ", ret2 > 0 ? '(' : (ret2 < 0 ? '[' : '<'), SIGNAM(s2), ret2 > 0 ? ')' : (ret2 < 0 ? ']' : '>')); AnsiColor(smart ? signansi((obj2-15) - (obj2 < 23)) : objectansi[obj2]); if (smart) { fprintf(S, "%dth cusp", (obj2-15) - (obj2 < 23)); if (obj2 < 23) printc(' '); } else fprintf(S, "%.10s", objectname[obj2]); } if (chart == 'D' || chart == 'T' || chart == 'U' || chart == 'a' || chart == 'A' || chart == 'm' || chart == 'M') PrintTab(' ', 10-StringLen(objectname[obj2])); } /* Search through a day, and print out the times of exact aspects among the */ /* planets during that day, as specified with the -d switch, as well as the */ /* times when a planet changes sign or direction. To do this, we cast charts */ /* for the beginning and end of the day, or a part of a day, and do a linear */ /* equation check to see if anything exciting happens during the interval. */ /* (This is probably the single most complicated procedure in the program.) */ void DisplayInDaySearch(prog) int prog; { int time[MAXINDAY], source[MAXINDAY], aspect[MAXINDAY], dest[MAXINDAY], sign1[MAXINDAY], sign2[MAXINDAY], D1, D2, occurcount, division, div, year, i, j, k, l, s1, s2; real divsiz, d1, d2, e1, e2, f1, f2, g; /* If parameter 'prog' is set, look for changes in a progressed chart. */ year = (exdisplay & DASHdm) && (Mon2 == 0); division = (year || prog) ? 1 : divisions; divsiz = 24.0/ (real) division*60.0; /* If -dm in effect, then search through the whole month, day by day. */ if (exdisplay & DASHdm) { D1 = 1; if (year) { Mon2 = 1; D2 = DayInYear(prog ? Yea2 : Yea); } else D2 = DayInMonth(prog ? Mon2 : Mon, prog ? Yea2 : Yea); } else D1 = D2 = Day; /* Start searching the day or days in question for exciting stuff. */ for (Day2 = D1; Day2 <= D2; Day2 = AddDay(Mon, Day2, Yea, 1)) { occurcount = 0; /* Cast chart for beginning of day and store it for future use. */ SetCore(year ? Mon2 : Mon, Day2, Yea, 0.0, Zon, Lon, Lat); if (progress = prog) { Jdp = (real)MdyToJulian(Mon2, DD, Yea2); SetCore(Mon, Day, Yea, Tim, Zon, Lon, Lat); } CastChart(TRUE); for (i = 1; i <= SIGNS; i++) { house2[i] = house[i]; inhouse2[i] = inhouse[i]; } for (i = 1; i <= total; i++) { planet2[i] = planet[i]; ret2[i] = ret[i]; } /* Now divide the day into segments and search each segment in turn. */ /* More segments is slower, but has slightly better time accuracy. */ for (div = 1; div <= division; div++) { /* Cast the chart for the ending time of the present segment. The */ /* beginning time chart is copied from the previous end time chart. */ SetCore(year ? Mon2 : Mon, Day2, Yea, DegToDec(24.0*(real)div/(real)division), Zon, Lon, Lat); if (prog) { Jdp = (real)MdyToJulian(Mon2, DD+1, Yea2); SetCore(Mon, Day, Yea, Tim, Zon, Lon, Lat); } CastChart(TRUE); for (i = 1; i <= SIGNS; i++) { house1[i] = house2[i]; inhouse1[i] = inhouse2[i]; house2[i] = house[i]; inhouse2[i] = inhouse[i]; } for (i = 1; i <= total; i++) { planet1[i] = planet2[i]; ret1[i] = ret2[i]; planet2[i] = planet[i]; ret2[i] = ret[i]; } /* Now search through the present segment for anything exciting. */ for (i = 1; i <= total; i++) if (!ignore[i] && (prog || IsThing(i))) { s1 = ZTOS(planet1[i])-1; s2 = ZTOS(planet2[i])-1; /* Does the current planet change into the next or previous sign? */ if (!ignore[i] && s1 != s2 && !ignore[0]) { source[occurcount] = i; aspect[occurcount] = _SIG; dest[occurcount] = s2+1; time[occurcount] = (int) (MinDistance(planet1[i], (real) (ret1[i] >= 0.0 ? s2 : s1) * 30.0) / MinDistance(planet1[i], planet2[i])*divsiz) + (int) ((real) (div-1)*divsiz); sign1[occurcount] = sign2[occurcount] = s1+1; occurcount++; } /* Does the current planet go retrograde or direct? */ if (!ignore[i] && (ret1[i] < 0.0) != (ret2[i] < 0.0) && !ignore2[0]) { source[occurcount] = i; aspect[occurcount] = _DIR; dest[occurcount] = ret2[i] < 0.0; time[occurcount] = (int) (dabs(ret1[i])/(dabs(ret1[i])+dabs(ret2[i])) *divsiz) + (int) ((real) (div-1)*divsiz); sign1[occurcount] = sign2[occurcount] = s1+1; occurcount++; } /* Now search for anything making an aspect to the current planet. */ for (j = i+1; j <= total; j++) if (!ignore[j] && (prog || IsThing(j))) for (k = 1; k <= aspects; k++) { d1 = planet1[i]; d2 = planet2[i]; e1 = planet1[j]; e2 = planet2[j]; if (MinDistance(d1, d2) < MinDistance(e1, e2)) { SwapReal(&d1, &e1); SwapReal(&d2, &e2); } /* We are searching each aspect in turn. Let's subtract the */ /* size of the aspect from the angular difference, so we can */ /* then treat it like a conjunction. */ if (MinDistance(e1, Mod(d1-aspectangle[k])) < MinDistance(e2, Mod(d2+aspectangle[k]))) { e1 = Mod(e1+aspectangle[k]); e2 = Mod(e2+aspectangle[k]); } else { e1 = Mod(e1-aspectangle[k]); e2 = Mod(e2-aspectangle[k]); } /* Check to see if the aspect actually occurs during our */ /* segment, making sure we take into account if one or both */ /* planets are retrograde or if they cross the Aries point. */ f1 = e1-d1; if (dabs(f1) > DEGHALF) f1 -= Sgn(f1)*DEGREES; f2 = e2-d2; if (dabs(f2) > DEGHALF) f2 -= Sgn(f2)*DEGREES; if (MinDistance(Midpoint(d1, d2), Midpoint(e1, e2)) < DEGQUAD && Sgn(f1) != Sgn(f2)) { source[occurcount] = i; aspect[occurcount] = k; dest[occurcount] = j; /* Horray! The aspect occurs sometime during the interval. */ /* Now we just have to solve an equation in two variables to */ /* find out where the "lines" cross, i.e. the aspect's time. */ f1 = d2-d1; if (dabs(f1) > DEGHALF) f1 -= Sgn(f1)*DEGREES; f2 = e2-e1; if (dabs(f2) > DEGHALF) f2 -= Sgn(f2)*DEGREES; g = (dabs(d1-e1) > DEGHALF ? (d1-e1)-Sgn(d1-e1)*DEGREES : d1-e1)/(f2-f1); time[occurcount] = (int) (g*divsiz) + (int) ((real) (div-1)*divsiz); sign1[occurcount] = (int) (Mod(planet1[i]+ Sgn(planet2[i]-planet1[i])* (dabs(planet2[i]-planet1[i]) > DEGHALF ? -1 : 1)* dabs(g)*MinDistance(planet1[i], planet2[i]))/30.0)+1; sign2[occurcount] = (int) (Mod(planet1[j]+ Sgn(planet2[j]-planet1[j])* (dabs(planet2[j]-planet1[j]) > DEGHALF ? -1 : 1)* dabs(g)*MinDistance(planet1[j], planet2[j]))/30.0)+1; occurcount++; } } } } /* After all the aspects, etc, in the day have been located, sort */ /* them by time at which they occur, so we can print them in order. */ for (i = 1; i < occurcount; i++) { j = i-1; while (j >= 0 && time[j] > time[j+1]) { SWAP(source[j], source[j+1]); SWAP(aspect[j], aspect[j+1]); SWAP(dest[j], dest[j+1]); SWAP(time[j], time[j+1]); SWAP(sign1[j], sign1[j+1]); SWAP(sign2[j], sign2[j+1]); j--; } } /* Finally, loop through and display each aspect and when it occurs. */ for (i = 0; i < occurcount; i++) { s1 = time[i]/60; s2 = time[i]-s1*60; j = Day2; if (year || prog) { l = Mon2; while (j > (k = DayInMonth(l, prog ? Yea2 : Yea))) { j -= k; l++; } } SetSave(year || prog ? l : Mon, j, prog ? Yea2 : Yea, DegToDec((real)time[i] / 60.0), Zon, Lon, Lat); k = DayOfWeek(year || prog ? l : Mon, j, prog ? Yea2 : Yea); AnsiColor(rainbowansi[k + 1]); fprintf(S, "(%c%c%c) ", DAYNAM(k)); AnsiColor(DEFAULT); fprintf(S, "%s %s ", CharDate(year || prog ? l : Mon, j, prog ? Yea2 : Yea, FALSE), CharTime(s1, s2)); PrintAspect(source[i], sign1[i], (int)Sgn(ret1[source[i]])+(int)Sgn(ret2[source[i]]), aspect[i], dest[i], sign2[i], (int)Sgn(ret1[dest[i]])+(int)Sgn(ret2[dest[i]]), prog ? 'e' : 'd'); PrintInDay(source[i], aspect[i], dest[i]); } } /* Recompute original chart placements as we've overwritten them. */ SetCore(Mon, Day, Yea, Tim, Zon, Lon, Lat); CastChart(TRUE); } /* Based on the given chart information, display all the aspects taking */ /* place in the chart, as specified with the -D switch. The aspects are */ /* printed in order of influence determined by treating them as happening */ /* outside among transiting planets, such that rare outer planet aspects */ /* are given more power than common ones among inner planets. (This is */ /* almost identical to the -m0 list, except the influences are different.) */ void DisplayInDayInfluence() { int source[MAXINDAY], aspect[MAXINDAY], dest[MAXINDAY]; real power[MAXINDAY]; int occurcount = 0, i, j, k, l, m; /* Go compute the aspects in the chart. */ i = exdisplay; exdisplay |= DASHga; /* We always want applying vs. separating orbs. */ CreateGrid(FALSE); exdisplay = i; /* Search through the grid and build up the list of aspects. */ for (j = 2; j <= total; j++) { if (ignore[j]) continue; for (i = 1; i < j; i++) { if (ignore[i] || (k = grid->n[i][j]) == 0 || occurcount >= MAXINDAY) continue; if (smartcusp && k > _OPP && IsCusp(j)) continue; source[occurcount] = i; aspect[occurcount] = k; dest[occurcount] = j; l = grid->v[i][j]; power[occurcount] = ((i <= BASE ? transitinf[i] : 2.0)/4.0)* ((j <= BASE ? transitinf[j] : 2.0)/4.0)* aspectinf[k]*(1.0-(real)abs(l)/60.0/Orb(i, j, k)); occurcount++; } } /* Sort aspects by order of influence. */ for (i = 1; i < occurcount; i++) { j = i-1; while (j >= 0 && power[j] < power[j+1]) { SWAP(source[j], source[j+1]); SWAP(aspect[j], aspect[j+1]); SWAP(dest[j], dest[j+1]); SwapReal(&power[j], &power[j+1]); j--; } } /* Now display each aspect line. */ for (i = 0; i < occurcount; i++) { fprintf(S, "%3d: ", i+1); j = source[i]; k = aspect[i]; l = dest[i]; PrintAspect( j, ZTOS(planet[j]), (int)Sgn(ret[j]), k, l, ZTOS(planet[l]), (int)Sgn(ret[l]), 'D'); m = grid->v[j][l]; AnsiColor(m < 0 ? WHITE : LTGRAY); fprintf(S, "- %s%2d%c%02d'", m < 0 ? "app" : "sep", abs(m)/60, DEGR1, abs(m)%60); AnsiColor(DKGREEN); fprintf(S, " - power:%6.2f", power[i]); PrintInDay(j, k, l); } } /* Search through a month, year, or years, and print out the times of exact */ /* transits where planets in the time frame make aspect to the planets in */ /* some other chart, as specified with the -t switch. To do this, we cast */ /* charts for the start and end of each month, or within a month, and do an */ /* equation check for aspects to the other base chart during the interval. */ void DisplayTransitSearch(prog) int prog; { real planet3[TOTAL+1], house3[SIGNS+1], ret3[TOTAL+1]; _int time[MAXINDAY]; int source[MAXINDAY], aspect[MAXINDAY], dest[MAXINDAY], sign[MAXINDAY], isret[MAXINDAY], M1, M2, Y1, Y2, occurcount, div, i, j, k, s1, s2, s3; real divsiz, daysiz, d, e1, e2, f1, f2; for (i = 1; i <= SIGNS; i++) house3[i] = house[i]; for (i = 1; i <= total; i++) { planet3[i] = planet[i]; ret3[i] = ret[i]; } /* Hacks: Searching month number zero means to search the whole year */ /* instead, month by month. Searching a negative month means to search */ /* multiple years, with the span off the year stored in the "day" field. */ Y1 = Y2 = Yea2; M1 = M2 = Mon2; if (Mon2 < 1) { M1 = 1; M2 = 12; if (Mon2 < 0) { if (Day2 < 1) { Y1 = Yea2 + Day2 + 1; Y2 = Yea2; } else { Y1 = Yea2; Y2 = Yea2 + Day2 - 1; } } } /* Start searching the year or years in question for any transits. */ for (Yea2 = Y1; Yea2 <= Y2; Yea2++) /* Start searching the month or months in question for any transits. */ for (Mon2 = M1; Mon2 <= M2; Mon2++) { daysiz = (real) DayInMonth(Mon2, Yea2)*24.0*60.0; divsiz = daysiz/ (real) divisions; /* Cast chart for beginning of month and store it for future use. */ SetCore(Mon2, 1, Yea2, 0.0, Zon2, Lon2, Lat2); if (progress = prog) { Jdp = (real)MdyToJulian(MM, DD, YY); SetCore(Mon, Day, Yea, Tim, Zon, Lon, Lat); } CastChart(TRUE); for (i = 1; i <= SIGNS; i++) house2[i] = house[i]; for (i = 1; i <= OBJECTS; i++) { planet2[i] = planet[i]; ret2[i] = ret[i]; } /* Divide our month into segments and then search each segment in turn. */ for (div = 1; div <= divisions; div++) { occurcount = 0; /* Cast the chart for the ending time of the present segment, and */ /* copy the start time chart from the previous end time chart. */ d = 1.0 + (daysiz/24.0/60.0)*(real)div/(real)divisions; SetCore(Mon2, (int)d, Yea2, DegToDec(FRACT(d)*24.0), Zon2, Lon2, Lat2); if (prog) { Jdp = (real)MdyToJulian(MM, DD, YY); SetCore(Mon, Day, Yea, Tim, Zon, Lon, Lat); } CastChart(TRUE); for (i = 1; i <= SIGNS; i++) { house1[i] = house2[i]; house2[i] = house[i]; } for (i = 1; i <= OBJECTS; i++) { planet1[i] = planet2[i]; ret1[i] = ret2[i]; planet2[i] = planet[i]; ret2[i] = ret[i]; } /* Now search through the present segment for any transits. Note that */ /* stars can be transited, but they can't make transits themselves. */ for (i = 1; i <= total; i++) if (!ignore[i]) for (j = 1; j <= BASE; j++) if (!ignore2[j] && (prog || IsThing(j))) /* Between each pair of planets, check if they make any aspects. */ for (k = 1; k <= aspects; k++) { d = planet3[i]; e1 = planet1[j]; e2 = planet2[j]; if (MinDistance(e1, Mod(d-aspectangle[k])) < MinDistance(e2, Mod(d+aspectangle[k]))) { e1 = Mod(e1+aspectangle[k]); e2 = Mod(e2+aspectangle[k]); } else { e1 = Mod(e1-aspectangle[k]); e2 = Mod(e2-aspectangle[k]); } /* Check to see if the present aspect actually occurs during the */ /* segment, making sure we check any Aries point crossings. */ f1 = e1-d; if (dabs(f1) > DEGHALF) f1 -= Sgn(f1)*DEGREES; f2 = e2-d; if (dabs(f2) > DEGHALF) f2 -= Sgn(f2)*DEGREES; if (MinDistance(d, Midpoint(e1, e2)) < DEGQUAD && Sgn(f1) != Sgn(f2) && occurcount < MAXINDAY) { /* Ok, we have found a transit. Now determine the time */ /* and save this transit in our list to be printed. */ source[occurcount] = j; aspect[occurcount] = k; dest[occurcount] = i; time[occurcount] = (int) (dabs(f1)/(dabs(f1)+dabs(f2))*divsiz) + (int) ((real) (div-1)*divsiz); sign[occurcount] = (int) (Mod( MinDistance(planet1[j], Mod(d-aspectangle[k])) < MinDistance(planet2[j], Mod(d+aspectangle[k])) ? d-aspectangle[k] : d+aspectangle[k])/30.0)+1; isret[occurcount] = (int)Sgn(ret1[j]) + (int)Sgn(ret2[j]); occurcount++; } } /* After all transits located, sort them by time at which they occur. */ for (i = 1; i < occurcount; i++) { j = i-1; while (j >= 0 && time[j] > time[j+1]) { SWAP(source[j], source[j+1]); SWAP(aspect[j], aspect[j+1]); SWAP(dest[j], dest[j+1]); SWAP(time[j], time[j+1]); SWAP(sign[j], sign[j+1]); SWAP(isret[j], isret[j+1]); j--; } } /* Now loop through list and display all the transits. */ for (i = 0; i < occurcount; i++) { k = smartcusp && IsCusp(dest[i]); if (k && aspect[i] > _OPP) continue; else k = k && aspect[i] == _OPP; s1 = time[i]/24/60; s3 = time[i]-s1*24*60; s2 = s3/60; s3 = s3-s2*60; SetSave(Mon2, s1+1, Yea2, DegToDec((real)(time[i]-s1*24*60) / 60.0), Zon2, Lon2, Lat2); fprintf(S, "%s %s ", CharDate(Mon2, s1+1, Yea2, FALSE), CharTime(s2, s3)); PrintAspect(source[i], sign[i], isret[i], aspect[i], dest[i], ZTOS(planet3[dest[i]]), (int)Sgn(ret3[dest[i]]), prog ? 'u' : 't'); /* Check for a Solar, Lunar, or any other return. */ if (aspect[i] == _CON && source[i] == dest[i]) { AnsiColor(WHITE); fprintf(S, " (%s Return)", source[i] == _SUN ? "Solar" : (source[i] == _MOO ? "Lunar" : objectname[source[i]])); } printl(); #ifdef INTERPRET if (interpret) InterpretTransit(source[i], aspect[i], dest[i]); #endif AnsiColor(DEFAULT); } } } } /* Given an arbitrary day, determine what aspects are made between this */ /* transiting chart and the given natal chart, as specified with the -T */ /* switch, and display the transits in order sorted by influence. */ void DisplayTransitInfluence(prog) int prog; { int source[MAXINDAY], aspect[MAXINDAY], dest[MAXINDAY]; real power[MAXINDAY]; byte ignore3[TOTAL+1]; int occurcount = 0, i, j, k, l, m; /* Cast the natal and transiting charts as with a relationship chart. */ for (i = 1; i <= SIGNS; i++) house1[i] = house[i]; for (i = 1; i <= total; i++) { planet1[i] = planet[i]; ret1[i] = ret[i]; } SetCore(Mon2, Day2, Yea2, Tim2, Zon2, Lon2, Lat2); if (progress = prog) { Jdp = (real)MdyToJulian(MM, DD, YY); MM = Mon; DD = Day; YY = Yea; } CastChart(TRUE); for (i = 1; i <= SIGNS; i++) house2[i] = house[i]; for (i = 1; i <= total; i++) { planet2[i] = planet[i]; ret2[i] = ret[i]; } /* Do a relationship aspect grid to get the transits. We have to make and */ /* restore three changes to get it right for this chart. (1) We make the */ /* natal planets have zero velocity so applying vs. separating is only a */ /* function of the transiter. (2) We force applying vs. separating orbs */ /* regardless if -ga or -ma is in effect or not. (3) Finally we tweak the */ /* main restrictions to allow for transiting objects not restricted. */ for (i = 1; i <= total; i++) { ret[i] = ret1[i]; ret1[i] = 0.0; ignore3[i] = ignore[i]; ignore[i] = ignore[i] && ignore2[i]; } i = exdisplay; exdisplay |= DASHga; CreateGridRelation(FALSE); exdisplay = i; for (i = 1; i <= total; i++) { ret1[i] = ret[i]; ignore[i] = ignore3[i]; } /* Loop through the grid, and build up a list of the valid transits. */ for (i = 1; i <= BASE; i++) { if (ignore2[i] || !IsThing(i)) continue; for (j = 1; j <= total; j++) { if (ignore[j] || (k = grid->n[i][j]) == 0 || occurcount >= MAXINDAY) continue; if (smartcusp && k > _OPP && IsCusp(j)) continue; source[occurcount] = i; aspect[occurcount] = k; dest[occurcount] = j; l = grid->v[i][j]; power[occurcount] = transitinf[i]* ((j <= BASE ? objectinf[j] : 2.0)/4.0)*aspectinf[k]* (1.0-(real)abs(l)/60.0/Orb(i, j, k)); occurcount++; } } /* After all transits located, sort them by their total power. */ for (i = 1; i < occurcount; i++) { j = i-1; while (j >= 0 && power[j] < power[j+1]) { SWAP(source[j], source[j+1]); SWAP(aspect[j], aspect[j+1]); SWAP(dest[j], dest[j+1]); SwapReal(&power[j], &power[j+1]); j--; } } /* Now loop through list and display each transit in effect at the time. */ for (i = 0; i < occurcount; i++) { k = aspect[i]; l = source[i]; fprintf(S, "%3d: ", i+1); j = ZTOS(planet2[l]); PrintAspect(l, j, (int)Sgn(ret2[l]), k, dest[i], ZTOS(planet1[dest[i]]), (int)Sgn(ret1[dest[i]]), prog ? 'U' : 'T'); m = grid->v[l][dest[i]]; AnsiColor(m < 0 ? WHITE : LTGRAY); fprintf(S, "- %s%2d%c%02d'", m < 0 ? "app" : "sep", abs(m)/60, DEGR1, abs(m)%60); AnsiColor(DKGREEN); fprintf(S, " - power:%6.2f", power[i]); if (k == _CON && l == dest[i]) { /* Print a small "R" for returns. */ AnsiColor(WHITE); fprintf(S, " R"); } printl(); #ifdef INTERPRET if (interpret) InterpretTransit(l, k, dest[i]); #endif AnsiColor(DEFAULT); } } /* Given the zodiac location of a planet in the sky and its declination, */ /* and a location on the Earth, compute the azimuth and altitude of where */ /* on the local horizon sky the planet would appear to one at the given */ /* location. A reference MC position at Greenwich is also needed for this. */ void EclToHorizon(azi, alt, planet, planetalt, lon, lat, mc) real *azi, *alt, planet, planetalt, lon, lat, mc; { real lonz, latz; lonz = DTOR(planet); latz = DTOR(planetalt); EclToEqu(&lonz, &latz); lonz = DTOR(Mod(RTOD(mc-lonz+lon))); lonz = DTOR(Mod(RTOD(lonz-lon+PI/2.0))); EquToLocal(&lonz, &latz, PI/2.0-lat); *azi = DEGREES-RTOD(lonz); *alt = RTOD(latz); } /* Display a list of planetary rising times relative to the local horizon */ /* for the day indicated in the chart information, as specified with the */ /* -Zd switch. For the day, the time each planet rises (transits horizon */ /* in East half of sky), sets (transits horizon in West), reaches its */ /* zenith point (transits meridian in South half of sky), and nadirs */ /* transits meridian in North), is displayed. */ void DisplayInDayHorizon() { int source[MAXINDAY], type[MAXINDAY], time[MAXINDAY], sign[MAXINDAY], isret[MAXINDAY], occurcount, division, div, s1, s2, i, j; real planetalt1[TOTAL+1], planetalt2[TOTAL+1], azialt[MAXINDAY], lon, lat, mc1, mc2, azi1, alt1, azi2, alt2, d, k; lon = DTOR(Mod(Lon)); lat = DTOR(Lat); division = divisions * 4; occurcount = 0; SetCore(Mon, Day, Yea, 0.0, Zon, Lon, Lat); CastChart(TRUE); mc2 = DTOR(planet[_MC]); k = DTOR(planetalt[_MC]); EclToEqu(&mc2, &k); for (i = 1; i <= SIGNS; i++) { house2[i] = house[i]; inhouse2[i] = inhouse[i]; } for (i = 1; i <= total; i++) { planet2[i] = planet[i]; planetalt2[i] = planetalt[i]; ret2[i] = ret[i]; } /* Loop thorough the day, dividing it into a certain number of segments. */ /* For each segment we get the planet positions at its endpoints. */ for (div = 1; div <= division; div++) { SetCore(Mon, Day, Yea, DegToDec(24.0*(real)div/(real)division), Zon, Lon, Lat); CastChart(TRUE); mc1 = mc2; mc2 = DTOR(planet[_MC]); k = DTOR(planetalt[_MC]); EclToEqu(&mc2, &k); for (i = 1; i <= SIGNS; i++) { house1[i] = house2[i]; inhouse1[i] = inhouse2[i]; house2[i] = house[i]; inhouse2[i] = inhouse[i]; } for (i = 1; i <= total; i++) { planet1[i] = planet2[i]; planet2[i] = planet[i]; planetalt1[i] = planetalt2[i]; planetalt2[i] = planetalt[i]; ret1[i] = ret2[i]; ret2[i] = ret[i]; } /* For our segment, check to see if each planet during it rises, sets, */ /* reaches its zenith, or reaches its nadir. */ for (i = 1; i <= total; i++) if (!ignore[i] && IsThing(i)) { EclToHorizon(&azi1, &alt1, planet1[i], planetalt1[i], lon, lat, mc1); EclToHorizon(&azi2, &alt2, planet2[i], planetalt2[i], lon, lat, mc2); j = 0; /* Check for transits to the horizon. */ if ((alt1 > 0.0) != (alt2 > 0.0)) { d = dabs(alt1)/(dabs(alt1)+dabs(alt2)); k = Mod(azi1 + d*MinDifference(azi1, azi2)); j = 1 + 2*(MinDistance(k, DEGHALF) < DEGQUAD); /* Check for transits to the meridian. */ } else if (Sgn(MinDifference(azi1, DEGQUAD)) != Sgn(MinDifference(azi2, DEGQUAD))) { j = 2 + 2*(MinDistance(azi1, DEGQUAD) < DEGQUAD); d = dabs(azi1 - (j > 2 ? DEGQUAD : 270.0))/MinDistance(azi1, azi2); k = alt1 + d*(alt2-alt1); } if (j && occurcount < MAXINDAY) { source[occurcount] = i; type[occurcount] = j; time[occurcount] = (int)(24.0*((real)(div-1)+d)/(real)division*60.0); sign[occurcount] = (int)Mod(planet1[i] + d*MinDifference(planet1[i], planet2[i]))/30 + 1; isret[occurcount] = (int)Sgn(ret1[i]) + (int)Sgn(ret2[i]); azialt[occurcount] = k; SetSave(Mon, Day, Yea, DegToDec((real)time[occurcount] / 60.0), Zon, Lon, Lat); occurcount++; } } } /* Sort each event in order of time when it happens during the day. */ for (i = 1; i < occurcount; i++) { j = i-1; while (j >= 0 && time[j] > time[j+1]) { SWAP(source[j], source[j+1]); SWAP(type[j], type[j+1]); SWAP(time[j], time[j+1]); SWAP(sign[j], sign[j+1]); SWAP(isret[j], isret[j+1]); SwapReal(&azialt[j], &azialt[j+1]); j--; } } /* Finally display the list showing each event and when it occurs. */ for (i = 0; i < occurcount; i++) { SetSave(Mon, Day, Yea, DegToDec((real)time[i] / 60.0), Zon, Lon, Lat); j = DayOfWeek(Mon, Day, Yea); AnsiColor(rainbowansi[j + 1]); fprintf(S, "(%c%c%c) ", DAYNAM(j)); AnsiColor(DEFAULT); s1 = time[i]/60; s2 = time[i]-s1*60; fprintf(S, "%s %s ", CharDate(Mon, Day, Yea, FALSE), CharTime(s1, s2)); AnsiColor(objectansi[source[i]]); fprintf(S, "%7.7s ", objectname[source[i]]); AnsiColor(signansi(sign[i])); fprintf(S, "%c%c%c%c%c ", isret[i] > 0 ? '(' : (isret[i] < 0 ? '[' : '<'), SIGNAM(sign[i]), isret[i] > 0 ? ')' : (isret[i] < 0 ? ']' : '>')); AnsiColor(elemansi[type[i]-1]); if (type[i] == 1) fprintf(S, "rises "); else if (type[i] == 2) fprintf(S, "zeniths"); else if (type[i] == 3) fprintf(S, "sets "); else fprintf(S, "nadirs "); AnsiColor(DEFAULT); fprintf(S, " at "); if (type[i] & 1) { j = (int) (FRACT(azialt[i])*60.0); fprintf(S, "%3d%c%02d'", (int) azialt[i], DEGR1, j); /* For rising and setting events, we'll also display a direction */ /* vector to make the 360 degree azimuth value thought of easier. */ azi1 = cos(DTOR(azialt[i])); alt1 = sin(DTOR(azialt[i])); if (dabs(azi1) < dabs(alt1)) { azi2 = dabs(azi1 / alt1); alt2 = 1.0; } else { alt2 = dabs(alt1 / azi1); azi2 = 1.0; } fprintf(S, " (%.2f%c %.2f%c)", alt2, alt1 < 0.0 ? 's' : 'n', azi2, azi1 > 0.0 ? 'e' : 'w'); } else PrintAltitude(azialt[i]); printl(); } /* Recompute original chart placements as we've overwritten them. */ SetCore(Mon, Day, Yea, Tim, Zon, Lon, Lat); CastChart(TRUE); } /* Print out an ephemeris - the positions of the planets (at the time in the */ /* current chart) each day during a specified month, as done with the -E */ /* switch. Display the ephemeris for the whole year if -Ey is in effect. */ void DisplayEphemeris() { int M0, M1, M2, daysiz, i, j, k, s, d, m; /* If -Ey is in effect, then loop through all months in the whole year. */ if (exdisplay & DASHEy) { M1 = 1; M2 = 12; } else M1 = M2 = Mon; /* Loop through the month or months in question, printing each ephemeris. */ for (M0 = M1; M0 <= M2; M0++) { daysiz = DayInMonth(M0, Yea); fprintf(S, eurodate ? "Dy/Mo/Yr" : "Mo/Dy/Yr"); for (k = 0, j = 1; j <= total; j++) { if (!ignore[j] && IsThing(j)) { fprintf(S, " %c%c%c%c ", OBJNAM(j), objectname[j][3] != 0 ? objectname[j][3] : ' '); k++; if (column80 && k >= 10) j = total; } } printl(); for (i = 1; i <= daysiz; i = AddDay(M0, i, Yea, 1)) { /* Loop through each day in the month, casting a chart for that day. */ SetCore(M0, i, Yea, Tim, Zon, Lon, Lat); CastChart(TRUE); fprintf(S, "%s ", CharDate(M0, i, Yea, -1)); for (k = 0, j = 1; j <= total; j++) if (!ignore[j] && IsThing(j)) { AnsiColor(objectansi[j]); s = ZTOS(planet[j]); d = (int) planet[j] - (s-1)*30; m = (int) (FRACT(planet[j])*60.0); fprintf(S, "%2d%s%02d%c", d, signabbrev[s], m, ret[j] >= 0.0 ? ' ' : '.'); k++; if (column80 && k >= 10) j = total; } printl(); AnsiColor(DEFAULT); } if (M0 < M2) printl(); } } /* Display a calendar for the given month in the chart, as specified with */ /* with the -K switch. When color is on, the title is white, weekends are */ /* highlighted in red, and the specific day in the chart is colored green. */ void DisplayCalendarMonth() { int i, j, k; AnsiColor(WHITE); PrintTab(' ', 16-StringLen(monthname[Mon]) >> 1); fprintf(S, "%s%5d\n", monthname[Mon], Yea); for (i = 0; i < 7; i++) fprintf(S, "%c%c%c", dayname[i][0], dayname[i][1], i < 6 ? ' ' : '\n'); j = DayOfWeek(Mon, 1, Yea); AnsiColor(DEFAULT); for (i = 0; i < j; i++) { if (i == 0) AnsiColor(RED); fprintf(S, "-- "); if (i == 0) AnsiColor(DEFAULT); } k = DayInMonth(Mon, Yea); for (i = 1; i <= k; i = AddDay(Mon, i, Yea, 1)) { if (i == (int)Day) AnsiColor(GREEN); else if (j == 0 || j == 6) AnsiColor(RED); fprintf(S, "%2d", i); if (j == 0 || j == 6 || i == Day) AnsiColor(DEFAULT); if (j < 6) { j++; printc(' '); } else { j = 0; printl(); } } while (j > 0 && j < 7) { if (j == 6) AnsiColor(RED); j++; fprintf(S, "--%c", j < 7 ? ' ' : '\n'); } AnsiColor(DEFAULT); } /* Display a calendar for the entire year given in the chart, as specified */ /* with the -Ky switch. This is just like twelve of the individual month */ /* calendars above displayed together, with same color highlights and all. */ void DisplayCalendarYear() { int r, w, c, m, d, dy, p[3], l[3], n[3]; dy = DayOfWeek(1, 1, Yea); for (r = 0; r < 4; r++) { /* Loop over one set of three months */ AnsiColor(WHITE); for (c = 0; c < 3; c++) { m = r*3+c+1; PrintTab(' ', 16-StringLen(monthname[m]) >> 1); fprintf(S, "%s%5d", monthname[m], Yea); if (c < 2) PrintTab(' ', 20 + MONTHSPACE - (16-StringLen(monthname[m]) >> 1) - StringLen(monthname[m]) - 5); } printl(); for (c = 0; c < 3; c++) { for (d = 0; d < 7; d++) fprintf(S, "%c%c%c", dayname[d][0], dayname[d][1], d < 6 || c < 2 ? ' ' : '\n'); if (c < 2) PrintTab(' ', MONTHSPACE-1); m = r*3+c+1; p[c] = dy % 7; l[c] = DayInMonth(m, Yea); n[c] = 0; dy += DaysInMonth(m, Yea); } for (w = 0; w < 6; w++) { /* Loop over one set of week rows */ for (c = 0; c < 3; c++) { /* Loop over one week in a month */ m = r*3+c+1; d = 0; if (w == 0) while (d < p[c]) { if (d == 0) AnsiColor(RED); fprintf(S, "-- "); if (d == 0) AnsiColor(DEFAULT); d++; } AnsiColor(DEFAULT); while (d < 7 && n[c] < l[c]) { n[c] = AddDay(m, n[c], Yea, 1); if (n[c] == Day && m == Mon) AnsiColor(GREEN); else if (d == 0 || d == 6) AnsiColor(RED); fprintf(S, "%2d%c", n[c], d < 6 || c < 2 ? ' ' : '\n'); if (d == 0 || d == 6 || (n[c] == Day && m == Mon)) AnsiColor(DEFAULT); d++; } while (d < 7) { if (d == 0 || d == 6) AnsiColor(RED); fprintf(S, "--%c", d < 6 || c < 2 ? ' ' : '\n'); if (d == 0) AnsiColor(DEFAULT); d++; } if (c < 2) PrintTab(' ', MONTHSPACE-1); } } if (r < 3) printl(); } AnsiColor(DEFAULT); } /* Display either a biorhythm chart or the time difference in various units */ /* between two charts, i.e. two types of relationship "charts" that aren't */ /* related in any way to planetary positions, as specified by either the */ /* -rb or -rd switches, respectively. */ void DisplayRelation() { #ifdef BIORHYTHM int i, j; real k, l; #endif /* If we are calculating the difference between two dates, then display */ /* the value and return, as with the -rd switch. */ if (relation == DASHrd) { fprintf(S, "Differences between the dates in the two charts:\n"); AnsiColor(rainbowansi[1]); fprintf(S, "Years : %.0f\n", JD/365.25); AnsiColor(rainbowansi[2]); fprintf(S, "Months : %.0f\n", JD/(365.25/12)); AnsiColor(rainbowansi[3]); fprintf(S, "Weeks : %.0f\n", JD/7.0); AnsiColor(rainbowansi[4]); fprintf(S, "Days : %.0f\n", JD); AnsiColor(rainbowansi[5]); fprintf(S, "Hours : %.0f\n", JD*24.0); AnsiColor(rainbowansi[6]); fprintf(S, "Minutes: %.0f\n", JD*24.0*60.0); AnsiColor(rainbowansi[7]); fprintf(S, "Seconds: %.0f\n", JD*24.0*3600.0); AnsiColor(DEFAULT); return; } #ifdef BIORHYTHM /* If we are doing a biorhythm (-rb switch), then we'll calculate it for */ /* someone born on the older date, at the time of the younger date. Loop */ /* through the week preceeding and following the date in question. */ JD = floor(JD + ROUND); for (JD -= 7.0, i = -7; i <= 7; i++, JD += 1.0) { if (i == 0) AnsiColor(WHITE); else if (i == 1) AnsiColor(DEFAULT); fprintf(S, "T%c%d Day%c:", i < 0 ? '-' : '+', abs(i), abs(i) != 1 ? 's' : ' '); for (j = 1; j <= 3; j++) { printc(' '); switch (j) { case 1: k = _PHY; AnsiColor(RED); fprintf(S, "Physical"); break; case 2: k = _EMO; AnsiColor(BLUE); fprintf(S, "Emotional"); break; case 3: k = _INT; AnsiColor(GREEN); fprintf(S, "Intellectual"); break; } AnsiColor(i ? DEFAULT : WHITE); /* The biorhythm calculation is below. */ l = Biorhythm(JD, k); fprintf(S, " at %c%3.0f%%", l < 0.0 ? '-' : '+', dabs(l)); /* Print smiley face, medium face, or sad face based on current cycle. */ AnsiColor(PURPLE); fprintf(S, " :%c", l > 50.0 ? ')' : (l < -50.0 ? '(' : '|')); AnsiColor(i ? DEFAULT : WHITE); if (j < 3) printc(','); } printl(); } #endif /* BIORHYTHM */ } /* Another important procedure: Display any of the types of (text) charts */ /* that the user specified they wanted, by calling the appropriate routines. */ void PrintChart(prog) { if (todisplay == 0) /* Assume the -v chart if user */ todisplay |= DASHv; /* didn't indicate anything. */ if (todisplay & DASHv) { if (relation < DASHrd) ChartLocation(); else /* If the -rb or -rd relationship charts are in effect, then instead */ /* of doing the standard -v chart, print either of these chart types. */ DisplayRelation(); if (todisplay - (todisplay & DASHv*2-1)) printl2(); } if (todisplay & DASHw) { ChartWheel(); if (todisplay - (todisplay & DASHw*2-1)) printl2(); } if (todisplay & DASHg) { if (relation > DASHr0) { CreateGrid(FALSE); ChartGrid(); if (exdisplay & DASHg0) { /* If -g0 switch in effect, then */ printl(); /* display aspect configurations. */ DisplayGrands(); } } else { /* Do a relationship aspect grid between two charts if -r0 in effect. */ CreateGridRelation((exdisplay & DASHg0) > 0); DisplayGridRelation(); } if (todisplay - (todisplay & DASHg*2-1)) printl2(); } if (todisplay & DASHm) { if (!(todisplay & DASHg) || relation <= DASHr0) CreateGrid(FALSE); if (relation > DASHr0) { if (exdisplay & DASHm0) ChartAspect(); else ChartMidpoint(); if (todisplay - (todisplay & DASHm*2-1)) printl2(); } else { CreateGridRelation((exdisplay & DASHm0) == 0); if (exdisplay & DASHm0) DisplayAspectRelation(); else DisplayMidpointRelation(); } } if (todisplay & DASHZ) { if (exdisplay & DASHZd) DisplayInDayHorizon(); else ChartHorizon(); if (todisplay - (todisplay & DASHZ*2-1)) printl2(); } if (todisplay & DASHS) { ChartSpace(); if (todisplay - (todisplay & DASHS*2-1)) printl2(); } if (todisplay & DASHj) { ChartInfluence(); if (todisplay - (todisplay & DASHj*2-1)) printl2(); } if (todisplay & DASHL) { ChartAstroGraph(); if (todisplay - (todisplay & DASHL*2-1)) printl2(); } if (todisplay & DASHK) { if (exdisplay & DASHKy) DisplayCalendarYear(); else DisplayCalendarMonth(); if (todisplay - (todisplay & DASHK*2-1)) printl2(); } if (todisplay & DASHd) { DisplayInDaySearch(prog); if (todisplay - (todisplay & DASHd*2-1)) printl2(); } if (todisplay & DASHD) { DisplayInDayInfluence(); if (todisplay - (todisplay & DASHD*2-1)) printl2(); } if (todisplay & DASHE) { DisplayEphemeris(); if (todisplay - (todisplay & DASHE*2-1)) printl2(); } if (todisplay & DASHt) { DisplayTransitSearch(prog); if (todisplay - (todisplay & DASHt*2-1)) printl2(); } if (todisplay & DASHT) DisplayTransitInfluence(prog); } /* options.c */
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.