home *** CD-ROM | disk | FTP | other *** search
- /*
- ** Astrolog (Version 4.00) File: formulas.c
- **
- ** IMPORTANT NOTICE: the graphics database and chart display routines
- ** used in this program are Copyright (C) 1991-1993 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 12/31/1993.
- */
-
- #include "astrolog.h"
-
- real MC, Asc, Vtx, OB,
- X, Y, A, R, M, D, B, Q, L, G, O, RA, S0, NU;
-
- real planet1[TOTAL+1], planet2[TOTAL+1],
- planetalt1[TOTAL+1], planetalt2[TOTAL+1],
- house1[SIGNS+1], house2[SIGNS+1], ret1[TOTAL+1], ret2[TOTAL+1];
-
- real FAR *datapointer;
-
-
- /*
- ******************************************************************************
- ** Specific Calculations.
- ******************************************************************************
- */
-
-
- /* Integer division - like the "/" operator but always rounds result down. */
-
- long Dvd(x, y)
- long x, y;
- {
- long z;
-
- if (y == 0)
- return x;
- z = x / y;
- if ((x >= 0 == y >= 0) || x-z*y == 0)
- return z;
- return z - 1;
- }
-
-
- #ifdef MATRIX
- /* Given a month, day, and year, convert it into a single Julian day value, */
- /* i.e. the number of days passed since a fixed reference date. */
-
- long MdyToJulian(mon, day, yea)
- int mon, day, yea;
- {
- long im, j;
-
- im = 12*((long)yea+4800)+(long)mon-3;
- j = (2*(im%12) + 7 + 365*im)/12;
- j += (long)day + im/48 - 32083;
- if (j > 2299171) /* Take care of dates in */
- j += im/4800 - im/1200 + 38; /* Gregorian calendar. */
- return j;
- }
-
-
- /* Take a Julian day value, and convert it back into the corresponding */
- /* month, day, and year. */
-
- void JulianToMdy(JD, mon, day, yea)
- real JD;
- int *mon, *day, *yea;
- {
- long L, N, IT, JT, K, IK;
-
- L = (long)floor(JD+ROUND)+68569L;
- N = Dvd(4L*L, 146097L);
- L -= Dvd(146097L*N + 3L, 4L);
- IT = Dvd(4000L*(L+1L), 1461001L);
- L -= Dvd(1461L*IT, 4L) - 31L;
- JT = Dvd(80L*L, 2447L);
- K = L-Dvd(2447L*JT, 80L);
- L = Dvd(JT, 11L);
- JT += 2L - 12L*L;
- IK = 100L*(N-49L) + IT + L;
- *mon = (int)JT; *day = (int)K; *yea = (int)IK;
- }
-
-
- /* This is a subprocedure of CastChart(). Once we have the chart parameters, */
- /* calculate a few important things related to the date, i.e. the Greenwich */
- /* time, the Julian day and fractional part of the day, the offset to the */
- /* sidereal, and a couple of other things. */
-
- real ProcessInput(var)
- int var;
- {
- real Off, Ln;
-
- TT = Sgn(TT)*floor(dabs(TT))+FRACT(dabs(TT))*100.0/60.0+DecToDeg(ZZ);
- OO = DecToDeg(OO);
- AA = DTOR(DecToDeg(AA));
- AA = MIN(AA, 89.9999); /* Make sure the chart isn't being cast */
- AA = MAX(AA, -89.9999); /* on the precise north or south pole. */
-
- /* if parameter 'var' isn't set, then we can assume that the true time */
- /* has already been determined (as in a -rm switch time midpoint chart). */
-
- if (var) {
- JD = (real)MdyToJulian(MM, DD, YY);
- if (!progress || (operation & DASHp0) > 0)
- T = ((JD-2415020.0)+TT/24.0-0.5)/36525.0;
- else
-
- /* Determine actual time that a progressed chart is to be cast for. */
-
- T = (((Jdp-JD)/progday+JD)-2415020.0+TT/24.0-0.5)/36525.0;
- }
-
- /* Compute angle that the ecliptic is inclined to the Celestial Equator */
- OB = DTOR(23.452294-0.0130125*T);
-
- Ln = Mod((933060-6962911*T+7.5*T*T)/3600.0); /* Mean lunar node */
- Off = (259205536.0*T+2013816.0)/3600.0; /* Mean Sun */
- Off = 17.23*sin(DTOR(Ln))+1.27*sin(DTOR(Off))-(5025.64+1.11*T)*T;
- Off = (Off-84038.27)/3600.0;
- SD = operation & DASHs ? Off : 0.0;
- return Off;
- }
-
-
- /* Convert polar to rectangular coordinates. */
-
- void PolToRec(A, R, X, Y)
- real A, R, *X, *Y;
- {
- if (A == 0.0)
- A = SMALL;
- *X = R*cos(A);
- *Y = R*sin(A);
- }
-
-
- /* Convert rectangular to polar coordinates. */
-
- void RecToPol(X, Y, A, R)
- real X, Y, *A, *R;
- {
- if (Y == 0.0)
- Y = SMALL;
- *R = sqrt(X*X+Y*Y);
- *A = Angle(X, Y);
- }
-
-
- /* Convert rectangular to spherical coordinates. */
-
- void RecToSph()
- {
- A = B; R = 1.0;
- PolToRec(A, R, &X, &Y);
- Q = Y; R = X; A = L;
- PolToRec(A, R, &X, &Y);
- G = X; X = Y; Y = Q;
- RecToPol(X, Y, &A, &R);
- A += O;
- PolToRec(A, R, &X, &Y);
- Q = ASIN(Y);
- Y = X; X = G;
- RecToPol(X, Y, &A, &R);
- if (A < 0.0)
- A += 2*PI;
- G = A;
- }
-
-
- /* Do a coordinate transformation: Given a longitude and latitude value, */
- /* return the new longitude and latitude values that the same location */
- /* would have, were the equator tilted by a specified number of degrees. */
- /* In other words, do a pole shift! This is used to convert among ecliptic, */
- /* equatorial, and local coordinates, each of which have zero declination */
- /* in different planes. In other words, take into account the Earth's axis. */
-
- void CoorXform(azi, alt, tilt)
- real *azi, *alt, tilt;
- {
- real x, y, a1, l1;
- real sinalt, cosalt, sinazi, sintilt, costilt;
-
- sinalt = sin(*alt); cosalt = cos(*alt); sinazi = sin(*azi);
- sintilt = sin(tilt); costilt = cos(tilt);
-
- x = cosalt * sinazi * costilt;
- y = sinalt * sintilt;
- x -= y;
- a1 = cosalt;
- y = cosalt * cos(*azi);
- l1 = Angle(y, x);
- a1 = a1 * sinazi * sintilt + sinalt * costilt;
- a1 = ASIN(a1);
- *azi = l1; *alt = a1;
- }
-
-
- /* This is another subprocedure of CastChart(). Calculate a few variables */
- /* corresponding to the chart parameters that are used later on. The */
- /* astrological vertex (object number twenty) is also calculated here. */
-
- void ComputeVariables()
- {
- real R2;
-
- RA = DTOR(Mod((6.6460656+2400.0513*T+2.58E-5*T*T+TT)*15.0-OO));
- R2 = RA; O = -OB; B = AA; A = R2; R = 1.0;
- PolToRec(A, R, &X, &Y);
- X *= cos(O);
- RecToPol(X, Y, &A, &R);
- MC = Mod(SD+RTOD(A)); /* Midheaven */
- L = R2;
- RecToSph();
- #if FALSE
- AZ = Mod(SD+Mod(G+PI/2.0)); /* Ascendant */
- #endif
- L= R2+PI; B = PI/2.0-dabs(B);
- if (AA < 0.0)
- B = -B;
- RecToSph();
- Vtx = Mod(SD+RTOD(G+PI/2.0)); /* Vertex */
- }
- #endif /* MATRIX */
-
-
- /*
- ******************************************************************************
- ** House Cusp Calculations.
- ******************************************************************************
- */
-
- /* This is a subprocedure of HousePlace(). Given a zodiac position, return */
- /* which of the twelve houses it falls in. Remember that a special check */
- /* has to be done for the house that spans 0 degrees Aries. */
-
- int HousePlaceIn(point)
- real point;
- {
- int i = 0;
-
- point = Mod(point + 0.5/60.0/60.0);
- do {
- i++;
- } while (!(i >= SIGNS ||
- (point >= house[i] && point < house[Mod12(i+1)]) ||
- (house[i] > house[Mod12(i+1)] &&
- (point >= house[i] || point < house[Mod12(i+1)]))));
- return i;
- }
-
-
- /* For each object in the chart, determine what house it belongs in. */
-
- void HousePlace()
- {
- int i;
-
- for (i = 1; i <= total; i++)
- inhouse[i] = HousePlaceIn(planet[i]);
- }
-
-
- #ifdef MATRIX
- /* The following two functions calculate the midheaven and ascendant of */
- /* the chart in question, based on time and location. They are also used */
- /* in some of the house cusp calculation routines as a quick way to get */
- /* the 10th and 1st house cusps. */
-
- real CuspMidheaven()
- {
- real MC;
-
- MC = ATAN(tan(RA)/cos(OB));
- if (MC < 0.0)
- MC += PI;
- if (RA > PI)
- MC += PI;
- return Mod(RTOD(MC)+SD);
- }
-
- real CuspAscendant()
- {
- real Asc;
-
- Asc = Angle(-sin(RA)*cos(OB)-tan(AA)*sin(OB), cos(RA));
- return Mod(RTOD(Asc)+SD);
- }
-
-
- /* These are various different algorithms for calculating the house cusps: */
-
- real CuspPlacidus(deg, FF, neg)
- real deg, FF;
- bool neg;
- {
- int i;
- real LO, R1, R2, XS;
-
- R1 = RA+DTOR(deg);
- if (neg)
- X = 1.0;
- else
- X = -1.0;
- for (i = 1; i <= 10; i++) {
-
- /* This formula works except at 0 latitude (AA == 0.0). */
-
- XS = X*sin(R1)*tan(OB)*tan(AA == 0.0 ? 0.0001 : AA);
- XS = ACOS(XS);
- if (XS < 0.0)
- XS += PI;
- if (neg)
- R2 = RA+PI-(XS/FF);
- else
- R2 = RA+(XS/FF);
- R1 = R2;
- }
- LO = ATAN(tan(R1)/cos(OB));
- if (LO < 0.0)
- LO += PI;
- if (sin(R1) < 0.0)
- LO += PI;
- return RTOD(LO);
- }
-
- void HousePlacidus()
- {
- int i;
-
- house[1] = Mod(Asc-SD);
- house[4] = Mod(MC+DEGHALF-SD);
- house[5] = CuspPlacidus(30.0, 3.0, FALSE) + DEGHALF;
- house[6] = CuspPlacidus(60.0, 1.5, FALSE) + DEGHALF;
- house[2] = CuspPlacidus(120.0, 1.5, TRUE);
- house[3] = CuspPlacidus(150.0, 3.0, TRUE);
- for (i = 1; i <= SIGNS; i++) {
- if (i <= 6)
- house[i] = Mod(house[i]+SD);
- else
- house[i] = Mod(house[i-6]+DEGHALF);
- }
- }
-
- void HouseKoch()
- {
- real A1, A2, A3, KN;
- int i;
-
- A1 = sin(RA)*tan(AA)*tan(OB);
- A1 = ASIN(A1);
- for (i = 1; i <= SIGNS; i++) {
- D = Mod(60.0+30.0*(real)i);
- A2 = D/DEGQUAD-1.0; KN = 1.0;
- if (D >= DEGHALF) {
- KN = -1.0;
- A2 = D/DEGQUAD-3.0;
- }
- A3 = DTOR(Mod(RTOD(RA)+D+A2*RTOD(A1)));
- X = Angle(cos(A3)*cos(OB)-KN*tan(AA)*sin(OB), sin(A3));
- house[i] = Mod(RTOD(X)+SD);
- }
- }
-
- void HouseEqual()
- {
- int i;
-
- for (i = 1; i <= SIGNS; i++)
- house[i] = Mod(Asc-30.0+30.0*(real)i);
- }
-
- void HouseCampanus()
- {
- real KO, DN;
- int i;
-
- for (i = 1; i <= SIGNS; i++) {
- KO = DTOR(60.000001+30.0*(real)i);
- DN = ATAN(tan(KO)*cos(AA));
- if (DN < 0.0)
- DN += PI;
- if (sin(KO) < 0.0)
- DN += PI;
- X = Angle(cos(RA+DN)*cos(OB)-sin(DN)*tan(AA)*sin(OB), sin(RA+DN));
- house[i] = Mod(RTOD(X)+SD);
- }
- }
-
- void HouseMeridian()
- {
- int i;
-
- for (i = 1; i <= SIGNS; i++) {
- D = DTOR(60.0+30.0*(real)i);
- X = Angle(cos(RA+D)*cos(OB), sin(RA+D));
- house[i] = Mod(RTOD(X)+SD);
- }
- }
-
- void HouseRegiomontanus()
- {
- int i;
-
- for (i = 1; i <= SIGNS; i++) {
- D = DTOR(60.0+30.0*(real)i);
- X = Angle(cos(RA+D)*cos(OB)-sin(D)*tan(AA)*sin(OB), sin(RA+D));
- house[i] = Mod(RTOD(X)+SD);
- }
- }
-
- void HousePorphyry()
- {
- int i;
-
- X = Asc-MC;
- if (X < 0.0)
- X += DEGREES;
- Y = X/3.0;
- for (i = 1; i <= 2; i++)
- house[i+4] = Mod(DEGHALF+MC+i*Y);
- X = Mod(DEGHALF+MC)-Asc;
- if (X < 0.0)
- X += DEGREES;
- house[1]=Asc;
- Y = X/3.0;
- for (i = 1; i <= 3; i++)
- house[i+1] = Mod(Asc+i*Y);
- for (i = 1; i <= 6; i++)
- house[i+6] = Mod(house[i]+DEGHALF);
- }
-
- void HouseMorinus()
- {
- int i;
-
- for (i = 1; i <= SIGNS; i++) {
- D = DTOR(60.0+30.0*(real)i);
- X = Angle(cos(RA+D), sin(RA+D)*cos(OB));
- house[i] = Mod(RTOD(X)+SD);
- }
- }
-
- real CuspTopocentric(deg)
- real deg;
- {
- real OA, X, LO;
-
- OA = Mod(RA+DTOR(deg));
- X = ATAN(tan(AA)/cos(OA));
- LO = ATAN(cos(X)*tan(OA)/cos(X+OB));
- if (LO < 0.0)
- LO += PI;
- if (sin(OA) < 0.0)
- LO += PI;
- return LO;
- }
-
- void HouseTopocentric()
- {
- real TL, P1, P2, LT;
- int i;
-
- modulus = 2.0*PI;
- house[4] = Mod(DTOR(MC+DEGHALF-SD));
- TL = tan(AA); P1 = ATAN(TL/3.0); P2 = ATAN(TL/1.5); LT = AA;
- AA = P1; house[5] = CuspTopocentric(30.0) + PI;
- AA = P2; house[6] = CuspTopocentric(60.0) + PI;
- AA = LT; house[1] = CuspTopocentric(90.0);
- AA = P2; house[2] = CuspTopocentric(120.0);
- AA = P1; house[3] = CuspTopocentric(150.0);
- AA = LT; modulus = DEGREES;
- for (i = 1; i <= 6; i++) {
- house[i] = Mod(RTOD(house[i])+SD);
- house[i+6] = Mod(house[i]+DEGHALF);
- }
- }
- #endif /* MATRIX */
-
- /* In "null" houses, the cusps are always fixed to start at their */
- /* corresponding sign, i.e. the 1st house is always at 0 degrees Aries, etc. */
-
- void HouseNull()
- {
- int i;
-
- for (i = 1; i <= SIGNS; i++)
- house[i] = Mod(STOZ(i)+SD);
- }
-
-
- /* Calculate the house cusp positions, using the specified algorithm. */
-
- void ComputeHouses(housesystem)
- int housesystem;
- {
- char string[STRING];
-
- if (dabs(AA) > DTOR(DEGQUAD-TROPIC) && housesystem == 0) {
- sprintf(string,
- "The %s system of houses is not defined at extreme latitudes.",
- systemname[housesystem]);
- PrintError(string);
- Terminate(_FATAL);
- }
- switch (housesystem) {
- case 1: HouseKoch(); break;
- case 2: HouseEqual(); break;
- case 3: HouseCampanus(); break;
- case 4: HouseMeridian(); break;
- case 5: HouseRegiomontanus(); break;
- case 6: HousePorphyry(); break;
- case 7: HouseMorinus(); break;
- case 8: HouseTopocentric(); break;
- case 9: HouseNull(); break;
- default: HousePlacidus();
- }
- }
-
-
- #ifdef MATRIX
- /*
- ******************************************************************************
- ** Planetary Position Calculations.
- ******************************************************************************
- */
-
- /* Read the next three values from the planet data stream, and return them */
- /* combined as the coefficients of a quadratic equation in the chart time. */
-
- real ReadThree()
- {
- real S1, S2;
-
- S0 = ReadPlanetData(); S1 = ReadPlanetData();
- S2 = ReadPlanetData();
- return S0 = DTOR(S0+S1*T+S2*T*T);
- }
-
-
- /* Another coordinate transformation. This is used by the ComputePlanets() */
- /* procedure to rotate rectangular coordinates by a certain amount. */
-
- void RecToSph2(AP, AN, IN)
- real AP, AN, IN;
- {
- RecToPol(X, Y, &A, &R); A += AP; PolToRec(A, R, &X, &Y);
- D = X; X = Y; Y = 0.0; RecToPol(X, Y, &A, &R);
- A += IN; PolToRec(A, R, &X, &Y);
- G = Y; Y = X; X = D; RecToPol(X, Y, &A, &R); A += AN;
- if (A < 0.0)
- A += 2.0*PI;
- PolToRec(A, R, &X, &Y);
- }
-
-
- /* Calculate some harmonic delta error correction factors to add onto the */
- /* coordinates of Jupiter through Pluto, for better accuracy. */
-
- void ErrorCorrect(ind, x, y, z)
- int ind;
- real *x, *y, *z;
- {
- real U, V, W, T0[4];
- int IK, IJ, errorindex;
-
- errorindex = errorcount[ind];
- for (IK = 1; IK <= 3; IK++) {
- if (ind == 6 && IK == 3) {
- T0[3] = 0.0;
- break;
- }
- if (IK == 3)
- errorindex--;
- ReadThree(); A = 0.0;
- for (IJ = 1; IJ <= errorindex; IJ++) {
- U = ReadPlanetData(); V = ReadPlanetData();
- W = ReadPlanetData();
- A = A+DTOR(U)*cos((V*T+W)*PI/DEGHALF);
- }
- T0[IK] = RTOD(S0+A);
- }
- *x += T0[2]; *y += T0[1]; *z += T0[3];
- }
-
-
- /* Another subprocedure of the ComputePlanets() routine. Convert the final */
- /* rectangular coordinates of a planet to zodiac position and declination. */
-
- void ProcessPlanet(ind, aber)
- int ind;
- real aber;
- {
- real ang, rad;
-
- RecToPol(spacex[ind], spacey[ind], &ang, &rad);
- planet[ind] = Mod(RTOD(ang)+NU-aber+SD);
- RecToPol(rad, spacez[ind], &ang, &rad);
- if (centerplanet == _SUN && ind == _SUN)
- ang = 0.0;
- planetalt[ind] = RTOD(ang);
- }
-
-
- /* This is probably the heart of the whole program of Astrolog. Calculate */
- /* the position of each body that orbits the Sun. A heliocentric chart is */
- /* most natural; extra calculation is needed to have other central bodies. */
-
- void ComputePlanets()
- {
- real helio[BASE+1], helioalt[BASE+1], helioret[BASE+1],
- heliox[BASE+1], helioy[BASE+1], helioz[BASE+1];
- real aber = 0.0, AU, E, EA, E1, XW, YW, AP, AN, IN, XS, YS, ZS;
- int ind = 1, i;
-
- datapointer = planetdata;
- while (ind <= (operation & DASHu ? BASE : PLANETS+1)) {
- modulus = 2.0*PI;
- EA = M = Mod(ReadThree()); /* Calculate mean anomaly */
- E = RTOD(ReadThree()); /* Calculate eccentricity */
- for (i = 1; i <= 5; i++)
- EA = M+E*sin(EA); /* Solve Kepler's equation */
- AU = ReadPlanetData(); /* Semi-major axis */
- E1 = 0.01720209/(pow(AU, 1.5)*
- (1.0-E*cos(EA))); /* Begin velocity coordinates */
- XW = -AU*E1*sin(EA); /* Perifocal coordinates */
- YW = AU*E1*pow(1.0-E*E,0.5)*cos(EA);
- AP = ReadThree(); AN = ReadThree();
- IN = ReadThree(); /* Calculate inclination */
- X = XW; Y = YW; RecToSph2(AP, AN, IN); /* Rotate velocity coordinates */
- heliox[ind] = X; helioy[ind] = Y;
- helioz[ind] = G; /* Helio ecliptic rectangtular */
- modulus = DEGREES;
- X = AU*(cos(EA)-E); /* Perifocal coordinates for */
- Y = AU*sin(EA)*pow(1.0-E*E,0.5); /* rectangular position coordinates */
- RecToSph2(AP, AN, IN); /* Rotate for rectangular */
- XS = X; YS = Y; ZS = G; /* position coordinates */
- if (ind >= _JUP && ind <= _PLU)
- ErrorCorrect(ind, &XS, &YS, &ZS);
- ret[ind] = /* Helio daily motion */
- (XS*helioy[ind]-YS*heliox[ind])/(XS*XS+YS*YS);
- spacex[ind] = XS; spacey[ind] = YS; spacez[ind] = ZS;
- ProcessPlanet(ind, 0.0);
- ind += (ind == 1 ? 2 : (ind != PLANETS+1 ? 1 : 10));
- }
- spacex[0] = spacey[0] = spacez[0] = 0.0;
-
- if (!centerplanet) {
- if (exdisplay & DASHv0)
- for (i = 0; i <= BASE; i++) /* Use relative velocity */
- ret[i] = DTOR(1.0); /* if -v0 is in effect */
- return;
- }
- #endif /* MATRIX */
-
- /* A second loop is needed for geocentric charts or central bodies other */
- /* than the Sun. For example, we can't find the position of Mercury in */
- /* relation to Pluto until we know the position of Pluto in relation to */
- /* the Sun, and since Mercury is calculated first, another pass needed. */
-
- ind = centerplanet;
- for (i = 0; i <= BASE; i++) {
- helio[i] = planet[i];
- helioalt[i] = planetalt[i];
- helioret[i] = ret[i];
- if (i != _MOO && i != ind) {
- spacex[i] -= spacex[ind];
- spacey[i] -= spacey[ind];
- spacez[i] -= spacez[ind];
- }
- }
- spacex[ind] = spacey[ind] = spacez[ind] = 0.0;
- SwapReal(&spacex[0], &spacex[ind]);
- SwapReal(&spacey[0], &spacey[ind]); /* Do some swapping - we want */
- SwapReal(&spacez[0], &spacez[ind]); /* the central body to be in */
- SwapReal(&spacex[1], &spacex[ind]); /* object position number zero. */
- SwapReal(&spacey[1], &spacey[ind]);
- SwapReal(&spacez[1], &spacez[ind]);
- for (i = 1; i <= (operation & DASHu ? BASE : PLANETS+1);
- i += (i == 1 ? 2 : (i != PLANETS+1 ? 1 : 10))) {
- XS = spacex[i]; YS = spacey[i]; ZS = spacez[i];
- if (ind != _SUN || i != _SUN)
- ret[i] = (XS*(helioy[i]-helioy[ind])-YS*(heliox[i]-heliox[ind]))/
- (XS*XS+YS*YS);
- if (ind == _SUN)
- aber = 0.0057756*sqrt(XS*XS+YS*YS+ZS*ZS)*RTOD(ret[i]); /* Aberration */
- ProcessPlanet(i, aber);
- if (exdisplay & DASHv0) /* Use relative velocity */
- ret[i] = DTOR(ret[i]/helioret[i]); /* if -v0 is in effect */
- }
- }
-
-
- #ifdef MATRIX
- /*
- ******************************************************************************
- ** Lunar Position Calculations
- ******************************************************************************
- */
-
- /* Calculate the position and declination of the Moon, and the Moon's North */
- /* Node. This has to be done separately from the other planets, because they */
- /* all orbit the Sun, while the Moon orbits the Earth. */
-
- void ComputeLunar(moonlo, moonla, nodelo, nodela)
- real *moonlo, *moonla, *nodelo, *nodela;
- {
- real LL, G, N, G1, D, L, ML, L1, MB, T1, M = 3600.0;
-
- LL = 973563.0+1732564379.0*T-4.0*T*T; /* Compute mean lunar longitude */
- G = 1012395.0+6189.0*T; /* Sun's mean longitude of perigee */
- N = 933060.0-6962911.0*T+7.5*T*T; /* Compute mean lunar node */
- G1 = 1203586.0+14648523.0*T-37.0*T*T; /* Mean longitude of lunar perigee */
- D = 1262655.0+1602961611.0*T-5.0*T*T; /* Mean elongation of Moon from Sun */
- L = (LL-G1)/M; L1 = ((LL-D)-G)/M; /* Some auxiliary angles */
- T1 = (LL-N)/M; D = D/M; Y = 2.0*D;
-
- /* Compute Moon's perturbations. */
-
- ML = 22639.6*SIND(L)-4586.4*SIND(L-Y)+2369.9*SIND(Y)+769.0*SIND(2.0*L)-
- 669.0*SIND(L1)-411.6*SIND(2.0*T1)-212.0*SIND(2.0*L-Y)-206.0*SIND(L+L1-Y);
- ML += 192.0*SIND(L+Y)-165.0*SIND(L1-Y)+148.0*SIND(L-L1)-125.0*SIND(D)-110.0*
- SIND(L+L1)-55.0*SIND(2.0*T1-Y)-45.0*SIND(L+2.0*T1)+40.0*SIND(L-2.0*T1);
-
- *moonlo = G = Mod((LL+ML)/M+SD); /* Lunar longitude */
-
- /* Compute lunar latitude. */
-
- MB = 18461.5*SIND(T1)+1010.0*SIND(L+T1)-999.0*SIND(T1-L)-624.0*SIND(T1-Y)+
- 199.0*SIND(T1+Y-L)-167.0*SIND(L+T1-Y);
- MB += 117.0*SIND(T1+Y)+62.0*SIND(2.0*L+T1)-
- 33.0*SIND(T1-Y-L)-32.0*SIND(T1-2.0*L)-30.0*SIND(L1+T1-Y);
- *moonla = MB =
- Sgn(MB)*((dabs(MB)/M)/DEGREES-floor((dabs(MB)/M)/DEGREES))*DEGREES;
-
- /* Compute position of the north node. One can compute the true North */
- /* Node here if they like, but the Mean Node seems to be the one used */
- /* in astrology, so that's the one Astrolog returns by default. */
-
- #ifdef TRUENODE
- N = N+5392.0*SIND(2.0*T1-Y)-541.0*SIND(L1)-442.0*SIND(Y)+423.0*SIND(2.0*T1)-
- 291.0*SIND(2.0*L-2.0*T1);
- #endif
- *nodelo = Mod(N/M+SD);
- *nodela = 0.0;
- }
- #endif /* MATRIX */
-
-
- /*
- ******************************************************************************
- ** Star Position Calculations
- ******************************************************************************
- */
-
- /* This is used by the chart calculation routine to calculate the positions */
- /* of the fixed stars. Since the stars don't move in the sky over time, */
- /* getting their positions is mostly just reading info from an array and */
- /* converting it to the correct reference frame. However, we have to add */
- /* in the correct precession for the tropical zodiac, and sort the final */
- /* index list based on what order the stars are supposed to be printed in. */
-
- void ComputeStars(SD)
- real SD;
- {
- int i, j;
- real x, y, z;
-
- /* Read in star positions. */
-
- for (i = 1; i <= STARS; i++) {
- x = stardata[i*6-6]; y = stardata[i*6-5]; z = stardata[i*6-4];
- planet[BASE+i] = DTOR(x*DEGREES/24.0+y*15.0/60.0+z*0.25/60.0);
- x = stardata[i*6-3]; y = stardata[i*6-2]; z = stardata[i*6-1];
- planetalt[BASE+i] = DTOR(x+y/60.0+z/60.0/60.0);
- EquToEcl(&planet[BASE+i], &planetalt[BASE+i]); /* Convert to */
- planet[BASE+i] = Mod(RTOD(planet[BASE+i])+SD2000+SD); /* ecliptic. */
- planetalt[BASE+i] = RTOD(planetalt[BASE+i]);
- starname[i] = i;
- }
-
- /* Sort the index list if -Uz, -Ul, -Un, or -Ub switch in effect. */
-
- if (universe > 1) for (i = 2; i <= STARS; i++) {
- j = i-1;
-
- /* Compare star names for -Un switch. */
-
- if (universe == 'n') while (j > 0 && StringCmp(
- objectname[BASE+starname[j]], objectname[BASE+starname[j+1]]) > 0) {
- SWAP(starname[j], starname[j+1]);
- j--;
-
- /* Compare star brightnesses for -Ub switch. */
-
- } else if (universe == 'b') while (j > 0 &&
- starbright[starname[j]] > starbright[starname[j+1]]) {
- SWAP(starname[j], starname[j+1]);
- j--;
-
- /* Compare star zodiac locations for -Uz switch. */
-
- } else if (universe == 'z') while (j > 0 &&
- planet[BASE+starname[j]] > planet[BASE+starname[j+1]]) {
- SWAP(starname[j], starname[j+1]);
- j--;
-
- /* Compare star declinations for -Ul switch. */
-
- } else if (universe == 'l') while (j > 0 &&
- planetalt[BASE+starname[j]] < planetalt[BASE+starname[j+1]]) {
- SWAP(starname[j], starname[j+1]);
- j--;
- }
- }
- }
-
-
- /*
- ******************************************************************************
- ** Chart Calculation.
- ******************************************************************************
- */
-
- #ifdef PLACALC
- /* Compute the positions of the planets at a certain time using the Placalc */
- /* accurate formulas and ephemeris. This will superseed the Matrix routine */
- /* values and is only called with the -b switch is in effect. Not all */
- /* objects or modes are available using this, but some additional values */
- /* such as Moon and Node velocities not available without -b are. (This is */
- /* the one place in Astrolog which calls the Placalc package functions.) */
-
- void ComputePlacalc(t)
- real t;
- {
- int i;
- real r1, r2, r3, r4, r;
-
- /* We can compute the positions of Sun through Pluto, Chiron, and the */
- /* North Node using Placalc. The other object must be done elsewhere. */
-
- for (i = _SUN; i <= _NOD; i++) if (i <= _CHI || i >= _NOD) {
- if (PlacalcPlanet(i, t*36525.0+2415020.0, centerplanet != _SUN,
- &r1, &r2, &r3, &r4)) {
-
- /* Note that this can't compute charts with central planets other */
- /* than the Sun or Earth or relative velocities in current state. */
-
- planet[i] = Mod(r1 + SD);
- planetalt[i] = r2;
- ret[i] = DTOR(r3);
-
- /* Compute x,y,z coordinates from azimuth, altitude, and distance. */
-
- spacez[i] = r4*SIND(planetalt[i]);
- r = r4*COSD(planetalt[i]);
- spacex[i] = r*COSD(planet[i]);
- spacey[i] = r*SIND(planet[i]);
- }
- }
- }
- #endif
-
-
- /* This is probably the main routine in all of Astrolog. It generates a */
- /* chart, calculating the positions of all the celestial bodies and house */
- /* cusps, based on the current chart information, and saves them for use */
- /* by any of the display routines. */
-
- real CastChart(var)
- int var;
- {
- int i, k;
- real housetemp[SIGNS+1], Off = 0.0, j;
-
- if (MM == -1) {
-
- /* Hack: If month is negative, then we know chart was read in through a */
- /* -o0 position file, so the planet positions are already in the arrays. */
-
- MC = planet[_MC]; Asc = planet[_ASC]; Vtx = planet[_VTX];
- } else {
- Off = ProcessInput(var);
- ComputeVariables();
- if (operation & DASHG) /* Check for -G geodetic chart. */
- RA = DTOR(Mod(-OO));
- MC = CuspMidheaven(); /* Calculate our Ascendant & Midheaven. */
- Asc = CuspAscendant();
- ComputeHouses(housesystem); /* Go calculate house cusps. */
- for (i = 1; i <= total; i++)
- ret[i] = 1.0; /* Assume direct until we say otherwise. */
-
- /* Go calculate planet, Moon, and North Node positions. */
-
- ComputePlanets();
- ComputeLunar(&planet[_MOO], &planetalt[_MOO],
- &planet[_NOD], &planetalt[_NOD]);
- ret[_NOD] = -1.0;
-
- /* Compute more accurate ephemeris positions for certain objects. */
-
- #ifdef PLACALC
- if (placalc)
- ComputePlacalc(T);
- #endif
-
- /* Calculate position of Part of Fortune. */
-
- j = planet[_MOO]-planet[_SUN];
- j = dabs(j) < DEGQUAD ? j : j - Sgn(j)*DEGREES;
- planet[_FOR] = Mod(j+Asc);
-
- /* Fill in "planet" positions corresponding to house cusps. */
-
- planet[_MC] = MC; planet[_ASC] = Asc; planet[_VTX] = Vtx;
- planet[C_LO] = house[11]; planet[C_LO+1] = house[12];
- planet[C_LO+2] = house[2]; planet[C_LO+3] = house[3];
- }
-
- /* Go calculate star positions if -U switch in effect. */
-
- if (universe)
- ComputeStars(operation & DASHs ? 0.0 : -Off);
-
- /* Now, we may have to modify the base positions we calculated above based */
- /* on what type of chart we are generating. */
-
- if (operation & DASHp0) { /* Are we doing a -p0 solar arc chart? */
- for (i = 1; i <= total; i++)
- planet[i] = Mod(planet[i] + (Jdp - JD) / progday);
- for (i = 1; i <= SIGNS; i++)
- house[i] = Mod(house[i] + (Jdp - JD) / progday);
- }
- if (multiplyfactor > 1) /* Are we doing a -x harmonic chart? */
- for (i = 1; i <= total; i++)
- planet[i] = Mod(planet[i] * (real)multiplyfactor);
- if (onasc) {
- if (onasc > 0) /* Is -1 put on Ascendant in effect? */
- j = planet[onasc]-Asc;
- else /* Or -2 put object on Midheaven switch? */
- j = planet[-onasc]-MC;
- for (i = 1; i <= SIGNS; i++) /* If so, rotate the houses accordingly. */
- house[i] = Mod(house[i]+j);
- }
-
- /* Check to see if we are -F forcing any objects to be particular values. */
-
- for (i = 1; i <= total; i++)
- if (force[i] != 0.0) {
- planet[i] = force[i]-DEGREES;
- planetalt[i] = ret[i] = 0.0;
- }
- HousePlace(); /* Figure out what house everything falls in. */
-
- /* If -f domal chart switch in effect, switch planet and house positions. */
-
- if (operation & DASHf) {
- for (i = 1; i <= total; i++) {
- k = inhouse[i];
- inhouse[i] = ZTOS(planet[i]);
- planet[i] = STOZ(k)+MinDistance(house[k], planet[i]) /
- MinDistance(house[k], house[Mod12(k+1)])*30.0;
- }
- for (i = 1; i <= SIGNS; i++) {
- k = HousePlaceIn(STOZ(i));
- housetemp[i] = STOZ(k)+MinDistance(house[k], STOZ(i)) /
- MinDistance(house[k], house[Mod12(k+1)])*30.0;
- }
- for (i = 1; i <= SIGNS; i++)
- house[i] = housetemp[i];
- }
-
- /* If -3 decan chart switch in effect, edit planet positions accordingly. */
-
- if (operation & DASH3)
- for (i = 1; i <= total; i++) {
- k = ZTOS(planet[i]);
- j = planet[i] - STOZ(k);
- k = Mod12(k + 4*((int)floor(j/10.0)));
- j = (j - floor(j/10.0)*10.0)*3.0;
- planet[i] = STOZ(k)+j;
- HousePlace();
- }
- return T;
- }
-
- /* formulas.c */
-