swe4r 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/ext/swe4r/extconf.rb +3 -0
- data/ext/swe4r/src/swemptab.c +10642 -0
- data/ext/swe4r/swe4r.c +129 -0
- data/ext/swe4r/swecl.c +4948 -0
- data/ext/swe4r/swedate.c +590 -0
- data/ext/swe4r/swedate.h +82 -0
- data/ext/swe4r/swehel.c +3445 -0
- data/ext/swe4r/swehouse.c +1727 -0
- data/ext/swe4r/swehouse.h +85 -0
- data/ext/swe4r/swejpl.c +937 -0
- data/ext/swe4r/swejpl.h +105 -0
- data/ext/swe4r/swemmoon.c +1824 -0
- data/ext/swe4r/swemplan.c +959 -0
- data/ext/swe4r/swenut2000a.h +2820 -0
- data/ext/swe4r/sweodef.h +325 -0
- data/ext/swe4r/sweph.c +6241 -0
- data/ext/swe4r/sweph.h +556 -0
- data/ext/swe4r/swephexp.h +749 -0
- data/ext/swe4r/swephlib.c +2581 -0
- data/ext/swe4r/swephlib.h +177 -0
- data/lib/swe4r.rb +2 -0
- metadata +66 -0
data/ext/swe4r/swecl.c
ADDED
@@ -0,0 +1,4948 @@
|
|
1
|
+
/* SWISSEPH
|
2
|
+
$Header: /home/dieter/sweph/RCS/swecl.c,v 1.75 2008/08/26 07:23:27 dieter Exp $
|
3
|
+
|
4
|
+
Ephemeris computations
|
5
|
+
Author: Dieter Koch
|
6
|
+
|
7
|
+
************************************************************/
|
8
|
+
/* Copyright (C) 1997 - 2008 Astrodienst AG, Switzerland. All rights reserved.
|
9
|
+
|
10
|
+
License conditions
|
11
|
+
------------------
|
12
|
+
|
13
|
+
This file is part of Swiss Ephemeris.
|
14
|
+
|
15
|
+
Swiss Ephemeris is distributed with NO WARRANTY OF ANY KIND. No author
|
16
|
+
or distributor accepts any responsibility for the consequences of using it,
|
17
|
+
or for whether it serves any particular purpose or works at all, unless he
|
18
|
+
or she says so in writing.
|
19
|
+
|
20
|
+
Swiss Ephemeris is made available by its authors under a dual licensing
|
21
|
+
system. The software developer, who uses any part of Swiss Ephemeris
|
22
|
+
in his or her software, must choose between one of the two license models,
|
23
|
+
which are
|
24
|
+
a) GNU public license version 2 or later
|
25
|
+
b) Swiss Ephemeris Professional License
|
26
|
+
|
27
|
+
The choice must be made before the software developer distributes software
|
28
|
+
containing parts of Swiss Ephemeris to others, and before any public
|
29
|
+
service using the developed software is activated.
|
30
|
+
|
31
|
+
If the developer choses the GNU GPL software license, he or she must fulfill
|
32
|
+
the conditions of that license, which includes the obligation to place his
|
33
|
+
or her whole software project under the GNU GPL or a compatible license.
|
34
|
+
See http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
35
|
+
|
36
|
+
If the developer choses the Swiss Ephemeris Professional license,
|
37
|
+
he must follow the instructions as found in http://www.astro.com/swisseph/
|
38
|
+
and purchase the Swiss Ephemeris Professional Edition from Astrodienst
|
39
|
+
and sign the corresponding license contract.
|
40
|
+
|
41
|
+
The License grants you the right to use, copy, modify and redistribute
|
42
|
+
Swiss Ephemeris, but only under certain conditions described in the License.
|
43
|
+
Among other things, the License requires that the copyright notices and
|
44
|
+
this notice be preserved on all copies.
|
45
|
+
|
46
|
+
Authors of the Swiss Ephemeris: Dieter Koch and Alois Treindl
|
47
|
+
|
48
|
+
The authors of Swiss Ephemeris have no control or influence over any of
|
49
|
+
the derived works, i.e. over software or services created by other
|
50
|
+
programmers which use Swiss Ephemeris functions.
|
51
|
+
|
52
|
+
The names of the authors or of the copyright holder (Astrodienst) must not
|
53
|
+
be used for promoting any software, product or service which uses or contains
|
54
|
+
the Swiss Ephemeris. This copyright notice is the ONLY place where the
|
55
|
+
names of the authors can legally appear, except in cases where they have
|
56
|
+
given special permission in writing.
|
57
|
+
|
58
|
+
The trademarks 'Swiss Ephemeris' and 'Swiss Ephemeris inside' may be used
|
59
|
+
for promoting such software, products or services.
|
60
|
+
*/
|
61
|
+
|
62
|
+
#include "swejpl.h"
|
63
|
+
#include "swephexp.h"
|
64
|
+
#include "sweph.h"
|
65
|
+
#include "swephlib.h"
|
66
|
+
|
67
|
+
#define SEFLG_EPHMASK (SEFLG_JPLEPH|SEFLG_SWIEPH|SEFLG_MOSEPH)
|
68
|
+
static int find_maximum(double y00, double y11, double y2, double dx,
|
69
|
+
double *dxret, double *yret);
|
70
|
+
static int find_zero(double y00, double y11, double y2, double dx,
|
71
|
+
double *dxret, double *dxret2);
|
72
|
+
static double calc_dip(double geoalt, double atpress, double attemp, double lapse_rate);
|
73
|
+
static double calc_astronomical_refr(double geoalt,double atpress, double attemp);
|
74
|
+
static double const_lapse_rate = SE_LAPSE_RATE; /* for refraction */
|
75
|
+
|
76
|
+
#if 0
|
77
|
+
#define DSUN (1391978489.9 / AUNIT) /* this value is consistent with
|
78
|
+
* 959.63 arcsec at AU distance (Astr. Alm.) */
|
79
|
+
#else
|
80
|
+
#define DSUN (1392000000.0 / AUNIT)
|
81
|
+
#endif
|
82
|
+
#define DMOON (3476300.0 / AUNIT)
|
83
|
+
#define DEARTH (6378140.0 * 2 / AUNIT)
|
84
|
+
#define RSUN (DSUN / 2)
|
85
|
+
#define RMOON (DMOON / 2)
|
86
|
+
#define REARTH (DEARTH / 2)
|
87
|
+
/*#define SEI_OCC_FAST (16 * 1024L)*/
|
88
|
+
static int32 eclipse_where( double tjd_ut, int32 ipl, char *starname, int32 ifl, double *geopos,
|
89
|
+
double *dcore, char *serr);
|
90
|
+
static int32 eclipse_how( double tjd_ut, int32 ipl, char *starname, int32 ifl,
|
91
|
+
double geolon, double geolat, double geohgt,
|
92
|
+
double *attr, char *serr);
|
93
|
+
static int32 eclipse_when_loc(double tjd_start, int32 ifl, double *geopos,
|
94
|
+
double *tret, double *attr, AS_BOOL backward, char *serr);
|
95
|
+
static int32 occult_when_loc(double tjd_start, int32 ipl, char *starname, int32 ifl,
|
96
|
+
double *geopos, double *tret, double *attr, AS_BOOL backward, char *serr);
|
97
|
+
static int32 lun_eclipse_how(double tjd_ut, int32 ifl, double *attr,
|
98
|
+
double *dcore, char *serr);
|
99
|
+
static int32 calc_mer_trans(
|
100
|
+
double tjd_ut, int32 ipl, int32 epheflag, int32 rsmi,
|
101
|
+
double *geopos,
|
102
|
+
char *starname,
|
103
|
+
double *tret,
|
104
|
+
char *serr);
|
105
|
+
static int32 calc_planet_star(double tjd_et, int32 ipl, char *starname, int32 iflag, double *x, char *serr);
|
106
|
+
|
107
|
+
struct saros_data {int series_no; double tstart;};
|
108
|
+
|
109
|
+
#define SAROS_CYCLE 6585.3213
|
110
|
+
#define NSAROS_SOLAR 181
|
111
|
+
struct saros_data saros_data_solar[NSAROS_SOLAR] = {
|
112
|
+
{0, 641886.5}, /* 23 May -2955 */
|
113
|
+
{1, 672214.5}, /* 04 Jun -2872 */
|
114
|
+
{2, 676200.5}, /* 04 May -2861 */
|
115
|
+
{3, 693357.5}, /* 24 Apr -2814 */
|
116
|
+
{4, 723685.5}, /* 06 May -2731 */
|
117
|
+
{5, 727671.5}, /* 04 Apr -2720 */
|
118
|
+
{6, 744829.5}, /* 27 Mar -2673 */
|
119
|
+
{7, 775157.5}, /* 08 Apr -2590 */
|
120
|
+
{8, 779143.5}, /* 07 Mar -2579 */
|
121
|
+
{9, 783131.5}, /* 06 Feb -2568 */
|
122
|
+
{10, 820044.5}, /* 28 Feb -2467 */
|
123
|
+
{11, 810859.5}, /* 06 Jan -2492 */
|
124
|
+
{12, 748993.5}, /* 20 Aug -2662 */
|
125
|
+
{13, 792492.5}, /* 23 Sep -2543 */
|
126
|
+
{14, 789892.5}, /* 11 Aug -2550 */
|
127
|
+
{15, 787294.5}, /* 01 Jul -2557 */
|
128
|
+
{16, 824207.5}, /* 23 Jul -2456 */
|
129
|
+
{17, 834779.5}, /* 03 Jul -2427 */
|
130
|
+
{18, 838766.5}, /* 02 Jun -2416 */
|
131
|
+
{19, 869094.5}, /* 15 Jun -2333 */
|
132
|
+
{20, 886251.5}, /* 05 Jun -2286 */
|
133
|
+
{21, 890238.5}, /* 05 May -2275 */
|
134
|
+
{22, 927151.5}, /* 28 May -2174 */
|
135
|
+
{23, 937722.5}, /* 07 May -2145 */
|
136
|
+
{24, 941709.5}, /* 06 Apr -2134 */
|
137
|
+
{25, 978623.5}, /* 30 Apr -2033 */
|
138
|
+
{26, 989194.5}, /* 08 Apr -2004 */
|
139
|
+
{27, 993181.5}, /* 09 Mar -1993 */
|
140
|
+
{28, 1023510.5}, /* 22 Mar -1910 */
|
141
|
+
{29, 1034081.5}, /* 01 Mar -1881 */
|
142
|
+
{30, 972214.5}, /* 12 Oct -2051 */
|
143
|
+
{31, 1061811.5}, /* 31 Jan -1805 */
|
144
|
+
{32, 1006529.5}, /* 24 Sep -1957 */
|
145
|
+
{33, 997345.5}, /* 02 Aug -1982 */
|
146
|
+
{34, 1021088.5}, /* 04 Aug -1917 */
|
147
|
+
{35, 1038245.5}, /* 25 Jul -1870 */
|
148
|
+
{36, 1042231.5}, /* 23 Jun -1859 */
|
149
|
+
{37, 1065974.5}, /* 25 Jun -1794 */
|
150
|
+
{38, 1089716.5}, /* 26 Jun -1729 */
|
151
|
+
{39, 1093703.5}, /* 26 May -1718 */
|
152
|
+
{40, 1117446.5}, /* 28 May -1653 */
|
153
|
+
{41, 1141188.5}, /* 28 May -1588 */
|
154
|
+
{42, 1145175.5}, /* 28 Apr -1577 */
|
155
|
+
{43, 1168918.5}, /* 29 Apr -1512 */
|
156
|
+
{44, 1192660.5}, /* 30 Apr -1447 */
|
157
|
+
{45, 1196647.5}, /* 30 Mar -1436 */
|
158
|
+
{46, 1220390.5}, /* 01 Apr -1371 */
|
159
|
+
{47, 1244132.5}, /* 02 Apr -1306 */
|
160
|
+
{48, 1234948.5}, /* 08 Feb -1331 */
|
161
|
+
{49, 1265277.5}, /* 22 Feb -1248 */
|
162
|
+
{50, 1282433.5}, /* 11 Feb -1201 */
|
163
|
+
{51, 1207395.5}, /* 02 Sep -1407 */
|
164
|
+
{52, 1217968.5}, /* 14 Aug -1378 */
|
165
|
+
{53, 1254881.5}, /* 06 Sep -1277 */
|
166
|
+
{54, 1252282.5}, /* 25 Jul -1284 */
|
167
|
+
{55, 1262855.5}, /* 06 Jul -1255 */
|
168
|
+
{56, 1293182.5}, /* 17 Jul -1172 */
|
169
|
+
{57, 1297169.5}, /* 17 Jun -1161 */
|
170
|
+
{58, 1314326.5}, /* 07 Jun -1114 */
|
171
|
+
{59, 1344654.5}, /* 19 Jun -1031 */
|
172
|
+
{60, 1348640.5}, /* 18 May -1020 */
|
173
|
+
{61, 1365798.5}, /* 10 May -0973 */
|
174
|
+
{62, 1396126.5}, /* 22 May -0890 */
|
175
|
+
{63, 1400112.5}, /* 20 Apr -0879 */
|
176
|
+
{64, 1417270.5}, /* 11 Apr -0832 */
|
177
|
+
{65, 1447598.5}, /* 24 Apr -0749 */
|
178
|
+
{66, 1444999.5}, /* 12 Mar -0756 */
|
179
|
+
{67, 1462157.5}, /* 04 Mar -0709 */
|
180
|
+
{68, 1492485.5}, /* 16 Mar -0626 */
|
181
|
+
{69, 1456959.5}, /* 09 Dec -0724 */
|
182
|
+
{70, 1421434.5}, /* 05 Sep -0821 */
|
183
|
+
{71, 1471518.5}, /* 19 Oct -0684 */
|
184
|
+
{72, 1455748.5}, /* 16 Aug -0727 */
|
185
|
+
{73, 1466320.5}, /* 27 Jul -0698 */
|
186
|
+
{74, 1496648.5}, /* 08 Aug -0615 */
|
187
|
+
{75, 1500634.5}, /* 07 Jul -0604 */
|
188
|
+
{76, 1511207.5}, /* 18 Jun -0575 */
|
189
|
+
{77, 1548120.5}, /* 11 Jul -0474 */
|
190
|
+
{78, 1552106.5}, /* 09 Jun -0463 */
|
191
|
+
{79, 1562679.5}, /* 21 May -0434 */
|
192
|
+
{80, 1599592.5}, /* 13 Jun -0333 */
|
193
|
+
{81, 1603578.5}, /* 12 May -0322 */
|
194
|
+
{82, 1614150.5}, /* 22 Apr -0293 */
|
195
|
+
{83, 1644479.5}, /* 05 May -0210 */
|
196
|
+
{84, 1655050.5}, /* 14 Apr -0181 */
|
197
|
+
{85, 1659037.5}, /* 14 Mar -0170 */
|
198
|
+
{86, 1695950.5}, /* 06 Apr -0069 */
|
199
|
+
{87, 1693351.5}, /* 23 Feb -0076 */
|
200
|
+
{88, 1631484.5}, /* 06 Oct -0246 */
|
201
|
+
{89, 1727666.5}, /* 04 Feb 0018 */
|
202
|
+
{90, 1672384.5}, /* 28 Sep -0134 */
|
203
|
+
{91, 1663200.5}, /* 06 Aug -0159 */
|
204
|
+
{92, 1693529.5}, /* 19 Aug -0076 */
|
205
|
+
{93, 1710685.5}, /* 09 Aug -0029 */
|
206
|
+
{94, 1714672.5}, /* 09 Jul -0018 */
|
207
|
+
{95, 1738415.5}, /* 11 Jul 0047 */
|
208
|
+
{96, 1755572.5}, /* 01 Jul 0094 */
|
209
|
+
{97, 1766144.5}, /* 11 Jun 0123 */
|
210
|
+
{98, 1789887.5}, /* 12 Jun 0188 */
|
211
|
+
{99, 1807044.5}, /* 03 Jun 0235 */
|
212
|
+
{100, 1817616.5}, /* 13 May 0264 */
|
213
|
+
{101, 1841359.5}, /* 15 May 0329 */
|
214
|
+
{102, 1858516.5}, /* 05 May 0376 */
|
215
|
+
{103, 1862502.5}, /* 04 Apr 0387 */
|
216
|
+
{104, 1892831.5}, /* 17 Apr 0470 */
|
217
|
+
{105, 1903402.5}, /* 27 Mar 0499 */
|
218
|
+
{106, 1887633.5}, /* 23 Jan 0456 */
|
219
|
+
{107, 1924547.5}, /* 15 Feb 0557 */
|
220
|
+
{108, 1921948.5}, /* 04 Jan 0550 */
|
221
|
+
{109, 1873251.5}, /* 07 Sep 0416 */
|
222
|
+
{110, 1890409.5}, /* 30 Aug 0463 */
|
223
|
+
{111, 1914151.5}, /* 30 Aug 0528 */
|
224
|
+
{112, 1918138.5}, /* 31 Jul 0539 */
|
225
|
+
{113, 1935296.5}, /* 22 Jul 0586 */
|
226
|
+
{114, 1959038.5}, /* 23 Jul 0651 */
|
227
|
+
{115, 1963024.5}, /* 21 Jun 0662 */
|
228
|
+
{116, 1986767.5}, /* 23 Jun 0727 */
|
229
|
+
{117, 2010510.5}, /* 24 Jun 0792 */
|
230
|
+
{118, 2014496.5}, /* 24 May 0803 */
|
231
|
+
{119, 2031654.5}, /* 15 May 0850 */
|
232
|
+
{120, 2061982.5}, /* 27 May 0933 */
|
233
|
+
{121, 2065968.5}, /* 25 Apr 0944 */
|
234
|
+
{122, 2083126.5}, /* 17 Apr 0991 */
|
235
|
+
{123, 2113454.5}, /* 29 Apr 1074 */
|
236
|
+
{124, 2104269.5}, /* 06 Mar 1049 */
|
237
|
+
{125, 2108256.5}, /* 04 Feb 1060 */
|
238
|
+
{126, 2151755.5}, /* 10 Mar 1179 */
|
239
|
+
{127, 2083302.5}, /* 10 Oct 0991 */
|
240
|
+
{128, 2080704.5}, /* 29 Aug 0984 */
|
241
|
+
{129, 2124203.5}, /* 03 Oct 1103 */
|
242
|
+
{130, 2121603.5}, /* 20 Aug 1096 */
|
243
|
+
{131, 2132176.5}, /* 01 Aug 1125 */
|
244
|
+
{132, 2162504.5}, /* 13 Aug 1208 */
|
245
|
+
{133, 2166490.5}, /* 13 Jul 1219 */
|
246
|
+
{134, 2177062.5}, /* 22 Jun 1248 */
|
247
|
+
{135, 2207390.5}, /* 05 Jul 1331 */
|
248
|
+
{136, 2217962.5}, /* 14 Jun 1360 */
|
249
|
+
{137, 2228534.5}, /* 25 May 1389 */
|
250
|
+
{138, 2258862.5}, /* 06 Jun 1472 */
|
251
|
+
{139, 2269434.5}, /* 17 May 1501 */
|
252
|
+
{140, 2273421.5}, /* 16 Apr 1512 */
|
253
|
+
{141, 2310334.5}, /* 19 May 1613 */
|
254
|
+
{142, 2314320.5}, /* 17 Apr 1624 */
|
255
|
+
{143, 2311722.5}, /* 07 Mar 1617 */
|
256
|
+
{144, 2355221.5}, /* 11 Apr 1736 */
|
257
|
+
{145, 2319695.5}, /* 04 Jan 1639 */
|
258
|
+
{146, 2284169.5}, /* 19 Sep 1541 */
|
259
|
+
{147, 2314498.5}, /* 12 Oct 1624 */
|
260
|
+
{148, 2325069.5}, /* 21 Sep 1653 */
|
261
|
+
{149, 2329056.5}, /* 21 Aug 1664 */
|
262
|
+
{150, 2352799.5}, /* 24 Aug 1729 */
|
263
|
+
{151, 2369956.5}, /* 14 Aug 1776 */
|
264
|
+
{152, 2380528.5}, /* 26 Jul 1805 */
|
265
|
+
{153, 2404271.5}, /* 28 Jul 1870 */
|
266
|
+
{154, 2421428.5}, /* 19 Jul 1917 */
|
267
|
+
{155, 2425414.5}, /* 17 Jun 1928 */
|
268
|
+
{156, 2455743.5}, /* 01 Jul 2011 */
|
269
|
+
{157, 2472900.5}, /* 21 Jun 2058 */
|
270
|
+
{158, 2476886.5}, /* 20 May 2069 */
|
271
|
+
{159, 2500629.5}, /* 23 May 2134 */
|
272
|
+
{160, 2517786.5}, /* 13 May 2181 */
|
273
|
+
{161, 2515187.5}, /* 01 Apr 2174 */
|
274
|
+
{162, 2545516.5}, /* 15 Apr 2257 */
|
275
|
+
{163, 2556087.5}, /* 25 Mar 2286 */
|
276
|
+
{164, 2487635.5}, /* 24 Oct 2098 */
|
277
|
+
{165, 2504793.5}, /* 16 Oct 2145 */
|
278
|
+
{166, 2535121.5}, /* 29 Oct 2228 */
|
279
|
+
{167, 2525936.5}, /* 06 Sep 2203 */
|
280
|
+
{168, 2543094.5}, /* 28 Aug 2250 */
|
281
|
+
{169, 2573422.5}, /* 10 Sep 2333 */
|
282
|
+
{170, 2577408.5}, /* 09 Aug 2344 */
|
283
|
+
{171, 2594566.5}, /* 01 Aug 2391 */
|
284
|
+
{172, 2624894.5}, /* 13 Aug 2474 */
|
285
|
+
{173, 2628880.5}, /* 12 Jul 2485 */
|
286
|
+
{174, 2646038.5}, /* 04 Jul 2532 */
|
287
|
+
{175, 2669780.5}, /* 05 Jul 2597 */
|
288
|
+
{176, 2673766.5}, /* 04 Jun 2608 */
|
289
|
+
{177, 2690924.5}, /* 27 May 2655 */
|
290
|
+
{178, 2721252.5}, /* 09 Jun 2738 */
|
291
|
+
{179, 2718653.5}, /* 28 Apr 2731 */
|
292
|
+
{180, 2729226.5}, /* 08 Apr 2760 */
|
293
|
+
};
|
294
|
+
|
295
|
+
#define NSAROS_LUNAR 180
|
296
|
+
struct saros_data saros_data_lunar[NSAROS_LUNAR] = {
|
297
|
+
{1, 782437.5}, /* 14 Mar -2570 */
|
298
|
+
{2, 799593.5}, /* 03 Mar -2523 */
|
299
|
+
{3, 783824.5}, /* 30 Dec -2567 */
|
300
|
+
{4, 754884.5}, /* 06 Oct -2646 */
|
301
|
+
{5, 824724.5}, /* 22 Dec -2455 */
|
302
|
+
{6, 762857.5}, /* 04 Aug -2624 */
|
303
|
+
{7, 773430.5}, /* 16 Jul -2595 */
|
304
|
+
{8, 810343.5}, /* 08 Aug -2494 */
|
305
|
+
{9, 807743.5}, /* 26 Jun -2501 */
|
306
|
+
{10, 824901.5}, /* 17 Jun -2454 */
|
307
|
+
{11, 855229.5}, /* 29 Jun -2371 */
|
308
|
+
{12, 859215.5}, /* 28 May -2360 */
|
309
|
+
{13, 876373.5}, /* 20 May -2313 */
|
310
|
+
{14, 906701.5}, /* 01 Jun -2230 */
|
311
|
+
{15, 910687.5}, /* 30 Apr -2219 */
|
312
|
+
{16, 927845.5}, /* 21 Apr -2172 */
|
313
|
+
{17, 958173.5}, /* 04 May -2089 */
|
314
|
+
{18, 962159.5}, /* 02 Apr -2078 */
|
315
|
+
{19, 979317.5}, /* 24 Mar -2031 */
|
316
|
+
{20, 1009645.5}, /* 05 Apr -1948 */
|
317
|
+
{21, 1007046.5}, /* 22 Feb -1955 */
|
318
|
+
{22, 1017618.5}, /* 02 Feb -1926 */
|
319
|
+
{23, 1054531.5}, /* 25 Feb -1825 */
|
320
|
+
{24, 979493.5}, /* 16 Sep -2031 */
|
321
|
+
{25, 976895.5}, /* 06 Aug -2038 */
|
322
|
+
{26, 1020394.5}, /* 09 Sep -1919 */
|
323
|
+
{27, 1017794.5}, /* 28 Jul -1926 */
|
324
|
+
{28, 1028367.5}, /* 09 Jul -1897 */
|
325
|
+
{29, 1058695.5}, /* 21 Jul -1814 */
|
326
|
+
{30, 1062681.5}, /* 19 Jun -1803 */
|
327
|
+
{31, 1073253.5}, /* 30 May -1774 */
|
328
|
+
{32, 1110167.5}, /* 23 Jun -1673 */
|
329
|
+
{33, 1114153.5}, /* 22 May -1662 */
|
330
|
+
{34, 1131311.5}, /* 13 May -1615 */
|
331
|
+
{35, 1161639.5}, /* 25 May -1532 */
|
332
|
+
{36, 1165625.5}, /* 24 Apr -1521 */
|
333
|
+
{37, 1176197.5}, /* 03 Apr -1492 */
|
334
|
+
{38, 1213111.5}, /* 27 Apr -1391 */
|
335
|
+
{39, 1217097.5}, /* 26 Mar -1380 */
|
336
|
+
{40, 1221084.5}, /* 24 Feb -1369 */
|
337
|
+
{41, 1257997.5}, /* 18 Mar -1268 */
|
338
|
+
{42, 1255398.5}, /* 04 Feb -1275 */
|
339
|
+
{43, 1186946.5}, /* 07 Sep -1463 */
|
340
|
+
{44, 1283128.5}, /* 06 Jan -1199 */
|
341
|
+
{45, 1227845.5}, /* 29 Aug -1351 */
|
342
|
+
{46, 1225247.5}, /* 19 Jul -1358 */
|
343
|
+
{47, 1255575.5}, /* 31 Jul -1275 */
|
344
|
+
{48, 1272732.5}, /* 21 Jul -1228 */
|
345
|
+
{49, 1276719.5}, /* 21 Jun -1217 */
|
346
|
+
{50, 1307047.5}, /* 03 Jul -1134 */
|
347
|
+
{51, 1317619.5}, /* 13 Jun -1105 */
|
348
|
+
{52, 1328191.5}, /* 23 May -1076 */
|
349
|
+
{53, 1358519.5}, /* 05 Jun -0993 */
|
350
|
+
{54, 1375676.5}, /* 26 May -0946 */
|
351
|
+
{55, 1379663.5}, /* 25 Apr -0935 */
|
352
|
+
{56, 1409991.5}, /* 07 May -0852 */
|
353
|
+
{57, 1420562.5}, /* 16 Apr -0823 */
|
354
|
+
{58, 1424549.5}, /* 16 Mar -0812 */
|
355
|
+
{59, 1461463.5}, /* 09 Apr -0711 */
|
356
|
+
{60, 1465449.5}, /* 08 Mar -0700 */
|
357
|
+
{61, 1436509.5}, /* 13 Dec -0780 */
|
358
|
+
{62, 1493179.5}, /* 08 Feb -0624 */
|
359
|
+
{63, 1457653.5}, /* 03 Nov -0722 */
|
360
|
+
{64, 1435298.5}, /* 20 Aug -0783 */
|
361
|
+
{65, 1452456.5}, /* 11 Aug -0736 */
|
362
|
+
{66, 1476198.5}, /* 12 Aug -0671 */
|
363
|
+
{67, 1480184.5}, /* 11 Jul -0660 */
|
364
|
+
{68, 1503928.5}, /* 14 Jul -0595 */
|
365
|
+
{69, 1527670.5}, /* 15 Jul -0530 */
|
366
|
+
{70, 1531656.5}, /* 13 Jun -0519 */
|
367
|
+
{71, 1548814.5}, /* 04 Jun -0472 */
|
368
|
+
{72, 1579142.5}, /* 17 Jun -0389 */
|
369
|
+
{73, 1583128.5}, /* 16 May -0378 */
|
370
|
+
{74, 1600286.5}, /* 07 May -0331 */
|
371
|
+
{75, 1624028.5}, /* 08 May -0266 */
|
372
|
+
{76, 1628015.5}, /* 07 Apr -0255 */
|
373
|
+
{77, 1651758.5}, /* 09 Apr -0190 */
|
374
|
+
{78, 1675500.5}, /* 10 Apr -0125 */
|
375
|
+
{79, 1672901.5}, /* 27 Feb -0132 */
|
376
|
+
{80, 1683474.5}, /* 07 Feb -0103 */
|
377
|
+
{81, 1713801.5}, /* 19 Feb -0020 */
|
378
|
+
{82, 1645349.5}, /* 21 Sep -0208 */
|
379
|
+
{83, 1649336.5}, /* 22 Aug -0197 */
|
380
|
+
{84, 1686249.5}, /* 13 Sep -0096 */
|
381
|
+
{85, 1683650.5}, /* 02 Aug -0103 */
|
382
|
+
{86, 1694222.5}, /* 13 Jul -0074 */
|
383
|
+
{87, 1731136.5}, /* 06 Aug 0027 */
|
384
|
+
{88, 1735122.5}, /* 05 Jul 0038 */
|
385
|
+
{89, 1745694.5}, /* 15 Jun 0067 */
|
386
|
+
{90, 1776022.5}, /* 27 Jun 0150 */
|
387
|
+
{91, 1786594.5}, /* 07 Jun 0179 */
|
388
|
+
{92, 1797166.5}, /* 17 May 0208 */
|
389
|
+
{93, 1827494.5}, /* 30 May 0291 */
|
390
|
+
{94, 1838066.5}, /* 09 May 0320 */
|
391
|
+
{95, 1848638.5}, /* 19 Apr 0349 */
|
392
|
+
{96, 1878966.5}, /* 01 May 0432 */
|
393
|
+
{97, 1882952.5}, /* 31 Mar 0443 */
|
394
|
+
{98, 1880354.5}, /* 18 Feb 0436 */
|
395
|
+
{99, 1923853.5}, /* 24 Mar 0555 */
|
396
|
+
{100, 1881741.5}, /* 06 Dec 0439 */
|
397
|
+
{101, 1852801.5}, /* 11 Sep 0360 */
|
398
|
+
{102, 1889715.5}, /* 05 Oct 0461 */
|
399
|
+
{103, 1893701.5}, /* 03 Sep 0472 */
|
400
|
+
{104, 1897688.5}, /* 04 Aug 0483 */
|
401
|
+
{105, 1928016.5}, /* 16 Aug 0566 */
|
402
|
+
{106, 1938588.5}, /* 27 Jul 0595 */
|
403
|
+
{107, 1942575.5}, /* 26 Jun 0606 */
|
404
|
+
{108, 1972903.5}, /* 08 Jul 0689 */
|
405
|
+
{109, 1990059.5}, /* 27 Jun 0736 */
|
406
|
+
{110, 1994046.5}, /* 28 May 0747 */
|
407
|
+
{111, 2024375.5}, /* 10 Jun 0830 */
|
408
|
+
{112, 2034946.5}, /* 20 May 0859 */
|
409
|
+
{113, 2045518.5}, /* 29 Apr 0888 */
|
410
|
+
{114, 2075847.5}, /* 13 May 0971 */
|
411
|
+
{115, 2086418.5}, /* 21 Apr 1000 */
|
412
|
+
{116, 2083820.5}, /* 11 Mar 0993 */
|
413
|
+
{117, 2120733.5}, /* 03 Apr 1094 */
|
414
|
+
{118, 2124719.5}, /* 02 Mar 1105 */
|
415
|
+
{119, 2062852.5}, /* 14 Oct 0935 */
|
416
|
+
{120, 2086596.5}, /* 16 Oct 1000 */
|
417
|
+
{121, 2103752.5}, /* 06 Oct 1047 */
|
418
|
+
{122, 2094568.5}, /* 14 Aug 1022 */
|
419
|
+
{123, 2118311.5}, /* 16 Aug 1087 */
|
420
|
+
{124, 2142054.5}, /* 17 Aug 1152 */
|
421
|
+
{125, 2146040.5}, /* 17 Jul 1163 */
|
422
|
+
{126, 2169783.5}, /* 18 Jul 1228 */
|
423
|
+
{127, 2186940.5}, /* 09 Jul 1275 */
|
424
|
+
{128, 2197512.5}, /* 18 Jun 1304 */
|
425
|
+
{129, 2214670.5}, /* 10 Jun 1351 */
|
426
|
+
{130, 2238412.5}, /* 10 Jun 1416 */
|
427
|
+
{131, 2242398.5}, /* 10 May 1427 */
|
428
|
+
{132, 2266142.5}, /* 12 May 1492 */
|
429
|
+
{133, 2289884.5}, /* 13 May 1557 */
|
430
|
+
{134, 2287285.5}, /* 01 Apr 1550 */
|
431
|
+
{135, 2311028.5}, /* 13 Apr 1615 */
|
432
|
+
{136, 2334770.5}, /* 13 Apr 1680 */
|
433
|
+
{137, 2292659.5}, /* 17 Dec 1564 */
|
434
|
+
{138, 2276890.5}, /* 15 Oct 1521 */
|
435
|
+
{139, 2326974.5}, /* 09 Dec 1658 */
|
436
|
+
{140, 2304619.5}, /* 25 Sep 1597 */
|
437
|
+
{141, 2308606.5}, /* 25 Aug 1608 */
|
438
|
+
{142, 2345520.5}, /* 19 Sep 1709 */
|
439
|
+
{143, 2349506.5}, /* 18 Aug 1720 */
|
440
|
+
{144, 2360078.5}, /* 29 Jul 1749 */
|
441
|
+
{145, 2390406.5}, /* 11 Aug 1832 */
|
442
|
+
{146, 2394392.5}, /* 11 Jul 1843 */
|
443
|
+
{147, 2411550.5}, /* 02 Jul 1890 */
|
444
|
+
{148, 2441878.5}, /* 15 Jul 1973 */
|
445
|
+
{149, 2445864.5}, /* 13 Jun 1984 */
|
446
|
+
{150, 2456437.5}, /* 25 May 2013 */
|
447
|
+
{151, 2486765.5}, /* 06 Jun 2096 */
|
448
|
+
{152, 2490751.5}, /* 07 May 2107 */
|
449
|
+
{153, 2501323.5}, /* 16 Apr 2136 */
|
450
|
+
{154, 2538236.5}, /* 10 May 2237 */
|
451
|
+
{155, 2529052.5}, /* 18 Mar 2212 */
|
452
|
+
{156, 2473771.5}, /* 08 Nov 2060 */
|
453
|
+
{157, 2563367.5}, /* 01 Mar 2306 */
|
454
|
+
{158, 2508085.5}, /* 21 Oct 2154 */
|
455
|
+
{159, 2505486.5}, /* 09 Sep 2147 */
|
456
|
+
{160, 2542400.5}, /* 03 Oct 2248 */
|
457
|
+
{161, 2546386.5}, /* 02 Sep 2259 */
|
458
|
+
{162, 2556958.5}, /* 12 Aug 2288 */
|
459
|
+
{163, 2587287.5}, /* 27 Aug 2371 */
|
460
|
+
{164, 2597858.5}, /* 05 Aug 2400 */
|
461
|
+
{165, 2601845.5}, /* 06 Jul 2411 */
|
462
|
+
{166, 2632173.5}, /* 18 Jul 2494 */
|
463
|
+
{167, 2649330.5}, /* 09 Jul 2541 */
|
464
|
+
{168, 2653317.5}, /* 08 Jun 2552 */
|
465
|
+
{169, 2683645.5}, /* 22 Jun 2635 */
|
466
|
+
{170, 2694217.5}, /* 01 Jun 2664 */
|
467
|
+
{171, 2698203.5}, /* 01 May 2675 */
|
468
|
+
{172, 2728532.5}, /* 15 May 2758 */
|
469
|
+
{173, 2739103.5}, /* 24 Apr 2787 */
|
470
|
+
{174, 2683822.5}, /* 16 Dec 2635 */
|
471
|
+
{175, 2740492.5}, /* 11 Feb 2791 */
|
472
|
+
{176, 2724722.5}, /* 09 Dec 2747 */
|
473
|
+
{177, 2708952.5}, /* 05 Oct 2704 */
|
474
|
+
{178, 2732695.5}, /* 07 Oct 2769 */
|
475
|
+
{179, 2749852.5}, /* 27 Sep 2816 */
|
476
|
+
{180, 2753839.5}, /* 28 Aug 2827 */
|
477
|
+
};
|
478
|
+
|
479
|
+
/* Computes geographic location and type of solar eclipse
|
480
|
+
* for a given tjd
|
481
|
+
* iflag: to indicate ephemeris to be used
|
482
|
+
* (SEFLG_JPLEPH, SEFLG_SWIEPH, SEFLG_MOSEPH)
|
483
|
+
*
|
484
|
+
* Algorithms for the central line is taken from Montenbruck, pp. 179ff.,
|
485
|
+
* with the exception, that we consider refraction for the maxima of
|
486
|
+
* partial and noncentral eclipses.
|
487
|
+
* Geographical positions are referred to sea level / the mean ellipsoid.
|
488
|
+
*
|
489
|
+
* Errors:
|
490
|
+
* - from uncertainty of JPL-ephemerides (0.01 arcsec):
|
491
|
+
* about 40 meters
|
492
|
+
* - from displacement of shadow points by atmospheric refraction:
|
493
|
+
* a few meters
|
494
|
+
* - from deviation of the geoid from the ellipsoid
|
495
|
+
* a few meters
|
496
|
+
* - from polar motion
|
497
|
+
* a few meters
|
498
|
+
* For geographical locations that are interesting for observation,
|
499
|
+
* the error is always < 100 m.
|
500
|
+
* However, if the sun is close to the horizon,
|
501
|
+
* all of these errors can grow up to a km or more.
|
502
|
+
*
|
503
|
+
* Function returns:
|
504
|
+
* -1 (ERR) on error (e.g. if swe_calc() for sun or moon fails)
|
505
|
+
* 0 if there is no solar eclipse at tjd
|
506
|
+
* SE_ECL_TOTAL
|
507
|
+
* SE_ECL_ANNULAR
|
508
|
+
* SE_ECL_TOTAL | SE_ECL_CENTRAL
|
509
|
+
* SE_ECL_TOTAL | SE_ECL_NONCENTRAL
|
510
|
+
* SE_ECL_ANNULAR | SE_ECL_CENTRAL
|
511
|
+
* SE_ECL_ANNULAR | SE_ECL_NONCENTRAL
|
512
|
+
* SE_ECL_PARTIAL
|
513
|
+
*
|
514
|
+
* geopos[0]: geographic longitude of central line
|
515
|
+
* geopos[1]: geographic latitude of central line
|
516
|
+
*
|
517
|
+
* not implemented so far:
|
518
|
+
*
|
519
|
+
* geopos[2]: geographic longitude of northern limit of umbra
|
520
|
+
* geopos[3]: geographic latitude of northern limit of umbra
|
521
|
+
* geopos[4]: geographic longitude of southern limit of umbra
|
522
|
+
* geopos[5]: geographic latitude of southern limit of umbra
|
523
|
+
* geopos[6]: geographic longitude of northern limit of penumbra
|
524
|
+
* geopos[7]: geographic latitude of northern limit of penumbra
|
525
|
+
* geopos[8]: geographic longitude of southern limit of penumbra
|
526
|
+
* geopos[9]: geographic latitude of southern limit of penumbra
|
527
|
+
*
|
528
|
+
* Attention: "northern" and "southern" limits of umbra do not
|
529
|
+
* necessarily correspond to the northernmost or southernmost
|
530
|
+
* geographic position, where the total, annular, or partial
|
531
|
+
* phase is visible at a given time.
|
532
|
+
* Imagine a situation in northern summer, when the sun illuminates
|
533
|
+
* the northern polar circle. The southernmost point of the core
|
534
|
+
* shadow may then touch the north pole, and therefore the
|
535
|
+
* northernmost point will be more in the south.
|
536
|
+
* Note also that with annular eclipses, the northern edge is
|
537
|
+
* usually geographically the southern one. With annular-total
|
538
|
+
* ones, the two lines cross, usually twice. The maximum is always
|
539
|
+
* total in such cases.
|
540
|
+
*
|
541
|
+
* attr[0] fraction of solar diameter covered by moon (magnitude)
|
542
|
+
* attr[1] ratio of lunar diameter to solar one
|
543
|
+
* attr[2] fraction of solar disc covered by moon (obscuration)
|
544
|
+
* attr[3] diameter of core shadow in km
|
545
|
+
* attr[4] azimuth of sun at tjd
|
546
|
+
* attr[5] true altitude of sun above horizon at tjd
|
547
|
+
* attr[6] apparent altitude of sun above horizon at tjd
|
548
|
+
* attr[7] angular distance of moon from sun in degrees
|
549
|
+
* declare as attr[20] at least !
|
550
|
+
*/
|
551
|
+
int32 FAR PASCAL_CONV swe_sol_eclipse_where(
|
552
|
+
double tjd_ut,
|
553
|
+
int32 ifl,
|
554
|
+
double *geopos,
|
555
|
+
double *attr,
|
556
|
+
char *serr)
|
557
|
+
{
|
558
|
+
int32 retflag, retflag2;
|
559
|
+
double dcore[10];
|
560
|
+
ifl &= SEFLG_EPHMASK;
|
561
|
+
if ((retflag = eclipse_where(tjd_ut, SE_SUN, NULL, ifl, geopos, dcore, serr)) < 0)
|
562
|
+
return retflag;
|
563
|
+
if ((retflag2 = eclipse_how(tjd_ut, SE_SUN, NULL, ifl, geopos[0], geopos[1], 0, attr, serr)) == ERR)
|
564
|
+
return retflag2;
|
565
|
+
attr[3] = dcore[0];
|
566
|
+
return retflag;
|
567
|
+
}
|
568
|
+
|
569
|
+
int32 FAR PASCAL_CONV swe_lun_occult_where(
|
570
|
+
double tjd_ut,
|
571
|
+
int32 ipl,
|
572
|
+
char *starname,
|
573
|
+
int32 ifl,
|
574
|
+
double *geopos,
|
575
|
+
double *attr,
|
576
|
+
char *serr)
|
577
|
+
{
|
578
|
+
int32 retflag, retflag2;
|
579
|
+
double dcore[10];
|
580
|
+
ifl &= SEFLG_EPHMASK;
|
581
|
+
/* function calls for Pluto with asteroid number 134340
|
582
|
+
* are treated as calls for Pluto as main body SE_PLUTO */
|
583
|
+
if (ipl == SE_AST_OFFSET + 134340)
|
584
|
+
ipl = SE_PLUTO;
|
585
|
+
if ((retflag = eclipse_where(tjd_ut, ipl, starname, ifl, geopos, dcore, serr)) < 0)
|
586
|
+
return retflag;
|
587
|
+
if ((retflag2 = eclipse_how(tjd_ut, ipl, starname, ifl, geopos[0], geopos[1], 0, attr, serr)) == ERR)
|
588
|
+
return retflag2;
|
589
|
+
attr[3] = dcore[0];
|
590
|
+
return retflag;
|
591
|
+
}
|
592
|
+
|
593
|
+
/* Used by several swe_sol_eclipse_ functions.
|
594
|
+
* Like swe_sol_eclipse_where(), but instead of attr[0], it returns:
|
595
|
+
*
|
596
|
+
* dcore[0]: core shadow width in km
|
597
|
+
* dcore[2]: distance of shadow axis from geocenter r0
|
598
|
+
* dcore[3]: diameter of core shadow on fundamental plane d0
|
599
|
+
* dcore[4]: diameter of half-shadow on fundamental plane D0
|
600
|
+
*/
|
601
|
+
static int32 eclipse_where( double tjd_ut, int32 ipl, char *starname, int32 ifl, double *geopos, double *dcore,
|
602
|
+
char *serr)
|
603
|
+
{
|
604
|
+
int i;
|
605
|
+
int32 retc = 0, niter = 0;
|
606
|
+
double e[6], et[6], erm[6], rm[6], rs[6], rmt[6], rst[6], xs[6], xst[6];
|
607
|
+
double xssv[16], x[6];
|
608
|
+
double lm[6], ls[6], lx[6];
|
609
|
+
double dsm, dsmt, d0, D0, s0, r0, d, s, dm;
|
610
|
+
double de = 6378140.0 / AUNIT;
|
611
|
+
double earthobl = 1 - EARTH_OBLATENESS;
|
612
|
+
double deltat, tjd, sidt;
|
613
|
+
double drad;
|
614
|
+
double sinf1, sinf2, cosf1, cosf2;
|
615
|
+
int32 iflag, iflag2;
|
616
|
+
/* double ecce = sqrt(2 * EARTH_OBLATENESS - EARTH_OBLATENESS * EARTH_OBLATENESS); */
|
617
|
+
AS_BOOL no_eclipse = FALSE;
|
618
|
+
struct epsilon *oe = &swed.oec;
|
619
|
+
for (i = 0; i < 10; i++)
|
620
|
+
dcore[i] = 0;
|
621
|
+
/* nutation need not be in lunar and solar positions,
|
622
|
+
* if mean sidereal time will be used */
|
623
|
+
iflag = SEFLG_SPEED | SEFLG_EQUATORIAL | ifl;
|
624
|
+
iflag2 = iflag | SEFLG_RADIANS;
|
625
|
+
iflag = iflag | SEFLG_XYZ;
|
626
|
+
deltat = swe_deltat(tjd_ut);
|
627
|
+
tjd = tjd_ut + deltat;
|
628
|
+
/* moon in cartesian coordinates */
|
629
|
+
if ((retc = swe_calc(tjd, SE_MOON, iflag, rm, serr)) == ERR)
|
630
|
+
return retc;
|
631
|
+
/* moon in polar coordinates */
|
632
|
+
if ((retc = swe_calc(tjd, SE_MOON, iflag2, lm, serr)) == ERR)
|
633
|
+
return retc;
|
634
|
+
/* sun in cartesian coordinates */
|
635
|
+
if ((retc = calc_planet_star(tjd, ipl, starname, iflag, rs, serr)) == ERR)
|
636
|
+
return retc;
|
637
|
+
/* sun in polar coordinates */
|
638
|
+
if ((retc = calc_planet_star(tjd, ipl, starname, iflag2, ls, serr)) == ERR)
|
639
|
+
return retc;
|
640
|
+
/* save sun position */
|
641
|
+
for (i = 0; i <= 2; i++)
|
642
|
+
rst[i] = rs[i];
|
643
|
+
/* save moon position */
|
644
|
+
for (i = 0; i <= 2; i++)
|
645
|
+
rmt[i] = rm[i];
|
646
|
+
if (iflag & SEFLG_NONUT)
|
647
|
+
sidt = swe_sidtime0(tjd_ut, oe->eps * RADTODEG, 0) * 15 * DEGTORAD;
|
648
|
+
else
|
649
|
+
sidt = swe_sidtime(tjd_ut) * 15 * DEGTORAD;
|
650
|
+
/*
|
651
|
+
* radius of planet disk in AU
|
652
|
+
*/
|
653
|
+
if (starname != NULL && *starname != '\0')
|
654
|
+
drad = 0;
|
655
|
+
else if (ipl < NDIAM)
|
656
|
+
drad = pla_diam[ipl] / 2 / AUNIT;
|
657
|
+
else if (ipl > SE_AST_OFFSET)
|
658
|
+
drad = swed.ast_diam / 2 * 1000 / AUNIT; /* km -> m -> AU */
|
659
|
+
else
|
660
|
+
drad = 0;
|
661
|
+
iter_where:
|
662
|
+
for (i = 0; i <= 2; i++) {
|
663
|
+
rs[i] = rst[i];
|
664
|
+
rm[i] = rmt[i];
|
665
|
+
}
|
666
|
+
/* Account for oblateness of earth:
|
667
|
+
* Instead of flattening the earth, we apply the
|
668
|
+
* correction to the z coordinate of the moon and
|
669
|
+
* the sun. This makes the calculation easier.
|
670
|
+
*/
|
671
|
+
for (i = 0; i <= 2; i++)
|
672
|
+
lx[i] = lm[i];
|
673
|
+
swi_polcart(lx, rm);
|
674
|
+
rm[2] /= earthobl;
|
675
|
+
/* distance of moon from geocenter */
|
676
|
+
dm = sqrt(square_sum(rm));
|
677
|
+
/* Account for oblateness of earth */
|
678
|
+
for (i = 0; i <= 2; i++)
|
679
|
+
lx[i] = ls[i];
|
680
|
+
swi_polcart(lx, rs);
|
681
|
+
rs[2] /= earthobl;
|
682
|
+
/* sun - moon vector */
|
683
|
+
for (i = 0; i <= 2; i++) {
|
684
|
+
e[i] = (rm[i] - rs[i]);
|
685
|
+
et[i] = (rmt[i] - rst[i]);
|
686
|
+
}
|
687
|
+
/* distance sun - moon */
|
688
|
+
dsm = sqrt(square_sum(e));
|
689
|
+
dsmt = sqrt(square_sum(et));
|
690
|
+
/* sun - moon unit vector */
|
691
|
+
for (i = 0; i <= 2; i++) {
|
692
|
+
e[i] /= dsm;
|
693
|
+
et[i] /= dsmt;
|
694
|
+
erm[i] = rm[i] / dm;
|
695
|
+
}
|
696
|
+
sinf1 = ((drad - RMOON) / dsm);
|
697
|
+
cosf1 = sqrt(1 - sinf1 * sinf1);
|
698
|
+
sinf2 = ((drad + RMOON) / dsm);
|
699
|
+
cosf2 = sqrt(1 - sinf2 * sinf2);
|
700
|
+
/* distance of moon from fundamental plane */
|
701
|
+
s0 = -dot_prod(rm, e);
|
702
|
+
/* distance of shadow axis from geocenter */
|
703
|
+
r0 = sqrt(dm * dm - s0 * s0);
|
704
|
+
/* diameter of core shadow on fundamental plane */
|
705
|
+
d0 = (s0 / dsm * (drad * 2 - DMOON) - DMOON) / cosf1;
|
706
|
+
/* diameter of half-shadow on fundamental plane */
|
707
|
+
D0 = (s0 / dsm * (drad * 2 + DMOON) + DMOON) / cosf2;
|
708
|
+
dcore[2] = r0;
|
709
|
+
dcore[3] = d0;
|
710
|
+
dcore[4] = D0;
|
711
|
+
dcore[5] = cosf1;
|
712
|
+
dcore[6] = cosf2;
|
713
|
+
for (i = 2; i < 5; i++)
|
714
|
+
dcore[i] *= AUNIT / 1000.0;
|
715
|
+
/**************************
|
716
|
+
* central (total or annular) phase
|
717
|
+
**************************/
|
718
|
+
retc = 0;
|
719
|
+
if (de * cosf1 >= r0) {
|
720
|
+
retc |= SE_ECL_CENTRAL;
|
721
|
+
} else if (r0 <= de * cosf1 + fabs(d0) / 2) {
|
722
|
+
retc |= SE_ECL_NONCENTRAL;
|
723
|
+
} else if (r0 <= de * cosf2 + D0 / 2) {
|
724
|
+
retc |= (SE_ECL_PARTIAL | SE_ECL_NONCENTRAL);
|
725
|
+
} else {
|
726
|
+
if (serr != NULL)
|
727
|
+
sprintf(serr, "no solar eclipse at tjd = %f", tjd);
|
728
|
+
for (i = 0; i < 10; i++)
|
729
|
+
geopos[i] = 0;
|
730
|
+
*dcore = 0;
|
731
|
+
retc = 0;
|
732
|
+
d = 0;
|
733
|
+
no_eclipse = TRUE;
|
734
|
+
/*return retc;*/
|
735
|
+
}
|
736
|
+
/* distance of shadow point from fundamental plane */
|
737
|
+
d = s0 * s0 + de * de - dm * dm;
|
738
|
+
if (d > 0)
|
739
|
+
d = sqrt(d);
|
740
|
+
else
|
741
|
+
d = 0;
|
742
|
+
/* distance of moon from shadow point on earth */
|
743
|
+
s = s0 - d;
|
744
|
+
/* next: geographic position of eclipse center.
|
745
|
+
* if shadow axis does not touch the earth,
|
746
|
+
* place on earth with maximum occultation is computed.
|
747
|
+
*/
|
748
|
+
#if 0 /* the following stuff is meaningless for observations */
|
749
|
+
/*
|
750
|
+
* account for refraction at horizon
|
751
|
+
*/
|
752
|
+
if (d == 0) {
|
753
|
+
double ds, a, b;
|
754
|
+
/* distance of sun from geocenter */
|
755
|
+
ds = sqrt(square_sum(rs));
|
756
|
+
a = PI - acos(swi_dot_prod_unit(e, erm));
|
757
|
+
/* refraction at horizon + sun radius = about 0.83 degrees */
|
758
|
+
b = 34.4556 / 60.0 * DEGTORAD + asin(drad / ds);
|
759
|
+
# if 0
|
760
|
+
/* at edge of umbra and penumbra
|
761
|
+
* light rays are not parallel to shadow axis.
|
762
|
+
* for a short time close to contact of umbra and
|
763
|
+
* penumbra, an angle < 0.27 degrees would have
|
764
|
+
* to be subtracted from b;
|
765
|
+
*/
|
766
|
+
if (retc & SE_ECL_PARTIAL) {
|
767
|
+
d = d0;
|
768
|
+
sinf = sinf1;
|
769
|
+
} else {
|
770
|
+
d = D0;
|
771
|
+
sinf = sinf2;
|
772
|
+
}
|
773
|
+
c = (r0 - de) / d * 2 * sinf;
|
774
|
+
if (c > sinf1) {
|
775
|
+
b -= .....;
|
776
|
+
}
|
777
|
+
printf("%f %f %f", a * RADTODEG, b * RADTODEG, s);
|
778
|
+
printf(" %f\n", s);
|
779
|
+
# else
|
780
|
+
if (retc & SE_ECL_PARTIAL)
|
781
|
+
b -= asin(sinf2); /* maximum! */
|
782
|
+
else
|
783
|
+
b -= asin(sinf1);
|
784
|
+
# endif
|
785
|
+
s += tan(b) * cos(PI / 2 - a) * dm;
|
786
|
+
}
|
787
|
+
#endif
|
788
|
+
/* geographic position of eclipse center (maximum) */
|
789
|
+
for (i = 0; i <= 2; i++)
|
790
|
+
xs[i] = rm[i] + s * e[i];
|
791
|
+
/* we need geographic position with correct z, as well */
|
792
|
+
for (i = 0; i <= 2; i++)
|
793
|
+
xst[i] = xs[i];
|
794
|
+
xst[2] *= earthobl;
|
795
|
+
swi_cartpol(xst, xst);
|
796
|
+
if (niter <= 0) {
|
797
|
+
double cosfi = cos(xst[1]);
|
798
|
+
double sinfi = sin(xst[1]);
|
799
|
+
double eobl = EARTH_OBLATENESS;
|
800
|
+
double cc= 1 / sqrt(cosfi * cosfi + (1-eobl) * (1-eobl) * sinfi * sinfi);
|
801
|
+
double ss= (1-eobl) * (1-eobl) * cc;
|
802
|
+
earthobl = ss;
|
803
|
+
niter++;
|
804
|
+
goto iter_where;
|
805
|
+
}
|
806
|
+
swi_polcart(xst, xst);
|
807
|
+
/* to longitude and latitude */
|
808
|
+
swi_cartpol(xs, xs);
|
809
|
+
/* measure from sidereal time at greenwich */
|
810
|
+
xs[0] -= sidt;
|
811
|
+
xs[0] *= RADTODEG;
|
812
|
+
xs[1] *= RADTODEG;
|
813
|
+
xs[0] = swe_degnorm(xs[0]);
|
814
|
+
/* west is negative */
|
815
|
+
if (xs[0] > 180)
|
816
|
+
xs[0] -= 360;
|
817
|
+
xssv[0] = xs[0];
|
818
|
+
xssv[1] = xs[1];
|
819
|
+
geopos[0] = xs[0];
|
820
|
+
geopos[1] = xs[1];
|
821
|
+
/* diameter of core shadow:
|
822
|
+
* first, distance moon - place of eclipse on earth */
|
823
|
+
for (i = 0; i <= 2; i++)
|
824
|
+
x[i] = rmt[i] - xst[i];
|
825
|
+
s = sqrt(square_sum(x));
|
826
|
+
/* diameter of core shadow at place of maximum eclipse */
|
827
|
+
*dcore = (s / dsmt * ( drad * 2 - DMOON) - DMOON) * cosf1;
|
828
|
+
*dcore *= AUNIT / 1000.0;
|
829
|
+
/* diameter of penumbra at place of maximum eclipse */
|
830
|
+
dcore[1] = (s / dsmt * ( drad * 2 + DMOON) + DMOON) * cosf2;
|
831
|
+
dcore[1] *= AUNIT / 1000.0;
|
832
|
+
if (!(retc & SE_ECL_PARTIAL) && !no_eclipse) {
|
833
|
+
if (*dcore > 0) {
|
834
|
+
/*printf("annular\n");*/
|
835
|
+
retc |= SE_ECL_ANNULAR;
|
836
|
+
} else {
|
837
|
+
/*printf("total\n");*/
|
838
|
+
retc |= SE_ECL_TOTAL;
|
839
|
+
}
|
840
|
+
}
|
841
|
+
return retc;
|
842
|
+
}
|
843
|
+
|
844
|
+
static int32 calc_planet_star(double tjd_et, int32 ipl, char *starname, int32 iflag, double *x, char *serr)
|
845
|
+
{
|
846
|
+
int i;
|
847
|
+
int retc = OK;
|
848
|
+
if (starname == NULL || *starname == '\0') {
|
849
|
+
retc = swe_calc(tjd_et, ipl, iflag, x, serr);
|
850
|
+
} else {
|
851
|
+
if ((retc = swe_fixstar(starname, tjd_et, iflag, x, serr)) == OK) {
|
852
|
+
/* fixstars have the standard distance 1.
|
853
|
+
* in the occultation routines, this might lead to errors
|
854
|
+
* if interpreted as AU distance. To avoid this, we make it very high.
|
855
|
+
*/
|
856
|
+
if (iflag & SEFLG_XYZ) {
|
857
|
+
for (i = 0; i < 3; i++)
|
858
|
+
x[i] *= 100000000;
|
859
|
+
} else {
|
860
|
+
x[2] *= 100000000;
|
861
|
+
}
|
862
|
+
}
|
863
|
+
}
|
864
|
+
return retc;
|
865
|
+
}
|
866
|
+
|
867
|
+
/* Computes attributes of a solar eclipse for given tjd, geo. longitude,
|
868
|
+
* geo. latitude, and geo. height.
|
869
|
+
*
|
870
|
+
* retflag SE_ECL_TOTAL or SE_ECL_ANNULAR or SE_ECL_PARTIAL
|
871
|
+
* SE_ECL_NONCENTRAL
|
872
|
+
* if 0, no eclipse is visible at geogr. position.
|
873
|
+
*
|
874
|
+
* attr[0] fraction of solar diameter covered by moon
|
875
|
+
* attr[1] ratio of lunar diameter to solar one
|
876
|
+
* attr[2] fraction of solar disc covered by moon (obscuration)
|
877
|
+
* attr[3] diameter of core shadow in km
|
878
|
+
* attr[4] azimuth of sun at tjd
|
879
|
+
* attr[5] true altitude of sun above horizon at tjd
|
880
|
+
* attr[6] apparent altitude of sun above horizon at tjd
|
881
|
+
* attr[7] elongation of moon in degrees
|
882
|
+
* attr[8] magnitude (= attr[0] or attr[1] depending on eclipse type)
|
883
|
+
* attr[9] saros series number
|
884
|
+
* attr[10] saros series member number
|
885
|
+
* declare as attr[20] at least !
|
886
|
+
*
|
887
|
+
*/
|
888
|
+
int32 FAR PASCAL_CONV swe_sol_eclipse_how(
|
889
|
+
double tjd_ut,
|
890
|
+
int32 ifl,
|
891
|
+
double *geopos,
|
892
|
+
double *attr,
|
893
|
+
char *serr)
|
894
|
+
{
|
895
|
+
int32 retflag, retflag2;
|
896
|
+
double dcore[10];
|
897
|
+
double geopos2[20];
|
898
|
+
ifl &= SEFLG_EPHMASK;
|
899
|
+
if ((retflag = eclipse_how(tjd_ut, SE_SUN, NULL, ifl, geopos[0], geopos[1], geopos[2], attr, serr)) == ERR)
|
900
|
+
return retflag;
|
901
|
+
if ((retflag2 = eclipse_where(tjd_ut, SE_SUN, NULL, ifl, geopos2, dcore, serr)) == ERR)
|
902
|
+
return retflag2;
|
903
|
+
if (retflag)
|
904
|
+
retflag |= (retflag2 & (SE_ECL_CENTRAL | SE_ECL_NONCENTRAL));
|
905
|
+
attr[3] = dcore[0];
|
906
|
+
return retflag;
|
907
|
+
}
|
908
|
+
|
909
|
+
static int32 eclipse_how( double tjd_ut, int32 ipl, char *starname, int32 ifl,
|
910
|
+
double geolon, double geolat, double geohgt,
|
911
|
+
double *attr, char *serr)
|
912
|
+
{
|
913
|
+
int i, j, k;
|
914
|
+
int32 retc = 0;
|
915
|
+
double te, d;
|
916
|
+
double xs[6], xm[6], ls[6], lm[6], x1[6], x2[6];
|
917
|
+
double rmoon, rsun, rsplusrm, rsminusrm;
|
918
|
+
double dctr;
|
919
|
+
double drad;
|
920
|
+
int32 iflag = SEFLG_EQUATORIAL | SEFLG_TOPOCTR | ifl;
|
921
|
+
int32 iflagcart = iflag | SEFLG_XYZ;
|
922
|
+
double mdd, eps, sidt, armc, xh[6], hmin_appr;
|
923
|
+
double lsun, lmoon, lctr, lsunleft, a, b, sc1, sc2;
|
924
|
+
for (i = 0; i < 10; i++)
|
925
|
+
attr[i] = 0;
|
926
|
+
te = tjd_ut + swe_deltat(tjd_ut);
|
927
|
+
swe_set_topo(geolon, geolat, geohgt);
|
928
|
+
if (calc_planet_star(te, ipl, starname, iflag, ls, serr) == ERR)
|
929
|
+
return ERR;
|
930
|
+
if (swe_calc(te, SE_MOON, iflag, lm, serr) == ERR)
|
931
|
+
return ERR;
|
932
|
+
if (calc_planet_star(te, ipl, starname, iflagcart, xs, serr) == ERR)
|
933
|
+
return ERR;
|
934
|
+
if (swe_calc(te, SE_MOON, iflagcart, xm, serr) == ERR)
|
935
|
+
return ERR;
|
936
|
+
/*
|
937
|
+
* radius of planet disk in AU
|
938
|
+
*/
|
939
|
+
if (starname != NULL && *starname != '\0')
|
940
|
+
drad = 0;
|
941
|
+
else if (ipl < NDIAM)
|
942
|
+
drad = pla_diam[ipl] / 2 / AUNIT;
|
943
|
+
else if (ipl > SE_AST_OFFSET)
|
944
|
+
drad = swed.ast_diam / 2 * 1000 / AUNIT; /* km -> m -> AU */
|
945
|
+
else
|
946
|
+
drad = 0;
|
947
|
+
/*
|
948
|
+
* azimuth and altitude of sun or planet
|
949
|
+
*/
|
950
|
+
eps = swi_epsiln(te);
|
951
|
+
if (iflag & SEFLG_NONUT)
|
952
|
+
sidt = swe_sidtime0(tjd_ut, eps * RADTODEG, 0) * 15;
|
953
|
+
else
|
954
|
+
sidt = swe_sidtime(tjd_ut) * 15;
|
955
|
+
armc = sidt + geolon;
|
956
|
+
mdd = swe_degnorm(ls[0] - armc);
|
957
|
+
xh[0] = swe_degnorm(mdd - 90);
|
958
|
+
xh[1] = ls[1];
|
959
|
+
xh[2] = ls[2];
|
960
|
+
swe_cotrans(xh, xh, 90 - geolat); /* azimuth from east, counterclock */
|
961
|
+
/* eclipse description */
|
962
|
+
rmoon = asin(RMOON / lm[2]) * RADTODEG;
|
963
|
+
rsun = asin(drad / ls[2]) * RADTODEG;
|
964
|
+
rsplusrm = rsun + rmoon;
|
965
|
+
rsminusrm = rsun - rmoon;
|
966
|
+
for (i = 0; i < 3; i++) {
|
967
|
+
x1[i] = xs[i] / ls[2];
|
968
|
+
x2[i] = xm[i] / lm[2];
|
969
|
+
}
|
970
|
+
dctr = acos(swi_dot_prod_unit(x1, x2)) * RADTODEG;
|
971
|
+
/*
|
972
|
+
* phase
|
973
|
+
*/
|
974
|
+
if (dctr < rsminusrm)
|
975
|
+
retc = SE_ECL_ANNULAR;
|
976
|
+
else if (dctr < fabs(rsminusrm))
|
977
|
+
retc = SE_ECL_TOTAL;
|
978
|
+
else if (dctr < rsplusrm)
|
979
|
+
retc = SE_ECL_PARTIAL;
|
980
|
+
else {
|
981
|
+
retc = 0;
|
982
|
+
if (serr != NULL)
|
983
|
+
sprintf(serr, "no solar eclipse at tjd = %f", tjd_ut);
|
984
|
+
}
|
985
|
+
/*
|
986
|
+
* percentage of eclipse
|
987
|
+
*/
|
988
|
+
#if 0
|
989
|
+
attr[0] = (rsplusrm - dctr) / rsun / 2 * 100;
|
990
|
+
#else
|
991
|
+
/*
|
992
|
+
* eclipse magnitude:
|
993
|
+
* fraction of solar diameter covered by moon
|
994
|
+
*/
|
995
|
+
lsun = asin(rsun / 2 * DEGTORAD) * 2;
|
996
|
+
#if 0
|
997
|
+
lmoon = asin(rmoon / 2 * DEGTORAD) * 2;
|
998
|
+
lctr = asin(dctr / 2 * DEGTORAD) * 2;
|
999
|
+
#endif
|
1000
|
+
lsunleft = (-dctr + rsun + rmoon);
|
1001
|
+
if (lsun > 0) {
|
1002
|
+
attr[0] = lsunleft / rsun / 2;
|
1003
|
+
} else {
|
1004
|
+
attr[0] = 100;
|
1005
|
+
}
|
1006
|
+
/*
|
1007
|
+
* ratio of diameter of moon to that of sun
|
1008
|
+
*/
|
1009
|
+
if (rsun > 0)
|
1010
|
+
attr[1] = rmoon / rsun;
|
1011
|
+
else
|
1012
|
+
attr[1] = 0;
|
1013
|
+
/*
|
1014
|
+
* obscuration:
|
1015
|
+
* fraction of solar disc obscured by moon
|
1016
|
+
*/
|
1017
|
+
lsun = rsun;
|
1018
|
+
lmoon = rmoon;
|
1019
|
+
lctr = dctr;
|
1020
|
+
if (retc == 0 || lsun == 0)
|
1021
|
+
attr[2] = 100;
|
1022
|
+
else if (retc == SE_ECL_TOTAL || retc == SE_ECL_ANNULAR)
|
1023
|
+
attr[2] = lmoon * lmoon / lsun / lsun;
|
1024
|
+
else {
|
1025
|
+
a = 2 * lctr * lmoon;
|
1026
|
+
b = 2 * lctr * lsun;
|
1027
|
+
if (a < 1e-9) {
|
1028
|
+
attr[2] = lmoon * lmoon / lsun / lsun;
|
1029
|
+
} else {
|
1030
|
+
a = (lctr * lctr + lmoon * lmoon - lsun * lsun) / a;
|
1031
|
+
if (a > 1) a = 1;
|
1032
|
+
if (a < -1) a = -1;
|
1033
|
+
b = (lctr * lctr + lsun * lsun - lmoon * lmoon) / b;
|
1034
|
+
if (b > 1) b = 1;
|
1035
|
+
if (b < -1) b = -1;
|
1036
|
+
a = acos(a);
|
1037
|
+
b = acos(b);
|
1038
|
+
sc1 = a * lmoon * lmoon / 2;
|
1039
|
+
sc2 = b * lsun * lsun / 2;
|
1040
|
+
sc1 -= (cos(a) * sin(a)) * lmoon * lmoon / 2;
|
1041
|
+
sc2 -= (cos(b) * sin(b)) * lsun * lsun / 2;
|
1042
|
+
attr[2] = (sc1 + sc2) * 2 / PI / lsun / lsun;
|
1043
|
+
}
|
1044
|
+
}
|
1045
|
+
#endif
|
1046
|
+
attr[7] = dctr;
|
1047
|
+
/* approximate minimum height for visibility, considering
|
1048
|
+
* refraction and dip
|
1049
|
+
* 34.4556': refraction at horizon, from Bennets formulae
|
1050
|
+
* 1.75' / sqrt(geohgt): dip of horizon
|
1051
|
+
* 0.37' / sqrt(geohgt): refraction between horizon and observer */
|
1052
|
+
hmin_appr = -(34.4556 + (1.75 + 0.37) * sqrt(geohgt)) / 60;
|
1053
|
+
if (xh[1] + rsun + fabs(hmin_appr) >= 0 && retc)
|
1054
|
+
retc |= SE_ECL_VISIBLE; /* eclipse visible */
|
1055
|
+
attr[4] = swe_degnorm(90 - xh[0]); /* azimuth, from north, clockwise */
|
1056
|
+
attr[5] = xh[1]; /* height */
|
1057
|
+
if (ipl == SE_SUN && (starname == NULL || *starname == '\0')) {
|
1058
|
+
/* magnitude of solar eclipse */
|
1059
|
+
attr[8] = attr[0]; /* fraction of diameter occulted */
|
1060
|
+
if (retc & (SE_ECL_TOTAL | SE_ECL_ANNULAR))
|
1061
|
+
attr[8] = attr[1]; /* ration between diameters of sun and moon */
|
1062
|
+
/* saros series and member */
|
1063
|
+
for (i = 0; i < NSAROS_SOLAR; i++) {
|
1064
|
+
d = (tjd_ut - saros_data_solar[i].tstart) / SAROS_CYCLE;
|
1065
|
+
if (d < 0) continue;
|
1066
|
+
j = (int) d;
|
1067
|
+
if ((d - j) * SAROS_CYCLE < 2) {
|
1068
|
+
attr[9] = (double) saros_data_solar[i].series_no;
|
1069
|
+
attr[10] = (double) j + 1;
|
1070
|
+
break;
|
1071
|
+
}
|
1072
|
+
k = j + 1;
|
1073
|
+
if ((k - d) * SAROS_CYCLE < 2) {
|
1074
|
+
attr[9] = (double) saros_data_solar[i].series_no;
|
1075
|
+
attr[10] = (double) k + 1;
|
1076
|
+
break;
|
1077
|
+
}
|
1078
|
+
}
|
1079
|
+
if (i == NSAROS_SOLAR) {
|
1080
|
+
attr[9] = attr[10] = -99999999;
|
1081
|
+
}
|
1082
|
+
}
|
1083
|
+
return retc;
|
1084
|
+
}
|
1085
|
+
|
1086
|
+
/* When is the next solar eclipse anywhere on earth?
|
1087
|
+
*
|
1088
|
+
* input parameters:
|
1089
|
+
*
|
1090
|
+
* tjd_start start time for search (UT)
|
1091
|
+
* ifl ephemeris to be used (SEFLG_SWIEPH, etc.)
|
1092
|
+
* ifltype eclipse type to be searched (SE_ECL_TOTAL, etc.)
|
1093
|
+
* 0, if any type of eclipse is wanted
|
1094
|
+
*
|
1095
|
+
* return values:
|
1096
|
+
*
|
1097
|
+
* retflag SE_ECL_TOTAL or SE_ECL_ANNULAR or SE_ECL_PARTIAL
|
1098
|
+
* or SE_ECL_ANNULAR_TOTAL
|
1099
|
+
* SE_ECL_CENTRAL
|
1100
|
+
* SE_ECL_NONCENTRAL
|
1101
|
+
*
|
1102
|
+
* tret[0] time of maximum eclipse
|
1103
|
+
* tret[1] time, when eclipse takes place at local apparent noon
|
1104
|
+
* tret[2] time of eclipse begin
|
1105
|
+
* tret[3] time of eclipse end
|
1106
|
+
* tret[4] time of totality begin
|
1107
|
+
* tret[5] time of totality end
|
1108
|
+
* tret[6] time of center line begin
|
1109
|
+
* tret[7] time of center line end
|
1110
|
+
* tret[8] time when annular-total eclipse becomes total
|
1111
|
+
* not implemented so far
|
1112
|
+
* tret[9] time when annular-total eclipse becomes annular again
|
1113
|
+
* not implemented so far
|
1114
|
+
* declare as tret[10] at least!
|
1115
|
+
*
|
1116
|
+
*/
|
1117
|
+
int32 FAR PASCAL_CONV swe_sol_eclipse_when_glob(double tjd_start, int32 ifl, int32 ifltype,
|
1118
|
+
double *tret, int32 backward, char *serr)
|
1119
|
+
{
|
1120
|
+
int i, j, k, m, n, o, i1 = 0, i2 = 0;
|
1121
|
+
int32 retflag = 0, retflag2 = 0;
|
1122
|
+
double de = 6378.140, a;
|
1123
|
+
double t, tt, tjd, tjds, dt, dtint, dta, dtb;
|
1124
|
+
double T, T2, T3, T4, K, M, Mm;
|
1125
|
+
double E, Ff;
|
1126
|
+
double xs[6], xm[6], ls[6], lm[6];
|
1127
|
+
double rmoon, rsun, dcore[10];
|
1128
|
+
double dc[3], dctr;
|
1129
|
+
double twohr = 2.0 / 24.0;
|
1130
|
+
double tenmin = 10.0 / 24.0 / 60.0;
|
1131
|
+
double dt1, dt2;
|
1132
|
+
double geopos[20], attr[20];
|
1133
|
+
double dtstart, dtdiv;
|
1134
|
+
double xa[6], xb[6];
|
1135
|
+
int direction = 1;
|
1136
|
+
AS_BOOL dont_times = FALSE;
|
1137
|
+
int32 iflag, iflagcart;
|
1138
|
+
ifl &= SEFLG_EPHMASK;
|
1139
|
+
iflag = SEFLG_EQUATORIAL | ifl;
|
1140
|
+
iflagcart = iflag | SEFLG_XYZ;
|
1141
|
+
if (ifltype == (SE_ECL_PARTIAL | SE_ECL_CENTRAL)) {
|
1142
|
+
if (serr != NULL)
|
1143
|
+
strcpy(serr, "central partial eclipses do not exist");
|
1144
|
+
return ERR;
|
1145
|
+
}
|
1146
|
+
if (ifltype == 0)
|
1147
|
+
ifltype = SE_ECL_TOTAL | SE_ECL_ANNULAR | SE_ECL_PARTIAL
|
1148
|
+
| SE_ECL_ANNULAR_TOTAL | SE_ECL_NONCENTRAL | SE_ECL_CENTRAL;
|
1149
|
+
if (backward)
|
1150
|
+
direction = -1;
|
1151
|
+
K = (int) ((tjd_start - J2000) / 365.2425 * 12.3685);
|
1152
|
+
K -= direction;
|
1153
|
+
next_try:
|
1154
|
+
retflag = 0;
|
1155
|
+
dont_times = FALSE;
|
1156
|
+
for (i = 0; i <= 9; i++)
|
1157
|
+
tret[i] = 0;
|
1158
|
+
T = K / 1236.85;
|
1159
|
+
T2 = T * T; T3 = T2 * T; T4 = T3 * T;
|
1160
|
+
Ff = swe_degnorm(160.7108 + 390.67050274 * K
|
1161
|
+
- 0.0016341 * T2
|
1162
|
+
- 0.00000227 * T3
|
1163
|
+
+ 0.000000011 * T4);
|
1164
|
+
if (Ff > 180)
|
1165
|
+
Ff -= 180;
|
1166
|
+
if (Ff > 21 && Ff < 159) { /* no eclipse possible */
|
1167
|
+
K += direction;
|
1168
|
+
goto next_try;
|
1169
|
+
}
|
1170
|
+
/* approximate time of geocentric maximum eclipse
|
1171
|
+
* formula from Meeus, German, p. 381 */
|
1172
|
+
tjd = 2451550.09765 + 29.530588853 * K
|
1173
|
+
+ 0.0001337 * T2
|
1174
|
+
- 0.000000150 * T3
|
1175
|
+
+ 0.00000000073 * T4;
|
1176
|
+
M = swe_degnorm(2.5534 + 29.10535669 * K
|
1177
|
+
- 0.0000218 * T2
|
1178
|
+
- 0.00000011 * T3);
|
1179
|
+
Mm = swe_degnorm(201.5643 + 385.81693528 * K
|
1180
|
+
+ 0.1017438 * T2
|
1181
|
+
+ 0.00001239 * T3
|
1182
|
+
+ 0.000000058 * T4);
|
1183
|
+
E = 1 - 0.002516 * T - 0.0000074 * T2;
|
1184
|
+
M *= DEGTORAD;
|
1185
|
+
Mm *= DEGTORAD;
|
1186
|
+
tjd = tjd - 0.4075 * sin(Mm)
|
1187
|
+
+ 0.1721 * E * sin(M);
|
1188
|
+
/*
|
1189
|
+
* time of maximum eclipse (if eclipse) =
|
1190
|
+
* minimum geocentric angle between sun and moon edges.
|
1191
|
+
* After this time has been determined, check
|
1192
|
+
* whether or not an eclipse is taking place with
|
1193
|
+
* the functions eclipse_where() and _how().
|
1194
|
+
*/
|
1195
|
+
dtstart = 1;
|
1196
|
+
if (tjd < 2000000)
|
1197
|
+
dtstart = 5;
|
1198
|
+
dtdiv = 4;
|
1199
|
+
for (dt = dtstart;
|
1200
|
+
dt > 0.0001;
|
1201
|
+
dt /= dtdiv) {
|
1202
|
+
for (i = 0, t = tjd - dt; i <= 2; i++, t += dt) {
|
1203
|
+
if (swe_calc(t, SE_SUN, iflag, ls, serr) == ERR)
|
1204
|
+
return ERR;
|
1205
|
+
if (swe_calc(t, SE_MOON, iflag, lm, serr) == ERR)
|
1206
|
+
return ERR;
|
1207
|
+
if (swe_calc(t, SE_SUN, iflagcart, xs, serr) == ERR)
|
1208
|
+
return ERR;
|
1209
|
+
if (swe_calc(t, SE_MOON, iflagcart, xm, serr) == ERR)
|
1210
|
+
return ERR;
|
1211
|
+
for (m = 0; m < 3; m++) {
|
1212
|
+
xa[m] = xs[m] / ls[2];
|
1213
|
+
xb[m] = xm[m] / lm[2];
|
1214
|
+
}
|
1215
|
+
dc[i] = acos(swi_dot_prod_unit(xa, xb)) * RADTODEG;
|
1216
|
+
rmoon = asin(RMOON / lm[2]) * RADTODEG;
|
1217
|
+
rsun = asin(RSUN / ls[2]) * RADTODEG;
|
1218
|
+
dc[i] -= (rmoon + rsun);
|
1219
|
+
}
|
1220
|
+
find_maximum(dc[0], dc[1], dc[2], dt, &dtint, &dctr);
|
1221
|
+
tjd += dtint + dt;
|
1222
|
+
}
|
1223
|
+
tjds = tjd = tjd - swe_deltat(tjd);
|
1224
|
+
if ((retflag = eclipse_where(tjd, SE_SUN, NULL, ifl, geopos, dcore, serr)) == ERR)
|
1225
|
+
return retflag;
|
1226
|
+
retflag2 = retflag;
|
1227
|
+
/* in extreme cases _where() returns no eclipse, where there is
|
1228
|
+
* actually a very small one, therefore call _how() with the
|
1229
|
+
* coordinates returned by _where(): */
|
1230
|
+
if ((retflag2 = eclipse_how(tjd, SE_SUN, NULL, ifl, geopos[0], geopos[1], 0, attr, serr)) == ERR)
|
1231
|
+
return retflag2;
|
1232
|
+
if (retflag2 == 0) {
|
1233
|
+
K += direction;
|
1234
|
+
goto next_try;
|
1235
|
+
}
|
1236
|
+
tret[0] = tjd;
|
1237
|
+
if ((backward && tret[0] >= tjd_start - 0.0001)
|
1238
|
+
|| (!backward && tret[0] <= tjd_start + 0.0001)) {
|
1239
|
+
K += direction;
|
1240
|
+
goto next_try;
|
1241
|
+
}
|
1242
|
+
/*
|
1243
|
+
* eclipse type, SE_ECL_TOTAL, _ANNULAR, etc.
|
1244
|
+
* SE_ECL_ANNULAR_TOTAL will be discovered later
|
1245
|
+
*/
|
1246
|
+
if ((retflag = eclipse_where(tjd, SE_SUN, NULL, ifl, geopos, dcore, serr)) == ERR)
|
1247
|
+
return retflag;
|
1248
|
+
if (retflag == 0) { /* can happen with extremely small percentage */
|
1249
|
+
retflag = SE_ECL_PARTIAL | SE_ECL_NONCENTRAL;
|
1250
|
+
tret[4] = tret[5] = tjd; /* fix this ???? */
|
1251
|
+
dont_times = TRUE;
|
1252
|
+
}
|
1253
|
+
/*
|
1254
|
+
* check whether or not eclipse type found is wanted
|
1255
|
+
*/
|
1256
|
+
/* non central eclipse is wanted: */
|
1257
|
+
if (!(ifltype & SE_ECL_NONCENTRAL) && (retflag & SE_ECL_NONCENTRAL)) {
|
1258
|
+
K += direction;
|
1259
|
+
goto next_try;
|
1260
|
+
}
|
1261
|
+
/* central eclipse is wanted: */
|
1262
|
+
if (!(ifltype & SE_ECL_CENTRAL) && (retflag & SE_ECL_CENTRAL)) {
|
1263
|
+
K += direction;
|
1264
|
+
goto next_try;
|
1265
|
+
}
|
1266
|
+
/* non annular eclipse is wanted: */
|
1267
|
+
if (!(ifltype & SE_ECL_ANNULAR) && (retflag & SE_ECL_ANNULAR)) {
|
1268
|
+
K += direction;
|
1269
|
+
goto next_try;
|
1270
|
+
}
|
1271
|
+
/* non partial eclipse is wanted: */
|
1272
|
+
if (!(ifltype & SE_ECL_PARTIAL) && (retflag & SE_ECL_PARTIAL)) {
|
1273
|
+
K += direction;
|
1274
|
+
goto next_try;
|
1275
|
+
}
|
1276
|
+
/* annular-total eclipse will be discovered later */
|
1277
|
+
if (!(ifltype & (SE_ECL_TOTAL | SE_ECL_ANNULAR_TOTAL)) && (retflag & SE_ECL_TOTAL)) {
|
1278
|
+
K += direction;
|
1279
|
+
goto next_try;
|
1280
|
+
}
|
1281
|
+
if (dont_times)
|
1282
|
+
goto end_search_global;
|
1283
|
+
/*
|
1284
|
+
* n = 0: times of eclipse begin and end
|
1285
|
+
* n = 1: times of totality begin and end
|
1286
|
+
* n = 2: times of center line begin and end
|
1287
|
+
*/
|
1288
|
+
if (retflag & SE_ECL_PARTIAL)
|
1289
|
+
o = 0;
|
1290
|
+
else if (retflag & SE_ECL_NONCENTRAL)
|
1291
|
+
o = 1;
|
1292
|
+
else
|
1293
|
+
o = 2;
|
1294
|
+
dta = twohr;
|
1295
|
+
dtb = tenmin / 3.0;
|
1296
|
+
for (n = 0; n <= o; n++) {
|
1297
|
+
if (n == 0) {
|
1298
|
+
/*dc[1] = dcore[3] / 2 + de - dcore[1];*/
|
1299
|
+
i1 = 2; i2 = 3;
|
1300
|
+
} else if (n == 1) {
|
1301
|
+
if (retflag & SE_ECL_PARTIAL)
|
1302
|
+
continue;
|
1303
|
+
i1 = 4; i2 = 5;
|
1304
|
+
} else if (n == 2) {
|
1305
|
+
if (retflag & SE_ECL_NONCENTRAL)
|
1306
|
+
continue;
|
1307
|
+
i1 = 6; i2 = 7;
|
1308
|
+
}
|
1309
|
+
for (i = 0, t = tjd - dta; i <= 2; i += 1, t += dta) {
|
1310
|
+
if ((retflag2 = eclipse_where(t, SE_SUN, NULL, ifl, geopos, dcore, serr)) == ERR)
|
1311
|
+
return retflag2;
|
1312
|
+
if (n == 0)
|
1313
|
+
dc[i] = dcore[4] / 2 + de / dcore[5] - dcore[2];
|
1314
|
+
else if (n == 1)
|
1315
|
+
dc[i] = fabs(dcore[3]) / 2 + de / dcore[6] - dcore[2];
|
1316
|
+
else if (n == 2)
|
1317
|
+
dc[i] = de / dcore[6] - dcore[2];
|
1318
|
+
}
|
1319
|
+
find_zero(dc[0], dc[1], dc[2], dta, &dt1, &dt2);
|
1320
|
+
tret[i1] = tjd + dt1 + dta;
|
1321
|
+
tret[i2] = tjd + dt2 + dta;
|
1322
|
+
for (m = 0, dt = dtb; m < 3; m++, dt /= 3) {
|
1323
|
+
for (j = i1; j <= i2; j += (i2 - i1)) {
|
1324
|
+
for (i = 0, t = tret[j] - dt; i < 2; i++, t += dt) {
|
1325
|
+
if ((retflag2 = eclipse_where(t, SE_SUN, NULL, ifl, geopos, dcore, serr)) == ERR)
|
1326
|
+
return retflag2;
|
1327
|
+
if (n == 0)
|
1328
|
+
dc[i] = dcore[4] / 2 + de / dcore[5] - dcore[2];
|
1329
|
+
else if (n == 1)
|
1330
|
+
dc[i] = fabs(dcore[3]) / 2 + de / dcore[6] - dcore[2];
|
1331
|
+
else if (n == 2)
|
1332
|
+
dc[i] = de / dcore[6] - dcore[2];
|
1333
|
+
}
|
1334
|
+
dt1 = dc[1] / ((dc[1] - dc[0]) / dt);
|
1335
|
+
tret[j] -= dt1;
|
1336
|
+
}
|
1337
|
+
}
|
1338
|
+
}
|
1339
|
+
/*
|
1340
|
+
* annular-total eclipses
|
1341
|
+
*/
|
1342
|
+
if (retflag & SE_ECL_TOTAL) {
|
1343
|
+
if ((retflag2 = eclipse_where(tret[0], SE_SUN, NULL, ifl, geopos, dcore, serr)) == ERR)
|
1344
|
+
return retflag2;
|
1345
|
+
dc[0] = *dcore;
|
1346
|
+
if ((retflag2 = eclipse_where(tret[4], SE_SUN, NULL, ifl, geopos, dcore, serr)) == ERR)
|
1347
|
+
return retflag2;
|
1348
|
+
dc[1] = *dcore;
|
1349
|
+
if ((retflag2 = eclipse_where(tret[5], SE_SUN, NULL, ifl, geopos, dcore, serr)) == ERR)
|
1350
|
+
return retflag2;
|
1351
|
+
dc[2] = *dcore;
|
1352
|
+
/* the maximum is always total, and there is either one or
|
1353
|
+
* to times before and after, when the core shadow becomes
|
1354
|
+
* zero and totality changes into annularity or vice versa.
|
1355
|
+
*/
|
1356
|
+
if (dc[0] * dc[1] < 0 || dc[0] * dc[2] < 0) {
|
1357
|
+
retflag |= SE_ECL_ANNULAR_TOTAL;
|
1358
|
+
retflag &= ~SE_ECL_TOTAL;
|
1359
|
+
}
|
1360
|
+
}
|
1361
|
+
/* if eclipse is given but not wanted: */
|
1362
|
+
if (!(ifltype & SE_ECL_TOTAL) && (retflag & SE_ECL_TOTAL)) {
|
1363
|
+
K += direction;
|
1364
|
+
goto next_try;
|
1365
|
+
}
|
1366
|
+
/* if annular_total eclipse is given but not wanted: */
|
1367
|
+
if (!(ifltype & SE_ECL_ANNULAR_TOTAL) && (retflag & SE_ECL_ANNULAR_TOTAL)) {
|
1368
|
+
K += direction;
|
1369
|
+
goto next_try;
|
1370
|
+
}
|
1371
|
+
/*
|
1372
|
+
* time of maximum eclipse at local apparent noon
|
1373
|
+
*/
|
1374
|
+
/* first, find out, if there is a solar transit
|
1375
|
+
* between begin and end of eclipse */
|
1376
|
+
k = 2;
|
1377
|
+
for (i = 0; i < 2; i++) {
|
1378
|
+
j = i + k;
|
1379
|
+
tt = tret[j] + swe_deltat(tret[j]);
|
1380
|
+
if (swe_calc(tt, SE_SUN, iflag, ls, serr) == ERR)
|
1381
|
+
return ERR;
|
1382
|
+
if (swe_calc(tt, SE_MOON, iflag, lm, serr) == ERR)
|
1383
|
+
return ERR;
|
1384
|
+
dc[i] = swe_degnorm(ls[0] - lm[0]);
|
1385
|
+
if (dc[i] > 180)
|
1386
|
+
dc[i] -= 360;
|
1387
|
+
}
|
1388
|
+
if (dc[0] * dc[1] >= 0) /* no transit */
|
1389
|
+
tret[1] = 0;
|
1390
|
+
else {
|
1391
|
+
tjd = tjds;
|
1392
|
+
dt = 0.1;
|
1393
|
+
dt1 = (tret[3] - tret[2]) / 2.0;
|
1394
|
+
if (dt1 < dt)
|
1395
|
+
dt = dt1 / 2.0;
|
1396
|
+
for (j = 0;
|
1397
|
+
dt > 0.01;
|
1398
|
+
j++, dt /= 3) {
|
1399
|
+
for (i = 0, t = tjd; i <= 1; i++, t -= dt) {
|
1400
|
+
tt = t + swe_deltat(t);
|
1401
|
+
if (swe_calc(tt, SE_SUN, iflag, ls, serr) == ERR)
|
1402
|
+
return ERR;
|
1403
|
+
if (swe_calc(tt, SE_MOON, iflag, lm, serr) == ERR)
|
1404
|
+
return ERR;
|
1405
|
+
dc[i] = swe_degnorm(ls[0] - lm[0]);
|
1406
|
+
if (dc[i] > 180)
|
1407
|
+
dc[i] -= 360;
|
1408
|
+
if (dc[i] > 180)
|
1409
|
+
dc[i] -= 360;
|
1410
|
+
}
|
1411
|
+
a = (dc[1] - dc[0]) / dt;
|
1412
|
+
if (a < 1e-10)
|
1413
|
+
break;
|
1414
|
+
dt1 = dc[0] / a;
|
1415
|
+
tjd += dt1;
|
1416
|
+
}
|
1417
|
+
tret[1] = tjd;
|
1418
|
+
}
|
1419
|
+
end_search_global:
|
1420
|
+
return retflag;
|
1421
|
+
/*
|
1422
|
+
* the time of maximum occultation is practically identical
|
1423
|
+
* with the time of maximum core shadow diameter.
|
1424
|
+
*
|
1425
|
+
* the time, when duration of totality is maximal,
|
1426
|
+
* is not an interesting computation either. Near the maximum
|
1427
|
+
* occulation, the time of totality can be the same by
|
1428
|
+
* a second for hundreds of kilometers (for 10 minutes
|
1429
|
+
* or more).
|
1430
|
+
*
|
1431
|
+
* for annular eclipses the maximum duration is close to the
|
1432
|
+
* beginning and the end of the center lines, where is also
|
1433
|
+
* the minimum of core shadow diameter.
|
1434
|
+
*/
|
1435
|
+
}
|
1436
|
+
|
1437
|
+
/* When is the next lunar occultation anywhere on earth?
|
1438
|
+
* This function also finds solar eclipses, but is less efficient
|
1439
|
+
* than swe_sol_eclipse_when_glob().
|
1440
|
+
*
|
1441
|
+
* input parameters:
|
1442
|
+
*
|
1443
|
+
* tjd_start start time for search (UT)
|
1444
|
+
* ipl planet number of occulted body
|
1445
|
+
* starname name of occulted star. Must be NULL or "", if a planetary
|
1446
|
+
* occultation is to be calculated. For the use of this
|
1447
|
+
* field, also see swe_fixstar().
|
1448
|
+
* ifl ephemeris to be used (SEFLG_SWIEPH, etc.)
|
1449
|
+
* ephemeris flag.
|
1450
|
+
*
|
1451
|
+
* ifltype eclipse type to be searched (SE_ECL_TOTAL, etc.)
|
1452
|
+
* 0, if any type of eclipse is wanted
|
1453
|
+
* this functionality also works with occultations
|
1454
|
+
*
|
1455
|
+
* backward if 1, causes search backward in time
|
1456
|
+
*
|
1457
|
+
* If you want to have only one conjunction
|
1458
|
+
* of the moon with the body tested, add the following flag:
|
1459
|
+
* backward |= SE_ECL_ONE_TRY. If this flag is not set,
|
1460
|
+
* the function will search for an occultation until it
|
1461
|
+
* finds one. For bodies with ecliptical latitudes > 5,
|
1462
|
+
* the function may search successlessly until it reaches
|
1463
|
+
* the end of the ephemeris.
|
1464
|
+
* (Note: we do not add SE_ECL_ONE_TRY to ifl, because
|
1465
|
+
* ifl may contain SEFLG_TOPOCTR (=SE_ECL_ONE_TRY) from
|
1466
|
+
* the parameter iflag of swe_calc() etc. Although the
|
1467
|
+
* topocentric flag is irrelevant here, it might cause
|
1468
|
+
* confusion.)
|
1469
|
+
*
|
1470
|
+
* return values:
|
1471
|
+
*
|
1472
|
+
* retflag SE_ECL_TOTAL or SE_ECL_ANNULAR or SE_ECL_PARTIAL
|
1473
|
+
* or SE_ECL_ANNULAR_TOTAL
|
1474
|
+
* SE_ECL_CENTRAL
|
1475
|
+
* SE_ECL_NONCENTRAL
|
1476
|
+
*
|
1477
|
+
* tret[0] time of maximum eclipse
|
1478
|
+
* tret[1] time, when eclipse takes place at local apparent noon
|
1479
|
+
* tret[2] time of eclipse begin
|
1480
|
+
* tret[3] time of eclipse end
|
1481
|
+
* tret[4] time of totality begin
|
1482
|
+
* tret[5] time of totality end
|
1483
|
+
* tret[6] time of center line begin
|
1484
|
+
* tret[7] time of center line end
|
1485
|
+
* tret[8] time when annular-total eclipse becomes total
|
1486
|
+
* not implemented so far
|
1487
|
+
* tret[9] time when annular-total eclipse becomes annular again
|
1488
|
+
* not implemented so far
|
1489
|
+
* declare as tret[10] at least!
|
1490
|
+
*
|
1491
|
+
*/
|
1492
|
+
int32 FAR PASCAL_CONV swe_lun_occult_when_glob(
|
1493
|
+
double tjd_start, int32 ipl, char *starname, int32 ifl, int32 ifltype,
|
1494
|
+
double *tret, int32 backward, char *serr)
|
1495
|
+
{
|
1496
|
+
int i, j, k, m, n, o, i1, i2;
|
1497
|
+
int32 retflag = 0, retflag2 = 0;
|
1498
|
+
double de = 6378.140, a;
|
1499
|
+
double t, tt, tjd = 0, tjds, dt, dtint, dta, dtb;
|
1500
|
+
double drad;
|
1501
|
+
double xs[6], xm[6], ls[6], lm[6];
|
1502
|
+
double rmoon, rsun, dcore[10];
|
1503
|
+
double dc[20], dctr;
|
1504
|
+
double twohr = 2.0 / 24.0;
|
1505
|
+
double tenmin = 10.0 / 24.0 / 60.0;
|
1506
|
+
double dt1, dt2, dadd = 10, dadd2 = 6;
|
1507
|
+
int nstartpos = 10;
|
1508
|
+
double geopos[20];
|
1509
|
+
double dtstart, dtdiv;
|
1510
|
+
int direction = 1;
|
1511
|
+
char s[AS_MAXCH];
|
1512
|
+
int32 iflag, iflagcart;
|
1513
|
+
AS_BOOL dont_times = FALSE;
|
1514
|
+
int32 one_try = backward & SE_ECL_ONE_TRY;
|
1515
|
+
/*if (backward & SEI_OCC_FAST)
|
1516
|
+
dont_times = TRUE; */
|
1517
|
+
/* function calls for Pluto with asteroid number 134340
|
1518
|
+
* are treated as calls for Pluto as main body SE_PLUTO */
|
1519
|
+
if (ipl == SE_AST_OFFSET + 134340)
|
1520
|
+
ipl = SE_PLUTO;
|
1521
|
+
ifl &= SEFLG_EPHMASK;
|
1522
|
+
iflag = SEFLG_EQUATORIAL | ifl;
|
1523
|
+
iflagcart = iflag | SEFLG_XYZ;
|
1524
|
+
backward &= 1L;
|
1525
|
+
/*
|
1526
|
+
* initializations
|
1527
|
+
*/
|
1528
|
+
if (ifltype == (SE_ECL_PARTIAL | SE_ECL_CENTRAL)) {
|
1529
|
+
if (serr != NULL)
|
1530
|
+
strcpy(serr, "central partial eclipses do not exist");
|
1531
|
+
return ERR;
|
1532
|
+
}
|
1533
|
+
if (ifltype == 0)
|
1534
|
+
ifltype = SE_ECL_TOTAL | SE_ECL_ANNULAR | SE_ECL_PARTIAL
|
1535
|
+
| SE_ECL_ANNULAR_TOTAL | SE_ECL_NONCENTRAL | SE_ECL_CENTRAL;
|
1536
|
+
retflag = 0;
|
1537
|
+
for (i = 0; i <= 9; i++)
|
1538
|
+
tret[i] = 0;
|
1539
|
+
if (backward)
|
1540
|
+
direction = -1;
|
1541
|
+
t = tjd_start - direction * 0.001;
|
1542
|
+
next_try:
|
1543
|
+
for (i = 0; i < nstartpos; i++, t += direction * dadd2) {
|
1544
|
+
if (calc_planet_star(t, ipl, starname, iflagcart, xs, serr) == ERR)
|
1545
|
+
return ERR;
|
1546
|
+
if (swe_calc(t, SE_MOON, iflagcart, xm, serr) == ERR)
|
1547
|
+
return ERR;
|
1548
|
+
dc[i] = acos(swi_dot_prod_unit(xs, xm)) * RADTODEG;
|
1549
|
+
if (i > 1 && dc[i] > dc[i-1] && dc[i-2] > dc[i-1]) {
|
1550
|
+
tjd = t - direction * dadd2;
|
1551
|
+
break;
|
1552
|
+
} else if (i == nstartpos-1) {
|
1553
|
+
/*for (j = 0; j < nstartpos; j++)
|
1554
|
+
printf("%f ", dc[j]);*/
|
1555
|
+
if (serr != NULL) {
|
1556
|
+
if (starname != NULL && *starname != '\0')
|
1557
|
+
strcpy(s, starname);
|
1558
|
+
else
|
1559
|
+
swe_get_planet_name(ipl , s);
|
1560
|
+
sprintf(serr, "error in swe_lun_occult_when_glob(): conjunction of moon with planet %s not found\n", s);
|
1561
|
+
}
|
1562
|
+
return ERR;
|
1563
|
+
}
|
1564
|
+
}
|
1565
|
+
/*
|
1566
|
+
* radius of planet disk in AU
|
1567
|
+
*/
|
1568
|
+
if (starname != NULL && *starname != '\0')
|
1569
|
+
drad = 0;
|
1570
|
+
else if (ipl < NDIAM)
|
1571
|
+
drad = pla_diam[ipl] / 2 / AUNIT;
|
1572
|
+
else if (ipl > SE_AST_OFFSET)
|
1573
|
+
drad = swed.ast_diam / 2 * 1000 / AUNIT; /* km -> m -> AU */
|
1574
|
+
else
|
1575
|
+
drad = 0;
|
1576
|
+
/*
|
1577
|
+
* time of maximum eclipse (if eclipse) =
|
1578
|
+
* minimum geocentric angle between sun and moon edges.
|
1579
|
+
* After this time has been determined, check
|
1580
|
+
* whether or not an eclipse is taking place with
|
1581
|
+
* the functions eclipse_where() and _how().
|
1582
|
+
*/
|
1583
|
+
dtstart = dadd2; /* originally 1 */
|
1584
|
+
dtdiv = 3;
|
1585
|
+
for (dt = dtstart;
|
1586
|
+
dt > 0.0001;
|
1587
|
+
dt /= dtdiv) {
|
1588
|
+
for (i = 0, t = tjd - dt; i <= 2; i++, t += dt) {
|
1589
|
+
if (calc_planet_star(t, ipl, starname, iflag, ls, serr) == ERR)
|
1590
|
+
return ERR;
|
1591
|
+
if (swe_calc(t, SE_MOON, iflag, lm, serr) == ERR)
|
1592
|
+
return ERR;
|
1593
|
+
if (calc_planet_star(t, ipl, starname, iflagcart, xs, serr) == ERR)
|
1594
|
+
return ERR;
|
1595
|
+
if (swe_calc(t, SE_MOON, iflagcart, xm, serr) == ERR)
|
1596
|
+
return ERR;
|
1597
|
+
dc[i] = acos(swi_dot_prod_unit(xs, xm)) * RADTODEG;
|
1598
|
+
rmoon = asin(RMOON / lm[2]) * RADTODEG;
|
1599
|
+
rsun = asin(drad / ls[2]) * RADTODEG;
|
1600
|
+
dc[i] -= (rmoon + rsun);
|
1601
|
+
}
|
1602
|
+
find_maximum(dc[0], dc[1], dc[2], dt, &dtint, &dctr);
|
1603
|
+
tjd += dtint + dt;
|
1604
|
+
}
|
1605
|
+
tjd -= swe_deltat(tjd);
|
1606
|
+
tjds = tjd;
|
1607
|
+
if ((retflag = eclipse_where(tjd, ipl, starname, ifl, geopos, dcore, serr)) == ERR)
|
1608
|
+
return retflag;
|
1609
|
+
retflag2 = retflag;
|
1610
|
+
/* in extreme cases _where() returns no eclipse, where there is
|
1611
|
+
* actually a very small one, therefore call _how() with the
|
1612
|
+
* coordinates returned by _where(): */
|
1613
|
+
/* if ((retflag2 = eclipse_how(tjd, ipl, starname, ifl, geopos[0], geopos[1], 0, attr, serr)) == ERR)
|
1614
|
+
return retflag2; */
|
1615
|
+
if (retflag2 == 0) {
|
1616
|
+
/* only one try! */
|
1617
|
+
if (one_try) {
|
1618
|
+
tret[0] = tjd;
|
1619
|
+
return 0;
|
1620
|
+
}
|
1621
|
+
t= tjd + direction * dadd;
|
1622
|
+
goto next_try;
|
1623
|
+
}
|
1624
|
+
tret[0] = tjd;
|
1625
|
+
if ((backward && tret[0] >= tjd_start - 0.0001)
|
1626
|
+
|| (!backward && tret[0] <= tjd_start + 0.0001)) {
|
1627
|
+
t= tjd + direction * dadd;
|
1628
|
+
goto next_try;
|
1629
|
+
}
|
1630
|
+
/*
|
1631
|
+
* eclipse type, SE_ECL_TOTAL, _ANNULAR, etc.
|
1632
|
+
* SE_ECL_ANNULAR_TOTAL will be discovered later
|
1633
|
+
*/
|
1634
|
+
if ((retflag = eclipse_where(tjd, ipl, starname, ifl, geopos, dcore, serr)) == ERR)
|
1635
|
+
return retflag;
|
1636
|
+
if (retflag == 0) { /* can happen with extremely small percentage */
|
1637
|
+
retflag = SE_ECL_PARTIAL | SE_ECL_NONCENTRAL;
|
1638
|
+
tret[4] = tret[5] = tjd; /* fix this ???? */
|
1639
|
+
dont_times = TRUE;
|
1640
|
+
}
|
1641
|
+
/*
|
1642
|
+
* check whether or not eclipse type found is wanted
|
1643
|
+
*/
|
1644
|
+
/* non central eclipse is wanted: */
|
1645
|
+
if (!(ifltype & SE_ECL_NONCENTRAL) && (retflag & SE_ECL_NONCENTRAL)) {
|
1646
|
+
t= tjd + direction * dadd;
|
1647
|
+
goto next_try;
|
1648
|
+
}
|
1649
|
+
/* central eclipse is wanted: */
|
1650
|
+
if (!(ifltype & SE_ECL_CENTRAL) && (retflag & SE_ECL_CENTRAL)) {
|
1651
|
+
t= tjd + direction * dadd;
|
1652
|
+
goto next_try;
|
1653
|
+
}
|
1654
|
+
/* non annular eclipse is wanted: */
|
1655
|
+
if (!(ifltype & SE_ECL_ANNULAR) && (retflag & SE_ECL_ANNULAR)) {
|
1656
|
+
t= tjd + direction * dadd;
|
1657
|
+
goto next_try;
|
1658
|
+
}
|
1659
|
+
/* non partial eclipse is wanted: */
|
1660
|
+
if (!(ifltype & SE_ECL_PARTIAL) && (retflag & SE_ECL_PARTIAL)) {
|
1661
|
+
t= tjd + direction * dadd;
|
1662
|
+
goto next_try;
|
1663
|
+
}
|
1664
|
+
/* annular-total eclipse will be discovered later */
|
1665
|
+
if (!(ifltype & (SE_ECL_TOTAL | SE_ECL_ANNULAR_TOTAL)) && (retflag & SE_ECL_TOTAL)) {
|
1666
|
+
t= tjd + direction * dadd;
|
1667
|
+
goto next_try;
|
1668
|
+
}
|
1669
|
+
if (dont_times)
|
1670
|
+
goto end_search_global;
|
1671
|
+
/*
|
1672
|
+
* n = 0: times of eclipse begin and end
|
1673
|
+
* n = 1: times of totality begin and end
|
1674
|
+
* n = 2: times of center line begin and end
|
1675
|
+
*/
|
1676
|
+
if (retflag & SE_ECL_PARTIAL)
|
1677
|
+
o = 0;
|
1678
|
+
else if (retflag & SE_ECL_NONCENTRAL)
|
1679
|
+
o = 1;
|
1680
|
+
else
|
1681
|
+
o = 2;
|
1682
|
+
dta = twohr;
|
1683
|
+
dtb = tenmin;
|
1684
|
+
for (n = 0; n <= o; n++) {
|
1685
|
+
if (n == 0) {
|
1686
|
+
/*dc[1] = dcore[3] / 2 + de - dcore[1];*/
|
1687
|
+
i1 = 2; i2 = 3;
|
1688
|
+
} else if (n == 1) {
|
1689
|
+
if (retflag & SE_ECL_PARTIAL)
|
1690
|
+
continue;
|
1691
|
+
i1 = 4; i2 = 5;
|
1692
|
+
} else if (n == 2) {
|
1693
|
+
if (retflag & SE_ECL_NONCENTRAL)
|
1694
|
+
continue;
|
1695
|
+
i1 = 6; i2 = 7;
|
1696
|
+
}
|
1697
|
+
for (i = 0, t = tjd - dta; i <= 2; i += 1, t += dta) {
|
1698
|
+
if ((retflag2 = eclipse_where(t, ipl, starname, ifl, geopos, dcore, serr)) == ERR)
|
1699
|
+
return retflag2;
|
1700
|
+
if (n == 0)
|
1701
|
+
dc[i] = dcore[4] / 2 + de / dcore[5] - dcore[2];
|
1702
|
+
else if (n == 1)
|
1703
|
+
dc[i] = fabs(dcore[3]) / 2 + de / dcore[6] - dcore[2];
|
1704
|
+
else if (n == 2)
|
1705
|
+
dc[i] = de / dcore[6] - dcore[2];
|
1706
|
+
}
|
1707
|
+
find_zero(dc[0], dc[1], dc[2], dta, &dt1, &dt2);
|
1708
|
+
tret[i1] = tjd + dt1 + dta;
|
1709
|
+
tret[i2] = tjd + dt2 + dta;
|
1710
|
+
for (m = 0, dt = dtb; m < 3; m++, dt /= 3) {
|
1711
|
+
for (j = i1; j <= i2; j += (i2 - i1)) {
|
1712
|
+
for (i = 0, t = tret[j] - dt; i < 2; i++, t += dt) {
|
1713
|
+
if ((retflag2 = eclipse_where(t, ipl, starname, ifl, geopos, dcore, serr)) == ERR)
|
1714
|
+
return retflag2;
|
1715
|
+
if (n == 0)
|
1716
|
+
dc[i] = dcore[4] / 2 + de / dcore[5] - dcore[2];
|
1717
|
+
else if (n == 1)
|
1718
|
+
dc[i] = fabs(dcore[3]) / 2 + de / dcore[6] - dcore[2];
|
1719
|
+
else if (n == 2)
|
1720
|
+
dc[i] = de / dcore[6] - dcore[2];
|
1721
|
+
}
|
1722
|
+
dt1 = dc[1] / ((dc[1] - dc[0]) / dt);
|
1723
|
+
tret[j] -= dt1;
|
1724
|
+
}
|
1725
|
+
}
|
1726
|
+
}
|
1727
|
+
/*
|
1728
|
+
* annular-total eclipses
|
1729
|
+
*/
|
1730
|
+
if (retflag & SE_ECL_TOTAL) {
|
1731
|
+
if ((retflag2 = eclipse_where(tret[0], ipl, starname, ifl, geopos, dcore, serr)) == ERR)
|
1732
|
+
return retflag2;
|
1733
|
+
dc[0] = *dcore;
|
1734
|
+
if ((retflag2 = eclipse_where(tret[4], ipl, starname, ifl, geopos, dcore, serr)) == ERR)
|
1735
|
+
return retflag2;
|
1736
|
+
dc[1] = *dcore;
|
1737
|
+
if ((retflag2 = eclipse_where(tret[5], ipl, starname, ifl, geopos, dcore, serr)) == ERR)
|
1738
|
+
return retflag2;
|
1739
|
+
dc[2] = *dcore;
|
1740
|
+
/* the maximum is always total, and there is either one or
|
1741
|
+
* to times before and after, when the core shadow becomes
|
1742
|
+
* zero and totality changes into annularity or vice versa.
|
1743
|
+
*/
|
1744
|
+
if (dc[0] * dc[1] < 0 || dc[0] * dc[2] < 0) {
|
1745
|
+
retflag |= SE_ECL_ANNULAR_TOTAL;
|
1746
|
+
retflag &= ~SE_ECL_TOTAL;
|
1747
|
+
}
|
1748
|
+
}
|
1749
|
+
/* if eclipse is given but not wanted: */
|
1750
|
+
if (!(ifltype & SE_ECL_TOTAL) && (retflag & SE_ECL_TOTAL)) {
|
1751
|
+
t= tjd + direction * dadd;
|
1752
|
+
goto next_try;
|
1753
|
+
}
|
1754
|
+
/* if annular_total eclipse is given but not wanted: */
|
1755
|
+
if (!(ifltype & SE_ECL_ANNULAR_TOTAL) && (retflag & SE_ECL_ANNULAR_TOTAL)) {
|
1756
|
+
t= tjd + direction * dadd;
|
1757
|
+
goto next_try;
|
1758
|
+
}
|
1759
|
+
/*
|
1760
|
+
* time of maximum eclipse at local apparent noon
|
1761
|
+
*/
|
1762
|
+
/* first, find out, if there is a solar transit
|
1763
|
+
* between begin and end of eclipse */
|
1764
|
+
k = 2;
|
1765
|
+
for (i = 0; i < 2; i++) {
|
1766
|
+
j = i + k;
|
1767
|
+
tt = tret[j] + swe_deltat(tret[j]);
|
1768
|
+
if (calc_planet_star(tt, ipl, starname, iflag, ls, serr) == ERR)
|
1769
|
+
return ERR;
|
1770
|
+
if (swe_calc(tt, SE_MOON, iflag, lm, serr) == ERR)
|
1771
|
+
return ERR;
|
1772
|
+
dc[i] = swe_degnorm(ls[0] - lm[0]);
|
1773
|
+
if (dc[i] > 180)
|
1774
|
+
dc[i] -= 360;
|
1775
|
+
}
|
1776
|
+
if (dc[0] * dc[1] >= 0) /* no transit */
|
1777
|
+
tret[1] = 0;
|
1778
|
+
else {
|
1779
|
+
tjd = tjds;
|
1780
|
+
dt = 0.1;
|
1781
|
+
dt1 = (tret[3] - tret[2]) / 2.0;
|
1782
|
+
if (dt1 < dt)
|
1783
|
+
dt = dt1 / 2.0;
|
1784
|
+
for (j = 0;
|
1785
|
+
dt > 0.01;
|
1786
|
+
j++, dt /= 3) {
|
1787
|
+
for (i = 0, t = tjd; i <= 1; i++, t -= dt) {
|
1788
|
+
tt = t + swe_deltat(t);
|
1789
|
+
if (calc_planet_star(tt, ipl, starname, iflag, ls, serr) == ERR)
|
1790
|
+
return ERR;
|
1791
|
+
if (swe_calc(tt, SE_MOON, iflag, lm, serr) == ERR)
|
1792
|
+
return ERR;
|
1793
|
+
dc[i] = swe_degnorm(ls[0] - lm[0]);
|
1794
|
+
if (dc[i] > 180)
|
1795
|
+
dc[i] -= 360;
|
1796
|
+
if (dc[i] > 180)
|
1797
|
+
dc[i] -= 360;
|
1798
|
+
}
|
1799
|
+
a = (dc[1] - dc[0]) / dt;
|
1800
|
+
if (a < 1e-10)
|
1801
|
+
break;
|
1802
|
+
dt1 = dc[0] / a;
|
1803
|
+
tjd += dt1;
|
1804
|
+
}
|
1805
|
+
tret[1] = tjd;
|
1806
|
+
}
|
1807
|
+
end_search_global:
|
1808
|
+
return retflag;
|
1809
|
+
/*
|
1810
|
+
* the time of maximum occultation is practically identical
|
1811
|
+
* with the time of maximum core shadow diameter.
|
1812
|
+
*
|
1813
|
+
* the time, when duration of totality is maximal,
|
1814
|
+
* is not an interesting computation either. Near the maximum
|
1815
|
+
* occulation, the time of totality can be the same by
|
1816
|
+
* a second for hundreds of kilometers (for 10 minutes
|
1817
|
+
* or more).
|
1818
|
+
*
|
1819
|
+
* for annular eclipses the maximum duration is close to the
|
1820
|
+
* beginning and the end of the center lines, where is also
|
1821
|
+
* the minimum of core shadow diameter.
|
1822
|
+
*/
|
1823
|
+
}
|
1824
|
+
|
1825
|
+
/* When is the next solar eclipse at a given geographical position?
|
1826
|
+
* Note the uncertainty of Delta T for the remote past and for
|
1827
|
+
* the future.
|
1828
|
+
*
|
1829
|
+
* retflag SE_ECL_TOTAL or SE_ECL_ANNULAR or SE_ECL_PARTIAL
|
1830
|
+
* SE_ECL_VISIBLE,
|
1831
|
+
* SE_ECL_MAX_VISIBLE,
|
1832
|
+
* SE_ECL_1ST_VISIBLE, SE_ECL_2ND_VISIBLE
|
1833
|
+
* SE_ECL_3ST_VISIBLE, SE_ECL_4ND_VISIBLE
|
1834
|
+
*
|
1835
|
+
* tret[0] time of maximum eclipse
|
1836
|
+
* tret[1] time of first contact
|
1837
|
+
* tret[2] time of second contact
|
1838
|
+
* tret[3] time of third contact
|
1839
|
+
* tret[4] time of forth contact
|
1840
|
+
* tret[5] time of sun rise between first and forth contact
|
1841
|
+
(not implemented so far)
|
1842
|
+
* tret[6] time of sun set beween first and forth contact
|
1843
|
+
(not implemented so far)
|
1844
|
+
*
|
1845
|
+
* attr[0] fraction of solar diameter covered by moon (magnitude)
|
1846
|
+
* attr[1] ratio of lunar diameter to solar one
|
1847
|
+
* attr[2] fraction of solar disc covered by moon (obscuration)
|
1848
|
+
* attr[3] diameter of core shadow in km
|
1849
|
+
* attr[4] azimuth of sun at tjd
|
1850
|
+
* attr[5] true altitude of sun above horizon at tjd
|
1851
|
+
* attr[6] apparent altitude of sun above horizon at tjd
|
1852
|
+
* attr[7] elongation of moon in degrees
|
1853
|
+
* declare as attr[20] at least !
|
1854
|
+
*/
|
1855
|
+
int32 FAR PASCAL_CONV swe_sol_eclipse_when_loc(double tjd_start, int32 ifl,
|
1856
|
+
double *geopos, double *tret, double *attr, int32 backward, char *serr)
|
1857
|
+
{
|
1858
|
+
int32 retflag = 0, retflag2 = 0;
|
1859
|
+
double geopos2[20], dcore[10];
|
1860
|
+
ifl &= SEFLG_EPHMASK;
|
1861
|
+
if ((retflag = eclipse_when_loc(tjd_start, ifl, geopos, tret, attr, backward, serr)) <= 0)
|
1862
|
+
return retflag;
|
1863
|
+
/*
|
1864
|
+
* diameter of core shadow
|
1865
|
+
*/
|
1866
|
+
if ((retflag2 = eclipse_where(tret[0], SE_SUN, NULL, ifl, geopos2, dcore, serr)) == ERR)
|
1867
|
+
return retflag2;
|
1868
|
+
retflag |= (retflag2 & SE_ECL_NONCENTRAL);
|
1869
|
+
attr[3] = dcore[0];
|
1870
|
+
return retflag;
|
1871
|
+
}
|
1872
|
+
|
1873
|
+
/* Same declaration as swe_sol_eclipse_when_loc().
|
1874
|
+
* In addition:
|
1875
|
+
* int32 ipl planet number of occulted body
|
1876
|
+
* char* starname name of occulted star. Must be NULL or "", if a planetary
|
1877
|
+
* occultation is to be calculated. For the use of this
|
1878
|
+
* field, also see swe_fixstar().
|
1879
|
+
* int32 ifl ephemeris flag. If you want to have only one conjunction
|
1880
|
+
* of the moon with the body tested, add the following flag:
|
1881
|
+
* backward |= SE_ECL_ONE_TRY. If this flag is not set,
|
1882
|
+
* the function will search for an occultation until it
|
1883
|
+
* finds one. For bodies with ecliptical latitudes > 5,
|
1884
|
+
* the function may search unsuccessfully until it reaches
|
1885
|
+
* the end of the ephemeris.
|
1886
|
+
*/
|
1887
|
+
int32 FAR PASCAL_CONV swe_lun_occult_when_loc(double tjd_start, int32 ipl, char *starname, int32 ifl,
|
1888
|
+
double *geopos, double *tret, double *attr, int32 backward, char *serr)
|
1889
|
+
{
|
1890
|
+
int32 retflag = 0, retflag2 = 0;
|
1891
|
+
double geopos2[20], dcore[10];
|
1892
|
+
/* function calls for Pluto with asteroid number 134340
|
1893
|
+
* are treated as calls for Pluto as main body SE_PLUTO */
|
1894
|
+
if (ipl == SE_AST_OFFSET + 134340)
|
1895
|
+
ipl = SE_PLUTO;
|
1896
|
+
ifl &= SEFLG_EPHMASK;
|
1897
|
+
if ((retflag = occult_when_loc(tjd_start, ipl, starname, ifl, geopos, tret, attr, backward, serr)) <= 0)
|
1898
|
+
return retflag;
|
1899
|
+
/*
|
1900
|
+
* diameter of core shadow
|
1901
|
+
*/
|
1902
|
+
if ((retflag2 = eclipse_where(tret[0], ipl, starname, ifl, geopos2, dcore, serr)) == ERR)
|
1903
|
+
return retflag2;
|
1904
|
+
retflag |= (retflag2 & SE_ECL_NONCENTRAL);
|
1905
|
+
attr[3] = dcore[0];
|
1906
|
+
return retflag;
|
1907
|
+
}
|
1908
|
+
|
1909
|
+
static int32 eclipse_when_loc(double tjd_start, int32 ifl, double *geopos, double *tret, double *attr, int32 backward, char *serr)
|
1910
|
+
{
|
1911
|
+
int i, j, k, m;
|
1912
|
+
int32 retflag = 0;
|
1913
|
+
double t, tjd, dt, dtint, K, T, T2, T3, T4, F, M, Mm;
|
1914
|
+
double E, Ff, A1, Om;
|
1915
|
+
double xs[6], xm[6], ls[6], lm[6], x1[6], x2[6], dm, ds;
|
1916
|
+
double rmoon, rsun, rsplusrm, rsminusrm;
|
1917
|
+
double dc[3], dctr, dctrmin;
|
1918
|
+
double twomin = 2.0 / 24.0 / 60.0;
|
1919
|
+
double tensec = 10.0 / 24.0 / 60.0 / 60.0;
|
1920
|
+
double twohr = 2.0 / 24.0;
|
1921
|
+
double tenmin = 10.0 / 24.0 / 60.0;
|
1922
|
+
double dt1, dt2, dtdiv, dtstart;
|
1923
|
+
int32 iflag = SEFLG_EQUATORIAL | SEFLG_TOPOCTR | ifl;
|
1924
|
+
int32 iflagcart = iflag | SEFLG_XYZ;
|
1925
|
+
swe_set_topo(geopos[0], geopos[1], geopos[2]);
|
1926
|
+
K = (int) ((tjd_start - J2000) / 365.2425 * 12.3685);
|
1927
|
+
if (backward)
|
1928
|
+
K++;
|
1929
|
+
else
|
1930
|
+
K--;
|
1931
|
+
next_try:
|
1932
|
+
T = K / 1236.85;
|
1933
|
+
T2 = T * T; T3 = T2 * T; T4 = T3 * T;
|
1934
|
+
Ff = F = swe_degnorm(160.7108 + 390.67050274 * K
|
1935
|
+
- 0.0016341 * T2
|
1936
|
+
- 0.00000227 * T3
|
1937
|
+
+ 0.000000011 * T4);
|
1938
|
+
if (Ff > 180)
|
1939
|
+
Ff -= 180;
|
1940
|
+
if (Ff > 21 && Ff < 159) { /* no eclipse possible */
|
1941
|
+
if (backward)
|
1942
|
+
K--;
|
1943
|
+
else
|
1944
|
+
K++;
|
1945
|
+
goto next_try;
|
1946
|
+
}
|
1947
|
+
/* approximate time of geocentric maximum eclipse.
|
1948
|
+
* formula from Meeus, German, p. 381 */
|
1949
|
+
tjd = 2451550.09765 + 29.530588853 * K
|
1950
|
+
+ 0.0001337 * T2
|
1951
|
+
- 0.000000150 * T3
|
1952
|
+
+ 0.00000000073 * T4;
|
1953
|
+
M = swe_degnorm(2.5534 + 29.10535669 * K
|
1954
|
+
- 0.0000218 * T2
|
1955
|
+
- 0.00000011 * T3);
|
1956
|
+
Mm = swe_degnorm(201.5643 + 385.81693528 * K
|
1957
|
+
+ 0.1017438 * T2
|
1958
|
+
+ 0.00001239 * T3
|
1959
|
+
+ 0.000000058 * T4);
|
1960
|
+
Om = swe_degnorm(124.7746 - 1.56375580 * K
|
1961
|
+
+ 0.0020691 * T2
|
1962
|
+
+ 0.00000215 * T3);
|
1963
|
+
E = 1 - 0.002516 * T - 0.0000074 * T2;
|
1964
|
+
A1 = swe_degnorm(299.77 + 0.107408 * K - 0.009173 * T2);
|
1965
|
+
M *= DEGTORAD;
|
1966
|
+
Mm *= DEGTORAD;
|
1967
|
+
F *= DEGTORAD;
|
1968
|
+
Om *= DEGTORAD;
|
1969
|
+
A1 *= DEGTORAD;
|
1970
|
+
tjd = tjd - 0.4075 * sin(Mm)
|
1971
|
+
+ 0.1721 * E * sin(M);
|
1972
|
+
swe_set_topo(geopos[0], geopos[1], geopos[2]);
|
1973
|
+
dtdiv = 2;
|
1974
|
+
dtstart = 0.5;
|
1975
|
+
if (tjd < 1900000) /* because above formula is not good (delta t?) */
|
1976
|
+
dtstart = 2;
|
1977
|
+
for (dt = dtstart;
|
1978
|
+
dt > 0.00001;
|
1979
|
+
dt /= dtdiv) {
|
1980
|
+
if (dt < 0.1)
|
1981
|
+
dtdiv = 3;
|
1982
|
+
for (i = 0, t = tjd - dt; i <= 2; i++, t += dt) {
|
1983
|
+
/* this takes some time, but is necessary to avoid
|
1984
|
+
* missing an eclipse */
|
1985
|
+
if (swe_calc(t, SE_SUN, iflagcart, xs, serr) == ERR)
|
1986
|
+
return ERR;
|
1987
|
+
if (swe_calc(t, SE_SUN, iflag, ls, serr) == ERR)
|
1988
|
+
return ERR;
|
1989
|
+
if (swe_calc(t, SE_MOON, iflagcart, xm, serr) == ERR)
|
1990
|
+
return ERR;
|
1991
|
+
if (swe_calc(t, SE_MOON, iflag, lm, serr) == ERR)
|
1992
|
+
return ERR;
|
1993
|
+
dm = sqrt(square_sum(xm));
|
1994
|
+
ds = sqrt(square_sum(xs));
|
1995
|
+
for (k = 0; k < 3; k++) {
|
1996
|
+
x1[k] = xs[k] / ds /*ls[2]*/;
|
1997
|
+
x2[k] = xm[k] / dm /*lm[2]*/;
|
1998
|
+
}
|
1999
|
+
dc[i] = acos(swi_dot_prod_unit(x1, x2)) * RADTODEG;
|
2000
|
+
}
|
2001
|
+
find_maximum(dc[0], dc[1], dc[2], dt, &dtint, &dctr);
|
2002
|
+
tjd += dtint + dt;
|
2003
|
+
}
|
2004
|
+
if (swe_calc(tjd, SE_SUN, iflagcart, xs, serr) == ERR)
|
2005
|
+
return ERR;
|
2006
|
+
if (swe_calc(tjd, SE_SUN, iflag, ls, serr) == ERR)
|
2007
|
+
return ERR;
|
2008
|
+
if (swe_calc(tjd, SE_MOON, iflagcart, xm, serr) == ERR)
|
2009
|
+
return ERR;
|
2010
|
+
if (swe_calc(tjd, SE_MOON, iflag, lm, serr) == ERR)
|
2011
|
+
return ERR;
|
2012
|
+
dctr = acos(swi_dot_prod_unit(xs, xm)) * RADTODEG;
|
2013
|
+
rmoon = asin(RMOON / lm[2]) * RADTODEG;
|
2014
|
+
rsun = asin(RSUN / ls[2]) * RADTODEG;
|
2015
|
+
rsplusrm = rsun + rmoon;
|
2016
|
+
rsminusrm = rsun - rmoon;
|
2017
|
+
if (dctr > rsplusrm) {
|
2018
|
+
if (backward)
|
2019
|
+
K--;
|
2020
|
+
else
|
2021
|
+
K++;
|
2022
|
+
goto next_try;
|
2023
|
+
}
|
2024
|
+
tret[0] = tjd - swe_deltat(tjd);
|
2025
|
+
if ((backward && tret[0] >= tjd_start - 0.0001)
|
2026
|
+
|| (!backward && tret[0] <= tjd_start + 0.0001)) {
|
2027
|
+
if (backward)
|
2028
|
+
K--;
|
2029
|
+
else
|
2030
|
+
K++;
|
2031
|
+
goto next_try;
|
2032
|
+
}
|
2033
|
+
if (dctr < rsminusrm)
|
2034
|
+
retflag = SE_ECL_ANNULAR;
|
2035
|
+
else if (dctr < fabs(rsminusrm))
|
2036
|
+
retflag = SE_ECL_TOTAL;
|
2037
|
+
else if (dctr <= rsplusrm)
|
2038
|
+
retflag = SE_ECL_PARTIAL;
|
2039
|
+
dctrmin = dctr;
|
2040
|
+
/* contacts 2 and 3 */
|
2041
|
+
if (dctr > fabs(rsminusrm)) /* partial, no 2nd and 3rd contact */
|
2042
|
+
tret[2] = tret[3] = 0;
|
2043
|
+
else {
|
2044
|
+
dc[1] = fabs(rsminusrm) - dctrmin;
|
2045
|
+
for (i = 0, t = tjd - twomin; i <= 2; i += 2, t = tjd + twomin) {
|
2046
|
+
if (swe_calc(t, SE_SUN, iflagcart, xs, serr) == ERR)
|
2047
|
+
return ERR;
|
2048
|
+
if (swe_calc(t, SE_MOON, iflagcart, xm, serr) == ERR)
|
2049
|
+
return ERR;
|
2050
|
+
dm = sqrt(square_sum(xm));
|
2051
|
+
ds = sqrt(square_sum(xs));
|
2052
|
+
rmoon = asin(RMOON / dm) * RADTODEG;
|
2053
|
+
rsun = asin(RSUN / ds) * RADTODEG;
|
2054
|
+
rsminusrm = rsun - rmoon;
|
2055
|
+
for (k = 0; k < 3; k++) {
|
2056
|
+
x1[k] = xs[k] / ds /*ls[2]*/;
|
2057
|
+
x2[k] = xm[k] / dm /*lm[2]*/;
|
2058
|
+
}
|
2059
|
+
dctr = acos(swi_dot_prod_unit(x1, x2)) * RADTODEG;
|
2060
|
+
dc[i] = fabs(rsminusrm) - dctr;
|
2061
|
+
}
|
2062
|
+
find_zero(dc[0], dc[1], dc[2], twomin, &dt1, &dt2);
|
2063
|
+
tret[2] = tjd + dt1 + twomin;
|
2064
|
+
tret[3] = tjd + dt2 + twomin;
|
2065
|
+
for (m = 0, dt = tensec; m < 2; m++, dt /= 10) {
|
2066
|
+
for (j = 2; j <= 3; j++) {
|
2067
|
+
if (swe_calc(tret[j], SE_SUN, iflagcart | SEFLG_SPEED, xs, serr) == ERR)
|
2068
|
+
return ERR;
|
2069
|
+
if (swe_calc(tret[j], SE_MOON, iflagcart | SEFLG_SPEED, xm, serr) == ERR)
|
2070
|
+
return ERR;
|
2071
|
+
for (i = 0; i < 2; i++) {
|
2072
|
+
if (i == 1) {
|
2073
|
+
for(k = 0; k < 3; k++) {
|
2074
|
+
xs[k] -= xs[k+3] * dt;
|
2075
|
+
xm[k] -= xm[k+3] * dt;
|
2076
|
+
}
|
2077
|
+
}
|
2078
|
+
dm = sqrt(square_sum(xm));
|
2079
|
+
ds = sqrt(square_sum(xs));
|
2080
|
+
rmoon = asin(RMOON / dm) * RADTODEG;
|
2081
|
+
rsun = asin(RSUN / ds) * RADTODEG;
|
2082
|
+
rsminusrm = rsun - rmoon;
|
2083
|
+
for (k = 0; k < 3; k++) {
|
2084
|
+
x1[k] = xs[k] / ds /*ls[2]*/;
|
2085
|
+
x2[k] = xm[k] / dm /*lm[2]*/;
|
2086
|
+
}
|
2087
|
+
dctr = acos(swi_dot_prod_unit(x1, x2)) * RADTODEG;
|
2088
|
+
dc[i] = fabs(rsminusrm) - dctr;
|
2089
|
+
}
|
2090
|
+
dt1 = -dc[0] / ((dc[0] - dc[1]) / dt);
|
2091
|
+
tret[j] += dt1;
|
2092
|
+
}
|
2093
|
+
}
|
2094
|
+
tret[2] -= swe_deltat(tret[2]);
|
2095
|
+
tret[3] -= swe_deltat(tret[3]);
|
2096
|
+
}
|
2097
|
+
/* contacts 1 and 4 */
|
2098
|
+
dc[1] = rsplusrm - dctrmin;
|
2099
|
+
for (i = 0, t = tjd - twohr; i <= 2; i += 2, t = tjd + twohr) {
|
2100
|
+
if (swe_calc(t, SE_SUN, iflagcart, xs, serr) == ERR)
|
2101
|
+
return ERR;
|
2102
|
+
if (swe_calc(t, SE_MOON, iflagcart, xm, serr) == ERR)
|
2103
|
+
return ERR;
|
2104
|
+
dm = sqrt(square_sum(xm));
|
2105
|
+
ds = sqrt(square_sum(xs));
|
2106
|
+
rmoon = asin(RMOON / dm) * RADTODEG;
|
2107
|
+
rsun = asin(RSUN / ds) * RADTODEG;
|
2108
|
+
rsplusrm = rsun + rmoon;
|
2109
|
+
for (k = 0; k < 3; k++) {
|
2110
|
+
x1[k] = xs[k] / ds /*ls[2]*/;
|
2111
|
+
x2[k] = xm[k] / dm /*lm[2]*/;
|
2112
|
+
}
|
2113
|
+
dctr = acos(swi_dot_prod_unit(x1, x2)) * RADTODEG;
|
2114
|
+
dc[i] = rsplusrm - dctr;
|
2115
|
+
}
|
2116
|
+
find_zero(dc[0], dc[1], dc[2], twohr, &dt1, &dt2);
|
2117
|
+
tret[1] = tjd + dt1 + twohr;
|
2118
|
+
tret[4] = tjd + dt2 + twohr;
|
2119
|
+
for (m = 0, dt = tenmin; m < 3; m++, dt /= 10) {
|
2120
|
+
for (j = 1; j <= 4; j += 3) {
|
2121
|
+
if (swe_calc(tret[j], SE_SUN, iflagcart | SEFLG_SPEED, xs, serr) == ERR)
|
2122
|
+
return ERR;
|
2123
|
+
if (swe_calc(tret[j], SE_MOON, iflagcart | SEFLG_SPEED, xm, serr) == ERR)
|
2124
|
+
return ERR;
|
2125
|
+
for (i = 0; i < 2; i++) {
|
2126
|
+
if (i == 1) {
|
2127
|
+
for(k = 0; k < 3; k++) {
|
2128
|
+
xs[k] -= xs[k+3] * dt;
|
2129
|
+
xm[k] -= xm[k+3] * dt;
|
2130
|
+
}
|
2131
|
+
}
|
2132
|
+
dm = sqrt(square_sum(xm));
|
2133
|
+
ds = sqrt(square_sum(xs));
|
2134
|
+
rmoon = asin(RMOON / dm) * RADTODEG;
|
2135
|
+
rsun = asin(RSUN / ds) * RADTODEG;
|
2136
|
+
rsplusrm = rsun + rmoon;
|
2137
|
+
for (k = 0; k < 3; k++) {
|
2138
|
+
x1[k] = xs[k] / ds /*ls[2]*/;
|
2139
|
+
x2[k] = xm[k] / dm /*lm[2]*/;
|
2140
|
+
}
|
2141
|
+
dctr = acos(swi_dot_prod_unit(x1, x2)) * RADTODEG;
|
2142
|
+
dc[i] = fabs(rsplusrm) - dctr;
|
2143
|
+
}
|
2144
|
+
dt1 = -dc[0] / ((dc[0] - dc[1]) / dt);
|
2145
|
+
tret[j] += dt1;
|
2146
|
+
}
|
2147
|
+
}
|
2148
|
+
tret[1] -= swe_deltat(tret[1]);
|
2149
|
+
tret[4] -= swe_deltat(tret[4]);
|
2150
|
+
/*
|
2151
|
+
* visibility of eclipse phases
|
2152
|
+
*/
|
2153
|
+
for (i = 4; i >= 0; i--) { /* attr for i = 0 must be kept !!! */
|
2154
|
+
if (tret[i] == 0)
|
2155
|
+
continue;
|
2156
|
+
if (eclipse_how(tret[i], SE_SUN, NULL, ifl, geopos[0], geopos[1], geopos[2],
|
2157
|
+
attr, serr) == ERR)
|
2158
|
+
return ERR;
|
2159
|
+
/*if (retflag2 & SE_ECL_VISIBLE) { could be wrong for 1st/4th contact */
|
2160
|
+
if (attr[5] > 0) { /* this is save, sun above horizon */
|
2161
|
+
retflag |= SE_ECL_VISIBLE;
|
2162
|
+
switch(i) {
|
2163
|
+
case 0: retflag |= SE_ECL_MAX_VISIBLE; break;
|
2164
|
+
case 1: retflag |= SE_ECL_1ST_VISIBLE; break;
|
2165
|
+
case 2: retflag |= SE_ECL_2ND_VISIBLE; break;
|
2166
|
+
case 3: retflag |= SE_ECL_3RD_VISIBLE; break;
|
2167
|
+
case 4: retflag |= SE_ECL_4TH_VISIBLE; break;
|
2168
|
+
default: break;
|
2169
|
+
}
|
2170
|
+
}
|
2171
|
+
}
|
2172
|
+
#if 1
|
2173
|
+
if (!(retflag & SE_ECL_VISIBLE)) {
|
2174
|
+
if (backward)
|
2175
|
+
K--;
|
2176
|
+
else
|
2177
|
+
K++;
|
2178
|
+
goto next_try;
|
2179
|
+
}
|
2180
|
+
#endif
|
2181
|
+
return retflag;
|
2182
|
+
}
|
2183
|
+
|
2184
|
+
static int32 occult_when_loc(
|
2185
|
+
double tjd_start, int32 ipl, char *starname,
|
2186
|
+
int32 ifl, double *geopos, double *tret, double *attr,
|
2187
|
+
int32 backward, char *serr)
|
2188
|
+
{
|
2189
|
+
int i, j, k, m;
|
2190
|
+
int32 retflag = 0;
|
2191
|
+
double t, tjd, dt, dtint;
|
2192
|
+
double xs[6], xm[6], ls[6], lm[6], x1[6], x2[6], dm, ds;
|
2193
|
+
double rmoon, rsun, rsplusrm, rsminusrm;
|
2194
|
+
double dc[20], dctr, dctrmin;
|
2195
|
+
double twomin = 2.0 / 24.0 / 60.0;
|
2196
|
+
double tensec = 10.0 / 24.0 / 60.0 / 60.0;
|
2197
|
+
double twohr = 2.0 / 24.0;
|
2198
|
+
double tenmin = 10.0 / 24.0 / 60.0;
|
2199
|
+
double dt1, dt2, dtdiv, dtstart;
|
2200
|
+
double dadd2 = 6;
|
2201
|
+
int nstartpos = 10;
|
2202
|
+
double drad;
|
2203
|
+
int32 iflag = SEFLG_TOPOCTR | ifl;
|
2204
|
+
int32 iflaggeo = iflag & ~SEFLG_TOPOCTR;
|
2205
|
+
int32 iflagcart = iflag | SEFLG_XYZ;
|
2206
|
+
int32 iflagcartgeo = iflaggeo | SEFLG_XYZ;
|
2207
|
+
int direction = 1;
|
2208
|
+
int32 one_try = backward & SE_ECL_ONE_TRY;
|
2209
|
+
AS_BOOL stop_after_this = FALSE;
|
2210
|
+
backward &= 1L;
|
2211
|
+
retflag = 0;
|
2212
|
+
for (i = 0; i <= 9; i++)
|
2213
|
+
tret[i] = 0;
|
2214
|
+
if (backward)
|
2215
|
+
direction = -1;
|
2216
|
+
t = tjd_start - direction * 0.1;
|
2217
|
+
tjd = tjd_start;
|
2218
|
+
next_try:
|
2219
|
+
for (i = 0; i < nstartpos; i++, t += direction * dadd2) {
|
2220
|
+
if (calc_planet_star(t, ipl, starname, iflagcartgeo, xs, serr) == ERR)
|
2221
|
+
return ERR;
|
2222
|
+
if (swe_calc(t, SE_MOON, iflagcartgeo, xm, serr) == ERR)
|
2223
|
+
return ERR;
|
2224
|
+
dc[i] = acos(swi_dot_prod_unit(xs, xm)) * RADTODEG;
|
2225
|
+
if (i > 1 && dc[i] > dc[i-1] && dc[i-2] > dc[i-1]) {
|
2226
|
+
tjd = t - direction*dadd2;
|
2227
|
+
break;
|
2228
|
+
} else if (i == nstartpos-1) {
|
2229
|
+
for (j = 0; j < nstartpos; j++)
|
2230
|
+
printf("%f ", dc[j]);
|
2231
|
+
printf("swe_lun_occult_when_loc(): problem planet\n");
|
2232
|
+
return ERR;
|
2233
|
+
}
|
2234
|
+
}
|
2235
|
+
/*
|
2236
|
+
* radius of planet disk in AU
|
2237
|
+
*/
|
2238
|
+
if (starname != NULL && *starname != '\0')
|
2239
|
+
drad = 0;
|
2240
|
+
else if (ipl < NDIAM)
|
2241
|
+
drad = pla_diam[ipl] / 2 / AUNIT;
|
2242
|
+
else if (ipl > SE_AST_OFFSET)
|
2243
|
+
drad = swed.ast_diam / 2 * 1000 / AUNIT; /* km -> m -> AU */
|
2244
|
+
else
|
2245
|
+
drad = 0;
|
2246
|
+
/* now find out, if there is an occultation at our geogr. location */
|
2247
|
+
dtdiv = 3;
|
2248
|
+
dtstart = dadd2; /* formerly 0.2 */
|
2249
|
+
for (dt = dtstart;
|
2250
|
+
dt > 0.00001;
|
2251
|
+
dt /= dtdiv) {
|
2252
|
+
if (dt < 0.01)
|
2253
|
+
dtdiv = 3;
|
2254
|
+
for (i = 0, t = tjd - dt; i <= 2; i++, t += dt) {
|
2255
|
+
/* this takes some time, but is necessary to avoid
|
2256
|
+
* missing an eclipse */
|
2257
|
+
if (calc_planet_star(t, ipl, starname, iflagcart, xs, serr) == ERR)
|
2258
|
+
return ERR;
|
2259
|
+
if (calc_planet_star(t, ipl, starname, iflag, ls, serr) == ERR)
|
2260
|
+
return ERR;
|
2261
|
+
if (swe_calc(t, SE_MOON, iflagcart, xm, serr) == ERR)
|
2262
|
+
return ERR;
|
2263
|
+
if (swe_calc(t, SE_MOON, iflag, lm, serr) == ERR)
|
2264
|
+
return ERR;
|
2265
|
+
if (dt < 1 && fabs(ls[1] - lm[1]) > 2) {
|
2266
|
+
if (one_try) {
|
2267
|
+
stop_after_this = TRUE;
|
2268
|
+
} else {
|
2269
|
+
t = tjd + direction * 2;
|
2270
|
+
goto next_try;
|
2271
|
+
}
|
2272
|
+
}
|
2273
|
+
dc[i] = acos(swi_dot_prod_unit(xs, xm)) * RADTODEG;
|
2274
|
+
rmoon = asin(RMOON / lm[2]) * RADTODEG;
|
2275
|
+
rsun = asin(drad / ls[2]) * RADTODEG;
|
2276
|
+
dc[i] -= (rmoon + rsun);
|
2277
|
+
}
|
2278
|
+
find_maximum(dc[0], dc[1], dc[2], dt, &dtint, &dctr);
|
2279
|
+
tjd += dtint + dt;
|
2280
|
+
}
|
2281
|
+
if (stop_after_this) { /* has one_try = TRUE */
|
2282
|
+
tret[0] = tjd;
|
2283
|
+
return 0;
|
2284
|
+
}
|
2285
|
+
if (calc_planet_star(tjd, ipl, starname, iflagcart, xs, serr) == ERR)
|
2286
|
+
return ERR;
|
2287
|
+
if (calc_planet_star(tjd, ipl, starname, iflag, ls, serr) == ERR)
|
2288
|
+
return ERR;
|
2289
|
+
if (swe_calc(tjd, SE_MOON, iflagcart, xm, serr) == ERR)
|
2290
|
+
return ERR;
|
2291
|
+
if (swe_calc(tjd, SE_MOON, iflag, lm, serr) == ERR)
|
2292
|
+
return ERR;
|
2293
|
+
dctr = acos(swi_dot_prod_unit(xs, xm)) * RADTODEG;
|
2294
|
+
rmoon = asin(RMOON / lm[2]) * RADTODEG;
|
2295
|
+
rsun = asin(drad / ls[2]) * RADTODEG;
|
2296
|
+
rsplusrm = rsun + rmoon;
|
2297
|
+
rsminusrm = rsun - rmoon;
|
2298
|
+
if (dctr > rsplusrm) {
|
2299
|
+
if (one_try) {
|
2300
|
+
tret[0] = tjd;
|
2301
|
+
return 0;
|
2302
|
+
}
|
2303
|
+
t = tjd + direction;
|
2304
|
+
goto next_try;
|
2305
|
+
}
|
2306
|
+
tret[0] = tjd - swe_deltat(tjd);
|
2307
|
+
if ((backward && tret[0] >= tjd_start - 0.0001)
|
2308
|
+
|| (!backward && tret[0] <= tjd_start + 0.0001)) {
|
2309
|
+
t = tjd + direction;
|
2310
|
+
goto next_try;
|
2311
|
+
}
|
2312
|
+
if (dctr < rsminusrm)
|
2313
|
+
retflag = SE_ECL_ANNULAR;
|
2314
|
+
else if (dctr < fabs(rsminusrm))
|
2315
|
+
retflag = SE_ECL_TOTAL;
|
2316
|
+
else if (dctr <= rsplusrm)
|
2317
|
+
retflag = SE_ECL_PARTIAL;
|
2318
|
+
dctrmin = dctr;
|
2319
|
+
/* contacts 2 and 3 */
|
2320
|
+
if (dctr > fabs(rsminusrm)) /* partial, no 2nd and 3rd contact */
|
2321
|
+
tret[2] = tret[3] = 0;
|
2322
|
+
else {
|
2323
|
+
dc[1] = fabs(rsminusrm) - dctrmin;
|
2324
|
+
for (i = 0, t = tjd - twomin; i <= 2; i += 2, t = tjd + twomin) {
|
2325
|
+
if (calc_planet_star(t, ipl, starname, iflagcart, xs, serr) == ERR)
|
2326
|
+
return ERR;
|
2327
|
+
if (swe_calc(t, SE_MOON, iflagcart, xm, serr) == ERR)
|
2328
|
+
return ERR;
|
2329
|
+
dm = sqrt(square_sum(xm));
|
2330
|
+
ds = sqrt(square_sum(xs));
|
2331
|
+
rmoon = asin(RMOON / dm) * RADTODEG;
|
2332
|
+
rsun = asin(drad / ds) * RADTODEG;
|
2333
|
+
rsminusrm = rsun - rmoon;
|
2334
|
+
for (k = 0; k < 3; k++) {
|
2335
|
+
x1[k] = xs[k] / ds /*ls[2]*/;
|
2336
|
+
x2[k] = xm[k] / dm /*lm[2]*/;
|
2337
|
+
}
|
2338
|
+
dctr = acos(swi_dot_prod_unit(x1, x2)) * RADTODEG;
|
2339
|
+
dc[i] = fabs(rsminusrm) - dctr;
|
2340
|
+
}
|
2341
|
+
find_zero(dc[0], dc[1], dc[2], twomin, &dt1, &dt2);
|
2342
|
+
tret[2] = tjd + dt1 + twomin;
|
2343
|
+
tret[3] = tjd + dt2 + twomin;
|
2344
|
+
for (m = 0, dt = tensec; m < 2; m++, dt /= 10) {
|
2345
|
+
for (j = 2; j <= 3; j++) {
|
2346
|
+
if (calc_planet_star(tret[j], ipl, starname, iflagcart | SEFLG_SPEED, xs, serr) == ERR)
|
2347
|
+
return ERR;
|
2348
|
+
if (swe_calc(tret[j], SE_MOON, iflagcart | SEFLG_SPEED, xm, serr) == ERR)
|
2349
|
+
return ERR;
|
2350
|
+
for (i = 0; i < 2; i++) {
|
2351
|
+
if (i == 1) {
|
2352
|
+
for(k = 0; k < 3; k++) {
|
2353
|
+
xs[k] -= xs[k+3] * dt;
|
2354
|
+
xm[k] -= xm[k+3] * dt;
|
2355
|
+
}
|
2356
|
+
}
|
2357
|
+
dm = sqrt(square_sum(xm));
|
2358
|
+
ds = sqrt(square_sum(xs));
|
2359
|
+
rmoon = asin(RMOON / dm) * RADTODEG;
|
2360
|
+
rsun = asin(drad / ds) * RADTODEG;
|
2361
|
+
rsminusrm = rsun - rmoon;
|
2362
|
+
for (k = 0; k < 3; k++) {
|
2363
|
+
x1[k] = xs[k] / ds /*ls[2]*/;
|
2364
|
+
x2[k] = xm[k] / dm /*lm[2]*/;
|
2365
|
+
}
|
2366
|
+
dctr = acos(swi_dot_prod_unit(x1, x2)) * RADTODEG;
|
2367
|
+
dc[i] = fabs(rsminusrm) - dctr;
|
2368
|
+
}
|
2369
|
+
dt1 = -dc[0] / ((dc[0] - dc[1]) / dt);
|
2370
|
+
tret[j] += dt1;
|
2371
|
+
}
|
2372
|
+
}
|
2373
|
+
tret[2] -= swe_deltat(tret[2]);
|
2374
|
+
tret[3] -= swe_deltat(tret[3]);
|
2375
|
+
}
|
2376
|
+
/* contacts 1 and 4 */
|
2377
|
+
dc[1] = rsplusrm - dctrmin;
|
2378
|
+
for (i = 0, t = tjd - twohr; i <= 2; i += 2, t = tjd + twohr) {
|
2379
|
+
if (calc_planet_star(t, ipl, starname, iflagcart, xs, serr) == ERR)
|
2380
|
+
return ERR;
|
2381
|
+
if (swe_calc(t, SE_MOON, iflagcart, xm, serr) == ERR)
|
2382
|
+
return ERR;
|
2383
|
+
dm = sqrt(square_sum(xm));
|
2384
|
+
ds = sqrt(square_sum(xs));
|
2385
|
+
rmoon = asin(RMOON / dm) * RADTODEG;
|
2386
|
+
rsun = asin(drad / ds) * RADTODEG;
|
2387
|
+
rsplusrm = rsun + rmoon;
|
2388
|
+
for (k = 0; k < 3; k++) {
|
2389
|
+
x1[k] = xs[k] / ds /*ls[2]*/;
|
2390
|
+
x2[k] = xm[k] / dm /*lm[2]*/;
|
2391
|
+
}
|
2392
|
+
dctr = acos(swi_dot_prod_unit(x1, x2)) * RADTODEG;
|
2393
|
+
dc[i] = rsplusrm - dctr;
|
2394
|
+
}
|
2395
|
+
find_zero(dc[0], dc[1], dc[2], twohr, &dt1, &dt2);
|
2396
|
+
tret[1] = tjd + dt1 + twohr;
|
2397
|
+
tret[4] = tjd + dt2 + twohr;
|
2398
|
+
for (m = 0, dt = tenmin; m < 3; m++, dt /= 10) {
|
2399
|
+
for (j = 1; j <= 4; j += 3) {
|
2400
|
+
if (calc_planet_star(tret[j], ipl, starname, iflagcart | SEFLG_SPEED, xs, serr) == ERR)
|
2401
|
+
return ERR;
|
2402
|
+
if (swe_calc(tret[j], SE_MOON, iflagcart | SEFLG_SPEED, xm, serr) == ERR)
|
2403
|
+
return ERR;
|
2404
|
+
for (i = 0; i < 2; i++) {
|
2405
|
+
if (i == 1) {
|
2406
|
+
for(k = 0; k < 3; k++) {
|
2407
|
+
xs[k] -= xs[k+3] * dt;
|
2408
|
+
xm[k] -= xm[k+3] * dt;
|
2409
|
+
}
|
2410
|
+
}
|
2411
|
+
dm = sqrt(square_sum(xm));
|
2412
|
+
ds = sqrt(square_sum(xs));
|
2413
|
+
rmoon = asin(RMOON / dm) * RADTODEG;
|
2414
|
+
rsun = asin(drad / ds) * RADTODEG;
|
2415
|
+
rsplusrm = rsun + rmoon;
|
2416
|
+
for (k = 0; k < 3; k++) {
|
2417
|
+
x1[k] = xs[k] / ds /*ls[2]*/;
|
2418
|
+
x2[k] = xm[k] / dm /*lm[2]*/;
|
2419
|
+
}
|
2420
|
+
dctr = acos(swi_dot_prod_unit(x1, x2)) * RADTODEG;
|
2421
|
+
dc[i] = fabs(rsplusrm) - dctr;
|
2422
|
+
}
|
2423
|
+
dt1 = -dc[0] / ((dc[0] - dc[1]) / dt);
|
2424
|
+
tret[j] += dt1;
|
2425
|
+
}
|
2426
|
+
}
|
2427
|
+
tret[1] -= swe_deltat(tret[1]);
|
2428
|
+
tret[4] -= swe_deltat(tret[4]);
|
2429
|
+
/*
|
2430
|
+
* visibility of eclipse phases
|
2431
|
+
*/
|
2432
|
+
for (i = 4; i >= 0; i--) { /* attr for i = 0 must be kept !!! */
|
2433
|
+
if (tret[i] == 0)
|
2434
|
+
continue;
|
2435
|
+
if (eclipse_how(tret[i], ipl, starname, ifl, geopos[0], geopos[1], geopos[2],
|
2436
|
+
attr, serr) == ERR)
|
2437
|
+
return ERR;
|
2438
|
+
/*if (retflag2 & SE_ECL_VISIBLE) { could be wrong for 1st/4th contact */
|
2439
|
+
if (attr[5] > 0) { /* this is save, sun above horizon */
|
2440
|
+
retflag |= SE_ECL_VISIBLE;
|
2441
|
+
switch(i) {
|
2442
|
+
case 0: retflag |= SE_ECL_MAX_VISIBLE; break;
|
2443
|
+
case 1: retflag |= SE_ECL_1ST_VISIBLE; break;
|
2444
|
+
case 2: retflag |= SE_ECL_2ND_VISIBLE; break;
|
2445
|
+
case 3: retflag |= SE_ECL_3RD_VISIBLE; break;
|
2446
|
+
case 4: retflag |= SE_ECL_4TH_VISIBLE; break;
|
2447
|
+
default: break;
|
2448
|
+
}
|
2449
|
+
}
|
2450
|
+
}
|
2451
|
+
#if 1
|
2452
|
+
if (!(retflag & SE_ECL_VISIBLE)) {
|
2453
|
+
t = tjd + direction;
|
2454
|
+
goto next_try;
|
2455
|
+
}
|
2456
|
+
#endif
|
2457
|
+
return retflag;
|
2458
|
+
}
|
2459
|
+
|
2460
|
+
/*
|
2461
|
+
* swe_azalt()
|
2462
|
+
* Computes azimut and height, from either ecliptic or
|
2463
|
+
* equatorial coordinates
|
2464
|
+
*
|
2465
|
+
* input:
|
2466
|
+
* tjd_ut
|
2467
|
+
* iflag either SE_ECL2HOR or SE_EQU2HOR
|
2468
|
+
* geopos[3] geograph. longitude, latitude, height above sea
|
2469
|
+
* atpress atmospheric pressure at geopos in millibars (hPa)
|
2470
|
+
* attemp atmospheric temperature in degrees C
|
2471
|
+
* xin[2] input coordinates polar, in degrees
|
2472
|
+
*
|
2473
|
+
* Horizontal coordinates are returned in
|
2474
|
+
* xaz[3] xaz[0] = azimuth
|
2475
|
+
* xaz[1] = true altitude
|
2476
|
+
* xaz[2] = apparent altitude
|
2477
|
+
*
|
2478
|
+
* If atpress is not given (= 0), the programm assumes 1013.25 mbar;
|
2479
|
+
* if a non-zero height above sea is given, atpress is estimated.
|
2480
|
+
* geohgt height of observer above sea (optional)
|
2481
|
+
*/
|
2482
|
+
void FAR PASCAL_CONV swe_azalt(
|
2483
|
+
double tjd_ut,
|
2484
|
+
int32 calc_flag,
|
2485
|
+
double *geopos,
|
2486
|
+
double atpress,
|
2487
|
+
double attemp,
|
2488
|
+
double *xin,
|
2489
|
+
double *xaz)
|
2490
|
+
{
|
2491
|
+
int i;
|
2492
|
+
double x[6], xra[3];
|
2493
|
+
double armc = swe_degnorm(swe_sidtime(tjd_ut) * 15 + geopos[0]);
|
2494
|
+
double mdd, eps_true, tjd_et;
|
2495
|
+
for (i = 0; i < 2; i++)
|
2496
|
+
xra[i] = xin[i];
|
2497
|
+
xra[2] = 1;
|
2498
|
+
if (calc_flag == SE_ECL2HOR) {
|
2499
|
+
tjd_et = tjd_ut + swe_deltat(tjd_ut);
|
2500
|
+
swe_calc(tjd_et, SE_ECL_NUT, 0, x, NULL);
|
2501
|
+
eps_true = x[0];
|
2502
|
+
swe_cotrans(xra, xra, -eps_true);
|
2503
|
+
}
|
2504
|
+
mdd = swe_degnorm(xra[0] - armc);
|
2505
|
+
x[0] = swe_degnorm(mdd - 90);
|
2506
|
+
x[1] = xra[1];
|
2507
|
+
x[2] = 1;
|
2508
|
+
/* azimuth from east, counterclock */
|
2509
|
+
swe_cotrans(x, x, 90 - geopos[1]);
|
2510
|
+
/* azimuth from south to west */
|
2511
|
+
x[0] = swe_degnorm(x[0] + 90);
|
2512
|
+
xaz[0] = 360 - x[0];
|
2513
|
+
xaz[1] = x[1]; /* true height */
|
2514
|
+
if (atpress == 0) {
|
2515
|
+
/* estimate atmospheric pressure */
|
2516
|
+
atpress = 1013.25 * pow(1 - 0.0065 * geopos[2] / 288, 5.255);
|
2517
|
+
}
|
2518
|
+
xaz[2] = swe_refrac_extended(x[1], geopos[2], atpress, attemp, const_lapse_rate, SE_TRUE_TO_APP, NULL);
|
2519
|
+
/* xaz[2] = swe_refrac_extended(xaz[2], geopos[2], atpress, attemp, const_lapse_rate, SE_APP_TO_TRUE, NULL);*/
|
2520
|
+
}
|
2521
|
+
|
2522
|
+
/*
|
2523
|
+
* swe_azalt_rev()
|
2524
|
+
* computes either ecliptical or equatorial coordinates from
|
2525
|
+
* azimuth and true altitude in degrees.
|
2526
|
+
* For conversion between true and apparent altitude, there is
|
2527
|
+
* the function swe_refrac().
|
2528
|
+
*
|
2529
|
+
* input:
|
2530
|
+
* tjd_ut
|
2531
|
+
* iflag either SE_HOR2ECL or SE_HOR2EQU
|
2532
|
+
* xin[2] azimut and true altitude, in degrees
|
2533
|
+
*/
|
2534
|
+
void FAR PASCAL_CONV swe_azalt_rev(
|
2535
|
+
double tjd_ut,
|
2536
|
+
int32 calc_flag,
|
2537
|
+
double *geopos,
|
2538
|
+
double *xin,
|
2539
|
+
double *xout)
|
2540
|
+
{
|
2541
|
+
int i;
|
2542
|
+
double x[6], xaz[3];
|
2543
|
+
double geolon = geopos[0];
|
2544
|
+
double geolat = geopos[1];
|
2545
|
+
double armc = swe_degnorm(swe_sidtime(tjd_ut) * 15 + geolon);
|
2546
|
+
double eps_true, tjd_et, dang;
|
2547
|
+
for (i = 0; i < 2; i++)
|
2548
|
+
xaz[i] = xin[i];
|
2549
|
+
xaz[2] = 1;
|
2550
|
+
/* azimuth is from south, clockwise.
|
2551
|
+
* we need it from east, counterclock */
|
2552
|
+
xaz[0] = 360 - xaz[0];
|
2553
|
+
xaz[0] = swe_degnorm(xaz[0] - 90);
|
2554
|
+
/* equatorial positions */
|
2555
|
+
dang = geolat - 90;
|
2556
|
+
swe_cotrans(xaz, xaz, dang);
|
2557
|
+
xaz[0] = swe_degnorm(xaz[0] + armc + 90);
|
2558
|
+
xout[0] = xaz[0];
|
2559
|
+
xout[1] = xaz[1];
|
2560
|
+
/* ecliptic positions */
|
2561
|
+
if (calc_flag == SE_HOR2ECL) {
|
2562
|
+
tjd_et = tjd_ut + swe_deltat(tjd_ut);
|
2563
|
+
swe_calc(tjd_et, SE_ECL_NUT, 0, x, NULL);
|
2564
|
+
eps_true = x[0];
|
2565
|
+
swe_cotrans(xaz, x, eps_true);
|
2566
|
+
xout[0] = x[0];
|
2567
|
+
xout[1] = x[1];
|
2568
|
+
}
|
2569
|
+
}
|
2570
|
+
|
2571
|
+
/* swe_refrac()
|
2572
|
+
* Transforms apparent to true altitude and vice-versa.
|
2573
|
+
* These formulae do not handle the case when the
|
2574
|
+
* sun is visible below the geometrical horizon
|
2575
|
+
* (from a mountain top or an air plane)
|
2576
|
+
* input:
|
2577
|
+
* double inalt; * altitude of object in degrees *
|
2578
|
+
* double atpress; * millibars (hectopascal) *
|
2579
|
+
* double attemp; * degrees C *
|
2580
|
+
* int32 calc_flag; * either SE_CALC_APP_TO_TRUE or
|
2581
|
+
* * SE_CALC_TRUE_TO_APP
|
2582
|
+
*/
|
2583
|
+
double FAR PASCAL_CONV swe_refrac(double inalt, double atpress, double attemp, int32 calc_flag)
|
2584
|
+
{
|
2585
|
+
double a, refr;
|
2586
|
+
double pt_factor = atpress / 1010.0 * 283.0 / (273.0 + attemp);
|
2587
|
+
double trualt, appalt;
|
2588
|
+
#if 0
|
2589
|
+
/*
|
2590
|
+
* -- S. L. Moshier */
|
2591
|
+
double y, yy0, D0, N, D, P, Q;
|
2592
|
+
int i;
|
2593
|
+
if (calc_flag == SE_TRUE_TO_APP) {
|
2594
|
+
trualt = inalt;
|
2595
|
+
if( (trualt < -2.0) || (trualt >= 90.0) )
|
2596
|
+
return(trualt);
|
2597
|
+
/* For high altitude angle, AA page B61
|
2598
|
+
* Accuracy "usually about 0.1' ".
|
2599
|
+
*/
|
2600
|
+
if( trualt > 15.0 ) {
|
2601
|
+
D = 0.00452*atpress/((273.0+attemp)*tan( DEGTORAD*trualt ));
|
2602
|
+
return(trualt + D);
|
2603
|
+
}
|
2604
|
+
/* Formula for low altitude is from the Almanac for Computers.
|
2605
|
+
* It gives the correction for observed altitude, so has
|
2606
|
+
* to be inverted numerically to get the observed from the true.
|
2607
|
+
* Accuracy about 0.2' for -20C < T < +40C and 970mb < P < 1050mb.
|
2608
|
+
*/
|
2609
|
+
/* Start iteration assuming correction = 0
|
2610
|
+
*/
|
2611
|
+
y = trualt;
|
2612
|
+
D = 0.0;
|
2613
|
+
/* Invert Almanac for Computers formula numerically
|
2614
|
+
*/
|
2615
|
+
P = (atpress - 80.0)/930.0;
|
2616
|
+
Q = 4.8e-3 * (attemp - 10.0);
|
2617
|
+
yy0 = y;
|
2618
|
+
D0 = D;
|
2619
|
+
for( i=0; i<4; i++ ) {
|
2620
|
+
N = y + (7.31/(y+4.4));
|
2621
|
+
N = 1.0/tan(DEGTORAD*N);
|
2622
|
+
D = N*P/(60.0 + Q * (N + 39.0));
|
2623
|
+
N = y - yy0;
|
2624
|
+
yy0 = D - D0 - N; /* denominator of derivative */
|
2625
|
+
if( (N != 0.0) && (yy0 != 0.0) )
|
2626
|
+
/* Newton iteration with numerically estimated derivative */
|
2627
|
+
N = y - N*(trualt + D - y)/yy0;
|
2628
|
+
else
|
2629
|
+
/* Can't do it on first pass */
|
2630
|
+
N = trualt + D;
|
2631
|
+
yy0 = y;
|
2632
|
+
D0 = D;
|
2633
|
+
y = N;
|
2634
|
+
}
|
2635
|
+
return( trualt + D );
|
2636
|
+
} else {
|
2637
|
+
#else
|
2638
|
+
/* another algorithm, from Meeus, German, p. 114ff.
|
2639
|
+
*/
|
2640
|
+
if (calc_flag == SE_TRUE_TO_APP) {
|
2641
|
+
trualt = inalt;
|
2642
|
+
if (trualt > 15) {
|
2643
|
+
a = tan((90 - trualt) * DEGTORAD);
|
2644
|
+
refr = (58.276 * a - 0.0824 * a * a * a);
|
2645
|
+
refr *= pt_factor / 3600.0;
|
2646
|
+
} else if (trualt > -5) {
|
2647
|
+
/* the following tan is not defined for a value
|
2648
|
+
* of trualt near -5.00158 and 89.89158 */
|
2649
|
+
a = trualt + 10.3 / (trualt + 5.11);
|
2650
|
+
if (a + 1e-10 >= 90)
|
2651
|
+
refr = 0;
|
2652
|
+
else
|
2653
|
+
refr = 1.02 / tan(a * DEGTORAD);
|
2654
|
+
refr *= pt_factor / 60.0;
|
2655
|
+
} else
|
2656
|
+
refr = 0;
|
2657
|
+
appalt = trualt;
|
2658
|
+
if (appalt + refr > 0)
|
2659
|
+
appalt += refr;
|
2660
|
+
return appalt;
|
2661
|
+
} else {
|
2662
|
+
#endif
|
2663
|
+
/* apparent to true */
|
2664
|
+
appalt = inalt;
|
2665
|
+
/* the following tan is not defined for a value
|
2666
|
+
* of inalt near -4.3285 and 89.9225 */
|
2667
|
+
a = appalt + 7.31 / (appalt + 4.4);
|
2668
|
+
if (a + 1e-10 >= 90)
|
2669
|
+
refr = 0;
|
2670
|
+
else {
|
2671
|
+
refr = 1.00 / tan(a * DEGTORAD);
|
2672
|
+
refr -= 0.06 * sin(14.7 * refr + 13);
|
2673
|
+
}
|
2674
|
+
refr *= pt_factor / 60.0;
|
2675
|
+
trualt = appalt;
|
2676
|
+
if (appalt - refr > 0)
|
2677
|
+
trualt = appalt - refr;
|
2678
|
+
return trualt;
|
2679
|
+
}
|
2680
|
+
}
|
2681
|
+
|
2682
|
+
void FAR PASCAL_CONV swe_set_lapse_rate(double lapse_rate)
|
2683
|
+
{
|
2684
|
+
const_lapse_rate = lapse_rate;
|
2685
|
+
}
|
2686
|
+
|
2687
|
+
/* swe_refrac_extended()
|
2688
|
+
*
|
2689
|
+
* This function was created thanks to and with consultation with the
|
2690
|
+
* archaeoastronomer Victor Reijs.
|
2691
|
+
* It is more correct and more skilled than the old function swe_refrac():
|
2692
|
+
* - it allows correct calculation of refraction for altitudes above sea > 0,
|
2693
|
+
* where the ideal horizon and planets that are visible may have a
|
2694
|
+
* negative height. (for swe_refrac(), negative apparent heights do not
|
2695
|
+
* exist!)
|
2696
|
+
* - it allows to manipulate the refraction constant
|
2697
|
+
*
|
2698
|
+
* Transforms apparent to true altitude and vice-versa.
|
2699
|
+
* input:
|
2700
|
+
* double inalt; * altitude of object above geometric horizon in degrees*
|
2701
|
+
* * geometric horizon = plane perpendicular to gravity *
|
2702
|
+
* double geoalt; * altitude of observer above sea level in meters *
|
2703
|
+
* double atpress; * millibars (hectopascal) *
|
2704
|
+
* double lapse_rate; * (dT/dh) [deg K/m]
|
2705
|
+
* double attemp; * degrees C *
|
2706
|
+
* int32 calc_flag; * either SE_CALC_APP_TO_TRUE or
|
2707
|
+
* * SE_CALC_TRUE_TO_APP
|
2708
|
+
*
|
2709
|
+
* function returns:
|
2710
|
+
* case 1, conversion from true altitude to apparent altitude
|
2711
|
+
* - apparent altitude, if body appears above is observable above ideal horizon
|
2712
|
+
* - true altitude (the input value), otherwise
|
2713
|
+
* "ideal horizon" is the horizon as seen above an ideal sphere (as seen
|
2714
|
+
* from a plane over the ocean with a clear sky)
|
2715
|
+
* case 2, conversion from apparent altitude to true altitude
|
2716
|
+
* - the true altitude resulting from the input apparent altitude, if this value
|
2717
|
+
* is a plausible apparent altitude, i.e. if it is a position above the ideal
|
2718
|
+
* horizon
|
2719
|
+
* - the input altitude otherwise
|
2720
|
+
*
|
2721
|
+
* in addition the array dret[] is given the following values
|
2722
|
+
* - dret[0] true altitude, if possible; otherwise input value
|
2723
|
+
* - dret[1] apparent altitude, if possible; otherwise input value
|
2724
|
+
* - dret[2] refraction
|
2725
|
+
* - dret[3] dip of the horizon
|
2726
|
+
*
|
2727
|
+
* The body is above the horizon if the dret[0] != dret[1]
|
2728
|
+
*/
|
2729
|
+
double FAR PASCAL_CONV swe_refrac_extended(double inalt, double geoalt, double atpress, double attemp, double lapse_rate, int32 calc_flag, double *dret)
|
2730
|
+
{
|
2731
|
+
double refr;
|
2732
|
+
double trualt;
|
2733
|
+
double dip = calc_dip(geoalt, atpress, attemp, lapse_rate);
|
2734
|
+
double D, D0, N, y, yy0;
|
2735
|
+
int i;
|
2736
|
+
/* make sure that inalt <=90 */
|
2737
|
+
if( (inalt>90) )
|
2738
|
+
inalt=180-inalt;
|
2739
|
+
if (calc_flag == SE_TRUE_TO_APP) {
|
2740
|
+
if (inalt < -10) {
|
2741
|
+
if (dret != NULL) {
|
2742
|
+
dret[0]=inalt;
|
2743
|
+
dret[1]=inalt;
|
2744
|
+
dret[2]=0;
|
2745
|
+
dret[3]=dip;
|
2746
|
+
}
|
2747
|
+
return inalt;
|
2748
|
+
}
|
2749
|
+
/* by iteration */
|
2750
|
+
y = inalt;
|
2751
|
+
D = 0.0;
|
2752
|
+
yy0 = 0;
|
2753
|
+
D0 = D;
|
2754
|
+
for(i=0; i<5; i++) {
|
2755
|
+
D = calc_astronomical_refr(y,atpress,attemp);
|
2756
|
+
N = y - yy0;
|
2757
|
+
yy0 = D - D0 - N; /* denominator of derivative */
|
2758
|
+
if (N != 0.0 && yy0 != 0.0) /* sic !!! code by Moshier */
|
2759
|
+
N = y - N*(inalt + D - y)/yy0; /* Newton iteration with numerically estimated derivative */
|
2760
|
+
else /* Can't do it on first pass */
|
2761
|
+
N = inalt + D;
|
2762
|
+
yy0 = y;
|
2763
|
+
D0 = D;
|
2764
|
+
y = N;
|
2765
|
+
}
|
2766
|
+
refr = D;
|
2767
|
+
if( (inalt + refr < dip) ) {
|
2768
|
+
if (dret != NULL) {
|
2769
|
+
dret[0]=inalt;
|
2770
|
+
dret[1]=inalt;
|
2771
|
+
dret[2]=0;
|
2772
|
+
dret[3]=dip;
|
2773
|
+
}
|
2774
|
+
return inalt;
|
2775
|
+
}
|
2776
|
+
if (dret != NULL) {
|
2777
|
+
dret[0]=inalt;
|
2778
|
+
dret[1]=inalt+refr;
|
2779
|
+
dret[2]=refr;
|
2780
|
+
dret[3]=dip;
|
2781
|
+
}
|
2782
|
+
return inalt+refr;
|
2783
|
+
} else {
|
2784
|
+
refr = calc_astronomical_refr(inalt,atpress,attemp);
|
2785
|
+
trualt=inalt-refr;
|
2786
|
+
if (dret != NULL) {
|
2787
|
+
if (inalt > dip) {
|
2788
|
+
dret[0]=trualt;
|
2789
|
+
dret[1]=inalt;
|
2790
|
+
dret[2]=refr;
|
2791
|
+
dret[3]=dip;
|
2792
|
+
} else {
|
2793
|
+
dret[0]=inalt;
|
2794
|
+
dret[1]=inalt;
|
2795
|
+
dret[2]=0;
|
2796
|
+
dret[3]=dip;
|
2797
|
+
}
|
2798
|
+
}
|
2799
|
+
if (trualt > dip)
|
2800
|
+
return trualt;
|
2801
|
+
else
|
2802
|
+
return inalt;
|
2803
|
+
}
|
2804
|
+
}
|
2805
|
+
|
2806
|
+
/* calculate the astronomical refraction
|
2807
|
+
* input parameters:
|
2808
|
+
* double inalt * apparent altitude of object
|
2809
|
+
* double atpress * atmospheric pressure millibars (hectopascal) *
|
2810
|
+
* double attemp * atmospheric temperature degrees C *
|
2811
|
+
* returns double r in degrees
|
2812
|
+
*/
|
2813
|
+
static double calc_astronomical_refr(double inalt,double atpress, double attemp)
|
2814
|
+
{
|
2815
|
+
#if 0
|
2816
|
+
/* formula based on G.G. Bennett, The calculation of astronomical refraction in marine navigation,
|
2817
|
+
* Journal of Inst. Navigation, No. 35, page 255-259, 1982,
|
2818
|
+
* page 257 for refraction formula: formula H
|
2819
|
+
* and page 259 for atmospheric compensation
|
2820
|
+
*/
|
2821
|
+
double refractaccent = 1/tan(DEGTORAD*(inalt + 7.31/(inalt+4.4)));
|
2822
|
+
double r = (refractaccent - 0.06 * sin(DEGTORAD*(14.7*refractaccent +13)));
|
2823
|
+
r = ((atpress - 80) / 930 / (1 + 0.00008 * (r + 39) * (attemp - 10)) * r)/60;
|
2824
|
+
return r;
|
2825
|
+
#else
|
2826
|
+
/* Formula by Sinclair, see article mentioned above, p. 256. Better for
|
2827
|
+
* apparent altitudes < 0; */
|
2828
|
+
double r;
|
2829
|
+
if (inalt > 17.904104638432) { /* for continuous function, instead of '>15' */
|
2830
|
+
r = 0.97 / tan(inalt * DEGTORAD);
|
2831
|
+
} else {
|
2832
|
+
r = (34.46 + 4.23 * inalt + 0.004 * inalt * inalt) / (1 + 0.505 * inalt + 0.0845 * inalt * inalt);
|
2833
|
+
}
|
2834
|
+
r = ((atpress - 80) / 930 / (1 + 0.00008 * (r + 39) * (attemp - 10)) * r) / 60.0;
|
2835
|
+
return r;
|
2836
|
+
#endif
|
2837
|
+
}
|
2838
|
+
|
2839
|
+
/* calculate dip of the horizon
|
2840
|
+
* input parameters:
|
2841
|
+
* double geoalt * altitude of observer above sea level in meters *
|
2842
|
+
* double atpress * atmospheric pressure millibars (hectopascal) *
|
2843
|
+
* double attemp * atmospheric temperature degrees C *
|
2844
|
+
* double lapse_rate * (dT/dh) [deg K/m]
|
2845
|
+
* returns dip in degrees
|
2846
|
+
*/
|
2847
|
+
static double calc_dip(double geoalt, double atpress, double attemp, double lapse_rate)
|
2848
|
+
{
|
2849
|
+
/* below formula is based on A. Thom, Megalithic lunar observations, 1973 (page 32).
|
2850
|
+
* conversion to metric has been done by
|
2851
|
+
* V. Reijs, 2000, http://www.iol.ie/~geniet/eng/refract.htm
|
2852
|
+
*/
|
2853
|
+
double krefr = (0.0342 + lapse_rate) / (0.154 * 0.0238);
|
2854
|
+
double d = 1-1.8480*krefr*atpress/(273.16+attemp)/(273.16+attemp);
|
2855
|
+
/* return -0.03203*sqrt(geoalt)*sqrt(d); */
|
2856
|
+
/* double a = acos(1/(1+geoalt/EARTH_RADIUS));*/
|
2857
|
+
return -180.0/PI * acos(1 / (1 + geoalt / EARTH_RADIUS)) * sqrt(d);
|
2858
|
+
}
|
2859
|
+
|
2860
|
+
|
2861
|
+
/* Computes attributes of a lunar eclipse for given tjd and geopos
|
2862
|
+
*
|
2863
|
+
* retflag SE_ECL_TOTAL or SE_ECL_PARTIAL
|
2864
|
+
* SE_ECL_PENUMBRAL
|
2865
|
+
* if 0, there is no eclipse
|
2866
|
+
*
|
2867
|
+
* attr[0] umbral magnitude at tjd
|
2868
|
+
* attr[1] penumbral magnitude
|
2869
|
+
#if 0 not implemented so far
|
2870
|
+
* attr[4] azimuth of moon at tjd
|
2871
|
+
* attr[5] true altitude of moon above horizon at tjd
|
2872
|
+
* attr[6] apparent altitude of moon above horizon at tjd
|
2873
|
+
#endif
|
2874
|
+
* attr[7] distance of moon from opposition in degrees
|
2875
|
+
* attr[8] umbral magnitude at tjd (= attr[0])
|
2876
|
+
* attr[9] saros series number
|
2877
|
+
* attr[10] saros series member number
|
2878
|
+
* declare as attr[20] at least !
|
2879
|
+
*
|
2880
|
+
*/
|
2881
|
+
int32 FAR PASCAL_CONV swe_lun_eclipse_how(
|
2882
|
+
double tjd_ut,
|
2883
|
+
int32 ifl,
|
2884
|
+
double *geopos,
|
2885
|
+
double *attr,
|
2886
|
+
char *serr)
|
2887
|
+
{
|
2888
|
+
double dcore[10];
|
2889
|
+
/* attention: geopos[] is not used so far; may be NULL */
|
2890
|
+
if (geopos != NULL)
|
2891
|
+
geopos[0] = geopos[0]; /* to shut up mint */
|
2892
|
+
ifl = ifl & ~SEFLG_TOPOCTR;
|
2893
|
+
return lun_eclipse_how(tjd_ut, ifl, attr, dcore, serr);
|
2894
|
+
}
|
2895
|
+
|
2896
|
+
/*
|
2897
|
+
* attr[]: see swe_lun_eclipse_how()
|
2898
|
+
*
|
2899
|
+
* dcore[0]: distance of shadow axis from geocenter r0
|
2900
|
+
* dcore[1]: diameter of core shadow on fundamental plane d0
|
2901
|
+
* dcore[2]: diameter of half-shadow on fundamental plane D0
|
2902
|
+
*/
|
2903
|
+
static int32 lun_eclipse_how(
|
2904
|
+
double tjd_ut,
|
2905
|
+
int32 ifl,
|
2906
|
+
double *attr,
|
2907
|
+
double *dcore,
|
2908
|
+
char *serr)
|
2909
|
+
{
|
2910
|
+
int i, j, k;
|
2911
|
+
int32 retc = 0;
|
2912
|
+
double e[6], rm[6], rs[6];
|
2913
|
+
double dsm, d0, D0, s0, r0, ds, dm;
|
2914
|
+
double dctr, x1[6], x2[6];
|
2915
|
+
double f1, f2;
|
2916
|
+
double deltat, tjd, d;
|
2917
|
+
double cosf1, cosf2;
|
2918
|
+
int32 iflag;
|
2919
|
+
for (i = 0; i < 10; i++)
|
2920
|
+
dcore[i] = 0;
|
2921
|
+
for (i = 0; i < 20; i++)
|
2922
|
+
attr[i] = 0;
|
2923
|
+
/* nutation need not be in lunar and solar positions,
|
2924
|
+
* if mean sidereal time will be used */
|
2925
|
+
iflag = SEFLG_SPEED | SEFLG_EQUATORIAL | ifl;
|
2926
|
+
iflag = iflag | SEFLG_XYZ;
|
2927
|
+
deltat = swe_deltat(tjd_ut);
|
2928
|
+
tjd = tjd_ut + deltat;
|
2929
|
+
/* moon in cartesian coordinates */
|
2930
|
+
if (swe_calc(tjd, SE_MOON, iflag, rm, serr) == ERR)
|
2931
|
+
return ERR;
|
2932
|
+
/* distance of moon from geocenter */
|
2933
|
+
dm = sqrt(square_sum(rm));
|
2934
|
+
/* sun in cartesian coordinates */
|
2935
|
+
if (swe_calc(tjd, SE_SUN, iflag, rs, serr) == ERR)
|
2936
|
+
return ERR;
|
2937
|
+
/* distance of sun from geocenter */
|
2938
|
+
ds = sqrt(square_sum(rs));
|
2939
|
+
for (i = 0; i < 3; i++) {
|
2940
|
+
x1[i] = rs[i] / ds;
|
2941
|
+
x2[i] = rm[i] / dm;
|
2942
|
+
}
|
2943
|
+
dctr = acos(swi_dot_prod_unit(x1, x2)) * RADTODEG;
|
2944
|
+
/* selenocentric sun */
|
2945
|
+
for (i = 0; i <= 2; i++)
|
2946
|
+
rs[i] -= rm[i];
|
2947
|
+
/* selenocentric earth */
|
2948
|
+
for (i = 0; i <= 2; i++)
|
2949
|
+
rm[i] = -rm[i];
|
2950
|
+
/* sun - earth vector */
|
2951
|
+
for (i = 0; i <= 2; i++)
|
2952
|
+
e[i] = (rm[i] - rs[i]);
|
2953
|
+
/* distance sun - earth */
|
2954
|
+
dsm = sqrt(square_sum(e));
|
2955
|
+
/* sun - earth unit vector */
|
2956
|
+
for (i = 0; i <= 2; i++)
|
2957
|
+
e[i] /= dsm;
|
2958
|
+
f1 = ((RSUN - REARTH) / dsm);
|
2959
|
+
cosf1 = sqrt(1 - f1 * f1);
|
2960
|
+
f2 = ((RSUN + REARTH) / dsm);
|
2961
|
+
cosf2 = sqrt(1 - f2 * f2);
|
2962
|
+
/* distance of earth from fundamental plane */
|
2963
|
+
s0 = -dot_prod(rm, e);
|
2964
|
+
/* distance of shadow axis from selenocenter */
|
2965
|
+
r0 = sqrt(dm * dm - s0 * s0);
|
2966
|
+
/* diameter of core shadow on fundamental plane */
|
2967
|
+
d0 = fabs(s0 / dsm * (DSUN - DEARTH) - DEARTH) * (1 + 1.0 / 50) / cosf1;
|
2968
|
+
/* one 50th is added for effect of atmosphere, AA98, L4 */
|
2969
|
+
/* diameter of half-shadow on fundamental plane */
|
2970
|
+
D0 = (s0 / dsm * (DSUN + DEARTH) + DEARTH) * (1 + 1.0 / 50) / cosf2;
|
2971
|
+
d0 /= cosf1;
|
2972
|
+
D0 /= cosf2;
|
2973
|
+
dcore[0] = r0;
|
2974
|
+
dcore[1] = d0;
|
2975
|
+
dcore[2] = D0;
|
2976
|
+
dcore[3] = cosf1;
|
2977
|
+
dcore[4] = cosf2;
|
2978
|
+
/**************************
|
2979
|
+
* phase and umbral magnitude
|
2980
|
+
**************************/
|
2981
|
+
retc = 0;
|
2982
|
+
if (d0 / 2 >= r0 + RMOON / cosf1) {
|
2983
|
+
retc = SE_ECL_TOTAL;
|
2984
|
+
attr[0] = (d0 / 2 - r0 + RMOON) / DMOON;
|
2985
|
+
} else if (d0 / 2 >= r0 - RMOON / cosf1) {
|
2986
|
+
retc = SE_ECL_PARTIAL;
|
2987
|
+
attr[0] = (d0 / 2 - r0 + RMOON) / DMOON;
|
2988
|
+
} else if (D0 / 2 >= r0 - RMOON / cosf2) {
|
2989
|
+
retc = SE_ECL_PENUMBRAL;
|
2990
|
+
attr[0] = 0;
|
2991
|
+
} else {
|
2992
|
+
if (serr != NULL)
|
2993
|
+
sprintf(serr, "no lunar eclipse at tjd = %f", tjd);
|
2994
|
+
}
|
2995
|
+
attr[8] = attr[0];
|
2996
|
+
/**************************
|
2997
|
+
* penumbral magnitude
|
2998
|
+
**************************/
|
2999
|
+
attr[1] = (D0 / 2 - r0 + RMOON) / DMOON;
|
3000
|
+
if (retc != 0)
|
3001
|
+
attr[7] = 180 - fabs(dctr);
|
3002
|
+
/* saros series and member */
|
3003
|
+
for (i = 0; i < NSAROS_LUNAR; i++) {
|
3004
|
+
d = (tjd_ut - saros_data_lunar[i].tstart) / SAROS_CYCLE;
|
3005
|
+
if (d < 0) continue;
|
3006
|
+
j = (int) d;
|
3007
|
+
if ((d - j) * SAROS_CYCLE < 2) {
|
3008
|
+
attr[9] = (double) saros_data_lunar[i].series_no;
|
3009
|
+
attr[10] = (double) j + 1;
|
3010
|
+
break;
|
3011
|
+
}
|
3012
|
+
k = j + 1;
|
3013
|
+
if ((k - d) * SAROS_CYCLE < 2) {
|
3014
|
+
attr[9] = (double) saros_data_lunar[i].series_no;
|
3015
|
+
attr[10] = (double) k + 1;
|
3016
|
+
break;
|
3017
|
+
}
|
3018
|
+
}
|
3019
|
+
if (i == NSAROS_LUNAR) {
|
3020
|
+
attr[9] = attr[10] = -99999999;
|
3021
|
+
}
|
3022
|
+
return retc;
|
3023
|
+
}
|
3024
|
+
|
3025
|
+
/* When is the next lunar eclipse?
|
3026
|
+
*
|
3027
|
+
* retflag SE_ECL_TOTAL or SE_ECL_PENUMBRAL or SE_ECL_PARTIAL
|
3028
|
+
*
|
3029
|
+
* tret[0] time of maximum eclipse
|
3030
|
+
* tret[1]
|
3031
|
+
* tret[2] time of partial phase begin (indices consistent with solar eclipses)
|
3032
|
+
* tret[3] time of partial phase end
|
3033
|
+
* tret[4] time of totality begin
|
3034
|
+
* tret[5] time of totality end
|
3035
|
+
* tret[6] time of penumbral phase begin
|
3036
|
+
* tret[7] time of penumbral phase end
|
3037
|
+
*/
|
3038
|
+
int32 FAR PASCAL_CONV swe_lun_eclipse_when(double tjd_start, int32 ifl, int32 ifltype,
|
3039
|
+
double *tret, int32 backward, char *serr)
|
3040
|
+
{
|
3041
|
+
int i, j, m, n, o, i1 = 0, i2 = 0;
|
3042
|
+
int32 retflag = 0, retflag2 = 0;
|
3043
|
+
double t, tjd, dt, dtint, dta, dtb;
|
3044
|
+
double T, T2, T3, T4, K, F, M, Mm;
|
3045
|
+
double E, Ff, F1, A1, Om;
|
3046
|
+
double xs[6], xm[6], dm, ds;
|
3047
|
+
double rsun, rearth, dcore[10];
|
3048
|
+
double dc[3], dctr;
|
3049
|
+
double twohr = 2.0 / 24.0;
|
3050
|
+
double tenmin = 10.0 / 24.0 / 60.0;
|
3051
|
+
double dt1, dt2;
|
3052
|
+
double kk;
|
3053
|
+
double attr[20];
|
3054
|
+
double dtstart, dtdiv;
|
3055
|
+
double xa[6], xb[6];
|
3056
|
+
int direction = 1;
|
3057
|
+
int32 iflag;
|
3058
|
+
int32 iflagcart;
|
3059
|
+
ifl &= SEFLG_EPHMASK;
|
3060
|
+
iflag = SEFLG_EQUATORIAL | ifl;
|
3061
|
+
iflagcart = iflag | SEFLG_XYZ;
|
3062
|
+
if (ifltype == 0)
|
3063
|
+
ifltype = SE_ECL_TOTAL | SE_ECL_PENUMBRAL | SE_ECL_PARTIAL;
|
3064
|
+
if (backward)
|
3065
|
+
direction = -1;
|
3066
|
+
K = (int) ((tjd_start - J2000) / 365.2425 * 12.3685);
|
3067
|
+
K -= direction;
|
3068
|
+
next_try:
|
3069
|
+
retflag = 0;
|
3070
|
+
for (i = 0; i <= 9; i++)
|
3071
|
+
tret[i] = 0;
|
3072
|
+
kk = K + 0.5;
|
3073
|
+
T = kk / 1236.85;
|
3074
|
+
T2 = T * T; T3 = T2 * T; T4 = T3 * T;
|
3075
|
+
Ff = F = swe_degnorm(160.7108 + 390.67050274 * kk
|
3076
|
+
- 0.0016341 * T2
|
3077
|
+
- 0.00000227 * T3
|
3078
|
+
+ 0.000000011 * T4);
|
3079
|
+
if (Ff > 180)
|
3080
|
+
Ff -= 180;
|
3081
|
+
if (Ff > 21 && Ff < 159) { /* no eclipse possible */
|
3082
|
+
K += direction;
|
3083
|
+
goto next_try;
|
3084
|
+
}
|
3085
|
+
/* approximate time of geocentric maximum eclipse
|
3086
|
+
* formula from Meeus, German, p. 381 */
|
3087
|
+
tjd = 2451550.09765 + 29.530588853 * kk
|
3088
|
+
+ 0.0001337 * T2
|
3089
|
+
- 0.000000150 * T3
|
3090
|
+
+ 0.00000000073 * T4;
|
3091
|
+
M = swe_degnorm(2.5534 + 29.10535669 * kk
|
3092
|
+
- 0.0000218 * T2
|
3093
|
+
- 0.00000011 * T3);
|
3094
|
+
Mm = swe_degnorm(201.5643 + 385.81693528 * kk
|
3095
|
+
+ 0.1017438 * T2
|
3096
|
+
+ 0.00001239 * T3
|
3097
|
+
+ 0.000000058 * T4);
|
3098
|
+
Om = swe_degnorm(124.7746 - 1.56375580 * kk
|
3099
|
+
+ 0.0020691 * T2
|
3100
|
+
+ 0.00000215 * T3);
|
3101
|
+
E = 1 - 0.002516 * T - 0.0000074 * T2;
|
3102
|
+
A1 = swe_degnorm(299.77 + 0.107408 * kk - 0.009173 * T2);
|
3103
|
+
M *= DEGTORAD;
|
3104
|
+
Mm *= DEGTORAD;
|
3105
|
+
F *= DEGTORAD;
|
3106
|
+
Om *= DEGTORAD;
|
3107
|
+
F1 = F - 0.02665 * sin(Om) * DEGTORAD;
|
3108
|
+
A1 *= DEGTORAD;
|
3109
|
+
tjd = tjd - 0.4075 * sin(Mm)
|
3110
|
+
+ 0.1721 * E * sin(M)
|
3111
|
+
+ 0.0161 * sin(2 * Mm)
|
3112
|
+
- 0.0097 * sin(2 * F1)
|
3113
|
+
+ 0.0073 * E * sin(Mm - M)
|
3114
|
+
- 0.0050 * E * sin(Mm + M)
|
3115
|
+
- 0.0023 * sin(Mm - 2 * F1)
|
3116
|
+
+ 0.0021 * E * sin(2 * M)
|
3117
|
+
+ 0.0012 * sin(Mm + 2 * F1)
|
3118
|
+
+ 0.0006 * E * sin(2 * Mm + M)
|
3119
|
+
- 0.0004 * sin(3 * Mm)
|
3120
|
+
- 0.0003 * E * sin(M + 2 * F1)
|
3121
|
+
+ 0.0003 * sin(A1)
|
3122
|
+
- 0.0002 * E * sin(M - 2 * F1)
|
3123
|
+
- 0.0002 * E * sin(2 * Mm - M)
|
3124
|
+
- 0.0002 * sin(Om);
|
3125
|
+
/*
|
3126
|
+
* precise computation:
|
3127
|
+
* time of maximum eclipse (if eclipse) =
|
3128
|
+
* minimum selenocentric angle between sun and earth edges.
|
3129
|
+
* After this time has been determined, check
|
3130
|
+
* whether or not an eclipse is taking place with
|
3131
|
+
* the function lun_eclipse_how().
|
3132
|
+
*/
|
3133
|
+
dtstart = 0.1;
|
3134
|
+
if (tjd < 2000000)
|
3135
|
+
dtstart = 5;
|
3136
|
+
dtdiv = 4;
|
3137
|
+
for (j = 0, dt = dtstart;
|
3138
|
+
dt > 0.001;
|
3139
|
+
j++, dt /= dtdiv) {
|
3140
|
+
for (i = 0, t = tjd - dt; i <= 2; i++, t += dt) {
|
3141
|
+
if (swe_calc(t, SE_SUN, iflagcart, xs, serr) == ERR)
|
3142
|
+
return ERR;
|
3143
|
+
if (swe_calc(t, SE_MOON, iflagcart, xm, serr) == ERR)
|
3144
|
+
return ERR;
|
3145
|
+
for (m = 0; m < 3; m++) {
|
3146
|
+
xs[m] -= xm[m]; /* selenocentric sun */
|
3147
|
+
xm[m] = -xm[m]; /* selenocentric earth */
|
3148
|
+
}
|
3149
|
+
ds = sqrt(square_sum(xs));
|
3150
|
+
dm = sqrt(square_sum(xm));
|
3151
|
+
for (m = 0; m < 3; m++) {
|
3152
|
+
xa[m] = xs[m] / ds;
|
3153
|
+
xb[m] = xm[m] / dm;
|
3154
|
+
}
|
3155
|
+
dc[i] = acos(swi_dot_prod_unit(xa, xb)) * RADTODEG;
|
3156
|
+
rearth = asin(REARTH / dm) * RADTODEG;
|
3157
|
+
rsun = asin(RSUN / ds) * RADTODEG;
|
3158
|
+
dc[i] -= (rearth + rsun);
|
3159
|
+
}
|
3160
|
+
find_maximum(dc[0], dc[1], dc[2], dt, &dtint, &dctr);
|
3161
|
+
tjd += dtint + dt;
|
3162
|
+
}
|
3163
|
+
tjd = tjd - swe_deltat(tjd);
|
3164
|
+
if ((retflag = swe_lun_eclipse_how(tjd, ifl, NULL, attr, serr)) == ERR)
|
3165
|
+
return retflag;
|
3166
|
+
if (retflag == 0) {
|
3167
|
+
K += direction;
|
3168
|
+
goto next_try;
|
3169
|
+
}
|
3170
|
+
tret[0] = tjd;
|
3171
|
+
if ((backward && tret[0] >= tjd_start - 0.0001)
|
3172
|
+
|| (!backward && tret[0] <= tjd_start + 0.0001)) {
|
3173
|
+
K += direction;
|
3174
|
+
goto next_try;
|
3175
|
+
}
|
3176
|
+
/*
|
3177
|
+
* check whether or not eclipse type found is wanted
|
3178
|
+
*/
|
3179
|
+
/* non penumbral eclipse is wanted: */
|
3180
|
+
if (!(ifltype & SE_ECL_PENUMBRAL) && (retflag & SE_ECL_PENUMBRAL)) {
|
3181
|
+
K += direction;
|
3182
|
+
goto next_try;
|
3183
|
+
}
|
3184
|
+
/* non partial eclipse is wanted: */
|
3185
|
+
if (!(ifltype & SE_ECL_PARTIAL) && (retflag & SE_ECL_PARTIAL)) {
|
3186
|
+
K += direction;
|
3187
|
+
goto next_try;
|
3188
|
+
}
|
3189
|
+
/* annular-total eclipse will be discovered later */
|
3190
|
+
if (!(ifltype & (SE_ECL_TOTAL)) && (retflag & SE_ECL_TOTAL)) {
|
3191
|
+
K += direction;
|
3192
|
+
goto next_try;
|
3193
|
+
}
|
3194
|
+
/*
|
3195
|
+
* n = 0: times of eclipse begin and end
|
3196
|
+
* n = 1: times of totality begin and end
|
3197
|
+
* n = 2: times of center line begin and end
|
3198
|
+
*/
|
3199
|
+
if (retflag & SE_ECL_PENUMBRAL)
|
3200
|
+
o = 0;
|
3201
|
+
else if (retflag & SE_ECL_PARTIAL)
|
3202
|
+
o = 1;
|
3203
|
+
else
|
3204
|
+
o = 2;
|
3205
|
+
dta = twohr;
|
3206
|
+
dtb = tenmin;
|
3207
|
+
for (n = 0; n <= o; n++) {
|
3208
|
+
if (n == 0) {
|
3209
|
+
i1 = 6; i2 = 7;
|
3210
|
+
} else if (n == 1) {
|
3211
|
+
i1 = 2; i2 = 3;
|
3212
|
+
} else if (n == 2) {
|
3213
|
+
i1 = 4; i2 = 5;
|
3214
|
+
}
|
3215
|
+
#if 1
|
3216
|
+
for (i = 0, t = tjd - dta; i <= 2; i += 1, t += dta) {
|
3217
|
+
if ((retflag2 = lun_eclipse_how(t, ifl, attr, dcore, serr)) == ERR)
|
3218
|
+
return retflag2;
|
3219
|
+
if (n == 0)
|
3220
|
+
dc[i] = dcore[2] / 2 + RMOON / dcore[4] - dcore[0];
|
3221
|
+
else if (n == 1)
|
3222
|
+
dc[i] = dcore[1] / 2 + RMOON / dcore[3] - dcore[0];
|
3223
|
+
else if (n == 2)
|
3224
|
+
dc[i] = dcore[1] / 2 - RMOON / dcore[3] - dcore[0];
|
3225
|
+
}
|
3226
|
+
find_zero(dc[0], dc[1], dc[2], dta, &dt1, &dt2);
|
3227
|
+
dtb = (dt1 + dta) / 2;
|
3228
|
+
tret[i1] = tjd + dt1 + dta;
|
3229
|
+
tret[i2] = tjd + dt2 + dta;
|
3230
|
+
#else
|
3231
|
+
tret[i1] = tjd - dtb;
|
3232
|
+
tret[i2] = tjd + dtb;
|
3233
|
+
#endif
|
3234
|
+
for (m = 0, dt = dtb / 2; m < 3; m++, dt /= 2) {
|
3235
|
+
for (j = i1; j <= i2; j += (i2 - i1)) {
|
3236
|
+
for (i = 0, t = tret[j] - dt; i < 2; i++, t += dt) {
|
3237
|
+
if ((retflag2 = lun_eclipse_how(t, ifl, attr, dcore, serr)) == ERR)
|
3238
|
+
return retflag2;
|
3239
|
+
if (n == 0)
|
3240
|
+
dc[i] = dcore[2] / 2 + RMOON / dcore[4] - dcore[0];
|
3241
|
+
else if (n == 1)
|
3242
|
+
dc[i] = dcore[1] / 2 + RMOON / dcore[3] - dcore[0];
|
3243
|
+
else if (n == 2)
|
3244
|
+
dc[i] = dcore[1] / 2 - RMOON / dcore[3] - dcore[0];
|
3245
|
+
}
|
3246
|
+
dt1 = dc[1] / ((dc[1] - dc[0]) / dt);
|
3247
|
+
tret[j] -= dt1;
|
3248
|
+
}
|
3249
|
+
}
|
3250
|
+
}
|
3251
|
+
return retflag;
|
3252
|
+
}
|
3253
|
+
|
3254
|
+
/*
|
3255
|
+
* function calculates planetary phenomena
|
3256
|
+
*
|
3257
|
+
* attr[0] = phase angle (earth-planet-sun)
|
3258
|
+
* attr[1] = phase (illumined fraction of disc)
|
3259
|
+
* attr[2] = elongation of planet
|
3260
|
+
* attr[3] = apparent diameter of disc
|
3261
|
+
* attr[4] = apparent magnitude
|
3262
|
+
* attr[5] = geocentric horizontal parallax (Moon)
|
3263
|
+
* declare as attr[20] at least !
|
3264
|
+
*
|
3265
|
+
* Note: the lunar magnitude is quite a complicated thing,
|
3266
|
+
* but our algorithm is very simple.
|
3267
|
+
* The phase of the moon, its distance from the earth and
|
3268
|
+
* the sun is considered, but no other factors.
|
3269
|
+
*
|
3270
|
+
*/
|
3271
|
+
#define EULER 2.718281828459
|
3272
|
+
#define NMAG_ELEM (SE_VESTA + 1)
|
3273
|
+
static double mag_elem[NMAG_ELEM][4] = {
|
3274
|
+
/* DTV-Atlas Astronomie, p. 32 */
|
3275
|
+
{-26.86, 0, 0, 0},
|
3276
|
+
{-12.55, 0, 0, 0},
|
3277
|
+
/* IAU 1986 */
|
3278
|
+
{-0.42, 3.80, -2.73, 2.00},
|
3279
|
+
{-4.40, 0.09, 2.39, -0.65},
|
3280
|
+
{- 1.52, 1.60, 0, 0}, /* Mars */
|
3281
|
+
{- 9.40, 0.5, 0, 0}, /* Jupiter */
|
3282
|
+
{- 8.88, -2.60, 1.25, 0.044}, /* Saturn */
|
3283
|
+
{- 7.19, 0.0, 0, 0}, /* Uranus */
|
3284
|
+
{- 6.87, 0.0, 0, 0}, /* Neptune */
|
3285
|
+
{- 1.00, 0.0, 0, 0}, /* Pluto */
|
3286
|
+
{99, 0, 0, 0}, /* nodes and apogees */
|
3287
|
+
{99, 0, 0, 0},
|
3288
|
+
{99, 0, 0, 0},
|
3289
|
+
{99, 0, 0, 0},
|
3290
|
+
{99, 0, 0, 0}, /* Earth */
|
3291
|
+
/* from Bowell data base */
|
3292
|
+
{6.5, 0.15, 0, 0}, /* Chiron */
|
3293
|
+
{7.0, 0.15, 0, 0}, /* Pholus */
|
3294
|
+
{3.34, 0.12, 0, 0}, /* Ceres */
|
3295
|
+
{4.13, 0.11, 0, 0}, /* Pallas */
|
3296
|
+
{5.33, 0.32, 0, 0}, /* Juno */
|
3297
|
+
{3.20, 0.32, 0, 0}, /* Vesta */
|
3298
|
+
};
|
3299
|
+
int32 FAR PASCAL_CONV swe_pheno(double tjd, int32 ipl, int32 iflag, double *attr, char *serr)
|
3300
|
+
{
|
3301
|
+
int i;
|
3302
|
+
double xx[6], xx2[6], xxs[6], lbr[6], lbr2[6], dt = 0, dd;
|
3303
|
+
double fac;
|
3304
|
+
double T, in, om, sinB, u1, u2, du;
|
3305
|
+
double ph1, ph2, me[2];
|
3306
|
+
int32 iflagp, epheflag;
|
3307
|
+
/* function calls for Pluto with asteroid number 134340
|
3308
|
+
* are treated as calls for Pluto as main body SE_PLUTO */
|
3309
|
+
if (ipl == SE_AST_OFFSET + 134340)
|
3310
|
+
ipl = SE_PLUTO;
|
3311
|
+
for (i = 0; i < 20; i++)
|
3312
|
+
attr[i] = 0;
|
3313
|
+
/* Ceres - Vesta must be SE_CERES etc., not 10001 etc. */
|
3314
|
+
if (ipl > SE_AST_OFFSET && ipl <= SE_AST_OFFSET + 4)
|
3315
|
+
ipl = ipl - SE_AST_OFFSET - 1 + SE_CERES;
|
3316
|
+
iflag = iflag & (SEFLG_EPHMASK |
|
3317
|
+
SEFLG_TRUEPOS |
|
3318
|
+
SEFLG_J2000 |
|
3319
|
+
SEFLG_NONUT |
|
3320
|
+
SEFLG_NOGDEFL |
|
3321
|
+
SEFLG_NOABERR |
|
3322
|
+
SEFLG_TOPOCTR);
|
3323
|
+
iflagp = iflag & (SEFLG_EPHMASK |
|
3324
|
+
SEFLG_TRUEPOS |
|
3325
|
+
SEFLG_J2000 |
|
3326
|
+
SEFLG_NONUT |
|
3327
|
+
SEFLG_NOABERR);
|
3328
|
+
iflagp |= SEFLG_HELCTR;
|
3329
|
+
epheflag = iflag & SEFLG_EPHMASK;
|
3330
|
+
/*
|
3331
|
+
* geocentric planet
|
3332
|
+
*/
|
3333
|
+
if (swe_calc(tjd, (int) ipl, iflag | SEFLG_XYZ, xx, serr) == ERR)
|
3334
|
+
/* int cast can be removed when swe_calc() gets int32 ipl definition */
|
3335
|
+
return ERR;
|
3336
|
+
if (swe_calc(tjd, (int) ipl, iflag, lbr, serr) == ERR)
|
3337
|
+
/* int cast can be removed when swe_calc() gets int32 ipl definition */
|
3338
|
+
return ERR;
|
3339
|
+
/* if moon, we need sun as well, for magnitude */
|
3340
|
+
if (ipl == SE_MOON)
|
3341
|
+
if (swe_calc(tjd, SE_SUN, iflag | SEFLG_XYZ, xxs, serr) == ERR)
|
3342
|
+
return ERR;
|
3343
|
+
if (ipl != SE_SUN && ipl != SE_EARTH &&
|
3344
|
+
ipl != SE_MEAN_NODE && ipl != SE_TRUE_NODE &&
|
3345
|
+
ipl != SE_MEAN_APOG && ipl != SE_OSCU_APOG) {
|
3346
|
+
/*
|
3347
|
+
* light time planet - earth
|
3348
|
+
*/
|
3349
|
+
dt = lbr[2] * AUNIT / CLIGHT / 86400.0;
|
3350
|
+
if (iflag & SEFLG_TRUEPOS)
|
3351
|
+
dt = 0;
|
3352
|
+
/*
|
3353
|
+
* heliocentric planet at tjd - dt
|
3354
|
+
*/
|
3355
|
+
if (swe_calc(tjd - dt, (int) ipl, iflagp | SEFLG_XYZ, xx2, serr) == ERR)
|
3356
|
+
/* int cast can be removed when swe_calc() gets int32 ipl definition */
|
3357
|
+
return ERR;
|
3358
|
+
if (swe_calc(tjd - dt, (int) ipl, iflagp, lbr2, serr) == ERR)
|
3359
|
+
/* int cast can be removed when swe_calc() gets int32 ipl definition */
|
3360
|
+
return ERR;
|
3361
|
+
/*
|
3362
|
+
* phase angle
|
3363
|
+
*/
|
3364
|
+
attr[0] = acos(swi_dot_prod_unit(xx, xx2)) * RADTODEG;
|
3365
|
+
/*
|
3366
|
+
* phase
|
3367
|
+
*/
|
3368
|
+
attr[1] = (1 + cos(attr[0] * DEGTORAD)) / 2;
|
3369
|
+
}
|
3370
|
+
/*
|
3371
|
+
* apparent diameter of disk
|
3372
|
+
*/
|
3373
|
+
if (ipl < NDIAM)
|
3374
|
+
dd = pla_diam[ipl];
|
3375
|
+
else if (ipl > SE_AST_OFFSET)
|
3376
|
+
dd = swed.ast_diam * 1000; /* km -> m */
|
3377
|
+
else
|
3378
|
+
dd = 0;
|
3379
|
+
if (lbr[2] < dd / 2 / AUNIT)
|
3380
|
+
attr[3] = 180; /* assume position on surface of earth */
|
3381
|
+
else
|
3382
|
+
attr[3] = asin(dd / 2 / AUNIT / lbr[2]) * 2 * RADTODEG;
|
3383
|
+
/*
|
3384
|
+
* apparent magnitude
|
3385
|
+
*/
|
3386
|
+
if (ipl > SE_AST_OFFSET || (ipl < NMAG_ELEM && mag_elem[ipl][0] < 99)) {
|
3387
|
+
if (ipl == SE_SUN) {
|
3388
|
+
/* ratio apparent diameter : average diameter */
|
3389
|
+
fac = attr[3] / (asin(pla_diam[SE_SUN] / 2.0 / AUNIT) * 2 * RADTODEG);
|
3390
|
+
fac *= fac;
|
3391
|
+
attr[4] = mag_elem[ipl][0] - 2.5 * log10(fac);
|
3392
|
+
} else if (ipl == SE_MOON) {
|
3393
|
+
/* formula according to Allen, C.W., 1976, Astrophysical Quantities */
|
3394
|
+
/*attr[4] = -21.62 + 5 * log10(384410497.8 / EARTH_RADIUS) / log10(10) + 0.026 * fabs(attr[0]) + 0.000000004 * pow(attr[0], 4);*/
|
3395
|
+
attr[4] = -21.62 + 5 * log10(lbr[2] * AUNIT / EARTH_RADIUS) / log10(10) + 0.026 * fabs(attr[0]) + 0.000000004 * pow(attr[0], 4);
|
3396
|
+
#if 0
|
3397
|
+
/* ratio apparent diameter : average diameter */
|
3398
|
+
fac = attr[3] / (asin(pla_diam[SE_MOON] / 2.0 / 384400000.0) * 2 * RADTODEG);
|
3399
|
+
/* distance sun - moon */
|
3400
|
+
for (i = 0; i < 3; i++)
|
3401
|
+
xxs[i] -= xx[i];
|
3402
|
+
dsm = sqrt(square_sum(xxs));
|
3403
|
+
/* account for phase and distance of moon: */
|
3404
|
+
fac *= fac * attr[1];
|
3405
|
+
/* account for distance of sun from moon: */
|
3406
|
+
fac *= dsm * dsm;
|
3407
|
+
attr[4] = mag_elem[ipl][0] - 2.5 * log10(fac);
|
3408
|
+
#endif
|
3409
|
+
/*printf("1 = %f, 2 = %f\n", mag, mag2);*/
|
3410
|
+
} else if (ipl == SE_SATURN) {
|
3411
|
+
/* rings are considered according to Meeus, German, p. 329ff. */
|
3412
|
+
T = (tjd - dt - J2000) / 36525.0;
|
3413
|
+
in = (28.075216 - 0.012998 * T + 0.000004 * T * T) * DEGTORAD;
|
3414
|
+
om = (169.508470 + 1.394681 * T + 0.000412 * T * T) * DEGTORAD;
|
3415
|
+
sinB = fabs(sin(in) * cos(lbr[1] * DEGTORAD)
|
3416
|
+
* sin(lbr[0] * DEGTORAD - om)
|
3417
|
+
- cos(in) * sin(lbr[1] * DEGTORAD));
|
3418
|
+
u1 = atan2(sin(in) * tan(lbr2[1] * DEGTORAD)
|
3419
|
+
+ cos(in) * sin(lbr2[0] * DEGTORAD - om),
|
3420
|
+
cos(lbr2[0] * DEGTORAD - om)) * RADTODEG;
|
3421
|
+
u2 = atan2(sin(in) * tan(lbr[1] * DEGTORAD)
|
3422
|
+
+ cos(in) * sin(lbr[0] * DEGTORAD - om),
|
3423
|
+
cos(lbr[0] * DEGTORAD - om)) * RADTODEG;
|
3424
|
+
du = swe_degnorm(u1 - u2);
|
3425
|
+
if (du > 10)
|
3426
|
+
du = 360 - du;
|
3427
|
+
attr[4] = 5 * log10(lbr2[2] * lbr[2])
|
3428
|
+
+ mag_elem[ipl][1] * sinB
|
3429
|
+
+ mag_elem[ipl][2] * sinB * sinB
|
3430
|
+
+ mag_elem[ipl][3] * du
|
3431
|
+
+ mag_elem[ipl][0];
|
3432
|
+
} else if (ipl < SE_CHIRON) {
|
3433
|
+
attr[4] = 5 * log10(lbr2[2] * lbr[2])
|
3434
|
+
+ mag_elem[ipl][1] * attr[0] /100.0
|
3435
|
+
+ mag_elem[ipl][2] * attr[0] * attr[0] / 10000.0
|
3436
|
+
+ mag_elem[ipl][3] * attr[0] * attr[0] * attr[0] / 1000000.0
|
3437
|
+
+ mag_elem[ipl][0];
|
3438
|
+
} else if (ipl < NMAG_ELEM || ipl > SE_AST_OFFSET) { /* asteroids */
|
3439
|
+
ph1 = pow(EULER, -3.33 * pow(tan(attr[0] * DEGTORAD / 2), 0.63));
|
3440
|
+
ph2 = pow(EULER, -1.87 * pow(tan(attr[0] * DEGTORAD / 2), 1.22));
|
3441
|
+
if (ipl < NMAG_ELEM) { /* main asteroids */
|
3442
|
+
me[0] = mag_elem[ipl][0];
|
3443
|
+
me[1] = mag_elem[ipl][1];
|
3444
|
+
} else if (ipl == SE_AST_OFFSET + 1566) {
|
3445
|
+
/* Icarus has elements from JPL database */
|
3446
|
+
me[0] = 16.9;
|
3447
|
+
me[1] = 0.15;
|
3448
|
+
} else { /* other asteroids */
|
3449
|
+
me[0] = swed.ast_H;
|
3450
|
+
me[1] = swed.ast_G;
|
3451
|
+
}
|
3452
|
+
attr[4] = 5 * log10(lbr2[2] * lbr[2])
|
3453
|
+
+ me[0]
|
3454
|
+
- 2.5 * log10((1 - me[1]) * ph1 + me[1] * ph2);
|
3455
|
+
} else { /* ficticious bodies */
|
3456
|
+
attr[4] = 0;
|
3457
|
+
}
|
3458
|
+
}
|
3459
|
+
if (ipl != SE_SUN && ipl != SE_EARTH) {
|
3460
|
+
/*
|
3461
|
+
* elongation of planet
|
3462
|
+
*/
|
3463
|
+
if (swe_calc(tjd, SE_SUN, iflag | SEFLG_XYZ, xx2, serr) == ERR)
|
3464
|
+
return ERR;
|
3465
|
+
if (swe_calc(tjd, SE_SUN, iflag, lbr2, serr) == ERR)
|
3466
|
+
return ERR;
|
3467
|
+
attr[2] = acos(swi_dot_prod_unit(xx, xx2)) * RADTODEG;
|
3468
|
+
}
|
3469
|
+
/* horizontal parallax */
|
3470
|
+
if (ipl == SE_MOON) {
|
3471
|
+
double sinhp, xm[6];
|
3472
|
+
/* geocentric horizontal parallax */
|
3473
|
+
/* Expl.Suppl. to the AA 1984, p.400 */
|
3474
|
+
if (swe_calc(tjd, (int) ipl, epheflag|SEFLG_TRUEPOS|SEFLG_EQUATORIAL|SEFLG_RADIANS, xm, serr) == ERR)
|
3475
|
+
/* int cast can be removed when swe_calc() gets int32 ipl definition */
|
3476
|
+
return ERR;
|
3477
|
+
sinhp = EARTH_RADIUS / xm[2] / AUNIT;
|
3478
|
+
attr[5] = asin(sinhp) / DEGTORAD;
|
3479
|
+
/* topocentric horizontal parallax */
|
3480
|
+
if (iflag & SEFLG_TOPOCTR) {
|
3481
|
+
if (swe_calc(tjd, (int) ipl, epheflag|SEFLG_XYZ|SEFLG_TOPOCTR, xm, serr) == ERR)
|
3482
|
+
return ERR;
|
3483
|
+
if (swe_calc(tjd, (int) ipl, epheflag|SEFLG_XYZ, xx, serr) == ERR)
|
3484
|
+
return ERR;
|
3485
|
+
attr[5] = acos(swi_dot_prod_unit(xm, xx)) / DEGTORAD;
|
3486
|
+
#if 0
|
3487
|
+
{
|
3488
|
+
/* Expl. Suppl. to the Astronomical Almanac 1984, p. 400;
|
3489
|
+
* Does not take into account
|
3490
|
+
* - the topocentric distance of the moon
|
3491
|
+
* - the distance of the observer from the geocenter
|
3492
|
+
*/
|
3493
|
+
double tsid, h, e, f = EARTH_OBLATENESS;
|
3494
|
+
double cosz, sinz, phi;
|
3495
|
+
/* local apparent sidereal time */
|
3496
|
+
tsid = swe_sidtime(tjd - swe_deltat(tjd)) * 15 + swed.topd.geolon;
|
3497
|
+
/* local hour angle of the moon */
|
3498
|
+
h = swe_degnorm(tsid - xm[0] / DEGTORAD);
|
3499
|
+
/* geocentric latitude of the observer */
|
3500
|
+
e = sqrt(f * (2 - f));
|
3501
|
+
phi = atan((1 - e * e) * tan(swed.topd.geolat * DEGTORAD));
|
3502
|
+
/* sine of geocentric zenith angle of moon */
|
3503
|
+
cosz = sin(xm[1]) * sin(phi) + cos(xm[1]) * cos(phi) * cos(h * DEGTORAD);
|
3504
|
+
sinz = sqrt(1 - cosz * cosz);
|
3505
|
+
attr[5] = asin(sinz * sinhp / (1 - sinz * sinhp)) / DEGTORAD;
|
3506
|
+
}
|
3507
|
+
#endif
|
3508
|
+
}
|
3509
|
+
}
|
3510
|
+
return OK;
|
3511
|
+
}
|
3512
|
+
|
3513
|
+
int32 FAR PASCAL_CONV swe_pheno_ut(double tjd_ut, int32 ipl, int32 iflag, double *attr, char *serr)
|
3514
|
+
{
|
3515
|
+
return swe_pheno(tjd_ut + swe_deltat(tjd_ut), ipl, iflag, attr, serr);
|
3516
|
+
}
|
3517
|
+
|
3518
|
+
static int find_maximum(double y00, double y11, double y2, double dx,
|
3519
|
+
double *dxret, double *yret)
|
3520
|
+
{
|
3521
|
+
double a, b, c, x, y;
|
3522
|
+
c = y11;
|
3523
|
+
b = (y2 - y00) / 2.0;
|
3524
|
+
a = (y2 + y00) / 2.0 - c;
|
3525
|
+
x = -b / 2 / a;
|
3526
|
+
y = (4 * a * c - b * b) / 4 / a;
|
3527
|
+
*dxret = (x - 1) * dx;
|
3528
|
+
if (yret != NULL)
|
3529
|
+
*yret = y;
|
3530
|
+
return OK;
|
3531
|
+
}
|
3532
|
+
|
3533
|
+
static int find_zero(double y00, double y11, double y2, double dx,
|
3534
|
+
double *dxret, double *dxret2)
|
3535
|
+
{
|
3536
|
+
double a, b, c, x1, x2;
|
3537
|
+
c = y11;
|
3538
|
+
b = (y2 - y00) / 2.0;
|
3539
|
+
a = (y2 + y00) / 2.0 - c;
|
3540
|
+
if (b * b - 4 * a * c < 0)
|
3541
|
+
return ERR;
|
3542
|
+
x1 = (-b + sqrt(b * b - 4 * a * c)) / 2 / a;
|
3543
|
+
x2 = (-b - sqrt(b * b - 4 * a * c)) / 2 / a;
|
3544
|
+
*dxret = (x1 - 1) * dx;
|
3545
|
+
*dxret2 = (x2 - 1) * dx;
|
3546
|
+
return OK;
|
3547
|
+
}
|
3548
|
+
|
3549
|
+
double rdi_twilight(int32 rsmi)
|
3550
|
+
{
|
3551
|
+
double rdi = 0;
|
3552
|
+
if (rsmi & SE_BIT_CIVIL_TWILIGHT)
|
3553
|
+
rdi = 6;
|
3554
|
+
if (rsmi & SE_BIT_NAUTIC_TWILIGHT)
|
3555
|
+
rdi = 12;
|
3556
|
+
if (rsmi & SE_BIT_ASTRO_TWILIGHT)
|
3557
|
+
rdi = 18;
|
3558
|
+
return rdi;
|
3559
|
+
}
|
3560
|
+
|
3561
|
+
/* rise, set, and meridian transits of sun, moon, planets, and stars
|
3562
|
+
*
|
3563
|
+
* tjd_ut universal time from when on search ought to start
|
3564
|
+
* ipl planet number, neglected, if starname is given
|
3565
|
+
* starname pointer to string. if a planet, not a star, is
|
3566
|
+
* wanted, starname must be NULL or ""
|
3567
|
+
* epheflag used for ephemeris only
|
3568
|
+
* rsmi SE_CALC_RISE, SE_CALC_SET, SE_CALC_MTRANSIT, SE_CALC_ITRANSIT
|
3569
|
+
* | SE_BIT_DISC_CENTER for rises of disc center of body
|
3570
|
+
* | SE_BIT_DISC_BOTTOM for rises of disc bottom of body
|
3571
|
+
* | SE_BIT_NO_REFRACTION to neglect refraction
|
3572
|
+
* | SE_BIT_FIXED_DISC_SIZE neglect the effect of distance on disc size
|
3573
|
+
* geopos array of doubles for geogr. long., lat. and height above sea
|
3574
|
+
* atpress atmospheric pressure
|
3575
|
+
* attemp atmospheric temperature
|
3576
|
+
*
|
3577
|
+
* return variables:
|
3578
|
+
* tret time of rise, set, meridian transits
|
3579
|
+
* serr[256] error string
|
3580
|
+
* function return value -2 means that the body does not rise or set */
|
3581
|
+
#define SEFLG_EPHMASK (SEFLG_JPLEPH|SEFLG_SWIEPH|SEFLG_MOSEPH)
|
3582
|
+
int32 FAR PASCAL_CONV swe_rise_trans(
|
3583
|
+
double tjd_ut, int32 ipl, char *starname,
|
3584
|
+
int32 epheflag, int32 rsmi,
|
3585
|
+
double *geopos,
|
3586
|
+
double atpress, double attemp,
|
3587
|
+
double *tret,
|
3588
|
+
char *serr)
|
3589
|
+
{
|
3590
|
+
int i, j, k, ii, calc_culm, nculm = -1;
|
3591
|
+
double tjd_et = tjd_ut + swe_deltat(tjd_ut);
|
3592
|
+
double xc[6], xh[20][6], ah[6], aha;
|
3593
|
+
double tculm[4], tcu, tc[20], h[20], t2[6], dc[6], dtint, dx, rdi, dd = 0;
|
3594
|
+
int32 iflag = epheflag;
|
3595
|
+
int jmax = 14;
|
3596
|
+
double t, te, tt, dt, twohrs = 1.0 / 12.0;
|
3597
|
+
double curdist;
|
3598
|
+
AS_BOOL do_calc_twilight = 0;
|
3599
|
+
AS_BOOL do_fixstar = (starname != NULL && *starname != '\0');
|
3600
|
+
/* function calls for Pluto with asteroid number 134340
|
3601
|
+
* are treated as calls for Pluto as main body SE_PLUTO */
|
3602
|
+
if (ipl == SE_AST_OFFSET + 134340)
|
3603
|
+
ipl = SE_PLUTO;
|
3604
|
+
xh[0][0] = 0; /* to shut up mint */
|
3605
|
+
iflag &= SEFLG_EPHMASK;
|
3606
|
+
*tret = 0;
|
3607
|
+
iflag |= (SEFLG_EQUATORIAL | SEFLG_TOPOCTR);
|
3608
|
+
swe_set_topo(geopos[0], geopos[1], geopos[2]);
|
3609
|
+
if (rsmi & (SE_CALC_MTRANSIT | SE_CALC_ITRANSIT))
|
3610
|
+
return calc_mer_trans(tjd_ut, ipl, epheflag, rsmi,
|
3611
|
+
geopos, starname, tret, serr);
|
3612
|
+
if (!(rsmi & (SE_CALC_RISE | SE_CALC_SET)))
|
3613
|
+
rsmi |= SE_CALC_RISE;
|
3614
|
+
if (ipl == SE_SUN && (rsmi & (SE_BIT_CIVIL_TWILIGHT|SE_BIT_NAUTIC_TWILIGHT|SE_BIT_ASTRO_TWILIGHT))) {
|
3615
|
+
rsmi |= (SE_BIT_NO_REFRACTION | SE_BIT_DISC_CENTER);
|
3616
|
+
do_calc_twilight = 1;
|
3617
|
+
}
|
3618
|
+
/* find culmination points within 28 hours from t0 - twohrs.
|
3619
|
+
* culminations are required in case there are maxima or minima
|
3620
|
+
* in height slightly above or below the horizon.
|
3621
|
+
* we do not use meridian transits, because in polar regions
|
3622
|
+
* the culmination points may considerably deviate from
|
3623
|
+
* transits. also, there are cases where the moon rises in the
|
3624
|
+
* western half of the sky for a short time.
|
3625
|
+
*/
|
3626
|
+
if (do_fixstar) {
|
3627
|
+
if (swe_fixstar(starname, tjd_et, iflag, xc, serr) == ERR)
|
3628
|
+
return ERR;
|
3629
|
+
}
|
3630
|
+
for (ii = 0, t = tjd_ut - twohrs; ii <= jmax; ii++, t += twohrs) {
|
3631
|
+
tc[ii] = t;
|
3632
|
+
if (!do_fixstar) {
|
3633
|
+
te = t + swe_deltat(t);
|
3634
|
+
if (swe_calc(te, ipl, iflag, xc, serr) == ERR)
|
3635
|
+
return ERR;
|
3636
|
+
}
|
3637
|
+
/* diameter of object in km */
|
3638
|
+
if (ii == 0) {
|
3639
|
+
if (do_fixstar)
|
3640
|
+
dd = 0;
|
3641
|
+
else if (rsmi & SE_BIT_DISC_CENTER)
|
3642
|
+
dd = 0;
|
3643
|
+
else if (ipl < NDIAM)
|
3644
|
+
dd = pla_diam[ipl];
|
3645
|
+
else if (ipl > SE_AST_OFFSET)
|
3646
|
+
dd = swed.ast_diam * 1000; /* km -> m */
|
3647
|
+
else
|
3648
|
+
dd = 0;
|
3649
|
+
}
|
3650
|
+
curdist = xc[2];
|
3651
|
+
if ( rsmi & SE_BIT_FIXED_DISC_SIZE )
|
3652
|
+
{
|
3653
|
+
if ( ipl == SE_SUN )
|
3654
|
+
{
|
3655
|
+
curdist = 1.0;
|
3656
|
+
}
|
3657
|
+
else if ( ipl == SE_MOON )
|
3658
|
+
{
|
3659
|
+
curdist = 0.00257;
|
3660
|
+
}
|
3661
|
+
}
|
3662
|
+
/* apparent radius of disc */
|
3663
|
+
rdi = asin( dd / 2 / AUNIT / curdist ) * RADTODEG;
|
3664
|
+
/* twilight calculation: */
|
3665
|
+
if (do_calc_twilight)
|
3666
|
+
rdi = rdi_twilight(rsmi);
|
3667
|
+
/* true height of center of body */
|
3668
|
+
swe_azalt(t, SE_EQU2HOR, geopos, atpress, attemp, xc, xh[ii]);
|
3669
|
+
if ( rsmi & SE_BIT_DISC_BOTTOM )
|
3670
|
+
{
|
3671
|
+
/* true height of bottom point of body */
|
3672
|
+
xh[ii][1] -= rdi;
|
3673
|
+
}
|
3674
|
+
else
|
3675
|
+
{
|
3676
|
+
/* true height of uppermost point of body */
|
3677
|
+
xh[ii][1] += rdi;
|
3678
|
+
}
|
3679
|
+
/* apparent height of uppermost point of body */
|
3680
|
+
if (rsmi & SE_BIT_NO_REFRACTION) {
|
3681
|
+
h[ii] = xh[ii][1];
|
3682
|
+
} else {
|
3683
|
+
swe_azalt_rev(t, SE_HOR2EQU, geopos, xh[ii], xc);
|
3684
|
+
swe_azalt(t, SE_EQU2HOR, geopos, atpress, attemp, xc, xh[ii]);
|
3685
|
+
h[ii] = xh[ii][2];
|
3686
|
+
}
|
3687
|
+
calc_culm = 0;
|
3688
|
+
if (ii > 1) {
|
3689
|
+
dc[0] = xh[ii-2][1];
|
3690
|
+
dc[1] = xh[ii-1][1];
|
3691
|
+
dc[2] = xh[ii][1];
|
3692
|
+
if (dc[1] > dc[0] && dc[1] > dc[2])
|
3693
|
+
calc_culm = 1;
|
3694
|
+
if (dc[1] < dc[0] && dc[1] < dc[2])
|
3695
|
+
calc_culm = 2;
|
3696
|
+
}
|
3697
|
+
if (calc_culm) {
|
3698
|
+
dt = twohrs;
|
3699
|
+
tcu = t - dt;
|
3700
|
+
find_maximum(dc[0], dc[1], dc[2], dt, &dtint, &dx);
|
3701
|
+
tcu += dtint + dt;
|
3702
|
+
dt /= 3;
|
3703
|
+
for (; dt > 0.0001; dt /= 3) {
|
3704
|
+
for (i = 0, tt = tcu - dt; i < 3; tt += dt, i++) {
|
3705
|
+
te = tt + swe_deltat(tt);
|
3706
|
+
if (!do_fixstar)
|
3707
|
+
if (swe_calc(te, ipl, iflag, xc, serr) == ERR)
|
3708
|
+
return ERR;
|
3709
|
+
swe_azalt(tt, SE_EQU2HOR, geopos, atpress, attemp, xc, ah);
|
3710
|
+
dc[i] = ah[1];
|
3711
|
+
}
|
3712
|
+
find_maximum(dc[0], dc[1], dc[2], dt, &dtint, &dx);
|
3713
|
+
tcu += dtint + dt;
|
3714
|
+
}
|
3715
|
+
nculm++;
|
3716
|
+
tculm[nculm] = tcu;
|
3717
|
+
}
|
3718
|
+
}
|
3719
|
+
/* note: there can be a rise or set on the poles, even if
|
3720
|
+
* there is no culmination. So, we must not leave here
|
3721
|
+
* in any case. */
|
3722
|
+
/* insert culminations into array of heights */
|
3723
|
+
for (i = 0; i <= nculm; i++) {
|
3724
|
+
for (j = 1; j <= jmax; j++) {
|
3725
|
+
if (tculm[i] < tc[j]) {
|
3726
|
+
for (k = jmax; k >= j; k--) {
|
3727
|
+
tc[k+1] = tc[k];
|
3728
|
+
h[k+1] = h[k];
|
3729
|
+
}
|
3730
|
+
tc[j] = tculm[i];
|
3731
|
+
if (!do_fixstar) {
|
3732
|
+
te = tc[j] + swe_deltat(tc[j]);
|
3733
|
+
if (swe_calc(te, ipl, iflag, xc, serr) == ERR)
|
3734
|
+
return ERR;
|
3735
|
+
}
|
3736
|
+
curdist = xc[2];
|
3737
|
+
if ( rsmi & SE_BIT_FIXED_DISC_SIZE )
|
3738
|
+
{
|
3739
|
+
if ( ipl == SE_SUN )
|
3740
|
+
{
|
3741
|
+
curdist = 1.0;
|
3742
|
+
}
|
3743
|
+
else if ( ipl == SE_MOON )
|
3744
|
+
{
|
3745
|
+
curdist = 0.00257;
|
3746
|
+
}
|
3747
|
+
}
|
3748
|
+
/* apparent radius of disc */
|
3749
|
+
rdi = asin( dd / 2 / AUNIT / curdist ) * RADTODEG;
|
3750
|
+
/* twilight calculation: */
|
3751
|
+
if (do_calc_twilight)
|
3752
|
+
rdi = rdi_twilight(rsmi);
|
3753
|
+
/* true height of center of body */
|
3754
|
+
swe_azalt(tc[j], SE_EQU2HOR, geopos, atpress, attemp, xc, ah);
|
3755
|
+
if ( rsmi & SE_BIT_DISC_BOTTOM )
|
3756
|
+
{
|
3757
|
+
/* true height of bottom point of body */
|
3758
|
+
ah[1] -= rdi;
|
3759
|
+
}
|
3760
|
+
else
|
3761
|
+
{
|
3762
|
+
/* true height of uppermost point of body */
|
3763
|
+
ah[1] += rdi;
|
3764
|
+
}
|
3765
|
+
/* apparent height of uppermost point of body */
|
3766
|
+
if (rsmi & SE_BIT_NO_REFRACTION) {
|
3767
|
+
h[j] = ah[1];
|
3768
|
+
} else {
|
3769
|
+
swe_azalt_rev(tc[j], SE_HOR2EQU, geopos, ah, xc);
|
3770
|
+
swe_azalt(tc[j], SE_EQU2HOR, geopos, atpress, attemp, xc, ah);
|
3771
|
+
h[j] = ah[2];
|
3772
|
+
}
|
3773
|
+
jmax++;
|
3774
|
+
break;
|
3775
|
+
}
|
3776
|
+
}
|
3777
|
+
}
|
3778
|
+
*tret = 0;
|
3779
|
+
/* find points with zero height.
|
3780
|
+
* binary search */
|
3781
|
+
for (ii = 1; ii <= jmax; ii++) {
|
3782
|
+
if (h[ii-1] * h[ii] >= 0)
|
3783
|
+
continue;
|
3784
|
+
if (h[ii-1] < h[ii] && !(rsmi & SE_CALC_RISE))
|
3785
|
+
continue;
|
3786
|
+
if (h[ii-1] > h[ii] && !(rsmi & SE_CALC_SET))
|
3787
|
+
continue;
|
3788
|
+
dc[0] = h[ii-1];
|
3789
|
+
dc[1] = h[ii];
|
3790
|
+
t2[0] = tc[ii-1];
|
3791
|
+
t2[1] = tc[ii];
|
3792
|
+
for (i = 0; i < 20; i++) {
|
3793
|
+
t = (t2[0] + t2[1]) / 2;
|
3794
|
+
if (!do_fixstar) {
|
3795
|
+
te = t + swe_deltat(t);
|
3796
|
+
if (swe_calc(te, ipl, iflag, xc, serr) == ERR)
|
3797
|
+
return ERR;
|
3798
|
+
}
|
3799
|
+
curdist = xc[2];
|
3800
|
+
if ( rsmi & SE_BIT_FIXED_DISC_SIZE )
|
3801
|
+
{
|
3802
|
+
if ( ipl == SE_SUN )
|
3803
|
+
{
|
3804
|
+
curdist = 1.0;
|
3805
|
+
}
|
3806
|
+
else if ( ipl == SE_MOON )
|
3807
|
+
{
|
3808
|
+
curdist = 0.00257;
|
3809
|
+
}
|
3810
|
+
}
|
3811
|
+
/* apparent radius of disc */
|
3812
|
+
rdi = asin( dd / 2 / AUNIT / curdist ) * RADTODEG;
|
3813
|
+
/* twilight calculation: */
|
3814
|
+
if (do_calc_twilight)
|
3815
|
+
rdi = rdi_twilight(rsmi);
|
3816
|
+
/* true height of center of body */
|
3817
|
+
swe_azalt(t, SE_EQU2HOR, geopos, atpress, attemp, xc, ah);
|
3818
|
+
if ( rsmi & SE_BIT_DISC_BOTTOM )
|
3819
|
+
{
|
3820
|
+
/* true height of bottom point of body */
|
3821
|
+
ah[1] -= rdi;
|
3822
|
+
}
|
3823
|
+
else
|
3824
|
+
{
|
3825
|
+
/* true height of uppermost point of body */
|
3826
|
+
ah[1] += rdi;
|
3827
|
+
}
|
3828
|
+
/* apparent height of uppermost point of body */
|
3829
|
+
if (rsmi & SE_BIT_NO_REFRACTION) {
|
3830
|
+
aha = ah[1];
|
3831
|
+
} else {
|
3832
|
+
swe_azalt_rev(t, SE_HOR2EQU, geopos, ah, xc);
|
3833
|
+
swe_azalt(t, SE_EQU2HOR, geopos, atpress, attemp, xc, ah);
|
3834
|
+
aha = ah[2];
|
3835
|
+
}
|
3836
|
+
if (aha * dc[0] <= 0) {
|
3837
|
+
dc[1] = aha;
|
3838
|
+
t2[1] = t;
|
3839
|
+
} else {
|
3840
|
+
dc[0] = aha;
|
3841
|
+
t2[0] = t;
|
3842
|
+
}
|
3843
|
+
}
|
3844
|
+
if (t > tjd_ut) {
|
3845
|
+
*tret = t;
|
3846
|
+
return OK;
|
3847
|
+
}
|
3848
|
+
}
|
3849
|
+
if (serr)
|
3850
|
+
sprintf(serr, "rise or set not found for planet %d", ipl);
|
3851
|
+
return -2; /* no t of rise or set found */
|
3852
|
+
}
|
3853
|
+
|
3854
|
+
static int32 calc_mer_trans(
|
3855
|
+
double tjd_ut, int32 ipl, int32 epheflag, int32 rsmi,
|
3856
|
+
double *geopos,
|
3857
|
+
char *starname,
|
3858
|
+
double *tret,
|
3859
|
+
char *serr)
|
3860
|
+
{
|
3861
|
+
int i;
|
3862
|
+
double tjd_et = tjd_ut + swe_deltat(tjd_ut);
|
3863
|
+
double armc, armc0, arxc, x0[6], x[6], t, te;
|
3864
|
+
double mdd;
|
3865
|
+
int32 iflag = epheflag;
|
3866
|
+
AS_BOOL do_fixstar = (starname != NULL && *starname != '\0');
|
3867
|
+
iflag &= SEFLG_EPHMASK;
|
3868
|
+
*tret = 0;
|
3869
|
+
iflag |= (SEFLG_EQUATORIAL | SEFLG_TOPOCTR);
|
3870
|
+
armc0 = swe_sidtime(tjd_ut) + geopos[0] / 15;
|
3871
|
+
if (armc0 >= 24)
|
3872
|
+
armc0 -= 24;
|
3873
|
+
if (armc0 < 0)
|
3874
|
+
armc0 += 24;
|
3875
|
+
armc0 *= 15;
|
3876
|
+
if (do_fixstar) {
|
3877
|
+
if (swe_fixstar(starname, tjd_et, iflag, x0, serr) == ERR)
|
3878
|
+
return ERR;
|
3879
|
+
} else {
|
3880
|
+
if (swe_calc(tjd_et, ipl, iflag, x0, serr) == ERR)
|
3881
|
+
return ERR;
|
3882
|
+
}
|
3883
|
+
/*
|
3884
|
+
* meridian transits
|
3885
|
+
*/
|
3886
|
+
x[0] = x0[0];
|
3887
|
+
x[1] = x0[1];
|
3888
|
+
t = tjd_ut;
|
3889
|
+
arxc = armc0;
|
3890
|
+
if (rsmi & SE_CALC_ITRANSIT)
|
3891
|
+
arxc = swe_degnorm(arxc + 180);
|
3892
|
+
for (i = 0; i < 4; i++) {
|
3893
|
+
mdd = swe_degnorm(x[0] - arxc);
|
3894
|
+
if (i > 0 && mdd > 180)
|
3895
|
+
mdd -= 360;
|
3896
|
+
t += mdd / 361;
|
3897
|
+
armc = swe_sidtime(t) + geopos[0] / 15;
|
3898
|
+
if (armc >= 24)
|
3899
|
+
armc -= 24;
|
3900
|
+
if (armc < 0)
|
3901
|
+
armc += 24;
|
3902
|
+
armc *= 15;
|
3903
|
+
arxc = armc;
|
3904
|
+
if (rsmi & SE_CALC_ITRANSIT)
|
3905
|
+
arxc = swe_degnorm(arxc + 180);
|
3906
|
+
if (!do_fixstar) {
|
3907
|
+
te = t + swe_deltat(t);
|
3908
|
+
if (swe_calc(te, ipl, iflag, x, serr) == ERR)
|
3909
|
+
return ERR;
|
3910
|
+
}
|
3911
|
+
}
|
3912
|
+
*tret = t;
|
3913
|
+
return OK;
|
3914
|
+
}
|
3915
|
+
|
3916
|
+
/*
|
3917
|
+
Nodes and apsides of planets and moon
|
3918
|
+
|
3919
|
+
Planetary nodes can be defined in three different ways:
|
3920
|
+
a) They can be understood as a direction or as an axis
|
3921
|
+
defined by the intersection line of two orbital planes.
|
3922
|
+
E.g., the nodes of Mars are defined by the intersection
|
3923
|
+
line of Mars' orbital plane with the ecliptic (= the
|
3924
|
+
Earths orbit heliocentrically or the solar orbit
|
3925
|
+
geocentrically). However, as Michael Erlewine points
|
3926
|
+
out in his elaborate web page on this topic
|
3927
|
+
(http://thenewage.com/resources/articles/interface.html),
|
3928
|
+
planetary nodes can be defined for any couple of
|
3929
|
+
planets. E.g. there is also an intersection line for the
|
3930
|
+
two orbital planes of Mars and Saturn.
|
3931
|
+
Because such lines are, in principle, infinite, the
|
3932
|
+
heliocentric and the geocentric positions of the
|
3933
|
+
planetary nodes will be the same. There are astrologers
|
3934
|
+
that use such heliocentric planetary nodes in geocentric
|
3935
|
+
charts.
|
3936
|
+
The ascending and the descending node will, in this
|
3937
|
+
case, be in precise opposition.
|
3938
|
+
|
3939
|
+
b) The planetary nodes can also be understood in a
|
3940
|
+
different way, not as an axis, but as the two points on a
|
3941
|
+
planetary orbit that are located precisely on the
|
3942
|
+
intersection line of the two planes.
|
3943
|
+
This second definition makes no difference for the moon or
|
3944
|
+
for heliocentric positions of planets, but it does so for
|
3945
|
+
geocentric positions. There are two possibilities for
|
3946
|
+
geocentric planetary nodes based on this definition.
|
3947
|
+
1) The common solution is that the points on the
|
3948
|
+
planets orbit are transformed to the geocenter. The
|
3949
|
+
two points will not be in opposition anymore, or
|
3950
|
+
they will only roughly be so with the outer planets. The
|
3951
|
+
advantage of these nodes is that when a planet is in
|
3952
|
+
conjunction with its node, then its ecliptic latitude
|
3953
|
+
will be zero. This is not true when a planet is in
|
3954
|
+
geocentric conjunction with its heliocentric node.
|
3955
|
+
(And neither is it always true for the inner planets,
|
3956
|
+
i.e. Mercury and Venus.)
|
3957
|
+
2) The second possibility that nobody seems to have
|
3958
|
+
thought of so far: One may compute the points of
|
3959
|
+
the earth's orbit that lie exactly on another planet's
|
3960
|
+
orbital plane and transform it to the geocenter. The two
|
3961
|
+
points will always be in an approximate square.
|
3962
|
+
|
3963
|
+
c) Third, the planetary nodes could be defined as the
|
3964
|
+
intersection points of the plane defined by their
|
3965
|
+
momentary geocentric position and motion with the
|
3966
|
+
plane of the ecliptic. Such points would move very fast
|
3967
|
+
around the planetary stations. Here again, as in b)1),
|
3968
|
+
the planet would cross the ecliptic and its ecliptic
|
3969
|
+
latitude would be 0 exactly when it were in
|
3970
|
+
conjunction with one of its nodes.
|
3971
|
+
|
3972
|
+
The Swiss Ephemeris supports the solutions a) and b) 1).
|
3973
|
+
|
3974
|
+
Possible definitions for apsides
|
3975
|
+
|
3976
|
+
a) The planetary apsides can be defined as the perihelion and
|
3977
|
+
aphelion points on a planetary orbit. For a
|
3978
|
+
geocentric chart, these points could be transformed
|
3979
|
+
from the heliocenter to the geocenter.
|
3980
|
+
b) However, one might consider these points as
|
3981
|
+
astrologically relevant axes rather than as points on a
|
3982
|
+
planetary orbit. Again, this would allow heliocentric
|
3983
|
+
positions in a geocentric chart.
|
3984
|
+
|
3985
|
+
Note: For the "Dark Moon" or "Lilith", which I usually
|
3986
|
+
define as the lunar apogee, some astrologers give a
|
3987
|
+
different definition. They understand it as the second focal
|
3988
|
+
point of the moon's orbital ellipse. This definition does not
|
3989
|
+
make a difference for geocentric positions, because the
|
3990
|
+
apogee and the second focus are in exactly the same geocentric
|
3991
|
+
direction. However, it makes a difference with topocentric
|
3992
|
+
positions, because the two points do not have same distance.
|
3993
|
+
Analogous "black planets" have been proposed: they would be the
|
3994
|
+
second focal points of the planets' orbital ellipses. The
|
3995
|
+
heliocentric positions of these "black planets" are identical
|
3996
|
+
with the heliocentric positions of the aphelia, but geocentric
|
3997
|
+
positions are not identical, because the focal points are
|
3998
|
+
much closer to the sun than the aphelia.
|
3999
|
+
|
4000
|
+
The Swiss Ephemeris allows to compute the "black planets" as well.
|
4001
|
+
|
4002
|
+
Mean positions
|
4003
|
+
|
4004
|
+
Mean nodes and apsides can be computed for the Moon, the
|
4005
|
+
Earth and the planets Mercury - Neptune. They are taken
|
4006
|
+
from the planetary theory VSOP87. Mean points can not be
|
4007
|
+
calculated for Pluto and the asteroids, because there is no
|
4008
|
+
planetary theory for them.
|
4009
|
+
|
4010
|
+
Osculating nodes and apsides
|
4011
|
+
|
4012
|
+
Nodes and apsides can also be derived from the osculating
|
4013
|
+
orbital elements of a body, the paramaters that define an
|
4014
|
+
ideal unperturbed elliptic (two-body) orbit.
|
4015
|
+
For astrology, note that this is a simplification and
|
4016
|
+
idealization.
|
4017
|
+
Problem with Neptune: Neptune's orbit around the sun does not
|
4018
|
+
have much in common with an ellipse. There are often two
|
4019
|
+
perihelia and two aphelia within one revolution. As a result,
|
4020
|
+
there is a wild oscillation of the osculating perihelion (and
|
4021
|
+
aphelion).
|
4022
|
+
In actuality, Neptune's orbit is not heliocentric orbit at all.
|
4023
|
+
The twofold perihelia and aphelia are an effect of the motion of
|
4024
|
+
the sun about the solar system barycenter. This motion is
|
4025
|
+
much faster than the motion of Neptune, and Neptune
|
4026
|
+
cannot react on such fast displacements of the Sun. As a
|
4027
|
+
result, Neptune seems to move around the barycenter (or a
|
4028
|
+
mean sun) rather than around the true sun. In fact,
|
4029
|
+
Neptune's orbit around the barycenter is therefore closer to
|
4030
|
+
an ellipse than the his orbit around the sun. The same
|
4031
|
+
statement is also true for Saturn, Uranus and Pluto, but not
|
4032
|
+
for Jupiter and the inner planets.
|
4033
|
+
|
4034
|
+
This fundamental problem about osculating ellipses of
|
4035
|
+
planetary orbits does of course not only affect the apsides
|
4036
|
+
but also the nodes.
|
4037
|
+
|
4038
|
+
Two solutions can be thought of for this problem:
|
4039
|
+
1) The one would be to interpolate between actual
|
4040
|
+
passages of the planets through their nodes and
|
4041
|
+
apsides. However, this works only well with Mercury.
|
4042
|
+
With all other planets, the supporting points are too far
|
4043
|
+
apart as to make an accurate interpolation possible.
|
4044
|
+
This solution is not implemented, here.
|
4045
|
+
2) The other solution is to compute the apsides of the
|
4046
|
+
orbit around the barycenter rather than around the sun.
|
4047
|
+
This procedure makes sense for planets beyond Jupiter,
|
4048
|
+
it comes closer to the mean apsides and nodes for
|
4049
|
+
planets that have such points defined. For all other
|
4050
|
+
transsaturnian planets and asteroids, this solution yields
|
4051
|
+
a kind of "mean" nodes and apsides. On the other hand,
|
4052
|
+
the barycentric ellipse does not make any sense for
|
4053
|
+
inner planets and Jupiter.
|
4054
|
+
|
4055
|
+
The Swiss Ephemeris supports solution 2) for planets and
|
4056
|
+
asteroids beyond Jupiter.
|
4057
|
+
|
4058
|
+
Anyway, neither the heliocentric nor the barycentric ellipse
|
4059
|
+
is a perfect representation of the nature of a planetary orbit,
|
4060
|
+
and it will not yield the degree of precision that today's
|
4061
|
+
astrology is used to.
|
4062
|
+
The best choice of method will probably be:
|
4063
|
+
- For Mercury - Neptune: mean nodes and apsides
|
4064
|
+
- For asteroids that belong to the inner asteroid belt:
|
4065
|
+
osculating nodes/apsides from a heliocentric ellipse
|
4066
|
+
- For Pluto and outer asteroids: osculating nodes/apsides
|
4067
|
+
from a barycentric ellipse
|
4068
|
+
|
4069
|
+
The Moon is a special case: A "lunar true node" makes
|
4070
|
+
more sense, because it can be defined without the idea of an
|
4071
|
+
ellipse, e.g. as the intersection axis of the momentary lunar
|
4072
|
+
orbital plane with the ecliptic. Or it can be said that the
|
4073
|
+
momentary motion of the moon points to one of the two
|
4074
|
+
ecliptic points that are called the "true nodes". So, these
|
4075
|
+
points make sense. With planetary nodes, the situation is
|
4076
|
+
somewhat different, at least if we make a difference
|
4077
|
+
between heliocentric and geocentric positions. If so, the
|
4078
|
+
planetary nodes are points on a heliocentric orbital ellipse,
|
4079
|
+
which are transformed to the geocenter. An ellipse is
|
4080
|
+
required here, because a solar distance is required. In
|
4081
|
+
contrast to the planetary nodes, the lunar node does not
|
4082
|
+
require a distance, therefore manages without the idea of an
|
4083
|
+
ellipse and does not share its weaknesses.
|
4084
|
+
On the other hand, the lunar apsides DO require the idea of
|
4085
|
+
an ellipse. And because the lunar ellipse is actually
|
4086
|
+
extremely distorted, even more than any other celestial
|
4087
|
+
ellipse, the "true Lilith" (apogee), for which printed
|
4088
|
+
ephemerides are available, does not make any sense at all.
|
4089
|
+
(See the chapter on the lunar node and apogee.)
|
4090
|
+
|
4091
|
+
Special case: the Earth
|
4092
|
+
|
4093
|
+
The Earth is another special case. Instead of the motion of
|
4094
|
+
the Earth herself, the heliocentric motion of the Earth-
|
4095
|
+
Moon-Barycenter (EMB) is used to determine the
|
4096
|
+
osculating perihelion.
|
4097
|
+
There is no node of the earth orbit itself. However, there is
|
4098
|
+
an axis around which the earth's orbital plane slowly rotates
|
4099
|
+
due to planetary precession. The position points of this axis
|
4100
|
+
are not calculated by the Swiss Ephemeris.
|
4101
|
+
|
4102
|
+
Special case: the Sun
|
4103
|
+
|
4104
|
+
In addition to the Earth (EMB) apsides, the function
|
4105
|
+
computes so-to-say "apsides" of the sun, i.e. points on the
|
4106
|
+
orbit of the Sun where it is closest to and where it is farthest
|
4107
|
+
from the Earth. These points form an opposition and are
|
4108
|
+
used by some astrologers, e.g. by the Dutch astrologer
|
4109
|
+
George Bode or the Swiss astrologer Liduina Schmed. The
|
4110
|
+
perigee, located at about 13 Capricorn, is called the
|
4111
|
+
"Black Sun", the other one, in Cancer, the "Diamond".
|
4112
|
+
So, for a complete set of apsides, one ought to calculate
|
4113
|
+
them for the Sun and the Earth and all other planets.
|
4114
|
+
|
4115
|
+
The modes of the Swiss Ephemeris function
|
4116
|
+
swe_nod_aps()
|
4117
|
+
|
4118
|
+
The function swe_nod_aps() can be run in the following
|
4119
|
+
modes:
|
4120
|
+
1) Mean positions are given for nodes and apsides of Sun,
|
4121
|
+
Moon, Earth, and the up to Neptune. Osculating
|
4122
|
+
positions are given with Pluto and all asteroids. This is
|
4123
|
+
the default mode.
|
4124
|
+
2) Osculating positions are returned for nodes and apsides
|
4125
|
+
of all planets.
|
4126
|
+
3) Same as 2), but for planets and asteroids beyond
|
4127
|
+
Jupiter, a barycentric ellipse is used.
|
4128
|
+
4) Same as 1), but for Pluto and asteroids beyond Jupiter,
|
4129
|
+
a barycentric ellipse is used.
|
4130
|
+
|
4131
|
+
In all of these modes, the second focal point of the ellipse
|
4132
|
+
can be computed instead of the aphelion.
|
4133
|
+
Like the planetary function swe_calc(), swe_nod_aps() is
|
4134
|
+
able to return geocentric, topocentric, heliocentric, or
|
4135
|
+
barycentric position.
|
4136
|
+
*
|
4137
|
+
* tjd_ut julian day, ephemeris time
|
4138
|
+
* ipl planet number
|
4139
|
+
* iflag as usual, SEFLG_HELCTR, etc.
|
4140
|
+
* xnasc an array of 6 doubles: ascending node
|
4141
|
+
* xndsc an array of 6 doubles: ascending node
|
4142
|
+
* xperi an array of 6 doubles: perihelion
|
4143
|
+
* xaphe an array of 6 doubles: aphelion
|
4144
|
+
* method see below
|
4145
|
+
* serr error message
|
4146
|
+
*
|
4147
|
+
* method can have the following values:
|
4148
|
+
* - 0 or SE_NODBIT_MEAN. MEAN positions are given for
|
4149
|
+
* nodes and apsides of Sun, Moon, Earth, and the
|
4150
|
+
* planets up to Neptune. Osculating positions are
|
4151
|
+
* given with Pluto and all asteroids.
|
4152
|
+
* - SE_NODBIT_OSCU. Osculating positions are given
|
4153
|
+
* for all nodes and apsides.
|
4154
|
+
* - SE_NODBIT_OSCU_BAR. Osculating nodes and apsides
|
4155
|
+
* are computed from barycentric ellipses, for planets
|
4156
|
+
* beyond Jupiter, but from heliocentric ones for
|
4157
|
+
* ones for Jupiter and inner planets.
|
4158
|
+
* - SE_NODBIT_MEAN and SE_NODBIT_OSCU_BAR can be combined.
|
4159
|
+
* The program behaves the same way as with simple
|
4160
|
+
* SE_NODBIT_MEAN, but uses barycentric ellipses for
|
4161
|
+
* planets beyond Neptune and asteroids beyond Jupiter.
|
4162
|
+
* - SE_NODBIT_FOCAL can be combined with any of the other
|
4163
|
+
* bits. The second focal points of the ellipses will
|
4164
|
+
* be returned instead of the aphelia.
|
4165
|
+
*/
|
4166
|
+
/* mean elements for Mercury - Neptune from VSOP87 (mean equinox of date) */
|
4167
|
+
static double el_node[8][4] =
|
4168
|
+
{{ 48.330893, 1.1861890, 0.00017587, 0.000000211,}, /* Mercury */
|
4169
|
+
{ 76.679920, 0.9011190, 0.00040665, -0.000000080,}, /* Venus */
|
4170
|
+
{ 0 , 0 , 0 , 0 ,}, /* Earth */
|
4171
|
+
{ 49.558093, 0.7720923, 0.00001605, 0.000002325,}, /* Mars */
|
4172
|
+
{100.464441, 1.0209550, 0.00040117, 0.000000569,}, /* Jupiter */
|
4173
|
+
{113.665524, 0.8770970, -0.00012067, -0.000002380,}, /* Saturn */
|
4174
|
+
{ 74.005947, 0.5211258, 0.00133982, 0.000018516,}, /* Uranus */
|
4175
|
+
{131.784057, 1.1022057, 0.00026006, -0.000000636,}, /* Neptune */
|
4176
|
+
};
|
4177
|
+
static double el_peri[8][4] =
|
4178
|
+
{{ 77.456119, 1.5564775, 0.00029589, 0.000000056,}, /* Mercury */
|
4179
|
+
{131.563707, 1.4022188, -0.00107337, -0.000005315,}, /* Venus */
|
4180
|
+
{102.937348, 1.7195269, 0.00045962, 0.000000499,}, /* Earth */
|
4181
|
+
{336.060234, 1.8410331, 0.00013515, 0.000000318,}, /* Mars */
|
4182
|
+
{ 14.331309, 1.6126668, 0.00103127, -0.000004569,}, /* Jupiter */
|
4183
|
+
{ 93.056787, 1.9637694, 0.00083757, 0.000004899,}, /* Saturn */
|
4184
|
+
{173.005159, 1.4863784, 0.00021450, 0.000000433,}, /* Uranus */
|
4185
|
+
{ 48.123691, 1.4262677, 0.00037918, -0.000000003,}, /* Neptune */
|
4186
|
+
};
|
4187
|
+
static double el_incl[8][4] =
|
4188
|
+
{{ 7.004986, 0.0018215, -0.00001809, 0.000000053,}, /* Mercury */
|
4189
|
+
{ 3.394662, 0.0010037, -0.00000088, -0.000000007,}, /* Venus */
|
4190
|
+
{ 0, 0, 0, 0 ,}, /* Earth */
|
4191
|
+
{ 1.849726, -0.0006010, 0.00001276, -0.000000006,}, /* Mars */
|
4192
|
+
{ 1.303270, -0.0054966, 0.00000465, -0.000000004,}, /* Jupiter */
|
4193
|
+
{ 2.488878, -0.0037363, -0.00001516, 0.000000089,}, /* Saturn */
|
4194
|
+
{ 0.773196, 0.0007744, 0.00003749, -0.000000092,}, /* Uranus */
|
4195
|
+
{ 1.769952, -0.0093082, -0.00000708, 0.000000028,}, /* Neptune */
|
4196
|
+
};
|
4197
|
+
static double el_ecce[8][4] =
|
4198
|
+
{{ 0.20563175, 0.000020406, -0.0000000284, -0.00000000017,}, /* Mercury */
|
4199
|
+
{ 0.00677188, -0.000047766, 0.0000000975, 0.00000000044,}, /* Venus */
|
4200
|
+
{ 0.01670862, -0.000042037, -0.0000001236, 0.00000000004,}, /* Earth */
|
4201
|
+
{ 0.09340062, 0.000090483, -0.0000000806, -0.00000000035,}, /* Mars */
|
4202
|
+
{ 0.04849485, 0.000163244, -0.0000004719, -0.00000000197,}, /* Jupiter */
|
4203
|
+
{ 0.05550862, -0.000346818, -0.0000006456, 0.00000000338,}, /* Saturn */
|
4204
|
+
{ 0.04629590, -0.000027337, 0.0000000790, 0.00000000025,}, /* Uranus */
|
4205
|
+
{ 0.00898809, 0.000006408, -0.0000000008, -0.00000000005,}, /* Neptune */
|
4206
|
+
};
|
4207
|
+
static double el_sema[8][4] =
|
4208
|
+
{{ 0.387098310, 0.0, 0.0, 0.0,}, /* Mercury */
|
4209
|
+
{ 0.723329820, 0.0, 0.0, 0.0,}, /* Venus */
|
4210
|
+
{ 1.000001018, 0.0, 0.0, 0.0,}, /* Earth */
|
4211
|
+
{ 1.523679342, 0.0, 0.0, 0.0,}, /* Mars */
|
4212
|
+
{ 5.202603191, 0.0000001913, 0.0, 0.0,}, /* Jupiter */
|
4213
|
+
{ 9.554909596, 0.0000021389, 0.0, 0.0,}, /* Saturn */
|
4214
|
+
{ 19.218446062, -0.0000000372, 0.00000000098, 0.0,}, /* Uranus */
|
4215
|
+
{ 30.110386869, -0.0000001663, 0.00000000069, 0.0,}, /* Neptune */
|
4216
|
+
};
|
4217
|
+
/* Ratios of mass of Sun to masses of the planets */
|
4218
|
+
static double plmass[9] = {
|
4219
|
+
6023600, /* Mercury */
|
4220
|
+
408523.5, /* Venus */
|
4221
|
+
328900.5, /* Earth and Moon */
|
4222
|
+
3098710, /* Mars */
|
4223
|
+
1047.350, /* Jupiter */
|
4224
|
+
3498.0, /* Saturn */
|
4225
|
+
22960, /* Uranus */
|
4226
|
+
19314, /* Neptune */
|
4227
|
+
130000000, /* Pluto */
|
4228
|
+
};
|
4229
|
+
static int ipl_to_elem[15] = {2, 0, 0, 1, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 2,};
|
4230
|
+
int32 FAR PASCAL_CONV swe_nod_aps(double tjd_et, int32 ipl, int32 iflag,
|
4231
|
+
int32 method,
|
4232
|
+
double *xnasc, double *xndsc,
|
4233
|
+
double *xperi, double *xaphe,
|
4234
|
+
char *serr)
|
4235
|
+
{
|
4236
|
+
int ij, i, j;
|
4237
|
+
int32 iplx;
|
4238
|
+
int32 ipli;
|
4239
|
+
int istart, iend;
|
4240
|
+
int32 iflJ2000;
|
4241
|
+
double plm;
|
4242
|
+
double t = (tjd_et - J2000) / 36525, dt;
|
4243
|
+
double x[6], xx[24], *xp, xobs[6], x2000[6];
|
4244
|
+
double xpos[3][6], xnorm[6];
|
4245
|
+
double xposm[6];
|
4246
|
+
double xn[3][6], xs[3][6];
|
4247
|
+
double xq[3][6], xa[3][6];
|
4248
|
+
double xobs2[6], x2[6];
|
4249
|
+
double *xna, *xnd, *xpe, *xap;
|
4250
|
+
double incl, sema, ecce, parg, ea, vincl, vsema, vecce, pargx, eax;
|
4251
|
+
struct plan_data *pedp = &swed.pldat[SEI_EARTH];
|
4252
|
+
struct plan_data *psbdp = &swed.pldat[SEI_SUNBARY];
|
4253
|
+
struct plan_data pldat;
|
4254
|
+
double *xsun = psbdp->x;
|
4255
|
+
double *xear = pedp->x;
|
4256
|
+
double *ep;
|
4257
|
+
double Gmsm, dzmin;
|
4258
|
+
double rxy, rxyz, fac, sgn;
|
4259
|
+
double sinnode, cosnode, sinincl, cosincl, sinu, cosu, sinE, cosE, cosE2;
|
4260
|
+
double uu, ny, ny2, c2, v2, pp, ro, ro2, rn, rn2;
|
4261
|
+
struct epsilon *oe;
|
4262
|
+
AS_BOOL is_true_nodaps = FALSE;
|
4263
|
+
AS_BOOL do_aberr = !(iflag & (SEFLG_TRUEPOS | SEFLG_NOABERR));
|
4264
|
+
AS_BOOL do_defl = !(iflag & SEFLG_TRUEPOS) && !(iflag & SEFLG_NOGDEFL);
|
4265
|
+
AS_BOOL do_focal_point = method & SE_NODBIT_FOPOINT;
|
4266
|
+
AS_BOOL ellipse_is_bary = FALSE;
|
4267
|
+
int32 iflg0;
|
4268
|
+
/* function calls for Pluto with asteroid number 134340
|
4269
|
+
* are treated as calls for Pluto as main body SE_PLUTO */
|
4270
|
+
if (ipl == SE_AST_OFFSET + 134340)
|
4271
|
+
ipl = SE_PLUTO;
|
4272
|
+
xna = xx;
|
4273
|
+
xnd = xx+6;
|
4274
|
+
xpe = xx+12;
|
4275
|
+
xap = xx+18;
|
4276
|
+
xpos[0][0] = 0; /* to shut up mint */
|
4277
|
+
/* to get control over the save area: */
|
4278
|
+
swi_force_app_pos_etc();
|
4279
|
+
method %= SE_NODBIT_FOPOINT;
|
4280
|
+
ipli = ipl;
|
4281
|
+
if (ipl == SE_SUN)
|
4282
|
+
ipli = SE_EARTH;
|
4283
|
+
if (ipl == SE_MOON) {
|
4284
|
+
do_defl = FALSE;
|
4285
|
+
if (!(iflag & SEFLG_HELCTR))
|
4286
|
+
do_aberr = FALSE;
|
4287
|
+
}
|
4288
|
+
iflg0 = (iflag & (SEFLG_EPHMASK|SEFLG_NONUT)) | SEFLG_SPEED | SEFLG_TRUEPOS;
|
4289
|
+
if (ipli != SE_MOON)
|
4290
|
+
iflg0 |= SEFLG_HELCTR;
|
4291
|
+
if (ipl == SE_MEAN_NODE || ipl == SE_TRUE_NODE ||
|
4292
|
+
ipl == SE_MEAN_APOG || ipl == SE_OSCU_APOG ||
|
4293
|
+
ipl < 0 ||
|
4294
|
+
(ipl >= SE_NPLANETS && ipl <= SE_AST_OFFSET)) {
|
4295
|
+
/*(ipl >= SE_FICT_OFFSET && ipl - SE_FICT_OFFSET < SE_NFICT_ELEM)) */
|
4296
|
+
if (serr != NULL)
|
4297
|
+
sprintf(serr, "nodes/apsides for planet %5.0f are not implemented", (double) ipl);
|
4298
|
+
if (xnasc != NULL)
|
4299
|
+
for (i = 0; i <= 5; i++)
|
4300
|
+
xnasc[i] = 0;
|
4301
|
+
if (xndsc != NULL)
|
4302
|
+
for (i = 0; i <= 5; i++)
|
4303
|
+
xndsc[i] = 0;
|
4304
|
+
if (xaphe != NULL)
|
4305
|
+
for (i = 0; i <= 5; i++)
|
4306
|
+
xaphe[i] = 0;
|
4307
|
+
if (xperi != NULL)
|
4308
|
+
for (i = 0; i <= 5; i++)
|
4309
|
+
xperi[i] = 0;
|
4310
|
+
return ERR;
|
4311
|
+
}
|
4312
|
+
for (i = 0; i < 24; i++)
|
4313
|
+
xx[i] = 0;
|
4314
|
+
/***************************************
|
4315
|
+
* mean nodes and apsides
|
4316
|
+
***************************************/
|
4317
|
+
/* mean points only for Sun - Neptune */
|
4318
|
+
if ((method == 0 || (method & SE_NODBIT_MEAN)) &&
|
4319
|
+
((ipl >= SE_SUN && ipl <= SE_NEPTUNE) || ipl == SE_EARTH)) {
|
4320
|
+
if (ipl == SE_MOON) {
|
4321
|
+
swi_mean_lunar_elements(tjd_et, &xna[0], &xna[3], &xpe[0], &xpe[3]);
|
4322
|
+
incl = MOON_MEAN_INCL;
|
4323
|
+
vincl = 0;
|
4324
|
+
ecce = MOON_MEAN_ECC;
|
4325
|
+
vecce = 0;
|
4326
|
+
sema = MOON_MEAN_DIST / AUNIT;
|
4327
|
+
vsema = 0;
|
4328
|
+
} else {
|
4329
|
+
iplx = ipl_to_elem[ipl];
|
4330
|
+
ep = el_incl[iplx];
|
4331
|
+
incl = ep[0] + ep[1] * t + ep[2] * t * t + ep[3] * t * t * t;
|
4332
|
+
vincl = ep[1] / 36525;
|
4333
|
+
ep = el_sema[iplx];
|
4334
|
+
sema = ep[0] + ep[1] * t + ep[2] * t * t + ep[3] * t * t * t;
|
4335
|
+
vsema = ep[1] / 36525;
|
4336
|
+
ep = el_ecce[iplx];
|
4337
|
+
ecce = ep[0] + ep[1] * t + ep[2] * t * t + ep[3] * t * t * t;
|
4338
|
+
vecce = ep[1] / 36525;
|
4339
|
+
ep = el_node[iplx];
|
4340
|
+
/* ascending node */
|
4341
|
+
xna[0] = ep[0] + ep[1] * t + ep[2] * t * t + ep[3] * t * t * t;
|
4342
|
+
xna[3] = ep[1] / 36525;
|
4343
|
+
/* perihelion */
|
4344
|
+
ep = el_peri[iplx];
|
4345
|
+
xpe[0] = ep[0] + ep[1] * t + ep[2] * t * t + ep[3] * t * t * t;
|
4346
|
+
xpe[3] = ep[1] / 36525;
|
4347
|
+
}
|
4348
|
+
/* descending node */
|
4349
|
+
xnd[0] = swe_degnorm(xna[0] + 180);
|
4350
|
+
xnd[3] = xna[3];
|
4351
|
+
/* angular distance of perihelion from node */
|
4352
|
+
parg = xpe[0] = swe_degnorm(xpe[0] - xna[0]);
|
4353
|
+
pargx = xpe[3] = swe_degnorm(xpe[0] + xpe[3] - xna[3]);
|
4354
|
+
/* transform from orbital plane to mean ecliptic of date */
|
4355
|
+
swe_cotrans(xpe, xpe, -incl);
|
4356
|
+
/* xpe+3 is aux. position, not speed!!! */
|
4357
|
+
swe_cotrans(xpe+3, xpe+3, -incl-vincl);
|
4358
|
+
/* add node again */
|
4359
|
+
xpe[0] = swe_degnorm(xpe[0] + xna[0]);
|
4360
|
+
/* xpe+3 is aux. position, not speed!!! */
|
4361
|
+
xpe[3] = swe_degnorm(xpe[3] + xna[0] + xna[3]);
|
4362
|
+
/* speed */
|
4363
|
+
xpe[3] = swe_degnorm(xpe[3] - xpe[0]);
|
4364
|
+
/* heliocentric distance of perihelion and aphelion */
|
4365
|
+
xpe[2] = sema * (1 - ecce);
|
4366
|
+
xpe[5] = (sema + vsema) * (1 - ecce - vecce) - xpe[2];
|
4367
|
+
/* aphelion */
|
4368
|
+
xap[0] = swe_degnorm(xpe[0] + 180);
|
4369
|
+
xap[1] = -xpe[1];
|
4370
|
+
xap[3] = xpe[3];
|
4371
|
+
xap[4] = -xpe[4];
|
4372
|
+
if (do_focal_point) {
|
4373
|
+
xap[2] = sema * ecce * 2;
|
4374
|
+
xap[5] = (sema + vsema) * (ecce + vecce) * 2 - xap[2];
|
4375
|
+
} else {
|
4376
|
+
xap[2] = sema * (1 + ecce);
|
4377
|
+
xap[5] = (sema + vsema) * (1 + ecce + vecce) - xap[2];
|
4378
|
+
}
|
4379
|
+
/* heliocentric distance of nodes */
|
4380
|
+
ea = atan(tan(-parg * DEGTORAD / 2) * sqrt((1-ecce)/(1+ecce))) * 2;
|
4381
|
+
eax = atan(tan(-pargx * DEGTORAD / 2) * sqrt((1-ecce-vecce)/(1+ecce+vecce))) * 2;
|
4382
|
+
xna[2] = sema * (cos(ea) - ecce) / cos(parg * DEGTORAD);
|
4383
|
+
xna[5] = (sema+vsema) * (cos(eax) - ecce - vecce) / cos(pargx * DEGTORAD);
|
4384
|
+
xna[5] -= xna[2];
|
4385
|
+
ea = atan(tan((180 - parg) * DEGTORAD / 2) * sqrt((1-ecce)/(1+ecce))) * 2;
|
4386
|
+
eax = atan(tan((180 - pargx) * DEGTORAD / 2) * sqrt((1-ecce-vecce)/(1+ecce+vecce))) * 2;
|
4387
|
+
xnd[2] = sema * (cos(ea) - ecce) / cos((180 - parg) * DEGTORAD);
|
4388
|
+
xnd[5] = (sema+vsema) * (cos(eax) - ecce - vecce) / cos((180 - pargx) * DEGTORAD);
|
4389
|
+
xnd[5] -= xnd[2];
|
4390
|
+
/* no light-time correction because speed is extremely small */
|
4391
|
+
for (i = 0, xp = xx; i < 4; i++, xp += 6) {
|
4392
|
+
/* to cartesian coordinates */
|
4393
|
+
xp[0] *= DEGTORAD;
|
4394
|
+
xp[1] *= DEGTORAD;
|
4395
|
+
xp[3] *= DEGTORAD;
|
4396
|
+
xp[4] *= DEGTORAD;
|
4397
|
+
swi_polcart_sp(xp, xp);
|
4398
|
+
}
|
4399
|
+
/***************************************
|
4400
|
+
* "true" or osculating nodes and apsides
|
4401
|
+
***************************************/
|
4402
|
+
} else {
|
4403
|
+
/* first, we need a heliocentric distance of the planet */
|
4404
|
+
if (swe_calc(tjd_et, ipli, iflg0, x, serr) == ERR)
|
4405
|
+
return ERR;
|
4406
|
+
iflJ2000 = (iflag & SEFLG_EPHMASK)|SEFLG_J2000|SEFLG_EQUATORIAL|SEFLG_XYZ|SEFLG_TRUEPOS|SEFLG_NONUT|SEFLG_SPEED;
|
4407
|
+
ellipse_is_bary = FALSE;
|
4408
|
+
if (ipli != SE_MOON) {
|
4409
|
+
if ((method & SE_NODBIT_OSCU_BAR) && x[2] > 6) {
|
4410
|
+
iflJ2000 |= SEFLG_BARYCTR; /* only planets beyond Jupiter */
|
4411
|
+
ellipse_is_bary = TRUE;
|
4412
|
+
} else {
|
4413
|
+
iflJ2000 |= SEFLG_HELCTR;
|
4414
|
+
}
|
4415
|
+
}
|
4416
|
+
/* we need three positions and three speeds
|
4417
|
+
* for three nodes/apsides. from the three node positions,
|
4418
|
+
* the speed of the node will be computed. */
|
4419
|
+
if (ipli == SE_MOON) {
|
4420
|
+
dt = NODE_CALC_INTV;
|
4421
|
+
dzmin = 1e-15;
|
4422
|
+
Gmsm = GEOGCONST * (1 + 1 / EARTH_MOON_MRAT) /AUNIT/AUNIT/AUNIT*86400.0*86400.0;
|
4423
|
+
} else {
|
4424
|
+
if ((ipli >= SE_MERCURY && ipli <= SE_PLUTO) || ipli == SE_EARTH)
|
4425
|
+
plm = 1 / plmass[ipl_to_elem[ipl]];
|
4426
|
+
else
|
4427
|
+
plm = 0;
|
4428
|
+
dt = NODE_CALC_INTV * 10 * x[2];
|
4429
|
+
dzmin = 1e-15 * dt / NODE_CALC_INTV;
|
4430
|
+
Gmsm = HELGRAVCONST * (1 + plm) /AUNIT/AUNIT/AUNIT*86400.0*86400.0;
|
4431
|
+
}
|
4432
|
+
if (iflag & SEFLG_SPEED) {
|
4433
|
+
istart = 0;
|
4434
|
+
iend = 2;
|
4435
|
+
} else {
|
4436
|
+
istart = iend = 0;
|
4437
|
+
dt = 0;
|
4438
|
+
}
|
4439
|
+
for (i = istart, t = tjd_et - dt; i <= iend; i++, t += dt) {
|
4440
|
+
if (istart == iend)
|
4441
|
+
t = tjd_et;
|
4442
|
+
if (swe_calc(t, ipli, iflJ2000, xpos[i], serr) == ERR)
|
4443
|
+
return ERR;
|
4444
|
+
/* the EMB is used instead of the earth */
|
4445
|
+
if (ipli == SE_EARTH) {
|
4446
|
+
if (swe_calc(t, SE_MOON, iflJ2000 & ~(SEFLG_BARYCTR|SEFLG_HELCTR), xposm, serr) == ERR)
|
4447
|
+
return ERR;
|
4448
|
+
for (j = 0; j <= 2; j++)
|
4449
|
+
xpos[i][j] += xposm[j] / (EARTH_MOON_MRAT + 1.0);
|
4450
|
+
}
|
4451
|
+
swi_plan_for_osc_elem(iflg0, t, xpos[i]);
|
4452
|
+
}
|
4453
|
+
for (i = istart; i <= iend; i++) {
|
4454
|
+
if (fabs(xpos[i][5]) < dzmin)
|
4455
|
+
xpos[i][5] = dzmin;
|
4456
|
+
fac = xpos[i][2] / xpos[i][5];
|
4457
|
+
sgn = xpos[i][5] / fabs(xpos[i][5]);
|
4458
|
+
for (j = 0; j <= 2; j++) {
|
4459
|
+
xn[i][j] = (xpos[i][j] - fac * xpos[i][j+3]) * sgn;
|
4460
|
+
xs[i][j] = -xn[i][j];
|
4461
|
+
}
|
4462
|
+
}
|
4463
|
+
for (i = istart; i <= iend; i++) {
|
4464
|
+
/* node */
|
4465
|
+
rxy = sqrt(xn[i][0] * xn[i][0] + xn[i][1] * xn[i][1]);
|
4466
|
+
cosnode = xn[i][0] / rxy;
|
4467
|
+
sinnode = xn[i][1] / rxy;
|
4468
|
+
/* inclination */
|
4469
|
+
swi_cross_prod(xpos[i], xpos[i]+3, xnorm);
|
4470
|
+
rxy = xnorm[0] * xnorm[0] + xnorm[1] * xnorm[1];
|
4471
|
+
c2 = (rxy + xnorm[2] * xnorm[2]);
|
4472
|
+
rxyz = sqrt(c2);
|
4473
|
+
rxy = sqrt(rxy);
|
4474
|
+
sinincl = rxy / rxyz;
|
4475
|
+
cosincl = sqrt(1 - sinincl * sinincl);
|
4476
|
+
if (xnorm[2] < 0) cosincl = -cosincl; /* retrograde asteroid, e.g. 20461 Dioretsa */
|
4477
|
+
/* argument of latitude */
|
4478
|
+
cosu = xpos[i][0] * cosnode + xpos[i][1] * sinnode;
|
4479
|
+
sinu = xpos[i][2] / sinincl;
|
4480
|
+
uu = atan2(sinu, cosu);
|
4481
|
+
/* semi-axis */
|
4482
|
+
rxyz = sqrt(square_sum(xpos[i]));
|
4483
|
+
v2 = square_sum((xpos[i]+3));
|
4484
|
+
sema = 1 / (2 / rxyz - v2 / Gmsm);
|
4485
|
+
/* eccentricity */
|
4486
|
+
pp = c2 / Gmsm;
|
4487
|
+
ecce = sqrt(1 - pp / sema);
|
4488
|
+
/* eccentric anomaly */
|
4489
|
+
cosE = 1 / ecce * (1 - rxyz / sema);
|
4490
|
+
sinE = 1 / ecce / sqrt(sema * Gmsm) * dot_prod(xpos[i], (xpos[i]+3));
|
4491
|
+
/* true anomaly */
|
4492
|
+
ny = 2 * atan(sqrt((1+ecce)/(1-ecce)) * sinE / (1 + cosE));
|
4493
|
+
/* distance of perihelion from ascending node */
|
4494
|
+
xq[i][0] = swi_mod2PI(uu - ny);
|
4495
|
+
xq[i][1] = 0; /* latitude */
|
4496
|
+
xq[i][2] = sema * (1 - ecce); /* distance of perihelion */
|
4497
|
+
/* transformation to ecliptic coordinates */
|
4498
|
+
swi_polcart(xq[i], xq[i]);
|
4499
|
+
swi_coortrf2(xq[i], xq[i], -sinincl, cosincl);
|
4500
|
+
swi_cartpol(xq[i], xq[i]);
|
4501
|
+
/* adding node, we get perihelion in ecl. coord. */
|
4502
|
+
xq[i][0] += atan2(sinnode, cosnode);
|
4503
|
+
xa[i][0] = swi_mod2PI(xq[i][0] + PI);
|
4504
|
+
xa[i][1] = -xq[i][1];
|
4505
|
+
if (do_focal_point) {
|
4506
|
+
xa[i][2] = sema * ecce * 2; /* distance of aphelion */
|
4507
|
+
} else {
|
4508
|
+
xa[i][2] = sema * (1 + ecce); /* distance of aphelion */
|
4509
|
+
}
|
4510
|
+
swi_polcart(xq[i], xq[i]);
|
4511
|
+
swi_polcart(xa[i], xa[i]);
|
4512
|
+
/* new distance of node from orbital ellipse:
|
4513
|
+
* true anomaly of node: */
|
4514
|
+
ny = swi_mod2PI(ny - uu);
|
4515
|
+
ny2 = swi_mod2PI(ny + PI);
|
4516
|
+
/* eccentric anomaly */
|
4517
|
+
cosE = cos(2 * atan(tan(ny / 2) / sqrt((1+ecce) / (1-ecce))));
|
4518
|
+
cosE2 = cos(2 * atan(tan(ny2 / 2) / sqrt((1+ecce) / (1-ecce))));
|
4519
|
+
/* new distance */
|
4520
|
+
rn = sema * (1 - ecce * cosE);
|
4521
|
+
rn2 = sema * (1 - ecce * cosE2);
|
4522
|
+
/* old node distance */
|
4523
|
+
ro = sqrt(square_sum(xn[i]));
|
4524
|
+
ro2 = sqrt(square_sum(xs[i]));
|
4525
|
+
/* correct length of position vector */
|
4526
|
+
for (j = 0; j <= 2; j++) {
|
4527
|
+
xn[i][j] *= rn / ro;
|
4528
|
+
xs[i][j] *= rn2 / ro2;
|
4529
|
+
}
|
4530
|
+
}
|
4531
|
+
for (i = 0; i <= 2; i++) {
|
4532
|
+
if (iflag & SEFLG_SPEED) {
|
4533
|
+
xpe[i] = xq[1][i];
|
4534
|
+
xpe[i+3] = (xq[2][i] - xq[0][i]) / dt / 2;
|
4535
|
+
xap[i] = xa[1][i];
|
4536
|
+
xap[i+3] = (xa[2][i] - xa[0][i]) / dt / 2;
|
4537
|
+
xna[i] = xn[1][i];
|
4538
|
+
xna[i+3] = (xn[2][i] - xn[0][i]) / dt / 2;
|
4539
|
+
xnd[i] = xs[1][i];
|
4540
|
+
xnd[i+3] = (xs[2][i] - xs[0][i]) / dt / 2;
|
4541
|
+
} else {
|
4542
|
+
xpe[i] = xq[0][i];
|
4543
|
+
xpe[i+3] = 0;
|
4544
|
+
xap[i] = xa[0][i];
|
4545
|
+
xap[i+3] = 0;
|
4546
|
+
xna[i] = xn[0][i];
|
4547
|
+
xna[i+3] = 0;
|
4548
|
+
xnd[i] = xs[0][i];
|
4549
|
+
xnd[i+3] = 0;
|
4550
|
+
}
|
4551
|
+
}
|
4552
|
+
is_true_nodaps = TRUE;
|
4553
|
+
}
|
4554
|
+
/* to set the variables required in the save area,
|
4555
|
+
* i.e. ecliptic, nutation, barycentric sun, earth
|
4556
|
+
* we compute the planet */
|
4557
|
+
if (ipli == SE_MOON && (iflag & (SEFLG_HELCTR | SEFLG_BARYCTR))) {
|
4558
|
+
swi_force_app_pos_etc();
|
4559
|
+
if (swe_calc(tjd_et, SE_SUN, iflg0, x, serr) == ERR)
|
4560
|
+
return ERR;
|
4561
|
+
} else {
|
4562
|
+
if (swe_calc(tjd_et, ipli, iflg0 | (iflag & SEFLG_TOPOCTR), x, serr) == ERR)
|
4563
|
+
return ERR;
|
4564
|
+
}
|
4565
|
+
/***********************
|
4566
|
+
* position of observer
|
4567
|
+
***********************/
|
4568
|
+
if (iflag & SEFLG_TOPOCTR) {
|
4569
|
+
/* geocentric position of observer */
|
4570
|
+
if (swi_get_observer(tjd_et, iflag, FALSE, xobs, serr) != OK)
|
4571
|
+
return ERR;
|
4572
|
+
/*for (i = 0; i <= 5; i++)
|
4573
|
+
xobs[i] = swed.topd.xobs[i];*/
|
4574
|
+
} else {
|
4575
|
+
for (i = 0; i <= 5; i++)
|
4576
|
+
xobs[i] = 0;
|
4577
|
+
}
|
4578
|
+
if (iflag & (SEFLG_HELCTR | SEFLG_BARYCTR)) {
|
4579
|
+
if ((iflag & SEFLG_HELCTR) && !(iflag & SEFLG_MOSEPH))
|
4580
|
+
for (i = 0; i <= 5; i++)
|
4581
|
+
xobs[i] = xsun[i];
|
4582
|
+
} else if (ipl == SE_SUN && !(iflag & SEFLG_MOSEPH)) {
|
4583
|
+
for (i = 0; i <= 5; i++)
|
4584
|
+
xobs[i] = xsun[i];
|
4585
|
+
} else {
|
4586
|
+
/* barycentric position of observer */
|
4587
|
+
for (i = 0; i <= 5; i++)
|
4588
|
+
xobs[i] += xear[i];
|
4589
|
+
}
|
4590
|
+
/* ecliptic obliqity */
|
4591
|
+
if (iflag & SEFLG_J2000)
|
4592
|
+
oe = &swed.oec2000;
|
4593
|
+
else
|
4594
|
+
oe = &swed.oec;
|
4595
|
+
/*************************************************
|
4596
|
+
* conversions shared by mean and osculating points
|
4597
|
+
*************************************************/
|
4598
|
+
for (ij = 0, xp = xx; ij < 4; ij++, xp += 6) {
|
4599
|
+
/* no nodes for earth */
|
4600
|
+
if (ipli == SE_EARTH && ij <= 1) {
|
4601
|
+
for (i = 0; i <= 5; i++)
|
4602
|
+
xp[i] = 0;
|
4603
|
+
continue;
|
4604
|
+
}
|
4605
|
+
/*********************
|
4606
|
+
* to equator
|
4607
|
+
*********************/
|
4608
|
+
if (is_true_nodaps && !(iflag & SEFLG_NONUT)) {
|
4609
|
+
swi_coortrf2(xp, xp, -swed.nut.snut, swed.nut.cnut);
|
4610
|
+
if (iflag & SEFLG_SPEED)
|
4611
|
+
swi_coortrf2(xp+3, xp+3, -swed.nut.snut, swed.nut.cnut);
|
4612
|
+
}
|
4613
|
+
swi_coortrf2(xp, xp, -oe->seps, oe->ceps);
|
4614
|
+
swi_coortrf2(xp+3, xp+3, -oe->seps, oe->ceps);
|
4615
|
+
if (is_true_nodaps) {
|
4616
|
+
/****************************
|
4617
|
+
* to mean ecliptic of date
|
4618
|
+
****************************/
|
4619
|
+
if (!(iflag & SEFLG_NONUT))
|
4620
|
+
swi_nutate(xp, iflag, TRUE);
|
4621
|
+
}
|
4622
|
+
/*********************
|
4623
|
+
* to J2000
|
4624
|
+
*********************/
|
4625
|
+
swi_precess(xp, tjd_et, J_TO_J2000);
|
4626
|
+
if (iflag & SEFLG_SPEED)
|
4627
|
+
swi_precess_speed(xp, tjd_et, J_TO_J2000);
|
4628
|
+
/*********************
|
4629
|
+
* to barycenter
|
4630
|
+
*********************/
|
4631
|
+
if (ipli == SE_MOON) {
|
4632
|
+
for (i = 0; i <= 5; i++)
|
4633
|
+
xp[i] += xear[i];
|
4634
|
+
} else {
|
4635
|
+
if (!(iflag & SEFLG_MOSEPH) && !ellipse_is_bary)
|
4636
|
+
for (j = 0; j <= 5; j++)
|
4637
|
+
xp[j] += xsun[j];
|
4638
|
+
}
|
4639
|
+
/*********************
|
4640
|
+
* to correct center
|
4641
|
+
*********************/
|
4642
|
+
for (j = 0; j <= 5; j++)
|
4643
|
+
xp[j] -= xobs[j];
|
4644
|
+
/* geocentric perigee/apogee of sun */
|
4645
|
+
if (ipl == SE_SUN && !(iflag & (SEFLG_HELCTR | SEFLG_BARYCTR)))
|
4646
|
+
for (j = 0; j <= 5; j++)
|
4647
|
+
xp[j] = -xp[j];
|
4648
|
+
/*********************
|
4649
|
+
* light deflection
|
4650
|
+
*********************/
|
4651
|
+
dt = sqrt(square_sum(xp)) * AUNIT / CLIGHT / 86400.0;
|
4652
|
+
if (do_defl)
|
4653
|
+
swi_deflect_light(xp, dt, iflag);
|
4654
|
+
/*********************
|
4655
|
+
* aberration
|
4656
|
+
*********************/
|
4657
|
+
if (do_aberr) {
|
4658
|
+
swi_aberr_light(xp, xobs, iflag);
|
4659
|
+
/*
|
4660
|
+
* Apparent speed is also influenced by
|
4661
|
+
* the difference of speed of the earth between t and t-dt.
|
4662
|
+
* Neglecting this would result in an error of several 0.1"
|
4663
|
+
*/
|
4664
|
+
if (iflag & SEFLG_SPEED) {
|
4665
|
+
/* get barycentric sun and earth for t-dt into save area */
|
4666
|
+
if (swe_calc(tjd_et - dt, ipli, iflg0 | (iflag & SEFLG_TOPOCTR), x2, serr) == ERR)
|
4667
|
+
return ERR;
|
4668
|
+
if (iflag & SEFLG_TOPOCTR) {
|
4669
|
+
/* geocentric position of observer */
|
4670
|
+
/* if (swi_get_observer(tjd_et - dt, iflag, FALSE, xobs, serr) != OK)
|
4671
|
+
return ERR;*/
|
4672
|
+
for (i = 0; i <= 5; i++)
|
4673
|
+
xobs2[i] = swed.topd.xobs[i];
|
4674
|
+
} else {
|
4675
|
+
for (i = 0; i <= 5; i++)
|
4676
|
+
xobs2[i] = 0;
|
4677
|
+
}
|
4678
|
+
if (iflag & (SEFLG_HELCTR | SEFLG_BARYCTR)) {
|
4679
|
+
if ((iflag & SEFLG_HELCTR) && !(iflag & SEFLG_MOSEPH))
|
4680
|
+
for (i = 0; i <= 5; i++)
|
4681
|
+
xobs2[i] = xsun[i];
|
4682
|
+
} else if (ipl == SE_SUN && !(iflag & SEFLG_MOSEPH)) {
|
4683
|
+
for (i = 0; i <= 5; i++)
|
4684
|
+
xobs2[i] = xsun[i];
|
4685
|
+
} else {
|
4686
|
+
/* barycentric position of observer */
|
4687
|
+
for (i = 0; i <= 5; i++)
|
4688
|
+
xobs2[i] += xear[i];
|
4689
|
+
}
|
4690
|
+
for (i = 3; i <= 5; i++)
|
4691
|
+
xp[i] += xobs[i] - xobs2[i];
|
4692
|
+
/* The above call of swe_calc() has destroyed the
|
4693
|
+
* parts of the save area
|
4694
|
+
* (i.e. bary sun, earth nutation matrix!).
|
4695
|
+
* to restore it:
|
4696
|
+
*/
|
4697
|
+
if (swe_calc(tjd_et, SE_SUN, iflg0 | (iflag & SEFLG_TOPOCTR), x2, serr) == ERR)
|
4698
|
+
return ERR;
|
4699
|
+
}
|
4700
|
+
}
|
4701
|
+
/*********************
|
4702
|
+
* precession
|
4703
|
+
*********************/
|
4704
|
+
/* save J2000 coordinates; required for sidereal positions */
|
4705
|
+
for (j = 0; j <= 5; j++)
|
4706
|
+
x2000[j] = xp[j];
|
4707
|
+
if (!(iflag & SEFLG_J2000)) {
|
4708
|
+
swi_precess(xp, tjd_et, J2000_TO_J);
|
4709
|
+
if (iflag & SEFLG_SPEED)
|
4710
|
+
swi_precess_speed(xp, tjd_et, J2000_TO_J);
|
4711
|
+
}
|
4712
|
+
/*********************
|
4713
|
+
* nutation
|
4714
|
+
*********************/
|
4715
|
+
if (!(iflag & SEFLG_NONUT))
|
4716
|
+
swi_nutate(xp, iflag, FALSE);
|
4717
|
+
/* now we have equatorial cartesian coordinates; keep them */
|
4718
|
+
for (j = 0; j <= 5; j++)
|
4719
|
+
pldat.xreturn[18+j] = xp[j];
|
4720
|
+
/************************************************
|
4721
|
+
* transformation to ecliptic. *
|
4722
|
+
* with sidereal calc. this will be overwritten *
|
4723
|
+
* afterwards. *
|
4724
|
+
************************************************/
|
4725
|
+
swi_coortrf2(xp, xp, oe->seps, oe->ceps);
|
4726
|
+
if (iflag & SEFLG_SPEED)
|
4727
|
+
swi_coortrf2(xp+3, xp+3, oe->seps, oe->ceps);
|
4728
|
+
if (!(iflag & SEFLG_NONUT)) {
|
4729
|
+
swi_coortrf2(xp, xp, swed.nut.snut, swed.nut.cnut);
|
4730
|
+
if (iflag & SEFLG_SPEED)
|
4731
|
+
swi_coortrf2(xp+3, xp+3, swed.nut.snut, swed.nut.cnut);
|
4732
|
+
}
|
4733
|
+
/* now we have ecliptic cartesian coordinates */
|
4734
|
+
for (j = 0; j <= 5; j++)
|
4735
|
+
pldat.xreturn[6+j] = xp[j];
|
4736
|
+
/************************************
|
4737
|
+
* sidereal positions *
|
4738
|
+
************************************/
|
4739
|
+
if (iflag & SEFLG_SIDEREAL) {
|
4740
|
+
/* project onto ecliptic t0 */
|
4741
|
+
if (swed.sidd.sid_mode & SE_SIDBIT_ECL_T0) {
|
4742
|
+
if (swi_trop_ra2sid_lon(x2000, pldat.xreturn+6, pldat.xreturn+18, iflag, serr) != OK)
|
4743
|
+
return ERR;
|
4744
|
+
/* project onto solar system equator */
|
4745
|
+
} else if (swed.sidd.sid_mode & SE_SIDBIT_SSY_PLANE) {
|
4746
|
+
if (swi_trop_ra2sid_lon_sosy(x2000, pldat.xreturn+6, pldat.xreturn+18, iflag, serr) != OK)
|
4747
|
+
return ERR;
|
4748
|
+
} else {
|
4749
|
+
/* traditional algorithm */
|
4750
|
+
swi_cartpol_sp(pldat.xreturn+6, pldat.xreturn);
|
4751
|
+
pldat.xreturn[0] -= swe_get_ayanamsa(tjd_et) * DEGTORAD;
|
4752
|
+
swi_polcart_sp(pldat.xreturn, pldat.xreturn+6);
|
4753
|
+
}
|
4754
|
+
}
|
4755
|
+
if ((iflag & SEFLG_XYZ) && (iflag & SEFLG_EQUATORIAL)) {
|
4756
|
+
for (j = 0; j <= 5; j++)
|
4757
|
+
xp[j] = pldat.xreturn[18+j];
|
4758
|
+
continue;
|
4759
|
+
}
|
4760
|
+
if (iflag & SEFLG_XYZ) {
|
4761
|
+
for (j = 0; j <= 5; j++)
|
4762
|
+
xp[j] = pldat.xreturn[6+j];
|
4763
|
+
continue;
|
4764
|
+
}
|
4765
|
+
/************************************************
|
4766
|
+
* transformation to polar coordinates *
|
4767
|
+
************************************************/
|
4768
|
+
swi_cartpol_sp(pldat.xreturn+18, pldat.xreturn+12);
|
4769
|
+
swi_cartpol_sp(pldat.xreturn+6, pldat.xreturn);
|
4770
|
+
/**********************
|
4771
|
+
* radians to degrees *
|
4772
|
+
**********************/
|
4773
|
+
for (j = 0; j < 2; j++) {
|
4774
|
+
pldat.xreturn[j] *= RADTODEG; /* ecliptic */
|
4775
|
+
pldat.xreturn[j+3] *= RADTODEG;
|
4776
|
+
pldat.xreturn[j+12] *= RADTODEG; /* equator */
|
4777
|
+
pldat.xreturn[j+15] *= RADTODEG;
|
4778
|
+
}
|
4779
|
+
if (iflag & SEFLG_EQUATORIAL) {
|
4780
|
+
for (j = 0; j <= 5; j++)
|
4781
|
+
xp[j] = pldat.xreturn[12+j];
|
4782
|
+
continue;
|
4783
|
+
} else {
|
4784
|
+
for (j = 0; j <= 5; j++)
|
4785
|
+
xp[j] = pldat.xreturn[j];
|
4786
|
+
continue;
|
4787
|
+
}
|
4788
|
+
}
|
4789
|
+
for (i = 0; i <= 5; i++) {
|
4790
|
+
if (i > 2 && !(iflag & SEFLG_SPEED))
|
4791
|
+
xna[i] = xnd[i] = xpe[i] = xap[i] = 0;
|
4792
|
+
if (xnasc != NULL)
|
4793
|
+
xnasc[i] = xna[i];
|
4794
|
+
if (xndsc != NULL)
|
4795
|
+
xndsc[i] = xnd[i];
|
4796
|
+
if (xperi != NULL)
|
4797
|
+
xperi[i] = xpe[i];
|
4798
|
+
if (xaphe != NULL)
|
4799
|
+
xaphe[i] = xap[i];
|
4800
|
+
}
|
4801
|
+
return OK;
|
4802
|
+
}
|
4803
|
+
|
4804
|
+
int32 FAR PASCAL_CONV swe_nod_aps_ut(double tjd_ut, int32 ipl, int32 iflag,
|
4805
|
+
int32 method,
|
4806
|
+
double *xnasc, double *xndsc,
|
4807
|
+
double *xperi, double *xaphe,
|
4808
|
+
char *serr) {
|
4809
|
+
return swe_nod_aps(tjd_ut + swe_deltat(tjd_ut),
|
4810
|
+
ipl, iflag, method, xnasc, xndsc, xperi, xaphe,
|
4811
|
+
serr);
|
4812
|
+
}
|
4813
|
+
|
4814
|
+
/* function finds the gauquelin sector position of a planet or fixed star
|
4815
|
+
*
|
4816
|
+
* if starname != NULL then a star is computed.
|
4817
|
+
* iflag: use the flags SE_SWIEPH, SE_JPLEPH, SE_MOSEPH, SEFLG_TOPOCTR.
|
4818
|
+
*
|
4819
|
+
* imeth defines method:
|
4820
|
+
* imeth = 0 use Placidus house position
|
4821
|
+
* imeth = 1 use Placidus house posiition (with planetary lat = 0)
|
4822
|
+
* imeth = 2 use rise and set of body's disc center
|
4823
|
+
* imeth = 3 use rise and set of body's disc center with refraction
|
4824
|
+
* rise and set are defined as appearance and disappearance of disc center
|
4825
|
+
*
|
4826
|
+
* geopos is an array of 3 doubles for geo. longitude, geo. latitude, elevation.
|
4827
|
+
* atpress and attemp are only needed for imeth = 3. If imeth = 3,
|
4828
|
+
* If imeth=3 and atpress not given (= 0), the programm assumes 1013.25 mbar;
|
4829
|
+
* if a non-zero height above sea is given in geopos, atpress is estimated.
|
4830
|
+
* dgsect is return area (pointer to a double)
|
4831
|
+
* serr is pointer to error string, may be NULL
|
4832
|
+
*/
|
4833
|
+
int32 FAR PASCAL_CONV swe_gauquelin_sector(double t_ut, int32 ipl, char *starname, int32 iflag, int32 imeth, double *geopos, double atpress, double attemp, double *dgsect, char *serr)
|
4834
|
+
{
|
4835
|
+
AS_BOOL rise_found = TRUE;
|
4836
|
+
AS_BOOL set_found = TRUE;
|
4837
|
+
int32 retval;
|
4838
|
+
double tret[3];
|
4839
|
+
double t_et, t;
|
4840
|
+
double x0[6];
|
4841
|
+
double eps, nutlo[2], armc;
|
4842
|
+
int32 epheflag = iflag & SEFLG_EPHMASK;
|
4843
|
+
AS_BOOL do_fixstar = (starname != NULL && *starname != '\0');
|
4844
|
+
int32 risemeth = 0;
|
4845
|
+
AS_BOOL above_horizon = FALSE;
|
4846
|
+
if (imeth < 0 || imeth > 5) {
|
4847
|
+
if (serr)
|
4848
|
+
sprintf(serr, "invalid method: %d", imeth);
|
4849
|
+
return ERR;
|
4850
|
+
}
|
4851
|
+
/* function calls for Pluto with asteroid number 134340
|
4852
|
+
* are treated as calls for Pluto as main body SE_PLUTO */
|
4853
|
+
if (ipl == SE_AST_OFFSET + 134340)
|
4854
|
+
ipl = SE_PLUTO;
|
4855
|
+
/*
|
4856
|
+
* geometrically from ecl. longitude and latitude
|
4857
|
+
*/
|
4858
|
+
if (imeth == 0 || imeth == 1) {
|
4859
|
+
t_et = t_ut + swe_deltat(t_ut);
|
4860
|
+
eps = swi_epsiln(t_et) * RADTODEG;
|
4861
|
+
swi_nutation(t_et, nutlo);
|
4862
|
+
nutlo[0] *= RADTODEG;
|
4863
|
+
nutlo[1] *= RADTODEG;
|
4864
|
+
armc = swe_degnorm(swe_sidtime0(t_ut, eps + nutlo[1], nutlo[0]) * 15 + geopos[0]);
|
4865
|
+
if (do_fixstar) {
|
4866
|
+
if (swe_fixstar(starname, t_et, iflag, x0, serr) == ERR)
|
4867
|
+
return ERR;
|
4868
|
+
} else {
|
4869
|
+
if (swe_calc(t_et, ipl, iflag, x0, serr) == ERR)
|
4870
|
+
return ERR;
|
4871
|
+
}
|
4872
|
+
if (imeth == 1)
|
4873
|
+
x0[1] = 0;
|
4874
|
+
*dgsect = swe_house_pos(armc, geopos[1], eps + nutlo[1], 'G', x0, NULL);
|
4875
|
+
return OK;
|
4876
|
+
}
|
4877
|
+
/*
|
4878
|
+
* from rise and set times
|
4879
|
+
*/
|
4880
|
+
if (imeth == 2 || imeth == 4)
|
4881
|
+
risemeth |= SE_BIT_NO_REFRACTION;
|
4882
|
+
if (imeth == 2 || imeth == 3)
|
4883
|
+
risemeth |= SE_BIT_DISC_CENTER;
|
4884
|
+
/* find the next rising time of the planet or star */
|
4885
|
+
retval = swe_rise_trans(t_ut, ipl, starname, epheflag, SE_CALC_RISE|risemeth, geopos, atpress, attemp, &(tret[0]), serr);
|
4886
|
+
if (retval == ERR) {
|
4887
|
+
return ERR;
|
4888
|
+
} else if (retval == -2) {
|
4889
|
+
/* actually, we could return ERR here. However, we
|
4890
|
+
* keep this variable, in case we implement an algorithm
|
4891
|
+
* for Gauquelin sector positions of circumpolar bodies.
|
4892
|
+
* As with the Ludwig Otto procedure with Placidus, one
|
4893
|
+
* could replace missing rises or sets by meridian transits,
|
4894
|
+
* although there are cases where even this is not possible.
|
4895
|
+
* Sometimes a body both appears and disappears on the western
|
4896
|
+
* part of the horizon. Using true culminations rather than meridan
|
4897
|
+
* transits would not help in any case either, because there are
|
4898
|
+
* cases where a body does not have a culmination within days,
|
4899
|
+
* e.g. the sun near the poles.
|
4900
|
+
*/
|
4901
|
+
rise_found = FALSE;
|
4902
|
+
}
|
4903
|
+
/* find the next setting time of the planet or star */
|
4904
|
+
retval = swe_rise_trans(t_ut, ipl, starname, epheflag, SE_CALC_SET|risemeth, geopos, atpress, attemp, &(tret[1]), serr);
|
4905
|
+
if (retval == ERR) {
|
4906
|
+
return ERR;
|
4907
|
+
} else if (retval == -2) {
|
4908
|
+
set_found = FALSE;
|
4909
|
+
}
|
4910
|
+
if (tret[0] < tret[1] && rise_found == TRUE) {
|
4911
|
+
above_horizon = FALSE;
|
4912
|
+
/* find last set */
|
4913
|
+
t = t_ut - 1.2;
|
4914
|
+
if (set_found) t = tret[1] - 1.2;
|
4915
|
+
set_found = TRUE;
|
4916
|
+
retval = swe_rise_trans(t, ipl, starname, epheflag, SE_CALC_SET|risemeth, geopos, atpress, attemp, &(tret[1]), serr);
|
4917
|
+
if (retval == ERR) {
|
4918
|
+
return ERR;
|
4919
|
+
} else if (retval == -2) {
|
4920
|
+
set_found = FALSE;
|
4921
|
+
}
|
4922
|
+
} else if (tret[0] >= tret[1] && set_found == TRUE) {
|
4923
|
+
above_horizon = TRUE;
|
4924
|
+
/* find last rise */
|
4925
|
+
t = t_ut - 1.2;
|
4926
|
+
if (rise_found) t = tret[0] - 1.2;
|
4927
|
+
rise_found = TRUE;
|
4928
|
+
retval = swe_rise_trans(t, ipl, starname, epheflag, SE_CALC_RISE|risemeth, geopos, atpress, attemp, &(tret[0]), serr);
|
4929
|
+
if (retval == ERR) {
|
4930
|
+
return ERR;
|
4931
|
+
} else if (retval == -2) {
|
4932
|
+
rise_found = FALSE;
|
4933
|
+
}
|
4934
|
+
}
|
4935
|
+
if (rise_found && set_found) {
|
4936
|
+
if (above_horizon) {
|
4937
|
+
*dgsect = (t_ut - tret[0]) / (tret[1] - tret[0]) * 18 + 1;
|
4938
|
+
} else {
|
4939
|
+
*dgsect = (t_ut - tret[1]) / (tret[0] - tret[1]) * 18 + 19;
|
4940
|
+
}
|
4941
|
+
return OK;
|
4942
|
+
} else {
|
4943
|
+
*dgsect = 0;
|
4944
|
+
if (serr)
|
4945
|
+
sprintf(serr, "rise or set not found for planet %d", ipl);
|
4946
|
+
return ERR;
|
4947
|
+
}
|
4948
|
+
}
|