home *** CD-ROM | disk | FTP | other *** search
- /*
- ** Astrolog (Version 4.00) File: placalc.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 "placalc.h"
-
- #ifdef PLACALC
- #ifdef ASTROLOG
- /* Begin contents of placalc.c */
- #endif
- /*****************************************************
- $Header: placalc.c,v 1.14 93/07/19 22:13:07 alois Exp $
-
-
- ---------------------------------------------------------------
- | Copyright Astrodienst AG and Alois Treindl, 1989,1991,1993 |
- | The use of this source code is subject to regulations made |
- | by Astrodienst Zurich. The code is NOT in the public domain.|
- | |
- | This copyright notice must not be changed or removed |
- | by any user of this program. |
- ---------------------------------------------------------------
-
- Important changes:
- 11-jun-93 revision 1.12: fixed error which affected Mercury between -2100 and
- -3100 (it jumped wildly).
-
- *******************************************************/
-
- #ifndef ASTROLOG
- #include "placalc.h" /* includes ourdef.h */
- #include "astrolib.h" /* includes ourdef.h */
- #include "helconst.c" /* orbital elements and disturbations
- for inner planets and moon */
- #include "deltat.c"
- #else /* ASTROLOG */
- #ifdef ASTROLOG
- /* Begin contents of helconst.c */
- #endif
- /***********************************************************
- * $Header$
-
- definition module for planetary elements
- and disturbation coefficients
- version HP-UX C for new version with stored outer planets
- 31-jul-88
- by Alois Treindl
-
- ---------------------------------------------------------------
- | Copyright Astrodienst Zurich AG and Alois Treindl, 1989. |
- | The use of this source code is subject to regulations made |
- | by Astrodienst Zurich. The code is NOT in the public domain.|
- | |
- | This copyright notice must not be changed or removed |
- | by any user of this program. |
- ---------------------------------------------------------------
-
- ***********************************************************/
- /* In the elements degrees were kept as the units for the constants. This
- requires conversion to radians, when the actual calculations are performed.
- This approach is not the most efficient, but safer for development.
- Constant conversion could be done by writing all degree constants with
- value * DEGTORAD */
-
- # define TIDAL_26 TRUE /* decide wheter to use new or old lunar tidal
- term; a consistent system of delta t must be
- used */
- # define MOON_TEST_CORR FALSE /* to include more lunar terms in longitude */
-
- REAL8 ekld [4] = { 23.452294, -46.845, -.0059, 0.00181 };
- /* ecliptic with epoch1900, Ekd(0..3) in basic */
- struct eledata {
- REAL8 axis, /* mean distance, in a.u., A(N) in basic */
- period, /* days for one revolution, P(N) in basic */
- epoch, /* relative juldate of epoch, Ep(N) in basic */
- /* T = distance to epoch in jul.centuries 36525 day*/
- lg0,lg1,lg2,lg3,/* deg(epoch), degree/day, seconds/T^2,seconds/T^3 */
- /* Pd(N,0..2) in basic, lg3 was not present */
- pe0,pe1,pe2,pe3,/* deg(epoch), seconds/T, seconds/T^2,seconds/T^3 */
- /* Pd(N,3..5) in basic, pe3 was not present */
- ex0,ex1,ex2, /* ecl(epoch), 1/T, 1/T^2 */
- /* Pd(N,6..8) in basic */
- kn0,kn1,kn2,kn3,/* node(epoch),seconds/T, seconds/T^2,seconds/T^3 */
- /* Pd(N,9..11) in basic, kn3 was not present */
- in0,in1,in2; /* incl(epoch),1/T, 1/T^2 */
- /* Pd(N,12..14) in basic */
- } pd [MARS + 1] = {
- {/*earth*/ 1.00000023, 365.25636042, EPOCH1900,
- 99.696678, .9856473354, 1.089, 0,
- 101.220833, 6189.03, 1.63, 0.012,
- 0.01675104, -0.00004180, -0.000000126,
- 0, 0, 0, 0,
- 0, 0, 0},
- /* note 29 June 88 by Alois: G.M.Clemence, Astronomical Journal
- vol.53,p. 178 (1948) gives a correction to the perihel motion
- of -4.78" T, giving 6184.25 for the linear Term above. We have
- not yet applied this correction. It has been used in APAE 22,4
- on the motion of mars and does make an official impression. */
- {/*moon*/ 0.0025955307, 27.321661, EPOCH1900,
- # if ! TIDAL_26
- /* values from Improved Lunar Ephemeris, corresponding to tidal
- term -22.44"/cy and consistent with delta t ~ 29.949 T*T
- */
- 270.4341638, 13.176396526808121, -4.08, 0.0068,
- # endif
- # if TIDAL_26
- /* new values from Morrison 1979, with tidal term -26"/cy as
- stated in A.E. 1986 onwards, consistent with delta t ~ 44.3 T*T
- correction: -1.54" + 2.33" T - 1.78" T*T
- */
- 270.4337361, 13.176396544528099, -5.86, 0.0068,
- # endif
- 334.329556, 14648522.52, -37.17, -0.045,
- 0.054900489, 0, 0,
- 259.183275, -6962911.23, 7.48 , 0.008,
- 5.145388889, 0, 0},
- {/*mercury*/ .3870986, 87.969252, EPOCH1900,
- 178.179078, 4.0923770233, 1.084, 0,
- 75.89969722, 5599.76, 1.061, 0,
- 0.20561421, .00002046, -.000000030,
- 47.145944444, 4266.75, .626, 0,
- 7.0028805555, 6.699, -.066},
- {/*venus*/ .72333162, 224.700726, EPOCH1900,
- 342.767053, 1.6021687039, 1.1148, 0,
- 130.16383333, 5068.93, -3.515, 0,
- 0.00682069, -.00004774, .000000091,
- 75.7796472223,3239.46, 1.476, 0,
- 3.3936305555, 3.621, .0035},
- {/*mars*/ 1.5236914620, 686.9296097, EPOCH1900,
- /* These are the corrected elements by Ross */
- 293.74762778, .524071163814, 1.1184, 0,
- 334.21820278, 6626.73, .4675, -0.0043,
- 0.09331290, .000092064, -.000000077,
- 48.786441667, 2775.57, -.005, -0.0192,
- 1.85033333, -2.430, .0454}
- };
-
- /*
- * mimimum and maximum distances computed over 1000 years with plamimax,
- * required for relative distances rgeo, where the distance is given
- * as 100 when a planet is closest and as 0 when farthest from earth.
- */
- REAL8 rmima[CALC_N][2] = {
- { 0.98296342, 1.01704665},
- { 0.00238267, 0.00271861},
- { 0.54900496, 1.45169607},
- { 0.26411287, 1.73597885},
- { 0.37289847, 2.67626927},
- { 3.94877993, 6.45627627},
- { 7.99362824, 11.09276636},
- {17.28622633, 21.10714104},
- {28.81374786, 31.33507284},
- {28.67716748, 50.29208774},
- { 0.00, 0.00259553}, /* nodes don't get a real value*/
- { 0.00, 0.00259553},
- { 7.36277475, 19.86585062}};
-
-
-
- #define SDNUM 20
- struct sdat { /* 0..19 mean anomalies of disturbing planets
- Sd(0..19,0..1) in basic */
- REAL8 sd0, /* mean anomaly at epoch 1850 */
- sd1; /* degrees/year */
- } sd [SDNUM] = {
- 114.50, 585.17493,
- 109.856, 191.39977,
- 148.031, 30.34583,
- 284.716, 12.21794,
- 114.508, 585.17656,
- -0.56, 359.99213,
- 148.03, 30.34743,
- 284.72, 12.2196,
- 248.07, 1494.726615,
- 359.44, 359.993595,
- 109.86, 191.402867,
- 148.02, 30.348930,
- 114.503, 585.173715,
- 359.444, 359.989285,
- 148.021, 30.344620,
- 284.716, 12.21669,
- 148.0315, 30.34906264,
- 284.7158, 12.22117085,
- 220.1695, 4.284931111,
- 291.8024, 2.184704167
- };
-
- REAL8 sa [SDNUM];
-
- struct kor {
- int j, i;
- REAL8 lampl; /* amplitude of disturbation in long, seconds of arc */
- REAL8 lphase; /* phase of disturbation in long, degrees */
- INT4 rampl; /* ampl. of disturbation in radius, 9th place of log */
- REAL8 rphase; /* phase of disturbation in radius, degrees */
- int k; /* index into disturbing planet anomaly table sa[] */
- };
- /* delta long = lampl * COS (lphase - arg) in seconds of arc
- delta rad = rampl * COS (rphase - arg) in ninth place of log
- arg = j * sa (k) + i * ma (this planet)
- ma = mean anomaly
- sa = mean anomaly of disturbing planet, where this
- is taken from the aproximate value in sa[]
- For the COS (phase - arg) it is good enough to compute
- with 32 bit reals, because ampl and phase have only
- four to five significant digits.
- While saving constant space, it is costing execution time due
- to float/double conversions.
- */
- /* In basic, all correction terms for sun, mercury, venus and mars
- were contained in one array K(0..142,0..6); Nk(N,0) contained
- the index of the first term of planet N and Nk(N,1) the number
- of terms for this planet. Here, we use a 0 in the first column
- kor.j to indicate the end of the table for a planet.
- K(*) was a basic INTEGER array, therefore the amplitudes and phases
- had to be expressed as
- K(i,2) = ampl. of longitude in 0.001 seconds of arc
- K(i,3) = phase of longitude in 0.01 degrees
- K(i,4) = ampl. of radius in 9th place of log
- K(i,5) = phase of radius in 0.01 degrees.
- Here we have converted the amplitude of long. to seconds of arc
- and the phases to degrees.
- */
-
- struct kor earthkor[] = { /* 11-jul-88 all terms to 0.020" longitude */
- /* j i lampl lphase rampl rphase k */
- -1, 1, 0.013, 243, 28, 335, 8, /* mercury */
- -1, 3, 0.015, 357, 18, 267, 8,
- -1, 4, 0.023, 326, 5, 239, 8,
- -1, 0, 0.075, 296.6, 94, 205.0, 0, /* Venus */
- -1, 1, 4.838, 299.10, 2359, 209.08, 0,
- -1, 2, 0.074, 207.9, 69, 348.5, 0,
- -1, 3, 0.009, 249, 16, 330, 0,
- -2, 1, .116, 148.90, 160, 58.40, 0,
- -2, 2, 5.526, 148.31, 6842, 58.32, 0,
- -2, 3, 2.497, 315.94, 869, 226.70, 0,
- -2, 4, 0.044, 311.4, 52, 38.8, 0,
- -3, 2, 0.013, 176, 21, 90, 0,
- -3, 3, .666, 177.71, 1045, 87.57, 0,
- -3, 4, 1.559, -14.75, 1497, 255.25, 0,
- -3, 5, 1.024, 318.15, 194, 49.50, 0,
- -3, 6, 0.017, 315, 19, 43, 0,
- -4, 4, .210, 206.20, 376, 116.28, 0,
- -4, 5, .144, 195.40, 196, 105.20, 0,
- -4, 6, .152, -16.20, 94, 254.80, 0,
- -5, 5, 0.084, 235.6, 163, 145.4, 0,
- -5, 6, 0.037, 221.8, 59, 132.2, 0,
- -5, 7, .123, 195.30, 141, 105.40, 0,
- -5, 8, .154, -.40, 26, 270.00, 0,
- -6, 6, 0.038, 264.1, 80, 174.3, 0,
- -6, 7, 0.014, 253, 25, 164, 0,
- -6, 8, 0.01, 230, 14, 135, 0,
- -6, 9, 0.014, 12, 12, 284, 0,
- -7, 7, 0.020, 294, 42, 203.5, 0,
- -7, 8, 0.006, 279, 12, 194, 0,
- -8, 8, 0.011, 322, 24, 234, 0,
- -8, 12, 0.042, 259.2, 44, 169.7, 0,
- -8, 14, 0.032, 48.8, 33, 138.7, 0,
- -9, 9, 0.006, 351, 13, 261, 0,
- 1, -1, .273, 217.70, 150, 127.70, 1, /* mars */
- 1, 0, 0.048, 260.3, 28, 347, 1,
- 2, -3, 0.041, 346, 52, 255.4, 1,
- 2, -2, 2.043, 343.89, 2057, 253.83, 1,
- 2, -1, 1.770, 200.40, 151, 295.00, 1,
- 2, 0, 0.028, 148, 31, 234.3, 1,
- 3, -3, .129, 294.20, 168, 203.50, 1,
- 3, -2, .425, -21.12, 215, 249.00, 1,
- 4, -4, 0.034, 71, 49, 339.7, 1,
- 4, -3, .500, 105.18, 478, 15.17, 1,
- 4, -2, .585, -25.94, 105, 65.90, 1,
- 5, -4, 0.085, 54.6, 107, 324.6, 1,
- 5, -3, .204, 100.80, 89, 11.00, 1,
- 6, -5, 0.020, 186, 30, 95.7, 1,
- 6, -4, .154, 227.40, 139, 137.30, 1,
- 6, -3, .101, 96.30, 27, 188.00, 1,
- 7, -5, 0.049, 176.5, 60, 86.2, 1,
- 7, -4, .106, 222.70, 38, 132.90, 1,
- 8, -5, 0.052, 348.9, 45, 259.7, 1,
- 8, -4, 0.021, 215.2, 8, 310, 1,
- 8, -6, 0.010, 307, 15, 217, 1,
- 9, -6, 0.028, 298, 34, 208.1, 1,
- 9, -5, 0.062, 346, 17, 257, 1,
- 10, -6, 0.019, 111, 15, 23, 1,
- 11, -7, 0.017, 59, 20, 330, 1,
- 11, -6, 0.044, 105.9, 9, 21, 1,
- 13, -8, 0.013, 184, 15, 94, 1,
- 13, -7, 0.045, 227.8, 5, 143, 1,
- 15, -9, 0.021, 309, 22, 220, 1,
- 17, -9, 0.026, 113, 0, 0, 1,
- 1, -2, .163, 198.60, 208, 112.00, 2, /* jupiter */
- 1, -1, 7.208, 179.53, 7067, 89.55, 2,
- 1, 0, 2.600, 263.22, 244, -21.40, 2,
- 1, 1, 0.073, 276.3, 80, 6.5, 2,
- 2, -3, 0.069, 80.8, 103, 350.5, 2,
- 2, -2, 2.731, 87.15, 4026, -2.89, 2,
- 2, -1, 1.610, 109.49, 1459, 19.47, 2,
- 2, 0, 0.073, 252.6, 8, 263, 2,
- 3, -3, .164, 170.50, 281, 81.20, 2,
- 3, -2, .556, 82.65, 803, -7.44, 2,
- 3, -1, .210, 98.50, 174, 8.60, 2,
- 4, -4, 0.016, 259, 29, 170, 2,
- 4, -3, 0.044, 168.2, 74, 79.9, 2,
- 4, -2, 0.080, 77.7, 113, 347.7, 2,
- 4, -1, 0.023, 93, 17, 3, 2,
- 5, -2, 0.009, 71, 14, 343, 2,
- 1, -2, 0.011, 105, 15, 11, 3, /* saturn */
- 1, -1, .419, 100.58, 429, 10.60, 3,
- 1, 0, .320, 269.46, 8, -7.00, 3,
- 2, -2, .108, 290.60, 162, 200.60, 3,
- 2, -1, .112, 293.60, 112, 203.10, 3,
- 3, -2, 0.021, 289, 32, 200.1, 3,
- 3, -1, 0.017, 291, 17, 201, 3,
- ENDMARK
- };
-
- struct kor mercurykor[] = {
- 1, -1, .711, 35.47, 491, 305.28, 4,
- 2, -3, .552, 161.15, 712, 71.12, 4,
- 2, -2, 2.100, 161.15, 2370, 71.19, 4,
- 2, -1, 3.724, 160.69, 899, 70.49, 4,
- 2, 0, .729, 159.76, 763, 250.00, 4,
- 3, -3, .431, 105.37, 541, 15.53, 4,
- 3, -2, 1.329, 104.78, 1157, 14.84, 4,
- 3, -1, .539, 278.95, 14, 282.00, 4,
- 4, -2, .484, 226.40, 234, 136.02, 4,
- 5, -4, .685, -10.43, 849, 259.51, 4,
- 5, -3, 2.810, -10.14, 2954, 259.92, 4,
- 5, -2, 7.356, -12.22, 282, 255.43, 4,
- 5, -1, 1.471, -12.30, 1550, 77.75, 4,
- 5, 0, .375, -12.29, 472, 77.70, 4,
- 2, -1, .443, 218.48, 256, 128.36, 5,
- 4, -2, .374, 151.81, 397, 61.63, 5,
- 4, -1, .808, 145.93, 13, 35.00, 5,
- 1, -1, .697, 181.07, 708, 91.38, 6,
- 1, 0, .574, 236.72, 75, 265.40, 6,
- 2, -2, .938, 36.98, 1185, 306.97, 6,
- 2, -1, 3.275, 37.00, 3268, 306.99, 6,
- 2, 0, .499, 31.91, 371, 126.90, 6,
- 3, -1, .353, 25.84, 347, 295.76, 6,
- 2, -1, .380, 239.87, 0, 0, 7,
- ENDMARK
- };
-
- struct kor venuskor[] = {
- -1, 2, .264, -19.20, 175, 251.10, 8,
- -2, 5, .361, 167.68, 55, 77.20, 8,
- 1, -1, 4.889, 119.11, 2246, 29.11, 9,
- 2, -2, 11.261, 148.23, 9772, 58.21, 9,
- 3, -3, 7.128, -2.57, 8271, 267.42, 9,
- 3, -2, 3.446, 135.91, 737, 47.37, 9,
- 4, -4, 1.034, 26.54, 1426, 296.49, 9,
- 4, -3, .677, 165.32, 445, 75.70, 9,
- 5, -5, .330, 56.88, 510, -33.36, 9,
- 5, -4, 1.575, 193.93, 1572, 104.21, 9,
- 5, -3, 1.439, 138.08, 162, 229.90, 9,
- 6, -6, .143, 84.40, 236, -5.80, 9,
- 6, -5, .205, 44.20, 256, 314.20, 9,
- 6, -4, .176, 164.30, 70, 75.70, 9,
- 8, -5, .231, 180.00, 25, 75.00, 9,
- 3, -2, .673, 221.62, 717, 131.60, 10,
- 3, -1, 1.208, 237.57, 29, 149.00, 10,
- 1, -1, 2.966, 208.09, 2991, 118.09, 11,
- 1, 0, 1.563, 268.31, 91, -7.60, 11,
- 2, -2, .889, 145.16, 1335, 55.17, 11,
- 2, -1, .480, 171.01, 464, 80.95, 11,
- 3, -2, .169, 144.20, 250, 54.00, 11,
- ENDMARK
- };
-
- struct kor marskor[] = {
- -1, 1, .115, 65.84, 684, 156.14, 12,
- -1, 2, .623, 246.03, 812, 155.77, 12,
- -1, 3, 6.368, 57.60, 556, -32.06, 12,
- -1, 4, .588, 57.24, 616, 147.28, 12,
- -2, 5, .138, 39.18, 157, 309.39, 12,
- -2, 6, .459, 217.58, 82, 128.10, 12,
- -1, -1, .106, 33.60, 141, 303.45, 13,
- -1, 0, .873, 34.34, 1112, 304.05, 13,
- -1, 1, 8.559, 35.10, 6947, 304.45, 13,
- -1, 2, 13.966, 20.50, 2875, 113.20, 13,
- -1, 3, 1.487, 22.18, 1619, 112.38, 13,
- -1, 4, .175, 22.46, 225, 112.15, 13,
- -2, 2, .150, 18.96, 484, 266.42, 13,
- -2, 3, 7.355, 158.64, 6412, 68.62, 13,
- -2, 4, 4.905, 154.09, 1985, 244.70, 13,
- -2, 5, .489, 154.39, 543, 244.50, 13,
- -3, 3, .216, 111.06, 389, 21.10, 13,
- -3, 4, .355, 110.64, 587, 19.17, 13,
- -3, 5, 2.641, 280.58, 2038, 190.60, 13,
- -3, 6, .970, 276.06, 587, 6.75, 13,
- -3, 7, .100, 276.20, 116, 6.40, 13,
- -4, 5, .152, 232.48, 259, 142.60, 13,
- -4, 6, .264, 230.47, 387, 139.75, 13,
- -4, 7, 1.156, 41.64, 749, 312.67, 13,
- -4, 8, .259, 37.92, 205, 128.80, 13,
- -5, 8, .172, -8.99, 234, 260.70, 13,
- -5, 9, .575, 164.48, 308, 74.60, 13,
- -6, 10, .115, 113.70, 145, 23.53, 13,
- -6, 11, .363, 285.69, 144, 196.00, 13,
- -7, 13, .353, 48.83, 85, 319.10, 13,
- -8, 15, 1.553, 170.14, 110, 81.00, 13,
- -8, 16, .148, 170.74, 154, 259.94, 13,
- -9, 17, .193, 293.70, 23, 22.80, 13,
- 1, -3, .382, 46.48, 521, 316.25, 14,
- 1, -2, 3.144, 46.78, 3894, 316.39, 14,
- 1, -1, 25.384, 48.96, 23116, 318.87, 14,
- 1, 0, 3.732, -17.62, 1525, 117.81, 14,
- 1, 1, .474, -34.60, 531, 59.67, 14,
- 2, -4, .265, 192.88, 396, 103.12, 14,
- 2, -3, 2.108, 192.72, 3042, 102.89, 14,
- 2, -2, 16.035, 191.90, 22144, 101.99, 14,
- 2, -1, 21.869, 188.35, 16624, 98.33, 14,
- 2, 0, 1.461, 189.66, 1478, 279.04, 14,
- 2, 1, .167, 191.04, 224, 280.81, 14,
- 3, -4, .206, 167.11, 338, 76.13, 14,
- 3, -3, 1.309, 168.27, 2141, 76.24, 14,
- 3, -2, 2.607, 228.41, 3437, 139.74, 14,
- 3, -1, 3.174, 207.20, 1915, 115.83, 14,
- 3, 0, .232, 207.78, 240, 298.06, 14,
- 4, -4, .178, 127.25, 322, 36.16, 14,
- 4, -3, .241, 200.69, 389, 110.02, 14,
- 4, -2, .330, 267.57, 413, 179.86, 14,
- 4, -1, .416, 221.88, 184, 128.17, 14,
- 1, -2, .155, -38.20, 191, 231.58, 15,
- 1, -1, 1.351, -34.10, 1345, 235.85, 15,
- 1, 0, .884, 288.05, 111, 39.90, 15,
- 1, 1, .132, 284.88, 144, 15.67, 15,
- 2, -2, .620, 35.15, 869, 305.30, 15,
- 2, -1, 1.768, 32.50, 1661, 302.51, 15,
- 2, 0, .125, 18.73, 103, 119.90, 15,
- 3, -2, .141, 47.59, 199, 318.06, 15,
- 3, -1, .281, 40.95, 248, 310.75, 15,
- ENDMARK
- };
-
- #define NUM_MOON_CORR 93
- /* moon correction data; revised 30-jul-88: all long. to 0.3" */
- struct m45dat {
- int i0,i1,i2,i3;
- REAL8 lng,lat,par;
- } m45 [NUM_MOON_CORR] = {
- /* l, l', F, D, Long, Lat, Par),*/
- { 0, 0, 0, 4, 13.902, 14.06, 0.2607},
- { 0, 0, 0, 2, 2369.912, 2373.36, 28.2333},
- { 1, 0, 0, 4, 1.979, 6.98, 0.0433},
- { 1, 0, 0, 2, 191.953, 192.72, 3.0861},
- { 1, 0, 0, 0, 22639.500, 22609.1, 186.5398},
- { 1, 0, 0, -2, -4586.465, -4578.13, 34.3117},
- { 1, 0, 0, -4, -38.428, -38.64, 0.6008},
- { 1, 0, 0, -6, -0.393, -1.43, 0.0086},
- { 0, 1, 0, 4, -0.289, -1.59, -0.0053},
- { 0, 1, 0, 2, -24.420, -25.10, -0.3000},
- { 0, 1, 0, 0, -668.146, -126.98, -0.3997},
- { 0, 1, 0, -2, -165.145, -165.06, 1.9178},
- { 0, 1, 0, -4, -1.877, -6.46, 0.0339},
- { 0, 0, 0, 3, 0.403, -4.01, 0.0023},
- { 0, 0, 0, 1, -125.154, -112.79, -0.9781},
- { 2, 0, 0, 4, 0.213, 1.02, 0.0054},
- { 2, 0, 0, 2, 14.387, 14.78, 0.2833},
- { 2, 0, 0, 0, 769.016, 767.96, 10.1657},
- { 2, 0, 0, -2, -211.656, -152.53, -0.3039},
- { 2, 0, 0, -4, -30.773, -34.07, 0.3722},
- { 2, 0, 0, -6, -0.570, -1.40, 0.0109},
- { 1, 1, 0, 2, -2.921, -11.75, -0.0484},
- { 1, 1, 0, 0, -109.673, -115.18, -0.9490},
- { 1, 1, 0, -2, -205.962, -182.36, 1.4437},
- { 1, 1, 0, -4, -4.391, -9.66, 0.0673},
- { 1, -1, 0, 4, 0.283, 1.53, 0.0060},
- { 1, -1, 0, 2, 14.577, 31.70, 0.2302},
- { 1, -1, 0, 0, 147.687, 138.76, 1.1528},
- { 1, -1, 0, -2, 28.475, 23.59, -0.2257},
- { 1, -1, 0, -4, 0.636, 2.27, -0.0102},
- { 0, 2, 0, 2, -0.189, -1.68, -0.0028},
- { 0, 2, 0, 0, -7.486, -0.66, -0.0086},
- { 0, 2, 0, -2, -8.096, -16.35, 0.0918},
- { 0, 0, 2, 2, -5.741, -0.04, -0.0009},
- { 0, 0, 2, 0, -411.608, -0.2, -0.0124},
- { 0, 0, 2, -2, -55.173, -52.14, -0.1052},
- { 0, 0, 2, -4, 0.025, -1.67, 0.0031},
- { 1, 0, 0, 1, -8.466, -13.51, -0.1093},
- { 1, 0, 0, -1, 18.609, 3.59, 0.0118},
- { 1, 0, 0, -3, 3.215, 5.44, -0.0386},
- { 0, 1, 0, 1, 18.023, 17.93, 0.1494},
- { 0, 1, 0, -1, 0.560, 0.32, -0.0037},
- { 3, 0, 0, 2, 1.060, 2.96, 0.0243},
- { 3, 0, 0, 0, 36.124, 50.64, 0.6215},
- { 3, 0, 0, -2, -13.193, -16.40, -0.1187},
- { 3, 0, 0, -4, -1.187, -0.74, 0.0074},
- { 3, 0, 0, -6, -0.293, -0.31, 0.0046},
- { 2, 1, 0, 2, -0.290, -1.45, -0.0051},
- { 2, 1, 0, 0, -7.649, -10.56, -0.1038},
- { 2, 1, 0, -2, -8.627, -7.59, -0.0192},
- { 2, 1, 0, -4, -2.740, -2.54, 0.0324},
- { 2, -1, 0, 2, 1.181, 3.32, 0.0213},
- { 2, -1, 0, 0, 9.703, 11.67, 0.1268},
- { 2, -1, 0, -2, -2.494, -1.17, -0.0017},
- { 2, -1, 0, -4, 0.360, 0.20, -0.0043},
- { 1, 2, 0, 0, -1.167, -1.25, -0.0106},
- { 1, 2, 0, -2, -7.412, -6.12, 0.0484},
- { 1, 2, 0, -4, -0.311, -0.65, 0.0044},
- { 1, -2, 0, 2, 0.757, 1.82, 0.0112},
- { 1, -2, 0, 0, 2.580, 2.32, 0.0196},
- { 1, -2, 0, -2, 2.533, 2.40, -0.0212},
- { 0, 3, 0, -2, -0.344, -0.57, 0.0036},
- { 1, 0, 2, 2, -0.992, -0.02, 0},
- { 1, 0, 2, 0, -45.099, -0.02, -0.0010},
- { 1, 0, 2, -2, -0.179, -9.52, -0.0833},
- { 1, 0, -2, 2, -6.382, -3.37, -0.0481},
- { 1, 0, -2, 0, 39.528, 85.13, -0.7136},
- { 1, 0, -2, -2, 9.366, 0.71, -0.0112},
- { 0, 1, 2, 0, 0.415, 0.10, 0.0013},
- { 0, 1, 2, -2, -2.152, -2.26, -0.0066},
- { 0, 1, -2, 2, -1.440, -1.30, 0.0014},
- { 0, 1, -2, -2, 0.384, 0.0, 0.0},
- { 2, 0, 0, 1, -0.586, -1.20, -0.0100},
- { 2, 0, 0, -1, 1.750, 2.01, 0.0155},
- { 2, 0, 0, -3, 1.225, 0.91, -0.0088},
- { 1, 1, 0, 1, 1.267, 1.52, 0.0164},
- { 1, -1, 0, -1, -1.089, 0.55, 0},
- { 0, 0, 2, -1, 0.584, 8.84, 0.0071},
- { 4, 0, 0, 0, 1.938, 3.60, 0.0401},
- { 4, 0, 0, -2, -0.952, -1.58, -0.0130},
- { 3, 1, 0, 0, -0.551, 0.94, -0.0097},
- { 3, 1, 0, -2, -0.482, -0.57, -0.0045},
- { 3, -1, 0, 0, 0.681, 0.96, 0.0115},
- { 2, 0, 2, 0, -3.996, 0, 0.0004},
- { 2, 0, 2, -2, 0.557, -0.75, -0.0090},
- { 2, 0, -2, 2, -0.459, -0.38, -0.0053},
- { 2, 0, -2, 0, -1.298, 0.74, 0.0004},
- { 2, 0, -2, -2, 0.538, 1.14, -0.0141},
- { 1, 1, -2, -2, 0.426, 0.07, -0.0006},
- { 1, -1, 2, 0, -0.304, 0.03, 0.0003},
- { 1, -1, -2, 2, -0.372, -0.19, -0.0027},
- { 0, 0, 4, 0, 0.418, 0, 0},
- { 2, -1, 0, -1, -0.352, -0.37, -0.0028}
- };
-
- # if MOON_TEST_CORR
- /* moon additional correction terms */
- struct m5dat {
- REAL8 lng;
- int i0,i1,i2,i3;
- } m5 [] = {
- /* lng, l, l', F, D, */
- 0.127, 0, 0, 0, 6,
- -0.151, 0, 2, 0, -4,
- -0.085, 0, 0, 2, 4,
- 0.150, 0, 1, 0, 3,
- -0.091, 2, 1, 0, -6,
- -0.103, 0, 3, 0, 0,
- -0.301, 1, 0, 2, -4,
- 0.202, 1, 0, -2, -4,
- 0.137, 1, 1, 0, -1,
- 0.233, 1, 1, 0, -3,
- -0.122, 1, -1, 0, 1,
- -0.276, 1, -1, 0, -3,
- 0.255, 0, 0, 2, 1,
- 0.254, 0, 0, 2, -3,
- -0.100, 3, 1, 0, -4,
- -0.183, 3, -1, 0, -2,
- -0.297, 2, 2, 0, -2,
- -0.161, 2, 2, 0, -4,
- 0.197, 2, -2, 0, 0,
- 0.254, 2, -2, 0, -2,
- -0.250, 1, 3, 0, -2,
- -0.123, 2, 0, 2, 2,
- 0.173, 2, 0, -2, -4,
- 0.263, 1, 1, 2, 0,
- 0.130, 3, 0, 0, -1,
- 0.113, 5, 0, 0, 0,
- 0.092, 3, 0, 2, -2,
- 0, 99, 0, 0, 0 /* end mark */
- };
- # endif /* MOON_TEST_CORR */
- #ifdef ASTROLOG
- /* End contents of helconst.c */
- #endif
- #ifdef ASTROLOG
- /* Begin contents of deltat.c */
- #endif
- /*****************************************************
- $Header: deltat.c,v 1.10 93/01/27 14:37:06 alois Exp $
- deltat.c
- deltat(t): returns delta t (in julian days) from universal time t
- is included by users
- ET = UT + deltat
-
- ---------------------------------------------------------------
- | Copyright Astrodienst Zurich AG and Alois Treindl, 1989. |
- | The use of this source code is subject to regulations made |
- | by Astrodienst Zurich. The code is NOT in the public domain.|
- | |
- | This copyright notice must not be changed or removed |
- | by any user of this program. |
- ---------------------------------------------------------------
-
- ******************************************************/
-
- double deltat (double jd_ad) /* Astrodienst relative julian date */
- {
- double floor();
- static short int dt[] = { /* in centiseconds */
- /* dt from 1637 to 2000, as tabulated in A.E.
- the values 1620 - 1636 are not taken, as they fit
- badly the parabola 25.5 t*t for the next range. The
- best crossing point to switch to the parabola is
- 1637, where we have fitted the value for continuity */
- 6780, 6500, 6300,
- 6200, 6000, 5800, 5700, 5500,
- 5400, 5300, 5100, 5000, 4900,
- 4800, 4700, 4600, 4500, 4400,
- 4300, 4200, 4100, 4000, 3800, /* 1655 - 59 */
- 3700, 3600, 3500, 3400, 3300,
- 3200, 3100, 3000, 2800, 2700,
- 2600, 2500, 2400, 2300, 2200,
- 2100, 2000, 1900, 1800, 1700,
- 1600, 1500, 1400, 1400, 1300,
- 1200, 1200, 1100, 1100, 1000,
- 1000, 1000, 900, 900, 900,
- 900, 900, 900, 900, 900,
- 900, 900, 900, 900, 900, /* 1700 - 1704 */
- 900, 900, 900, 1000, 1000,
- 1000, 1000, 1000, 1000, 1000,
- 1000, 1000, 1100, 1100, 1100,
- 1100, 1100, 1100, 1100, 1100,
- 1100, 1100, 1100, 1100, 1100,
- 1100, 1100, 1100, 1100, 1200, /* 1730 - 1734 */
- 1200, 1200, 1200, 1200, 1200,
- 1200, 1200, 1200, 1200, 1300,
- 1300, 1300, 1300, 1300, 1300,
- 1300, 1400, 1400, 1400, 1400,
- 1400, 1400, 1400, 1500, 1500,
- 1500, 1500, 1500, 1500, 1500, /* 1760 - 1764 */
- 1600, 1600, 1600, 1600, 1600,
- 1600, 1600, 1600, 1600, 1600,
- 1700, 1700, 1700, 1700, 1700,
- 1700, 1700, 1700, 1700, 1700,
- 1700, 1700, 1700, 1700, 1700,
- 1700, 1700, 1600, 1600, 1600, /* 1790 - 1794 */
- 1600, 1500, 1500, 1400, 1400,
- 1370, 1340, 1310, 1290, 1270, /* 1800 - 1804 */
- 1260, 1250, 1250, 1250, 1250,
- 1250, 1250, 1250, 1250, 1250,
- 1250, 1250, 1240, 1230, 1220,
- 1200, 1170, 1140, 1110, 1060,
- 1020, 960, 910, 860, 800,
- 750, 700, 660, 630, 600, /* 1830 - 1834 */
- 580, 570, 560, 560, 560,
- 570, 580, 590, 610, 620,
- 630, 650, 660, 680, 690,
- 710, 720, 730, 740, 750,
- 760, 770, 770, 780, 780,
- 788, 782, 754, 697, 640, /* 1860 - 1864 */
- 602, 541, 410, 292, 182,
- 161, 10, -102, -128, -269,
- -324, -364, -454, -471, -511,
- -540, -542, -520, -546, -546,
- -579, -563, -564, -580, -566,
- -587, -601, -619, -664, -644, /* 1890 - 1894 */
- -647, -609, -576, -466, -374,
- -272, -154, -2, 124, 264,
- 386, 537, 614, 775, 913,
- 1046, 1153, 1336, 1465, 1601,
- 1720, 1824, 1906, 2025, 2095,
- 2116, 2225, 2241, 2303, 2349, /* 1920 - 1924 */
- 2362, 2386, 2449, 2434, 2408,
- 2402, 2400, 2387, 2395, 2386,
- 2393, 2373, 2392, 2396, 2402,
- 2433, 2483, 2530, 2570, 2624,
- 2677, 2728, 2778, 2825, 2871,
- 2915, 2957, 2997, 3036, 3072, /* 1950 - 1954 */
- 3107, 3135, 3168, 3218, 3268,
- 3315, 3359, 3400, 3447, 3503,
- 3573, 3654, 3743, 3829, 3920,
- 4018, 4117, 4223, 4337, 4449,
- 4548, 4646, 4752, 4853, 4959,
- 5054, 5138, 5217, 5296, 5379, /* 1980 - 1984 */
- 5434, 5487, 5532, 5582, 5630, /* 1985 - 89 from AE 1991 */
- 5686, 5757, 5900, 5900, 6000, /* AE 1993 and extrapol */
- 6050, 6100, 6150, 6200, 6250, /* 1995 - 1999 */
- 6300}; /* 2000 */
- double yr, cy, delta;
- long iyr, i;
- yr = (jd_ad + 18262) / 365.25 + 100.0; /* year relative 1800 */
- cy = yr / 100;
- iyr = (long) (floor (yr) + 1800); /* truncated to integer, rel 0 */
- # if TIDAL_26 /* Stephenson formula only when 26" tidal
- term in lunar motion */
- if ( iyr >= 1637 && iyr < 2000 ) {
- i = iyr - 1637;
- delta = dt[i] * 0.01 + (dt[i+1] - dt[i]) * (yr - floor (yr)) * 0.01;
- } else if (iyr >= 2000 ) { /* parabola, fitted at value[2000] */
- delta = 25.5 * cy * cy - 25.5 * 4 + 63.00;
- } else if (iyr >= 948) { /* from 948 - 1637 use parabola */
- delta = 25.5 * cy * cy;
- } else { /* before 984 use other parabola */
- delta = 1361.7 + 320 * cy + 44.3 * cy * cy; /* fits at 948 */
- }
- # else /* use Clemence value + 5 sec before 1690, new dt afterwards */
- cy -= 1; /* epoch 1900 */
- if ( iyr >= 1690 && iyr < 2000 ) {
- i = iyr - 1637;
- delta = dt[i] * 0.01 + (dt[i+1] - dt[i]) * (yr - floor (yr)) * 0.01;
- } else if (iyr >= 2000 ) { /* parabola, fitted at value[2000] */
- delta = 29.949 * cy * cy - 29.949 * 4 + 63.0;
- } else {
- delta = 5 + 24.349 + 72.3165 * cy + 29.949 * cy * cy; /* fits at 1690 */
- }
- # endif
- return (delta / 86400.0);
- }
- #ifdef ASTROLOG
- /* End contents of deltat.c */
- #endif
- #ifdef ASTROLOG
- /* Begin contents of d2l.c */
- #endif
- /*******************************************
- $Header: d2l.c,v 1.9 91/11/16 16:24:20 alois Exp $
- ********************************************/
-
- /*************************************
- double to long with rounding, no overflow check
- *************************************/
- long d2l (double x)
- {
- if (x >=0)
- return ((long) (x + 0.5));
- else
- return (- (long) (0.5 - x));
- }
- #ifdef ASTROLOG
- /* End contents of d2l.c */
- #endif
- #ifdef ASTROLOG
- /* Begin contents of csec.c */
- #endif
- /*
- * $Header$
- *
- * A collection of useful functions for centisec calculations.
-
- ---------------------------------------------------------------
- | Copyright Astrodienst Zurich AG and Alois Treindl, 1991. |
- | The use of this source code is subject to regulations made |
- | by Astrodienst Zurich. The code is NOT in the public domain.|
- | |
- | This copyright notice must not be changed or removed |
- | by any user of this program. |
- ---------------------------------------------------------------
- *******************************************************/
- #ifndef ASTROLOG
- #include "ourdef.h"
- #include "astrolib.h"
- #include "housasp.h"
- #endif
-
- /************************************
- normalize argument into interval [0..DEG360]
- *************************************/
- centisec csnorm(centisec p)
- {
- if (p < 0)
- do { p += DEG360; } while (p < 0);
- else if (p >= DEG360)
- do { p -= DEG360; } while (p >= DEG360);
- return (p);
- }
-
- double degnorm(double p)
- {
- if (p < 0)
- do { p += 360.0; } while (p < 0);
- else if (p >= 360.0)
- do { p -= 360.0; } while (p >= 360.0);
- return (p);
- }
-
- /************************************
- distance in centisecs p1 - p2
- normalized to [0..360[
- **************************************/
- centisec difcsn (centisec p1, centisec p2)
- {
- return (csnorm(p1 - p2));
- }
-
- double difdegn (double p1, double p2)
- {
- return (degnorm(p1 - p2));
- }
-
- /************************************
- distance in centisecs p1 - p2
- normalized to [-180..180[
- **************************************/
- centisec difcs2n (centisec p1, centisec p2)
- { centisec dif;
- dif = csnorm(p1 - p2);
- if (dif >= DEG180) return (dif - DEG360);
- return (dif);
- }
-
- double difdeg2n (double p1, double p2)
- { double dif;
- dif = degnorm(p1 - p2);
- if (dif >= 180.0) return (dif - 360.0);
- return (dif);
- }
-
- /*************************************
- round second, but at 29.5959 always down
- *************************************/
- centisec roundsec(centisec x)
- {
- centisec t;
- t = (x + 50) / 100 *100L; /* round to seconds */
- if (t > x && t % DEG30 == 0) /* was rounded up to next sign */
- t = x / 100 * 100L; /* round last second of sign downwards */
- return (t);
- }
-
-
- /******************************/
- double dcos(centisec x)
- {
- return (COS8 (CSTORAD * x));
- }
-
- /******************************/
- double dsin(centisec x)
- {
- return (SIN8 (CSTORAD * x));
- }
-
- /******************************/
- double dtan(centisec x)
- {
- return (TAN8 (CSTORAD * x));
- }
-
- /******************************/
- centisec datan(double x)
- {
- return (d2l (RADTOCS * ATAN8 (x)) );
- }
-
- /******************************/
- centisec dasin(double x)
- {
- return (d2l (RADTOCS * ASIN8 (x)));
- }
- #ifdef ASTROLOG
- /* End contents of csec.c */
- #endif
- #endif /* ASTROLOG */
- #include <string.h>
-
- #ifndef ASTROLOG
- #ifndef DIR_GLUE
- # if MSDOS
- # define DIR_GLUE "\\"
- # else
- # define DIR_GLUE "/"
- # endif
- #endif
- #else
- #define DIR_GLUE ""
- #endif /* ASTROLOG */
-
-
- /************************************************************
- externally accessible globals, defined as extern in placalc.h
- ************************************************************/
-
-
- REAL8 meanekl, ekl, nut;
- struct elements el [MARS + 1];
-
- /*
- * The global variable ephe_path indicates where the ephemeris files
- * LRZ5_xx and CHI_xx are stored.
- * By default it is set to the #defined EPHE_PATH, but the user of the
- * placalc module can change it to any other location before he
- * starts calling calc().
- */
- char *ephe_path = EPHE_PATH;
- /*
- * If there occurs an internal error in placalc, a message is
- * written to stderr or into the string variable placalc_err_text.
- * By default it is written to stderr, but if placalc_err_text is
- * not a NULL pointer, it is written to the string variable.
- * The user must set this pointer to a string of at least 160 bytes long,
- * if he/she wants to use it.
- */
- char *placalc_err_text = NULL;
-
-
- #ifndef ASTROLOG
- /**********************************************************
- function nacalc ()
- calculates an array of planet longitudes and speeds,
- as needed for complete nathan data records.
- The function knows itself how many planets and in which mode
- they have to be calculated for Nathan.
-
- return OK or ERR
-
- The returned positions are in centiseconds, our standard
- coordinate format for fast mathematics with planetary positions.
-
- This function is just a template of how the calc() package
- can be used.
- **********************************************************/
- int nacalc (REAL8 jd_ad, /* universal time relative julian date */
- centisec *plon, /* returned longitudes */
- centisec *pspe /* returned speeds, if not NULL pointer */
- )
- {
- int planet, flag;
- REAL8 rlng, rrad, rlat, rspeed;
- int result = OK;
- flag = CALC_BIT_SPEED; /* same, with speed */
- jd_ad += deltat( jd_ad ); /* ET = UT + Delta_T */
- for (planet = SUN; planet <= TRUE_NODE; planet++) {
- if (calc (planet, jd_ad, flag, &rlng, &rrad, &rlat, &rspeed) == OK) {
- plon [planet] = d2l (rlng * DEG);
- if (pspe != NULL) pspe [planet] = d2l (rspeed * DEG);
- } else {
- plon [planet] = -1;
- if (pspe != NULL) pspe [planet] = 0;
- result = ERR;
- }
- }
- planet = TRUE_NODE + 1; /* CHIRON may not be TRUE_NODE + 1 */
- if (calc (CHIRON, jd_ad, flag, &rlng, &rrad, &rlat, &rspeed) == OK) {
- plon [planet] = d2l (rlng * DEG);
- if (pspe != NULL) pspe [planet] = d2l (rspeed * DEG);
- } else {
- plon [planet] = -1;
- if (pspe != NULL) pspe [planet] = 0;
- result = ERR;
- }
- return result;
- } /* end nacalc */
- #endif /* !ASTROLOG */
-
- #ifdef ASTROLOG
- /* Given an object index and a Julian Day time, get its zodiac and */
- /* declination position (planetary longitude and latitude) of the object */
- /* and its velocity and distance from the Earth or Sun. This basically */
- /* just calls the Placalc calculation function to actually do it, but as */
- /* this is the one routine called from Astrolog, this is the one routine */
- /* which has knowledge of and uses both Astrolog and Placalc definitions, */
- /* and does things such as translation to Placalc indices and formats. */
-
- int PlacalcPlanet(ind, jd, helio, planet, planetalt, ret, space)
- int ind, helio;
- double jd;
- real *planet, *planetalt, *ret, *space;
- {
- int iplanet, flag;
- REAL8 jd_ad, rlng, rrad, rlat, rspeed;
-
- if (ind <= _PLU) /* Convert Astrolog object index to Placalc index. */
- iplanet = ind-1;
- else if (ind == _CHI)
- iplanet = CHIRON;
- else if (ind == _NOD)
- #ifdef TRUENODE
- iplanet = TRUE_NODE;
- #else
- iplanet = MEAN_NODE;
- #endif
- else
- return FALSE;
-
- jd_ad = jd - JUL_OFFSET;
- flag = helio ? CALC_BIT_SPEED | CALC_BIT_HELIO : CALC_BIT_SPEED;
- jd_ad += deltat(jd_ad);
- if (calc(iplanet, jd_ad, flag, &rlng, &rrad, &rlat, &rspeed) == OK) {
- *planet = rlng;
- *planetalt = rlat;
- *ret = rspeed;
- *space = rrad;
- return TRUE;
- }
- return FALSE;
- }
- #endif /* ASTROLOG */
-
- #ifndef ASTROLOG
- /******************************************************************
- * calculation server
- * delivers positions in string format which can be sent easily
- * over a communication line to the calculation client.
- ******************************************************************/
- int calcserv(int id, /* request id, random number to prevent phase err */
- REAL8 jd_ad, /* time as relative Astrodienst julian date */
- int flag, /* a set of CALC_BIT_ bitflags */
- int plalist,/* bit list of planets to be computed, 0 = all */
- char *so) /* output string, MUST BE LONG ENOUGH (800 bytes)*/
- {
- int p, planet, so_len;
- REAL8 rlng, rrad, rlat, rspeed, rau[CALC_N];
- centisec lcs[CALC_N], lpcs[CALC_N], betcs[CALC_N];
- #ifndef ASTROLOG
- int rgeo[CALC_N];
- #endif
- char s[MAXCHAR];
- if (plalist == 0) plalist = CALC_ALL_PLANET_BITS;
- /*
- * flag determines whether deltat is added to t;
- * if CALC_BIT_EPHE is set, jd_ad is considered as ephemeris time,
- * otherwise as universal time.
- */
- if ((flag & CALC_BIT_EPHE) == 0) {
- jd_ad += deltat (jd_ad);
- }
- for (p = SUN; p < CALC_N; p++) {
- if (! check_bit(plalist, p)) continue;
- if (calc (p, jd_ad, flag, &rlng, &rrad, &rlat, &rspeed) == OK) {
- lcs [p] = d2l (rlng * DEG);
- lpcs [p] = d2l (rspeed * DEG);
- betcs [p] = d2l (rlat * DEG);
- rau [p] = rrad;
- } else {
- sprintf(so,"error at planet %d", p);
- return ( ERR);
- }
- }
- /*
- * format comma separated list: id,teph,flag,plalist,ekl,nut
- * REAL8 is given with 8 digits precision after decimal point,
- * all angles are given in centiseconds.
- * then for each requested planet: longitude (csec)
- * then for each requested planet, if wanted: speed (csec/day)
- * then for each requested planet, if wanted: latitude (csec)
- * then for each requested planet, if wanted: rgeo (units 0..999)
- * then for each requested planet, if wanted: rau (A.U.)
- */
- sprintf (so, "%d,%.8lf,%d,%d,%ld,%ld", id, jd_ad, flag, plalist,
- d2l(ekl * DEG), d2l (nut * DEG) );
- so_len = strlen (so);
- for (planet = SUN; planet < CALC_N; planet++) {
- if (! check_bit(plalist, planet)) continue;
- sprintf (s ,",%ld", lcs[planet]);
- strcat (so + so_len, s);
- so_len += strlen (s);
- }
- if (flag & CALC_BIT_SPEED) {
- for (planet = SUN; planet < CALC_N; planet++) {
- if (! check_bit(plalist, planet)) continue;
- sprintf (s ,",%ld", lpcs[planet]);
- strcat (so + so_len, s);
- so_len += strlen (s);
- }
- }
- if (flag & CALC_BIT_BETA) {
- for (planet = SUN; planet < CALC_N; planet++) {
- if (! check_bit(plalist, planet)) continue;
- sprintf (s ,",%ld", betcs[planet]);
- strcat (so + so_len, s);
- so_len += strlen (s);
- }
- }
- if (flag & CALC_BIT_RGEO) {
- for (planet = SUN; planet < CALC_N; planet++) {
- if (! check_bit(plalist, planet)) continue;
- sprintf (s ,",%ld", rel_geo(planet,rau[planet]));
- strcat (so + so_len, s);
- so_len += strlen (s);
- }
- }
- if (flag & CALC_BIT_RAU) {
- for (planet = SUN; planet < CALC_N; planet++) {
- if (! check_bit(plalist, planet)) continue;
- sprintf (s ,",%.8lf", rau[planet]);
- strcat (so + so_len, s);
- so_len += strlen (s);
- }
- }
- return (OK);
- } /* end calcserv */
- #endif /* !ASTROLOG */
-
- /******************************************************************
- function calc():
- This is the main routine for computing a planets position.
- The function has several modes, which are controlled by bits in
- the parameter 'flag'. The normal mode (flag == 0) computes
- a planets apparent geocentric position in ecliptic coordinates relative to
- the true equinox of date, without speed
-
- Explanation of the arguments: see the functions header.
-
- Returns OK or ERR (if some planet out of time range). OK and ERR are
- defined in ourdef.h and must not be confused with TRUE and FALSE.
- OK and ERR are of type int, not of type BOOLEAN.
-
- Bits used in flag:
- CALC_BIT_HELIO 0 = geocentric, 1 = heliocentric
- CALC_BIT_NOAPP 0 = apparent positions, 1 = true positions
- CALC_BIT_NONUT 0 = do nutation (true equinox of date)
- 1 = don't do nutation (mean equinox of date).
-
- CALC_BIT_SPEED 0 = don't calc speed,
- 1 = calc speed, takes quite long for moon
- (is observed only for moon, with other
- planets speed is cheap)
-
- Side effects and local memory:
- For doing heliocentric positions the fucntion must know the
- earth's position for the desired time t. It remembers the earth
- position so it does not have to recompute it each time a planet
- position is wanted for the same time t.
- It calls helup(t), which leaves as a side effect the global
- variables meanekl, ekl and nut for the time t.
-
- Functions called by calc():
- helup(t)
- hel(t)
- moon(t)
- togeo()
-
- Time range:
- The function can be used savely in the time range 5000 BC to
- 3000 AD. The stored ephemeris is available only for this time
- range, so Jupiter ... Pluto cannot be computed outside. The
- function will return results for the other planets also outside
- of this time range, but they become meaningless pretty soon
- before 5000 BC, because Newcombs time series expansions for the
- elements will not work anymore.
-
- ******************************************************************/
- int calc(int planet, /* planet index as defined in placalc.h,
- SUN = 0, MOON = 1 etc.
- planet == -1 calc calculates only nut and ecl */
- REAL8 jd_ad, /* relative Astrodienst Juldate, ephemeris time.
- Astrodienst Juldate is relative 31 Dec 1949, noon. */
- int flag, /* See definition of flag bits above */
- REAL8 *alng,
- REAL8 *arad,
- REAL8 *alat,
- REAL8 *alngspeed)
- /* pointers to the return variables:
- alng = ecliptic longitude in degrees
- arad = radius vector in AU (astronomic units)
- alat = ecliptic latitude in degrees
- alngspeed = speed of planet in degrees per day
-
- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- The precision of the speed is quite limited.
- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- For Sun, Mercury, Venus and Mars we take only the speed from
- the undisturbed Kepler orbit. For the Moon there is no
- reasonable undisturbed orbit and we derive the speed from
- its position at t + dt and t - dt. We need these
- moon positions anyway for the true node calculation.
- For the outer planets and Chiron we derive the precise
- speed from the stored ephemeris by high order inter-
- polation; the precision is limited for the geocentric
- case due to the limited precision of the earth's/sun's
- speed.
- Applications who need precise speeds should
- get them by calling calc() with slightly different times.
- */
- /*
- * Comment 7 May 1991 by Alois Treindl:
- * Center of Earth versus Barycenter Earth-Moon:
- * Brown's theory of the moon gives the moon's coordinates relative
- * to the center of the earth. Newcomb's theory of the Sun gives the
- * coordinates of the earth's center relative to the center of the Sun.
- * This is what we need.
- *
- * How about the Mean Lunar Node?
- * The orbital elements of the Sun in Newcomb's theory are given
- * relative to the barycenter Earth-Moon; the reduction to geocentric
- * is only applied after doing the Kepler ellipse calculation.
- * Are the Lunar elements also relative to the barycenter??
- * If yes:
- * When we use the moon's mean node out of the elements, it is still
- * as seen from the barycenter. Because the node is close to the
- * earth, we would have to apply a considerable correction, which is of
- * the order of 4000/384000 km or 35' (minutes of arc).
- * Nobody has ever applied such a correction to the mean node.
- *
- * And the True Node?
- * When we calculate the osculating orbital elements of the Moon (true node),
- * are they relative to the barycenter or to the Earth's center?
- * Our derivation of true node from the actual Moon positions considers
- * the earth's center as the focal point of the osculating lunar ellipse.
- * A more correct approach would first reduce the lunar position from
- * geocentric to barycentric, then compute the orbital elements from
- * the reduced positions, and then reduce the desired items
- * (node, apogaeum, 'dark moon') to geocentric positions.
- * No known astrological ephemeris has ever used such a correction, which is
- * of the same order of magnitude as the correction to the meannode above.
- * When the moon is going through the ecliptic, the geocenter, barycenter
- * moon (and the node identical to the moon itself) line up; this is why
- * the error does not show up in normal considerations.
- */
- {
- struct rememberdat /* time for which the datas are calculated */
- { REAL8 calculation_time, lng, rad, zet, lngspeed, radspeed, zetspeed; };
- static struct rememberdat earthrem =
- { HUGE, HUGE, HUGE, HUGE, HUGE, HUGE, HUGE };
- static struct rememberdat moonrem =
- { HUGE, HUGE, HUGE, HUGE, HUGE, HUGE, HUGE };
- REAL8 c, s, x, knn, knv;
- REAL8 rp, zp; /* needed to call hel! */
- REAL8 *azet = alat;
- BOOLEAN calc_geo, calc_helio, calc_apparent, calc_speed,
- calc_nut;
-
- helup (jd_ad); /* helup checks whether it was already called with same time*/
- if ( planet == CALC_ONLY_ECL_NUT ) return (OK);
-
- calc_helio = flag & CALC_BIT_HELIO;
- calc_geo = ! calc_helio;
- calc_apparent = ! (flag & CALC_BIT_NOAPP);
- calc_nut = ! (flag & CALC_BIT_NONUT);
- calc_speed = flag & CALC_BIT_SPEED;
- /*
- * it is necessary to compute EARTH in the following cases:
- * heliocentric MOON or EARTH
- * geocentric any planet except MOON or nodes or LILITH
- */
- if (calc_helio && (planet == MOON || planet == EARTH)
- || calc_geo && planet != MOON
- && planet != MEAN_NODE
- && planet != TRUE_NODE
- && planet != LILITH) {
- if ( earthrem.calculation_time != jd_ad ) {
- hel ( EARTH, jd_ad, alng, arad, azet, alngspeed, &rp, &zp );
- /* store earthdata for geocentric calculation: */
- earthrem.lng = *alng;
- earthrem.rad = *arad;
- earthrem.zet = *azet;
- earthrem.lngspeed = *alngspeed;
- earthrem.radspeed = rp;
- earthrem.zetspeed = zp;
- earthrem.calculation_time = jd_ad;
- }
- }
- switch(planet) {
- case EARTH: /* has been already computed */
- *alng = earthrem.lng;
- *arad = earthrem.rad;
- *azet = earthrem.zet;
- *alngspeed = earthrem.lngspeed;
- rp = earthrem.radspeed;
- zp = earthrem.zetspeed;
- if ( calc_geo ) { /* SUN seen from earth */
- *alng = smod8360( *alng + 180.0 );
- *azet = - *azet;
- }
- if (calc_apparent)
- *alng = *alng - 0.0057683 * (*arad) * (*alngspeed);
- break;
- case MOON:
- moon( alng, arad, azet );
- moonrem.lng = *alng; /* moonrem will be used for TRUE_NODE */
- moonrem.rad = *arad;
- moonrem.zet = *azet;
- *alngspeed = 12;
- moonrem.calculation_time = jd_ad;
- if ( calc_helio || calc_speed ) {/* get a second moon position */
- REAL8 lng2, rad2, zet2;
- helup( jd_ad + MOON_SPEED_INTERVAL );
- moon( &lng2, &rad2, &zet2 );
- helup( jd_ad );
- if ( calc_helio ) { /* moon as seen from sun */
- togeo( earthrem.lng, -earthrem.rad, moonrem.lng, moonrem.rad,
- moonrem.zet, alng, arad );
- togeo( earthrem.lng + MOON_SPEED_INTERVAL * earthrem.lngspeed,
- -( earthrem.rad + MOON_SPEED_INTERVAL * earthrem.radspeed ),
- lng2, rad2, zet2, &lng2, &rad2 );
- }
- *alngspeed = diff8360( lng2, *alng ) / MOON_SPEED_INTERVAL;
- /* rp = ( rad2 - *arad ) / MOON_SPEED_INTERVAL;
- zp = ( zet2 - moonrem.zet ) / MOON_SPEED_INTERVAL; */
- }
- *alat = RADTODEG * ASIN8( *azet / *arad );
- /*
- * light time correction, not applied for moon or nodes;
- * moon would have only term of ca. 0.02", see Expl.Sup.1961 p.109
- */
- break;
- case MERCURY:
- case VENUS:
- case MARS:
- case JUPITER:
- case SATURN:
- case URANUS:
- case NEPTUNE:
- case PLUTO:
- case CHIRON:
- if (hel ( planet, jd_ad, alng, arad, azet, alngspeed, &rp, &zp ) != OK)
- return (ERR); /* outer planets can fail if out of ephemeris range */
- if ( calc_geo ) { /* geocentric */
- REAL8 lng1, rad1, lng2, rad2;
- togeo( earthrem.lng, earthrem.rad, *alng, *arad, *azet, &lng1, &rad1 );
- togeo( earthrem.lng + earthrem.lngspeed,
- earthrem.rad + earthrem.radspeed,
- *alng + *alngspeed, *arad + rp, *azet + zp, &lng2, &rad2 );
- *alng = lng1;
- *arad = rad1;
- *alngspeed = diff8360( lng2, lng1 );
- /* rp = rad2 - rad1; */
- }
- *alat = RADTODEG * ASIN8( *azet / *arad );
- if (calc_apparent)
- *alng = *alng - 0.0057683 * (*arad) * (*alngspeed);
- break;
- case MEAN_NODE:
- *alng = smod8360( el[MOON].kn);
- /*
- * the distance of the node is the 'orbital parameter' p = a (1-e^2);
- * Our current use of the axis a is wrong, but is never used.
- */
- *arad = pd[MOON].axis;
- *alat = 0.0;
- *alngspeed = -0.053;
- break;
- case TRUE_NODE: {
- /* see comment 'Note 7 May 1991' above */
- REAL8 ln, rn, zn,
- lv, rv, zv,
- l1, r1, z1,
- xn, yn, xv, yv, r0, x0, y0;
- helup( jd_ad + NODE_INTERVAL );
- moon( &ln, &rn, &zn );
- helup( jd_ad - NODE_INTERVAL );
- moon( &lv, &rv, &zv );
- helup( jd_ad );
- if ( moonrem.calculation_time != jd_ad )
- moon( &l1, &r1, &z1 );
- else { /* moon is already calculated */
- l1 = moonrem.lng;
- r1 = moonrem.rad;
- z1 = moonrem.zet;
- }
- rn = sqrt( rn * rn - zn * zn );
- rv = sqrt( rv * rv - zv * zv );
- r0 = sqrt( r1 * r1 - z1 * z1 );
- xn = rn * COS8( DEGTORAD * ln );
- yn = rn * SIN8( DEGTORAD * ln );
- xv = rv * COS8( DEGTORAD * lv );
- yv = rv * SIN8( DEGTORAD * lv );
- x0 = r0 * COS8( DEGTORAD * l1 );
- y0 = r0 * SIN8( DEGTORAD * l1 );
- x = test_near_zero( x0 * yn - xn * y0 );
- s = ( y0 * zn - z1 * yn ) / x;
- c = test_near_zero( ( x0 * zn - z1 * xn ) / x );
- knn = smod8360( RADTODEG * ATAN28( s, c )); /* = ATAN8( s / c ) */
- x = test_near_zero( y0 * xv - x0 * yv );
- s = ( yv * z1 - zv * y0 ) / x;
- c = test_near_zero( ( xv * z1 - zv * x0 ) / x );
- knv = smod8360( RADTODEG * ATAN28( s, c ));
- *alng = smod8360( ( knv + knn ) / 2 );
- /*
- * the distance of the node is the 'orbital parameter' p = a (1-e^2);
- * Our current use of the axis a is wrong.
- */
- *arad = pd[MOON].axis;
- *alat = 0.0;
- *alngspeed = diff8360( knn, knv ) / NODE_INTERVAL;
- }
- break;
- case LILITH: {
- /*
- * Added 22-Jun-93
- * Lilith or Dark Moon is the empty focal point of the mean lunar ellipse.
- * This is 180 degrees from the perihel.
- * Because the lunar orbit is not in the ecliptic, it must be
- * projected onto the ecliptic in the same way as the planetary orbits
- * are (see for example Montenbruck, Grundlagen der Ephemeridenrechnung).
- *
- * We compute the MEAN Lilith, not the TRUE one which would have to be
- * derived in a similar way as the true node.
- * For the radius vector of Lilith we use a simple formula;
- * to get a precise value, the fact that the focal point of the ellipse
- * is not at the center of the earth but at the barycenter moon-earth
- * would have to be accounted for.
- * For the speed we always return a constant: the T term from the
- * lunar perihel.
- * Joelle de Gravelaine publishes in her book "Lilith der schwarze Mond"
- * (Astrodata, 1990) an ephemeris which gives noon (12.00) positions
- * but does not project onto the ecliptic.
- * This creates deviations
- */
- double arg_lat, lon, cosi;
- struct elements *e = &el[MOON];
- arg_lat = degnorm(e->pe - e->kn + 180.0);
- cosi = COSDEG(e->in);
- if (e->in == 0 || ABS8( arg_lat - 90.0 ) < TANERRLIMIT
- || ABS8( arg_lat - 270.0 ) < TANERRLIMIT ) {
- lon = arg_lat;
- } else {
- lon = ATAN8( TANDEG( arg_lat ) * cosi );
- lon = RADTODEG * lon;
- if ( arg_lat > 90.0 && arg_lat < 270.0 ) lon += 180.0;
- }
- lon = degnorm(lon + e->kn);
- *alng = lon;
- *alngspeed = 0.111404; /* 6'41.05" per day */
- *arad = 2 * pd[MOON].axis * e->ex;
- /*
- * To test Gravalaines error, return unprojected long in alat.
- * the correct latitude would be:
- * *alat = RADTODEG * ASIN8(SINDEG(arg_lat) * SINDEG(e->in));
- */
- *alat = degnorm(arg_lat + e->kn); /* unprojected longitude, no nut */
- }
- break;
- default:
- fprintf(stderr, "calc() called with illegal planet %d\n", planet);
- return ERR;
- } /* end switch */
- if (calc_nut)
- *alng += nut;
- *alng = smod8360( *alng); /* normalize to circle */
- return (OK);
- } /* end calc */
-
- int rel_geo(int planet, double rau)
- {
- /*
- * get relative earth distance in range 0..1000:
- * To compute the relative distance we use fixed values of
- * mimimum and maximum distance measured empirically between
- * 1300 AD and 2300 AD (see helconst.c).
- * This approach is certainly fine for the
- * outer planets, but not the best for Sun and Moon, where it
- * would be better to look at the mean anomaly, i.e. the progress
- * the planet makes on it's Kepler orbit.
- * Considering the low importance astrologers give to the relative
- * distance, we consider the effort not worthwile.
- * Now we compare real radius with longtime-averaged distances.
- */
- int rgeo;
- if (planet == MEAN_NODE || planet == TRUE_NODE || planet == LILITH) {
- return 0;
- } else {
- #ifndef ASTROLOG
- rgeo = 1000 * (1.0 - (rau - rmima[planet][0]) / (rmima[planet][1] - rmima[planet][0]));
- #else
- rgeo = 1000 * (int)(1.0 - (rau - rmima[planet][0]) / (rmima[planet][1] - rmima[planet][0]));
- #endif
- }
- if (rgeo < 0)
- rgeo = 0;
- else if (rgeo > 999)
- rgeo = 999;
- return rgeo;
- }
-
- /******************************************************************
- helio to geocentric conversion
- ******************************************************************/
- void togeo(REAL8 lngearth,
- REAL8 radearth,
- REAL8 lng,
- REAL8 rad,
- REAL8 zet,
- REAL8 *alnggeo,
- REAL8 *aradgeo )
- {
- REAL8 r1, x, y;
- r1 = sqrt( rad * rad - zet * zet );
- x = r1 * COS8( DEGTORAD * lng ) - radearth * COS8( DEGTORAD * lngearth );
- y = r1 * SIN8( DEGTORAD * lng ) - radearth * SIN8( DEGTORAD * lngearth );
- *aradgeo = sqrt( x * x + y * y + zet * zet );
- x = test_near_zero( x );
- *alnggeo = smod8360( RADTODEG * ATAN28( y, x ) );
- } /* end togeo */
-
- /******************************************************************
- helup()
- prepares the orbital elements and the disturbation arguments for the
- inner planets and the moon. helup(t) is called by hel() and by calc().
- helup() returns its results in global variables.
- helup() remembers the t it has been called with before and does
- not recalculate its results when it is called more than once with
- the same t.
- ******************************************************************/
- void helup (REAL8 jd_ad ) /* relative julian date, ephemeris time */
- {
- int i;
- static REAL8 thelup = HUGE; /* is initialized only once at load time */
- struct elements *e = el; /* pointer to el[i] */
- struct elements *ee = el; /* pointer to el[EARTH] */
- struct eledata *d = pd; /* pointer to pd[i] */
- REAL8 td, ti, ti2, tj1, tj2, tj3;
-
- if ( thelup == jd_ad ) return; /* if already calculated then return */
- for ( i = SUN; i <= MARS; i++, d++, e++ )
- {
- td = jd_ad - d->epoch;
- ti = e->tj = td / 36525.0; /* julian centuries from epoch */
- ti2 = ti * ti;
- tj1 = ti / 3600.0; /* used when coefficients are in seconds of arc */
- tj2 = ti * tj1;
- tj3 = ti * tj2;
- e->lg = mod8360( d->lg0 + d->lg1 * td + d->lg2 * tj2 + d->lg3 * tj3 );
- /* also with moon lg1 *td is exact to 10e-8 degrees within 5000 years */
- e->pe = mod8360( d->pe0 + d->pe1 * tj1 + d->pe2 * tj2 + d->pe3 * tj3 );
- e->ex = d->ex0 + d->ex1 * ti + d->ex2 * ti2;
- e->kn = mod8360( d->kn0 + d->kn1 * tj1 + d->kn2 * tj2 + d->kn3 * tj3 );
- e->in = d->in0 + d->in1 * tj1 + d->in2 * tj2;
- e->ma = smod8360( e->lg - e->pe );
- if ( i == MOON ) { /* calculate ekliptic according Newcomb, APAE VI,
- and nutation according Exp.Suppl. 1961, identical
- with Mark Potttenger elemnut()
- all terms >= 0.01" only .
- The 1984 IAU Theory of Nutation, as published in
- AE 1984 suppl. has not yet been implemented
- because it would mean to use other elements of
- moon and sun */
- REAL8 mnode, mlong2, slong2, mg, sg, d2;
- mnode = DEGTORAD * e->kn; /* moon's mean node */
- mlong2 = DEGTORAD * 2.0 * e->lg; /* 2 x moon's mean longitude */
- mg = DEGTORAD * e->ma; /* moon's mean anomaly (g1) */
- slong2 = DEGTORAD * 2.0 * ee->lg; /* 2 x sun's mean longitude (L), with
- the phase 180 deg earth-sun irrelevant
- because 2 x 180 = 360 deg */
- sg = DEGTORAD * ee->ma; /* sun's mean anomaly = earth's */
- d2 = mlong2 - slong2; /* 2 x elongation of moon from sun */
- meanekl = ekld[0] + ekld[1] * tj1 + ekld[2] * tj2 + ekld[3] * tj3;
- ekl = meanekl +
- ( 9.2100 * COS8( mnode )
- - 0.0904 * COS8( 2.0 * mnode )
- + 0.0183 * COS8( mlong2 - mnode )
- + 0.0884 * COS8( mlong2 )
- + 0.0113 * COS8( mlong2 + mg )
- + 0.5522 * COS8( slong2 )
- + 0.0216 * COS8( slong2 + sg ) ) / 3600.0;
- nut = ( ( -17.2327 - 0.01737 * ti ) * SIN8( mnode )
- + 0.2088 * SIN8( 2.0 * mnode )
- + 0.0675 * SIN8( mg )
- - 0.0149 * SIN8( mg - d2 )
- - 0.0342 * SIN8( mlong2 - mnode)
- + 0.0114 * SIN8( mlong2 - mg)
- - 0.2037 * SIN8( mlong2 )
- - 0.0261 * SIN8( mlong2 + mg )
- + 0.0124 * SIN8( slong2 - mnode)
- + 0.0214 * SIN8( slong2 - sg)
- - 1.2729 * SIN8( slong2 )
- - 0.0497 * SIN8( slong2 + sg)
- + 0.1261 * SIN8( sg ) ) / 3600.0;
- }
- } /* for i */
-
- /* calculate the arguments sa[] for the disturbation terms */
- ti = (jd_ad - EPOCH1850) / 365.25; /* julian years from 1850 */
- for ( i = 0; i < SDNUM; i++ )
- sa [i] = mod8360 (sd [i].sd0 + sd [i].sd1 * ti);
- /*
- sa[2] += 0.3315 * SIN8 (DEGTORAD *(133.9099 + 38.39365 * el[SUN].tj));
- */
- /* correction of jupiter perturbation argument for sun from Pottenger;
- creates only .03" and 1e-7 rad, not applied because origin unclear */
- thelup = jd_ad; /* note the last helup time */
- } /* end helup() */
-
- /******************************************************************
- hel()
- Computes the heliocentric positions for all planets except the moon.
- The outer planets from Jupiter onwards, including Chiron, are
- actually done by a subsequent call to outer_hel() which takes
- exactly the same parameters.
- hel() does true position relative to the mean ecliptic and equinox
- of date. Nutation is not added and must be done so by the caller.
- The latitude of the Sun (max. 0.5") is neglected and always returned
- as zero.
-
- return: OK or ERR
- ******************************************************************/
- int hel( int planet, /* planet index as defined by placalc.h */
- REAL8 t, /* relative juliand date, ephemeris time */
- /* Now come 6 pointers to return values. */
- REAL8 *al, /* longitude in degrees */
- REAL8 *ar, /* radius in AU */
- REAL8 *az, /* distance from ecliptic in AU */
- REAL8 *alp, /* speed in longitude, degrees per day */
- REAL8 *arp, /* speed in radius, AU per day */
- REAL8 *azp) /* speed in z, AU per day */
- {
- void disturb();
- REAL8 fnu();
- register struct elements *e;
- register struct eledata *d;
- REAL8 lk = 0.0;
- REAL8 rk = 0.0;
- REAL8 b, h1, sini, sinv, cosi, cosu, cosv, man, truanom, esquare,
- k8, u, up, v, vp;
-
- if (planet >= JUPITER )
- return ( outer_hel( planet, t, al, ar, az, alp, arp, azp ));
- if (planet < SUN || planet == MOON)
- return (ERR);
-
- e = &el[planet];
- d = &pd[planet];
- sini = SIN8( DEGTORAD * e->in );
- cosi = COS8( DEGTORAD * e->in );
- esquare = sqrt( ( 1.0 + e->ex ) / ( 1.0 - e->ex ) ); /* H6 in old version */
- man = e->ma;
- if ( planet == EARTH ) /* some longperiodic terms in mean longitude */
- man += ( 0.266 * SIN8 ( DEGTORAD * ( 31.8 + 119.0 * e->tj ) )
- + 6.40 * SIN8 ( DEGTORAD * ( 231.19 + 20.2 * e->tj ) )
- + (1.882-0.016*e->tj) * SIN8( DEGTORAD * (57.24 + 150.27 * e->tj))
- ) / 3600.0;
- if ( planet == MARS ) /* some longperiodic terms */
- man += ( 0.606 * SIN8( DEGTORAD * (212.87 + e->tj * 119.051) )
- + 52.490 * SIN8( DEGTORAD * (47.48 + e->tj * 19.771) )
- + 0.319 * SIN8( DEGTORAD * (116.88 + e->tj * 773.444) )
- + 0.130 * SIN8( DEGTORAD * (74 + e->tj * 163) )
- + 0.280 * SIN8( DEGTORAD * (300 + e->tj * 40.8) )
- - ( 37.05 +13.5 * e->tj )
- ) / 3600.0;
- u = fnu ( man, e->ex, 0.0000003 ); /* error 0.001" returns radians */
- cosu = COS8( u );
- h1 = 1 - e->ex * cosu;
- *ar = d->axis * h1;
- if ( ABS8( M_PI - u ) < TANERRLIMIT )
- truanom = u; /* very close to aphel */
- else
- truanom = 2.0 * ATAN8( esquare * TAN8( u * 0.5 ) ); /* true anomaly, rad*/
- v = smod8360( truanom * RADTODEG + e->pe - e->kn ); /* argument of latitude */
- if ( sini == 0.0 || ABS8( v - 90.0 ) < TANERRLIMIT
- || ABS8( v - 270.0 ) < TANERRLIMIT ) {
- *al = v;
- } else {
- *al = RADTODEG * ATAN8( TAN8( v * DEGTORAD ) * cosi );
- if ( v > 90.0 && v < 270.0 ) *al += 180.0;
- }
- *al = smod8360( *al + e->kn );
- sinv = SIN8( v * DEGTORAD );
- cosv = COS8( v * DEGTORAD );
- *az = *ar * sinv * sini;
- b = ASIN8( sinv * sini ); /* latitude in radians */
- k8 = cosv / COS8( b ) * sini;
- up = 360.0 / d->period / h1; /* du/dt degrees/day */
- if ( ABS8 ( M_PI - u ) < TANERRLIMIT )
- vp = up / esquare; /* speed at aphel */
- else
- vp = up * esquare * ( 1 + COS8 ( truanom ) ) / ( 1 + cosu );
- /* dv/dt degrees/day */
- *arp = d->axis * up * DEGTORAD * SIN8( u ) * e->ex;
- /* dr/dt AU/day */
- *azp = *arp * sinv * sini + *ar * vp * DEGTORAD * cosv * sini; /* dz/dt */
- *alp = vp / cosi * ( 1 - k8 * k8 );
- /* now come the disturbations */
- switch ( planet ) {
- REAL8 am, mma, ema, u2;
- case EARTH:
- /*
- * earth has some special moon values and a disturbation series due to the
- * planets. The moon stuff is due to the fact, that the mean elements
- * give the coordinates of the earth-moon barycenter. By adding the
- * corrections we effectively reduce to the center of the earth.
- * We neglect the correction in latitude, which is about 0.5", because
- * for astrological purposes we want the Sun to have latitude zero.
- */
- am = DEGTORAD * smod8360( el[MOON].lg - e->lg + 180.0 ); /* degrees */
- mma = DEGTORAD * el[MOON].ma;
- ema = DEGTORAD * e->ma;
- u2 = 2.0 * DEGTORAD * (e->lg - 180.0 - el[MOON].kn); /* 2u' */
- lk = 6.454 * SIN8( am )
- + 0.013 * SIN8( 3.0 * am )
- + 0.177 * SIN8( am + mma )
- - 0.424 * SIN8( am - mma )
- + 0.039 * SIN8( 3.0 * am - mma )
- - 0.064 * SIN8( am + ema )
- + 0.172 * SIN8( am - ema )
- - 0.013 * SIN8( am - mma - ema)
- - 0.013 * SIN8( u2 );
- rk = 13360 * COS8( am )
- + 30 * COS8( 3.0 * am )
- + 370 * COS8( am + mma )
- - 1330 * COS8( am - mma )
- + 80 * COS8( 3.0 * am - mma )
- - 140 * COS8( am + ema )
- + 360 * COS8( am - ema )
- - 30 * COS8( am - mma - ema)
- + 30 * COS8( u2 );
- /* long periodic term from mars 15g''' - 8g'', Vol 6 p19, p24 */
- lk += 0.202 * SIN8( DEGTORAD * (315.6 + 893.3 * e->tj));
- disturb( earthkor, al, ar, lk, rk, man );
- break;
- case MERCURY: /* only normal disturbation series */
- disturb( mercurykor, al, ar, 0.0, 0.0, man );
- break;
- case VENUS: /* some longperiod terms and normal series */
- lk = (2.761 - 0.22*e->tj) * SIN8( DEGTORAD * (237.24 + 150.27 * e->tj))
- + 0.269 * SIN8( DEGTORAD * (212.2 + 119.05 * e->tj))
- - 0.208 * SIN8( DEGTORAD * (175.8 + 1223.5 * e->tj));
- /* make seconds */
- disturb( venuskor, al, ar, lk, 0.0, man );
- break;
- case MARS: /* only normal disturbation series */
- disturb( marskor, al, ar, 0.0, 0.0, man );
- break;
- } /* switch planet */
- return (OK);
- } /* hel */
-
- /******************************************************************/
- void disturb( k, al, ar, lk, rk, man )
- register struct kor *k; /* ENDMARK-terminated array of struct kor */
- REAL8 *al, /* longitude in degrees, use a pointer to return value */
- *ar; /* radius in AU */
- REAL8 lk, /* longitude correction in SECONDS OF ARC */
- /* function can be called with an lk and rk already
- != 0, but no value is returned */
- rk, /* radius correction in units of 9th place of log r */
- man; /* mean anomaly of planet */
- {
- REAL8 arg;
- while ( k->j != ENDMARK ) {
- arg = k->j * sa[k->k] + k->i * man;
- lk += k->lampl * COS8( DEGTORAD * ( k->lphase - arg ) );
- rk += k->rampl * COS8( DEGTORAD * ( k->rphase - arg ) );
- k++;
- } /* while */
- *ar *= EXP10 ( rk * 1.0E-9 ); /* 10^ rk */
- *al += lk / 3600.0;
- } /* disturb() */
-
- /******************************************************************/
- int moon(REAL8 *al, REAL8 *ar, REAL8 *az ) /* return OK or ERR */
- {
- REAL8 a1,a2,a3,a4,a5,a6,a7,a8,a9,c2,c4,arg,b,d,f,dgc,dlm,dpm,dkm,dls;
- REAL8 ca, cb, cd, f_2d, f_4d, g1c,lk,lk1,man,ms,nib,s,sinarg,sinp,sk;
- REAL8 t, tb, t2c, r2rad, i1corr, i2corr, dlid;
- #ifndef ASTROLOG
- int i, j;
- #else
- int i;
- #endif
- struct elements *e;
- struct m45dat *mp;
- # if MOON_TEST_CORR
- struct m5dat *m5p;
- # endif
- e = &el[MOON];
- t = e->tj * 36525; /* days from epoch 1900 */
-
- /* new format table II, parameters in full rotations of 360 degrees */
- r2rad = 360.0 * DEGTORAD;
- tb = t * 1e-12; /* units of 10^12 */
- t2c = t * t * 1e-16; /* units of 10^16 */
- a1 = SIN8( r2rad * (0.53733431 - 10104982 * tb + 191 * t2c ));
- a2 = SIN8( r2rad * (0.71995354 - 147094228 * tb + 43 * t2c ));
- c2 = COS8( r2rad * (0.71995354 - 147094228 * tb + 43 * t2c ));
- a3 = SIN8( r2rad * (0.14222222 + 1536238 * tb ));
- a4 = SIN8( r2rad * (0.48398132 - 147269147 * tb + 43 * t2c ));
- c4 = COS8( r2rad * (0.48398132 - 147269147 * tb + 43 * t2c ));
- a5 = SIN8( r2rad * (0.52453688 - 147162675 * tb + 43 * t2c ));
- a6 = SIN8( r2rad * (0.84536324 - 11459387 * tb ));
- a7 = SIN8( r2rad * (0.23363774 + 1232723 * tb + 191 * t2c ));
- a8 = SIN8( r2rad * (0.58750000 + 9050118 * tb ));
- a9 = SIN8( r2rad * (0.61043085 - 67718733 * tb ));
-
- dlm = 0.84 * a3 + 0.31 * a7 + 14.27 * a1 + 7.261 * a2 + 0.282 * a4
- + 0.237 * a6;
- dpm = -2.1 * a3 - 2.076 * a2 - 0.840 * a4 - 0.593 * a6;
- dkm = 0.63 * a3 + 95.96 * a2 + 15.58 * a4 + 1.86 * a5;
- dls = -6.4 * a3 - 0.27 * a8 - 1.89 * a6 + 0.20 * a9;
- dgc = (-4.318 * c2 - 0.698 * c4) / 3600.0 / 360.0; /* in revolutions */
- dgc = (1.000002708 + 139.978 * dgc); /* in this form used later */
- man = DEGTORAD * (e->ma + ( dlm - dpm ) / 3600.0);
- /* man with periodic and secular corr. */
- ms = DEGTORAD * (el[EARTH].ma + dls / 3600.0);
- f = DEGTORAD * (e->lg - e->kn + ( dlm - dkm ) / 3600.0);
- d = DEGTORAD * (e->lg + 180 - el[EARTH].lg + (dlm - dls) / 3600.0);
-
- lk = lk1 = sk = sinp = nib = g1c = 0;
- i1corr = 1.0 - 6.8320E-8 * t;
- i2corr = dgc * dgc; /* i2 occurs only as -2, 2 */
- for ( i = 0, mp = m45; i < NUM_MOON_CORR; i++, mp++ ) {
- /* arg = mp->i0 * man + mp->i1 * ms + mp->i2 * f + mp->i3 * d; */
- arg = mp->i0 * man;
- arg += mp->i3 * d;
- arg += mp->i2 * f;
- arg += mp->i1 * ms;
- sinarg = SIN8( arg );
- /* now apply corrections due to changes in constants;
- we correct only terms in l' (i1) and F (i2), not in l (i0), because
- the latter are < 0.05"
- We don't apply corrections for cos(arg), i.e. for parallax
- */
- if (mp->i1 != 0) { /* i1 can be -2, -1, 0, 1, 2 */
- sinarg *= i1corr;
- if (mp->i1 == 2 || mp->i1 == -2)
- sinarg *= i1corr;
- }
- if (mp->i2 != 0) /* i2 can be -2, 0, 2 */
- sinarg *= i2corr;
- lk += mp->lng * sinarg;
- sk += mp->lat * sinarg;
- sinp += mp->par * COS8 (arg) ;
- } /* for i */
-
- # if MOON_TEST_CORR /* optionally add more lunar longitudes */
- for ( m5p = m5; m5p->i0 != 99; m5p++ ) { /* i0 = 99 is end mark */
- arg = m5p->i0 * man + m5p->i1 * ms + m5p->i2 * f + m5p->i3 * d;
- sinarg = SIN8( arg );
- lk1 += m5p->lng * sinarg;
- }
- # endif
-
- /*now compute some planetary terms in longitude, list i delta;
- we take all > 0.5" and neglect secular terms in the arguments. These
- produce phase errors > 10 degrees only after 3000 years.
- */
- dlid = 0.822 * SIN8 ( r2rad * (0.32480 - 0.0017125594 * t ));
- dlid += 0.307 * SIN8 ( r2rad * (0.14905 - 0.0034251187 * t ));
- dlid += 0.348 * SIN8 ( r2rad * (0.68266 - 0.0006873156 * t ));
- dlid += 0.662 * SIN8 ( r2rad * (0.65162 + 0.0365724168 * t ));
- dlid += 0.643 * SIN8 ( r2rad * (0.88098 - 0.0025069941 * t ));
- dlid += 1.137 * SIN8 ( r2rad * (0.85823 + 0.0364487270 * t ));
- dlid += 0.436 * SIN8 ( r2rad * (0.71892 + 0.0362179180 * t ));
- dlid += 0.327 * SIN8 ( r2rad * (0.97639 + 0.0001734910 * t ));
-
- *al = smod8360(e->lg + (dlm + lk + lk1 + dlid) / 3600.0); /* without nutation */
-
- /* solar Terms in latitude Nibeta */
- f_2d = f - 2.0 * d;
- f_4d = f - 4.0 * d;
- nib += -526.069 * SIN8( f_2d );
- nib += -3.352 * SIN8( f_4d );
- nib += 44.297 * SIN8( man + f_2d );
- nib += -6.000 * SIN8( man + f_4d );
- nib += 20.599 * SIN8(-man + f );
- nib += -30.598 * SIN8(-man + f_2d );
- nib += -24.649 * SIN8(-2*man + f );
- nib += -2.000 * SIN8(-2*man + f_2d );
- nib += -22.571 * SIN8( ms + f_2d );
- nib += 10.985 * SIN8( -ms + f_2d );
-
- /* new gamma1C from 29 Jul 88, all terms > 0.4 " in table III, code 2 */
- g1c += -0.725 * COS8( d);
- g1c += 0.601 * COS8( 2 * d);
- g1c += 0.394 * COS8( 3 * d);
- g1c += -0.445 * COS8( man + 4 * d);
- g1c += 0.455 * COS8( man + 1 * d);
- g1c += 5.679 * COS8( 2 * man - 2 * d);
- g1c += -1.300 * COS8( 3 * man );
- g1c += -1.302 * COS8( ms );
- g1c += -0.416 * COS8( ms - 4 * d);
- g1c += -0.740 * COS8( 2 * ms - 2 * d);
- g1c += 0.787 * COS8( man + ms + 2 * d);
- g1c += 0.461 * COS8( man + ms );
- g1c += 2.056 * COS8( man + ms - 2 * d);
- g1c += -0.471 * COS8( man + ms - 4 * d);
- g1c += -0.443 * COS8( -man + ms + 2 * d);
- g1c += 0.679 * COS8( -man + ms );
- g1c += -1.540 * COS8( -man + ms - 2 * d);
-
- s = f + sk / 3600.0 * DEGTORAD;
- ca = 18519.7 + g1c;
- cb = -0.000336992 * ca * dgc * dgc * dgc;
- cd = ca / 18519.7;
- # ifdef MS_C
- /*
- * Microsoft C 5.0 runs out of heap space with this expression.
- * What a shit compiler!
- */
- b = ca * SIN8( s ) * dgc;
- b += cb * SIN8( 3.0 * s );
- b += cd * nib;
- b = b / 3600.0;
- # else
- b = ( ca * SIN8( s ) * dgc + cb * SIN8( 3.0 * s ) + cd * nib ) / 3600.0;
- # endif
- /* we neglect the planetary terms in latitude, code 4 in table III */
-
- sinp = ( sinp + 3422.451);
- /* Improved lunar ephemeris and APAE until ca. 1970 had here
- 3422.54 as constant of moon's sine parallax.
- The difference can be applied by direct addition of 0.089" to
- our parallax results.
-
- To get the radius in A.U. from the sine parallax,
- we use 1964 IAU value 8.794" for solar parallax.
- sinp is still in seconds of arc.
- To calculate moon parallax in " it would be:
- p = sinp ( 1 + sinp * sinp * 3.917405E-12)
- based on the formula p = sinp + 1/6 sinp^3
- and taking into account the conversion of " to radians.
- The semidiameter of the moon is: (Expl.Suppl. 61, p 109)
- s = 0.0796 + 0.272446 * p
- */
-
- *ar = 8.794 / sinp;
- *az = *ar * SIN8( DEGTORAD * b );
- return (OK);
- } /* end moon() */
-
- /******************************************************************/
- REAL8 fnu(REAL8 t,REAL8 ex,REAL8 err )
- /* solution of the kepler equation, return rad*/
- /* t = mean anomaly in degrees */
- /* ex = excentricity of orbit */
- /* err = maximum error in degrees */
- {
- REAL8 u0, delta;
- t *= DEGTORAD;
- u0 = t;
- err *= DEGTORAD;
- delta = 1;
- while ( ABS8( delta ) >= err ) {
- delta = ( t + ex * SIN8( u0 ) - u0 ) / ( 1 - ex * COS8( u0 ) );
- u0 += delta;
- }
- return( u0 );
- } /* end fnu() */
-
- /************************************************************************
- outer_hel()
- Computes the position of Jupiter, Saturn, Uranus, Neptune, Pluto and
- Chiron by reading our stored ephemeris in steps of 80 (!) days and
- applying a high order interpolation to it. The interpolation errors are
- less than 0.01" seconds or arc.
- The stored ephemeris is packed in a special format consisting of
- 32 bit numbers; it has been created on the Astrodienst Unix system
- by numerical integration with routines provided originally by Marc
- Pottenger, USA, which we improved for better long term precision.
- Because the Unix system uses a different byte order than the MSDOS
- systems, the bytes must be reordered for MSDOS after reading from
- the binary files.
-
- outer_hel() takes the same parameters as hel().
- It returns the same type of values.
-
- The access to the ephemeris files is done in the functions chi_file_posit()
- and lrz_file_posit().
- ****************************************************************************/
- int outer_hel( int planet, REAL8 jd_ad, REAL8 *al, REAL8 *ar, REAL8 *az,
- REAL8 *alp, REAL8 *arp, REAL8 *azp )
- /* jd_ad Astrodienst relative Julian ephemeris time */
- {
- static FILE *outerfp, *chironfp;
- static double last_j0_outer = HUGE;
- static double last_j0_chiron = HUGE;
- static long icoord[6][5][3], chicoord[6][3];
- REAL8 j0, jd, jfrac;
- REAL8 l[6], r[6], z[6];
- #ifndef ASTROLOG
- int i, n, order, p;
- #else
- int n, order, p;
- #endif
- if (planet < JUPITER || planet > PLUTO && planet != CHIRON)
- return (ERR);
- jd = jd_ad + JUL_OFFSET;
- j0 = floor ( (jd - 0.5) / EPHE_STEP) * EPHE_STEP + 0.5;
- jfrac = (jd - j0) / EPHE_STEP;
- if (planet == CHIRON ) {
- if (last_j0_chiron != j0) {
- for ( n = 0; n < 6; n++) { /* read 6 days */
- jd = j0 + (n - 2) * EPHE_STEP;
- if (chi_file_posit (jd, &chironfp) != OK) return (ERR);
- fread (&chicoord[n][0], sizeof(long), 3, chironfp);
- # if MSDOS
- longreorder (&chicoord[n][0], 3 * sizeof(long));
- # endif
- }
- last_j0_chiron = j0;
- }
- for ( n = 0; n < 6; n++) {
- l[n] = chicoord[n][0] / DEG2MSEC;
- r[n] = chicoord[n][1] / AU2INT;
- z[n] = chicoord[n][2] / AU2INT;
- } /* for n */
- } else { /* an outerplanet */
- if (last_j0_outer != j0) { /* read all 5 planets for 6 steps */
- for ( n = 0; n < 6; n++) {
- jd = j0 + (n - 2) * EPHE_STEP;
- if (lrz_file_posit (jd, &outerfp) != OK) return (ERR);
- fread (&icoord[n][0][0], sizeof(long), 15, outerfp);
- # if MSDOS
- longreorder (&icoord[n][0][0], 15 * sizeof(long));
- # endif
- }
- last_j0_outer = j0;
- }
- p = planet - JUPITER;
- for ( n = 0; n < 6; n++) {
- l[n] = icoord[n][p][0] / DEG2MSEC;
- r[n] = icoord[n][p][1] / AU2INT;
- z[n] = icoord[n][p][2] / AU2INT;
- } /* for n */
- }
- if (planet > SATURN)
- order = 3;
- else
- order = 5;
- inpolq(2, order, jfrac, l, al, alp);
- *alp /= EPHE_STEP;
- inpolq(2, order, jfrac, r, ar, arp);
- *arp /= EPHE_STEP;
- inpolq(2, order, jfrac, z, az, azp);
- *azp /= EPHE_STEP;
- return OK;
- }
-
- /*****************************************************
- quicker Everett interpolation, after Pottenger
- version 9 Jul 1988 by Alois Treindl
-
- return OK or ERR.
- *****************************************************/
- int inpolq(n,o,p,x,axu,adxu)
- int n, /* interpolate between x[n] and x[n-1], at argument n+p */
- o; /* order of interpolation, maximum 5 */
- double p, /* argument , intervall [0..1] */
- x[], /* array of function values, x[n-o]..x[n+o] must exist */
- *axu, /* pointer for storage of result */
- *adxu; /* pointer for storage of dx/dt */
- {
- static double q,q2,q3,q4,q5,
- p2,p3,p4,p5,
- u,u0,u1,u2;
- static double lastp = 9999;
- double dm2,dm1,d0,dp1,dp2,
- d2m1,d20,d2p1,d2p2,
- d30,d3p1,d3p2,
- d4p1,d4p2;
- double offset = 0.0;
-
- if (lastp != p) {
- q=1.0-p;
- q2 = q*q;
- q3 = (q+1.0)*q*(q-1.0)/6.0; /* q - 1 over 3; u5 */
- p2 = p*p;
- p3 = (p+1.0)*p*(p-1.0)/6.0; /* p - 1 over 3; u8 */
- u = (3.0*p2-1.0)/6.0;
- u0 = (3.0*q2-1.0)/6.0;
- q4 = q2*q2; /* f5 */
- p4 = p2*p2; /* f4 */
- u1 = (5.0*p4-15.0*p2+4.0)/120.0; /* u1 */
- u2 = (5.0*q4-15.0*q2+4.0)/120.0; /* u2 */
- q5 = q3*(q+2.0)*(q-2.0)/20.0; /* q - 2 over 5; u6 */
- p5 = (p+2.0)*p3*(p-2.0)/20.0; /* p - 2 over 5; u9 */
- lastp = p;
- }
- dm1 = x[n] - x[n-1];
- if (dm1 > 180.0) dm1 -= 360.0;
- if (dm1 < -180.0) dm1 += 360.0;
- d0 = x[n+1] - x[n];
- if (d0 > 180.0) {
- d0 -= 360.0;
- offset = 360.0;
- }
- if (d0 < -180.0) {
- d0 += 360.0;
- offset = -360.0;
- }
- dp1 = x[n+2] - x[n+1];
- if (dp1 > 180.0) dp1 -= 360.0;
- if (dp1 < -180.0) dp1 += 360.0;
- d20 = d0 - dm1; /* f8 */
- d2p1 = dp1 - d0; /* f9 */
-
- /* Everett interpolation 3rd order */
- *axu = q*(x[n] + offset) + q3*d20
- + p*x[n+1] + p3*d2p1;
- *adxu = d0 + u*d2p1 - u0*d20;
- if ( o > 3 ) { /* 5th order */
- dm2 = x[n-1] - x[n-2];
- if (dm2 > 180.0) dm2 -= 360.0;
- if (dm2 < -180.0) dm2 += 360.0;
- dp2 = x[n+3] - x[n+2];
- if (dp2 > 180.0) dp2 -= 360.0;
- if (dp2 < -180.0) dp2 += 360.0;
- d2m1 = dm1 - dm2;
- d2p2 = dp2 - dp1;
- d30 = d20 - d2m1;
- d3p1 = d2p1 - d20;
- d3p2 = d2p2 - d2p1;
- d4p1 = d3p1 - d30; /* f7 */
- d4p2 = d3p2 - d3p1; /* f */
- *axu += p5*d4p2 + q5*d4p1;
- *adxu += u1*d4p2 - u2*d4p1;
- }
- return (OK);
- } /* end inpolq() */
-
- /*********************************************************
- position lrz file at proper position for julian date jd;
- Return OK or ERR. Version for outer planets.
- The path where the ephemeris files are looked for is defined
- by ephe_path.
- **********************************************************/
- int lrz_file_posit (jd, lrzfpp)
- double jd; /* full Julian day number, not Astrodienst relative */
- FILE **lrzfpp; /* pointer to file pointer; this function
- opens or closes the ephemeris file, and caller
- should keep it open while using it. The caller
- should close it when he is finished with using
- the placalc() package. */
- {
- int filenr;
- long posit, jlong;
- static char fname[80];
- static int open_lrznr = -10000; /* local memory to remember whether
- an already open file is the one with
- the correct number for this date */
- #ifndef ASTROLOG
- jlong = floor (jd);
- filenr = jlong / EPHE_DAYS_PER_FILE;
- #else
- jlong = (long)floor (jd);
- filenr = (int)(jlong / EPHE_DAYS_PER_FILE);
- #endif
- if (jlong < 0 && filenr * EPHE_DAYS_PER_FILE != jlong) filenr--;
- posit = jlong - filenr * EPHE_DAYS_PER_FILE;
- posit = (posit / (int) EPHE_STEP) * EPHE_OUTER_BSIZE;
- if (*lrzfpp == NULL || open_lrznr != filenr) { /* no or wrong open file */
- open_lrznr = -10000;
- if (filenr >= 0)
- sprintf (fname, "%s%s%s%d", ephe_path, DIR_GLUE, EPHE_OUTER, filenr);
- else
- sprintf (fname, "%s%s%sM%d", ephe_path, DIR_GLUE, EPHE_OUTER, -filenr);
- if (*lrzfpp == NULL)
- *lrzfpp = fopen (fname, OPEN_EPHE); /* open for read */
- else
- *lrzfpp = freopen (fname, OPEN_EPHE, *lrzfpp);
- if (*lrzfpp == NULL) {
- if (placalc_err_text != NULL)
- sprintf (placalc_err_text,"lrz_file_posit: file %s does not exist", fname);
- else
- fprintf (stderr,"lrz_file_posit: file %s does not exist\n", fname);
- return (ERR);
- }
- open_lrznr = filenr;
- }
- if (fseek (*lrzfpp, posit, 0) == 0)
- return (OK);
- if (placalc_err_text != NULL)
- sprintf (placalc_err_text,"lrz_file_posit: fseek error %s posit %ld", fname, posit);
- else
- fprintf (stderr,"lrz_file_posit: fseek error %s posit %ld\n", fname, posit);
- return (ERR); /* this fseek error occurs only with incomplete files */
- } /* end lrz_file_posit */
-
- /*********************************************************
- position chiron file at proper position for julian date jd;
- Return OK or ERR. Version for Chiron.
- Sister function to lrz_file_posit().
- **********************************************************/
- int chi_file_posit (jd, lrzfpp)
- double jd; /* full Julian day number, not Astrodienst relative */
- FILE **lrzfpp; /* pointer to file pointer; this function
- opens or closes the ephemeris file, and caller
- should keep it open while using it */
- {
- int filenr;
- long posit, jlong;
- char fname[80];
- static int open_lrznr = -10000; /* local memory to remember whether
- an already open file is the one with
- the correct number for this date */
- #ifndef ASTROLOG
- jlong = floor (jd);
- filenr = jlong / EPHE_DAYS_PER_FILE;
- #else
- jlong = (long)floor (jd);
- filenr = (int)(jlong / EPHE_DAYS_PER_FILE);
- #endif
- if (jlong < 0 && filenr * EPHE_DAYS_PER_FILE != jlong) filenr--;
- posit = jlong - filenr * EPHE_DAYS_PER_FILE;
- posit = (posit / (int) EPHE_STEP) * EPHE_CHIRON_BSIZE;
- if (*lrzfpp == NULL || open_lrznr != filenr) { /* no or wrong open file */
- open_lrznr = -10000;
- if (filenr >= 0)
- sprintf (fname, "%s%s%s%d", ephe_path, DIR_GLUE, EPHE_CHIRON, filenr);
- else
- sprintf (fname, "%s%s%sM%d", ephe_path, DIR_GLUE, EPHE_CHIRON, -filenr);
- if (*lrzfpp == NULL)
- *lrzfpp = fopen (fname, OPEN_EPHE); /* open for read */
- else
- *lrzfpp = freopen (fname, OPEN_EPHE, *lrzfpp); /* open for read */
- if (*lrzfpp == NULL) {
- if (placalc_err_text != NULL)
- sprintf (placalc_err_text,"chi_file_posit: file %s does not exist", fname);
- else
- fprintf (stderr,"chi_file_posit: file %s does not exist\n", fname);
- return (ERR);
- }
- open_lrznr = filenr;
- }
- if (fseek (*lrzfpp, posit, 0) == 0)
- return (OK);
- if (placalc_err_text != NULL)
- sprintf (placalc_err_text,"chi_file_posit: fseek error %s posit %ld", fname, posit);
- else
- fprintf (stderr,"chi_file_posit: fseek error %s posit %ld\n", fname, posit);
- return (ERR); /* this fseek error occurs only with incomplete files */
- } /* end chi_file_posit */
-
-
- /***********************************************************************/
- REAL8 fraction (REAL8 x) /* positive fraction: 3.4 -> 0.4, -3.7 -> 0.7 */
- {
- return (x - floor (x));
- }
-
- /***********************************************************
- function sidtime (t): returns sidereal time at greenwich;
- Parameters differ from ASYS version! after AESuppl. 1961, page 75
- version 24-oct-87
- ***********************************************************/
- REAL8 sidtime (REAL8 jd_ad, REAL8 ecl, REAL8 nuta)
- /* jd_ad relative julian date */
- /* ecl, nuta ecliptic and nutation of date, in degrees */
- {
- REAL8 tj, sec, x;
- tj = (jd_ad + 18262.0) / 36525.0; /* julian centuries from epoch 1900.0 */
- sec = 23925.836 + 8640184.542 * tj + 0.0929 * tj * tj;
- x = sec / 3600.0 / 24.0 + fraction (jd_ad - 0.5)
- + nuta / 360.0 * COS8 (DEGTORAD * ecl);
- return fraction(x) * 24.0;
- }
-
- /******************************************************************/
- REAL8 smod8360( REAL8 x ) /* x MOD 360.0, so that x in 0..<360 */
- {
- while ( x >= 360.0 ) x -= 360.0;
- while ( x < 0.0) x += 360.0;
- return x;
- } /* smod8360 */
-
- /******************************************************************/
- REAL8 mod8360( REAL8 x ) /* x MOD 360.0, so that x in 0..360 */
- {
- if ( x >= 0 && x < 360.0 ) return( x );
- return( x - 360.0 * floor ( x / 360.0 ) );
- } /* mod8360 */
-
- /******************************************************************/
- REAL8 diff8360 (REAL8 a, REAL8 b)
- /* a - b on a 360 degree circle, result -180..180*/
- {
- REAL8 d;
- d = a - b;
- if ( d >= 180.0 ) return( d - 360.0 );
- if ( d < -180.0 ) return( d + 360.0 );
- return( d );
- } /* diff8360 */
-
- /******************************************************************/
- REAL8 test_near_zero(REAL8 x )
- {
- if ( ABS8( x ) >= NEAR_ZERO ) return( x );
- if ( x < 0 ) return( -NEAR_ZERO );
- return( NEAR_ZERO );
- } /* test_near_zero */
-
- # if MSDOS
- /********************************************************************/
- #ifndef ASTROLOG
- longreorder (UCHAR *p, int n)
- #else
- void longreorder (UCHAR *p, int n)
- #endif
- /* p points to memory filled with long values; for
- each of the values the seqeuence of the four bytes
- has to be reversed, to translate HP-UX and VAX
- ordering to MSDOS/Turboc ordering */
- {
- int i;
- unsigned char c0, c1, c2, c3;
- for (i = 0; i < n; i += 4, p += 4) {
- c0 = *p;
- c1 = *(p + 1);
- c2 = *(p + 2);
- c3 = *(p + 3);
- *p = c3;
- *(p + 1) = c2;
- *(p + 2) = c1;
- *(p + 3) = c0;
- }
- }
- # endif
-
- /*
- * get the planet index for an AFL letter
- * returns -1 if the letter does not correspond to a planet.
- */
- int afl2planet(int afl)
- {
- int p;
- switch (afl) {
- case AFL_SUN : p = SUN; break;
- case AFL_MON : p = MOON; break;
- case AFL_MER : p = MERCURY; break;
- case AFL_VEN : p = VENUS; break;
- case AFL_MAR : p = MARS; break;
- case AFL_JUP : p = JUPITER; break;
- case AFL_SAT : p = SATURN; break;
- case AFL_URA : p = URANUS; break;
- case AFL_NEP : p = NEPTUNE; break;
- case AFL_PLU : p = PLUTO; break;
- case AFL_MNODE : p = MEAN_NODE; break;
- case AFL_TNODE : p = TRUE_NODE; break;
- case AFL_CHI : p = CHIRON; break;
- case AFL_LIL : p = LILITH; break;
- case AFL_AC : p = AC; break;
- case AFL_MC : p = MC; break;
- default : p = -1; break;
- }
- return p;
- }
-
- /*******************************************************************
- precession direction cosines from equator of date to 1950.0
- correct non-symmetric version from Suppl. 1961, p 30
- and AA (Astr.Almanach) 1983, p B18
- (pre-1984 precession must be used for transformation of Vol.22 data!)
- ********************************************************************/
- void getdc50(double j, double dceqdt50[3][3])
- {
- double t,t2,t3;
- double zeta, zet, th, sinz0, cosz0, sinz, cosz, sinth, costh;
- t=(j-2433282.423)/36524.22;
- t2=t*t;
- t3=t2*t;
- zeta = (0.6402633 * t + 0.0000839 * t2 + 0.0000050 * t3) * DEGTORAD;
- zet = zeta + 0.0002197 * t2 * DEGTORAD;
- th = (0.5567376 * t - 0.0001183 * t2 - 0.0000117 * t3) * DEGTORAD;
- cosz0 = cos(zeta);
- sinz0 = sin(zeta);
- cosz = cos(zet);
- sinz = sin(zet);
- costh = cos(th);
- sinth = sin(th);
- dceqdt50[0][0] = cosz0 * costh * cosz - sinz0 * sinz; /* Xx */
- dceqdt50[1][0] = -sinz0 * costh * cosz - cosz0 * sinz; /* Yx */
- dceqdt50[2][0] = -sinth * cosz; /* Zx */
- dceqdt50[0][1] = cosz0 * costh * sinz + sinz0 * cosz; /* Xy */
- dceqdt50[1][1] = -sinz0 * costh * sinz + cosz0 * cosz; /* Yy */
- dceqdt50[2][1] = -sinth * sinz; /* Zy */
- dceqdt50[0][2] = cosz0 * sinth; /* Xz */
- dceqdt50[1][2] = -sinz0 * sinth; /* Yz */
- dceqdt50[2][2] = costh; /* Zz */
- }
-
- void to_mean_ekl (double jd, double xyz[], double lrz[])
- /*
- * jd = absolute julian day
- * xyz[0..2] array with x, y, z equator 1950.0
- * Transform equatorial coordinates 1950.0
- * to ecliptic coordinates mean equinox of date.
- * Return values are stored in lrz[0..2]
- * as lrz[0] = mean longitude, lrz[1] = radius, lrz[2] = r * sin(lat).
- *
- * This function is not used within placalc itself and can be removed;
- * it was used to transform the coordinates from the numerical integration
- * program into the format as stored in the ephemeris files.
- */
- {
- double ex, ey, ez, ex0, ey0, ez0, ix, iy, iz, il, ir;
- double cosobl, sinobl;
- double ti, tj1, tj2;
- double dceqdt50[3][3];
- getdc50(jd, dceqdt50); /* calc precession matrix to equator of date */
- ti = (jd - 2415020) / 36525.0; /* julian centuries from 1900 */
- tj1 = ti / 3600.0;
- tj2 = ti * tj1;
- /* should agree with what is in ekld[], see helconst.c */
- meanekl = 23.452294 - 46.845 * tj1 -0.0059 * tj2 + 0.00181 * tj2 * ti;
- ex0 = xyz[0];
- ey0 = xyz[1];
- ez0 = xyz[2];
- ex=dceqdt50[0][0]*ex0+dceqdt50[1][0]*ey0+dceqdt50[2][0]*ez0;
- ey=dceqdt50[0][1]*ex0+dceqdt50[1][1]*ey0+dceqdt50[2][1]*ez0;
- ez=dceqdt50[0][2]*ex0+dceqdt50[1][2]*ey0+dceqdt50[2][2]*ez0;
- /* now we have equator of date and go to mean ekl of date */
- cosobl = cos(meanekl * DEGTORAD);
- sinobl = sin(meanekl * DEGTORAD);
- ix = ex;
- iy = ey * cosobl + ez * sinobl;
- iz = -ey * sinobl + ez * cosobl;
- /* convert xyz to longitude = il and radius = ir */
- ir = sqrt(ix * ix + iy * iy + iz * iz);
- il = atan2(iy, ix) * RADTODEG; /* returns range -pi .. pi */
- if ( il < 0) il += 360.0;
- lrz[0] = il;
- lrz[1] = ir;
- lrz[2] = iz;
- }
- #endif /* PLACALC */
- #ifdef ASTROLOG
- /* End contents of placalc.c */
- #endif
-