swe4r 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,3445 @@
1
+ /* SWISSEPH
2
+ $Header: /home/dieter/sweph/RCS/swehel.c,v 1.1 2009/04/21 06:05:59 dieter Exp dieter $
3
+
4
+ Heliacal risings and related calculations
5
+
6
+ Author: Victor Reijs
7
+ This program code is a translation of part of:
8
+ Victor Reijs' software ARCHAEOCOSMO (archaeoastronomy and
9
+ geodesy functions),
10
+ http://www.iol.ie/~geniet/eng/archaeocosmoprocedures.htm
11
+
12
+ Translation from VB into C by Dieter Koch
13
+
14
+ Problem reports can be sent to victor.reijs@gmail.com or dieter@astro.ch
15
+
16
+ Copyright (c) Victor Reijs, 2008
17
+
18
+ License conditions
19
+ ------------------
20
+
21
+ This file is part of Swiss Ephemeris.
22
+
23
+ Swiss Ephemeris is distributed with NO WARRANTY OF ANY KIND. No author
24
+ or distributor accepts any responsibility for the consequences of using it,
25
+ or for whether it serves any particular purpose or works at all, unless he
26
+ or she says so in writing.
27
+
28
+ Swiss Ephemeris is made available by its authors under a dual licensing
29
+ system. The software developer, who uses any part of Swiss Ephemeris
30
+ in his or her software, must choose between one of the two license models,
31
+ which are
32
+ a) GNU public license version 2 or later
33
+ b) Swiss Ephemeris Professional License
34
+
35
+ The choice must be made before the software developer distributes software
36
+ containing parts of Swiss Ephemeris to others, and before any public
37
+ service using the developed software is activated.
38
+
39
+ If the developer choses the GNU GPL software license, he or she must fulfill
40
+ the conditions of that license, which includes the obligation to place his
41
+ or her whole software project under the GNU GPL or a compatible license.
42
+ See http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
43
+
44
+ If the developer choses the Swiss Ephemeris Professional license,
45
+ he must follow the instructions as found in http://www.astro.com/swisseph/
46
+ and purchase the Swiss Ephemeris Professional Edition from Astrodienst
47
+ and sign the corresponding license contract.
48
+
49
+ The License grants you the right to use, copy, modify and redistribute
50
+ Swiss Ephemeris, but only under certain conditions described in the License.
51
+ Among other things, the License requires that the copyright notices and
52
+ this notice be preserved on all copies.
53
+
54
+ The authors of Swiss Ephemeris have no control or influence over any of
55
+ the derived works, i.e. over software or services created by other
56
+ programmers which use Swiss Ephemeris functions.
57
+
58
+ The names of the authors or of the copyright holder must not
59
+ be used for promoting any software, product or service which uses or contains
60
+ the Swiss Ephemeris. This copyright notice is the ONLY place where the
61
+ names of the authors can legally appear, except in cases where they have
62
+ given special permission in writing.
63
+
64
+ The trademarks 'Swiss Ephemeris' and 'Swiss Ephemeris inside' may be used
65
+ for promoting such software, products or services.
66
+ */
67
+
68
+ #include "swephexp.h"
69
+ #include "sweph.h"
70
+ #include "swephlib.h"
71
+ #include <sys/stat.h>
72
+
73
+ #define PLSV 0 /*if Planet, Lunar and Stellar Visibility formula is needed PLSV=1*/
74
+ #define criticalangle 0.0 /*[deg]*/
75
+ #define BNIGHT 1479.0 /*[nL]*/
76
+ #define BNIGHT_FACTOR 1.0
77
+ #define PI M_PI
78
+ #define Min2Deg (1.0 / 60.0)
79
+ #define DEBUG 0
80
+ #define DONE 1
81
+ #define MaxTryHours 4
82
+ #define TimeStepDefault 1
83
+ #define LocalMinStep 8
84
+
85
+ /* time constants */
86
+ #define Y2D 365.25 /*[Day]*/
87
+ #define D2Y (1 / Y2D) /*[Year]*/
88
+ #define D2H 24.0 /*[Hour]*/
89
+ #define H2S 3600.0 /*[sec]*/
90
+ #define D2S (D2H * H2S) /*[sec]*/
91
+ #define S2H (1.0 / H2S) /*[Hour]*/
92
+ #define JC2D 36525.0 /*[Day]*/
93
+ #define M2S 60.0 /*[sec]*/
94
+
95
+ /* Determines which algorimths are used*/
96
+ #define USE_DELTA_T_VR 0
97
+ #define REFR_SINCLAIR 0
98
+ #define REFR_BENNETTH 1
99
+ #define FormAstroRefrac REFR_SINCLAIR /*for Astronomical refraction can be "bennetth" or "sinclair"*/
100
+ #define GravitySource 2 /*0=RGO, 1=Wikipedia,2=Exp. Suppl. 1992,3=van der Werf*/
101
+ #define REarthSource 1 /*0=RGO (constant), 1=WGS84 method*/
102
+
103
+ #define StartYear 1820 /*[year]*/
104
+ #define Average 1.80546834626888 /*[msec/cy]*/
105
+ #define Periodicy 1443.67123144531 /*[year]*/
106
+ #define Amplitude 3.75606495492684 /*[msec]*/
107
+ #define phase 0 /*[deg]*/
108
+ #define MAX_COUNT_SYNPER 5 /* search within 10 synodic periods */
109
+ #define MAX_COUNT_SYNPER_MAX 1000000 /* high, so there is not max count */
110
+ #define AvgRadiusMoon (15.541 / 60) /* '[Deg] at 2007 CE or BCE*/
111
+
112
+ /* WGS84 ellipsoid constants
113
+ * http://w3sli.wcape.gov.za/Surveys/Mapping/wgs84.htm*/
114
+ #define Ra 6378136.6 /*'[m]*/
115
+ #define Rb 6356752.314 /*'[m]*/
116
+
117
+ /* choices in Schaefer's model */
118
+ #define nL2erg (1.02E-15)
119
+ #define erg2nL (1 / nL2erg) /*erg2nL to nLambert*/
120
+ #define MoonDistance 384410.4978 /*[km]*/
121
+ #define scaleHwater 3000.0 /*[m] Ricchiazzi [1997] 8200 Schaefer [2000]*/
122
+ #define scaleHrayleigh 8515.0 /*[m] Su [2003] 8200 Schaefer [2000]*/
123
+ #define scaleHaerosol 3745.0 /*m Su [2003] 1500 Schaefer [2000]*/
124
+ #define scaleHozone 20000.0 /*[m] Schaefer [2000]*/
125
+ #define astr2tau 0.921034037197618 /*LN(10 ^ 0.4)*/
126
+ #define tau2astr 1 / astr2tau
127
+
128
+ /* meteorological constants*/
129
+ #define C2K 273.15 /*[K]*/
130
+ #define DELTA 18.36
131
+ #define TempNulDiff 0.000001
132
+ #define PressRef 1000 /*[mbar]*/
133
+ #define MD 28.964 /*[kg] Mol weight of dry air van der Werf*/
134
+ #define MW 18.016 /*[kg] Mol weight of water vapor*/
135
+ #define GCR 8314.472 /*[L/kmol/K] van der Werf*/
136
+ #define LapseSA 0.0065 /*[K/m] standard atmosphere*/
137
+ #define LapseDA 0.0098 /*[K/m] dry adiabatic*/
138
+
139
+ /* lowest apparent altitude to provide*/
140
+ #define LowestAppAlt -3.5 /*[Deg]*/
141
+
142
+ /*optimization delta*/
143
+ #define epsilon 0.001
144
+ /* for Airmass usage*/
145
+ #define staticAirmass 0 /* use staticAirmass=1 instead depending on difference k's*/
146
+
147
+ /* optic stuff */
148
+ #define GOpticMag 1 /*telescope magnification*/
149
+ #define GOpticTrans 0.8 /*telescope transmission*/
150
+ #define GBinocular 1 /*1-binocular 0=monocular*/
151
+ #define GOpticDia 50 /*telescope diameter [mm]*/
152
+
153
+ static double mymin(double a, double b)
154
+ {
155
+ if (a <= b)
156
+ return a;
157
+ return b;
158
+ }
159
+
160
+ static double mymax(double a, double b)
161
+ {
162
+ if (a >= b)
163
+ return a;
164
+ return b;
165
+ }
166
+
167
+ /*###################################################################*/
168
+ static double Tanh(double x)
169
+ {
170
+ return (exp(x) - exp(-x)) / (exp(x) + exp(-x));
171
+ }
172
+
173
+ /*
174
+ ' B [nL]
175
+ ' SN [-]
176
+ ' CVA [deg]
177
+ */
178
+ static double CVA(double B, double SN)
179
+ {
180
+ /*Schaefer, Astronomy and the limits of vision, Archaeoastronomy, 1993*/
181
+ if (B > BNIGHT)
182
+ return (40.0 / SN) * pow(10, (8.28 * pow(B, (-0.29)))) / 60.0 / 60.0;
183
+ else
184
+ return mymin(900, 380 / SN * pow(10, (0.3 * pow(B, (-0.29))))) / 60.0 / 60.0;
185
+ }
186
+
187
+ /*
188
+ ' age [year]
189
+ ' B [nL]
190
+ ' PupilDia [mm]
191
+ */
192
+ static double PupilDia(double Age, double B)
193
+ {
194
+ /* age dependancy from Garstang [2000]*/
195
+ return (0.534 - 0.00211 * Age - (0.236 - 0.00127 * Age) * Tanh(0.4 * log(B) / log(10) - 2.2)) * 10;
196
+ }
197
+
198
+ /*
199
+ 'Input
200
+ ' Bback [nL]
201
+ ' kX [-]
202
+ ' Binocular [-]
203
+ ' OpticMag [-]
204
+ ' OpticDia [mm]
205
+ ' OpticTrans [-]
206
+ ' JDNDaysUT [JDN]
207
+ ' Age [Year]
208
+ ' SN [-]
209
+ ' ObjectName
210
+ ' TypeFactor [0=itensity factor 1=background factor]
211
+ 'Output
212
+ ' OpticFactor [-]
213
+ */
214
+ static double OpticFactor(double Bback, double kX, double *dobs, double JDNDaysUT, char *ObjectName, int TypeFactor, int helflag)
215
+ {
216
+ double Pst, CIb, CIi, ObjectSize, Fb, Fe, Fsc, Fci, Fcb, Ft, Fp, Fa, Fr, Fm;
217
+ double Age = dobs[0];
218
+ double SN = dobs[1], SNi;
219
+ double Binocular = dobs[2];
220
+ double OpticMag = dobs[3];
221
+ double OpticDia = dobs[4];
222
+ double OpticTrans = dobs[5];
223
+ SNi = SN;
224
+ if (SNi <= 0.00000001) SNi = 0.00000001;
225
+ /* 23 jaar as standard from Garstang*/
226
+ Pst = PupilDia(23, Bback);
227
+ if (OpticMag == 1) { /*OpticMagn=1 means using eye*/
228
+ OpticTrans = 1;
229
+ OpticDia = Pst;
230
+ }
231
+ #if 0 /*is done in default_heliacal_parameters()*/
232
+ if (OpticMag == 0) { /*OpticMagn=0 (undefined) using eye*/
233
+ OpticTrans = 1;
234
+ OpticDia = Pst;
235
+ Binocular = 1;
236
+ OpticMag = 1;
237
+ }
238
+ #endif
239
+ /* Schaefer, Astronomy and the limits of vision, Archaeoastronomy, 1993*/
240
+ CIb = 0.7; /* color of background (from Ben Sugerman)*/
241
+ CIi = 0.5; /* Color index for white (from Ben Sugerman), should be function of ObjectName*/
242
+ ObjectSize = 0;
243
+ if (strcmp(ObjectName, "moon") == 0) {
244
+ /*ObjectSize and CI needs to be determined (depending on JDNDaysUT)*/
245
+ ;
246
+ }
247
+ Fb = 1;
248
+ if (Binocular == 0) Fb = 1.41;
249
+ if (Bback < BNIGHT && !(helflag & SE_HELFLAG_VISLIM_PHOTOPIC)) {
250
+ Fe = pow(10, (0.48 * kX));
251
+ Fsc = mymin(1, (1 - pow(Pst / 124.4, 4)) / (1 - pow((OpticDia / OpticMag / 124.4), 4)));
252
+ Fci = pow(10, (-0.4 * (1 - CIi / 2.0)));
253
+ Fcb = pow(10, (-0.4 * (1 - CIb / 2.0)));
254
+ } else {
255
+ Fe = pow(10, (0.4 * kX));
256
+ Fsc = mymin(1, pow((OpticDia / OpticMag / Pst), 2) * (1 - exp(-pow((Pst / 6.2), 2))) / (1 - exp(-pow((OpticDia / OpticMag / 6.2), 2))));
257
+ Fci = 1;
258
+ Fcb = 1;
259
+ }
260
+ Ft = 1 / OpticTrans;
261
+ Fp = mymax(1, pow((Pst / (OpticMag * PupilDia(Age, Bback))), 2));
262
+ Fa = pow((Pst / OpticDia), 2);
263
+ Fr = (1 + 0.03 * pow((OpticMag * ObjectSize / CVA(Bback, SNi)), 2)) / pow(SNi, 2);
264
+ Fm = pow(OpticMag, 2);
265
+ #if DEBUG
266
+ fprintf(stderr, "Pst=%f\n", Pst);
267
+ fprintf(stderr, "Fb =%f\n", Fb);
268
+ fprintf(stderr, "Fe =%f\n", Fe);
269
+ fprintf(stderr, "Ft =%f\n", Ft);
270
+ fprintf(stderr, "Fp =%f\n", Fp);
271
+ fprintf(stderr, "Fa =%f\n", Fa);
272
+ fprintf(stderr, "Fm =%f\n", Fm);
273
+ fprintf(stderr, "Fsc=%f\n", Fsc);
274
+ fprintf(stderr, "Fci=%f\n", Fci);
275
+ fprintf(stderr, "Fcb=%f\n", Fcb);
276
+ fprintf(stderr, "Fr =%f\n", Fr );
277
+ #endif
278
+ if (TypeFactor == 0)
279
+ return Fb * Fe * Ft * Fp * Fa * Fr * Fsc * Fci;
280
+ else
281
+ return Fb * Ft * Fp * Fa * Fm * Fsc * Fcb;
282
+ }
283
+
284
+ /*###################################################################
285
+ */
286
+ static int32 DeterObject(char *ObjectName)
287
+ {
288
+ char s[AS_MAXCH];
289
+ char *sp;
290
+ int32 ipl;
291
+ strcpy(s, ObjectName);
292
+ for (sp = s; *sp != '\0'; sp++)
293
+ *sp = tolower(*sp);
294
+ if (strncmp(s, "sun", 3) == 0)
295
+ return SE_SUN;
296
+ if (strncmp(s, "venus", 5) == 0)
297
+ return SE_VENUS;
298
+ if (strncmp(s, "mars", 4) == 0)
299
+ return SE_MARS;
300
+ if (strncmp(s, "mercur", 6) == 0)
301
+ return SE_MERCURY;
302
+ if (strncmp(s, "jupiter", 7) == 0)
303
+ return SE_JUPITER;
304
+ if (strncmp(s, "saturn", 6) == 0)
305
+ return SE_SATURN;
306
+ if (strncmp(s, "uranus", 6) == 0)
307
+ return SE_URANUS;
308
+ if (strncmp(s, "neptun", 6) == 0)
309
+ return SE_NEPTUNE;
310
+ if (strncmp(s, "moon", 4) == 0)
311
+ return SE_MOON;
312
+ if ((ipl = atoi(s)) > 0) {
313
+ ipl += SE_AST_OFFSET;
314
+ return ipl;
315
+ }
316
+ return -1;
317
+ }
318
+
319
+ #if 0
320
+ int32 call_swe_calc(double tjd, int32 ipl, int32 iflag, double *x, char *serr)
321
+ {
322
+ int32 retval = OK, ipli, i;
323
+ double dtjd;
324
+ static double tjdsv[3];
325
+ static double xsv[3][6];
326
+ static int32 iflagsv[3];
327
+ ipli = ipl;
328
+ if (ipli > SE_MOON)
329
+ ipli = 2;
330
+ dtjd = tjd - tjdsv[ipli];
331
+ if (tjdsv[ipli] != 0 && iflag == iflagsv[ipli] && fabs(dtjd) < 5.0 / 1440.0) {
332
+ for (i = 0; i < 3; i++)
333
+ x[i] = xsv[ipli][i] + dtjd * xsv[ipli][i+3];
334
+ for (i = 3; i < 6; i++)
335
+ x[i] = xsv[ipli][i];
336
+ } else {
337
+ retval = swe_calc(tjd, ipl, iflag, x, serr);
338
+ tjdsv[ipli] = tjd;
339
+ iflagsv[ipli] = iflag;
340
+ for (i = 0; i < 6; i++)
341
+ xsv[ipli][i] = x[i];
342
+ }
343
+ return retval;
344
+ }
345
+ #endif
346
+
347
+ /* avoids problems with star name string that may be overwritten by
348
+ swe_fixstar() */
349
+ int32 call_swe_fixstar(char *star, double tjd, int32 iflag, double *xx, char *serr)
350
+ {
351
+ int32 retval;
352
+ char star2[AS_MAXCH];
353
+ strcpy(star2, star);
354
+ retval = swe_fixstar(star2, tjd, iflag, xx, serr);
355
+ return retval;
356
+ }
357
+
358
+ /* avoids problems with star name string that may be overwritten by
359
+ swe_fixstar_mag() */
360
+ int32 call_swe_fixstar_mag(char *star, double *mag, char *serr)
361
+ {
362
+ int32 retval;
363
+ char star2[AS_MAXCH];
364
+ static double dmag;
365
+ static char star_save[AS_MAXCH];
366
+ if (strcmp(star, star_save) == 0) {
367
+ *mag = dmag;
368
+ return OK;
369
+ }
370
+ strcpy(star_save, star);
371
+ strcpy(star2, star);
372
+ retval = swe_fixstar_mag(star2, &dmag, serr);
373
+ *mag = dmag;
374
+ return retval;
375
+ }
376
+
377
+ /* avoids problems with star name string that may be overwritten by
378
+ swe_fixstar() */
379
+ int32 call_swe_rise_trans(double tjd, int32 ipl, char *star, int32 helflag, int32 eventtype, double *dgeo, double atpress, double attemp, double *tret, char *serr)
380
+ {
381
+ int32 retval;
382
+ int32 iflag = helflag & (SEFLG_JPLEPH|SEFLG_SWIEPH|SEFLG_MOSEPH);
383
+ char star2[AS_MAXCH];
384
+ strcpy(star2, star);
385
+ retval = swe_rise_trans(tjd, ipl, star2, iflag, eventtype, dgeo, atpress, attemp, tret, serr);
386
+ return retval;
387
+ }
388
+
389
+ /*
390
+ * Written by Dieter Koch:
391
+ * Fast function for risings and settings of planets, can be used instead of
392
+ * swe_rise_trans(), which is much slower.
393
+ * For circumpolar and near-circumpolar planets use swe_rise_trans(), or
394
+ * generally use it for geographical latitudes higher than 58N/S.
395
+ * For fixed stars, swe_rise_trans() is fast enough.
396
+ */
397
+ static int32 calc_rise_and_set(double tjd_start, int32 ipl, double *dgeo, double *datm, int32 eventflag, int32 helflag, double *trise, char *serr)
398
+ {
399
+ int retc = OK, i;
400
+ double sda, xs[6], xx[6], xaz[6], xaz2[6], dfac = 1/365.25;
401
+ double rdi, rh;
402
+ double tjd0 = tjd_start, tjdrise;
403
+ double tjdnoon = (int) tjd0 - dgeo[0] / 15.0 / 24.0;
404
+ int32 iflag = helflag & (SEFLG_JPLEPH|SEFLG_SWIEPH|SEFLG_MOSEPH);
405
+ iflag |= SEFLG_EQUATORIAL;
406
+ if (!(helflag & SE_HELFLAG_HIGH_PRECISION))
407
+ iflag |= SEFLG_NONUT|SEFLG_TRUEPOS;
408
+ if (swe_calc_ut(tjd0, SE_SUN, iflag, xs, serr) == 0) {
409
+ if (serr != NULL)
410
+ strcpy(serr, "error in calc_rise_and_set(): calc(sun) failed ");
411
+ return ERR;
412
+ }
413
+ if (swe_calc_ut(tjd0, ipl, iflag, xx, serr) == 0) {
414
+ if (serr != NULL)
415
+ strcpy(serr, "error in calc_rise_and_set(): calc(sun) failed ");
416
+ return ERR;
417
+ }
418
+ tjdnoon -= swe_degnorm(xs[0] - xx[0])/360.0 + 0;
419
+ /* is planet above horizon or below? */
420
+ swe_azalt(tjd0, SE_EQU2HOR, dgeo, datm[0], datm[1], xx, xaz);
421
+ if (eventflag & SE_CALC_RISE) {
422
+ if (xaz[2] > 0) {
423
+ while (tjdnoon - tjd0 < 0.5) {/*printf("e");*/tjdnoon += 1;}
424
+ while (tjdnoon - tjd0 > 1.5) {/*printf("f");*/tjdnoon -= 1;}
425
+ } else {
426
+ while (tjdnoon - tjd0 < 0.0) {/*printf("g");*/tjdnoon += 1;}
427
+ while (tjdnoon - tjd0 > 1.0) {/*printf("h");*/tjdnoon -= 1;}
428
+ }
429
+ } else {
430
+ if (xaz[2] > 0) {
431
+ while (tjd0 - tjdnoon > 0.5) {/*printf("a");*/ tjdnoon += 1;}
432
+ while (tjd0 - tjdnoon < -0.5) {/*printf("b");*/ tjdnoon -= 1;}
433
+ } else {
434
+ while (tjd0 - tjdnoon > 0.0) {/*printf("c");*/ tjdnoon += 1;}
435
+ while (tjd0 - tjdnoon < -1.0) {/*printf("d");*/ tjdnoon -= 1;}
436
+ }
437
+ }
438
+ /* position of planet */
439
+ if (swe_calc_ut(tjdnoon, ipl, iflag, xx, serr) == ERR) {
440
+ if (serr != NULL)
441
+ strcpy(serr, "error in calc_rise_and_set(): calc(sun) failed ");
442
+ return ERR;
443
+ }
444
+ /* apparent radius of solar disk (ignoring refraction) */
445
+ rdi = asin(696000000.0 / 1.49597870691e+11 / xx[2]) / DEGTORAD;
446
+ if (eventflag & SE_BIT_DISC_CENTER)
447
+ rdi = 0;
448
+ /* true altitude of sun, when it appears at the horizon */
449
+ /* refraction for a body visible at the horizon at 0m above sea,
450
+ * atmospheric temperature 10 deg C, atmospheric pressure 1013.25 is 34.5 arcmin*/
451
+ rh = -(34.5 / 60.0 + rdi);
452
+ /* semidiurnal arc of sun */
453
+ sda = acos(-tan(dgeo[1] * DEGTORAD) * tan(xx[1] * DEGTORAD)) * RADTODEG;
454
+ /* rough rising and setting times */
455
+ if (eventflag & SE_CALC_RISE)
456
+ tjdrise = tjdnoon - sda / 360.0;
457
+ else
458
+ tjdrise = tjdnoon + sda / 360.0;
459
+ /*ph->tset = tjd_start + sda / 360.0;*/
460
+ /* now calculate more accurate rising and setting times.
461
+ * use vertical speed in order to determine crossing of the horizon
462
+ * refraction of 34' and solar disk diameter of 16' = 50' = 0.84 deg */
463
+ iflag = SEFLG_SPEED|SEFLG_EQUATORIAL;
464
+ if (ipl == SE_MOON)
465
+ iflag |= SEFLG_TOPOCTR;
466
+ if (!(helflag & SE_HELFLAG_HIGH_PRECISION))
467
+ iflag |= SEFLG_NONUT|SEFLG_TRUEPOS;
468
+ for (i = 0; i < 2; i++) {
469
+ if (swe_calc_ut(tjdrise, ipl, iflag, xx, serr) == ERR)
470
+ return ERR;
471
+ swe_azalt(tjdrise, SE_EQU2HOR, dgeo, datm[0], datm[1], xx, xaz);
472
+ xx[0] -= xx[3] * dfac;
473
+ xx[1] -= xx[4] * dfac;
474
+ swe_azalt(tjdrise - dfac, SE_EQU2HOR, dgeo, datm[0], datm[1], xx, xaz2);
475
+ tjdrise -= (xaz[1] - rh) / (xaz[1] - xaz2[1]) * dfac;
476
+ /*fprintf(stderr, "%f\n", ph->trise);*/
477
+ }
478
+ *trise = tjdrise;
479
+ return retc;
480
+ }
481
+
482
+ static int32 my_rise_trans(double tjd, int32 ipl, char* starname, int32 eventtype, int32 helflag, double *dgeo, double *datm, double *tret, char *serr)
483
+ {
484
+ int retc = OK;
485
+ if (starname != NULL && *starname != '\0')
486
+ ipl = DeterObject(starname);
487
+ /* for non-circumpolar planets we can use a faster algorithm */
488
+ /*if (!(helflag & SE_HELFLAG_HIGH_PRECISION) && ipl != -1 && fabs(dgeo[1]) < 58) {*/
489
+ if (ipl != -1 && fabs(dgeo[1]) < 63) {
490
+ retc = calc_rise_and_set(tjd, ipl, dgeo, datm, eventtype, helflag, tret, serr);
491
+ /* for stars and circumpolar planets we use a rigorous algorithm */
492
+ } else {
493
+ retc = call_swe_rise_trans(tjd, ipl, starname, helflag, eventtype, dgeo, datm[0], datm[1], tret, serr);
494
+ }
495
+ /* printf("%f, %f\n", tjd, *tret);*/
496
+ return retc;
497
+ }
498
+
499
+ /*###################################################################
500
+ ' JDNDaysUT [Days]
501
+ ' dgeo [array: longitude, latitude, eye height above sea m]
502
+ ' TempE [C]
503
+ ' PresE [mbar]
504
+ ' ObjectName (string)
505
+ ' RSEvent (1=rise, 2=set,3=up transit,4=down transit)
506
+ ' Rim [0=center,1=top]
507
+ ' RiseSet [Day]
508
+ */
509
+ static int32 RiseSet(double JDNDaysUT, double *dgeo, double *datm, char *ObjectName, int32 RSEvent, int32 helflag, int32 Rim, double *tret, char *serr)
510
+ {
511
+ int32 eventtype = RSEvent, Planet, retval;
512
+ if (Rim == 0)
513
+ eventtype |= SE_BIT_DISC_CENTER;
514
+ Planet = DeterObject(ObjectName);
515
+ if (Planet != -1)
516
+ retval = my_rise_trans(JDNDaysUT, Planet, "", eventtype, helflag, dgeo, datm, tret, serr);
517
+ else
518
+ retval = my_rise_trans(JDNDaysUT, -1, ObjectName, eventtype, helflag, dgeo, datm, tret, serr);
519
+ return retval;
520
+ }
521
+
522
+ /*###################################################################
523
+ ' JDNDaysUT [Days]
524
+ ' actual [0= approximation, 1=actual]
525
+ ' SunRA [deg]
526
+ */
527
+ static double SunRA(double JDNDaysUT, int32 helflag, char *serr)
528
+ {
529
+ double tjd_tt;
530
+ int imon, iday, iyar, calflag = SE_GREG_CAL;
531
+ double dut;
532
+ static double tjdlast;
533
+ static double ralast;
534
+ tjd_tt = 0;
535
+ if (JDNDaysUT == tjdlast)
536
+ return ralast;
537
+ #ifndef SIMULATE_VICTORVB
538
+ if (1) { /*helflag & SE_HELFLAG_HIGH_PRECISION) {*/
539
+ double x[6];
540
+ int32 epheflag = helflag & (SEFLG_JPLEPH|SEFLG_SWIEPH|SEFLG_MOSEPH);
541
+ int32 iflag = epheflag | SEFLG_EQUATORIAL;
542
+ iflag |= SEFLG_NONUT | SEFLG_TRUEPOS;
543
+ tjd_tt = JDNDaysUT + swe_deltat(JDNDaysUT);
544
+ if (swe_calc(tjd_tt, SE_SUN, iflag, x, serr) != ERR) {
545
+ ralast = x[0];
546
+ tjdlast = JDNDaysUT;
547
+ return ralast;
548
+ }
549
+ }
550
+ #endif
551
+ swe_revjul(JDNDaysUT, calflag, &iyar, &imon, &iday, &dut); /* this seems to be much faster than calling swe_revjul() ! Note: only because SunRA is called 1000s of times */
552
+ tjdlast = JDNDaysUT;
553
+ ralast = swe_degnorm((imon + (iday - 1) / 30.4 - 3.69) * 30);
554
+ /*ralast = (DatefromJDut(JDNDaysUT, 2) + (DatefromJDut(JDNDaysUT, 3) - 1) / 30.4 - 3.69) * 30;*/
555
+ return ralast;
556
+ }
557
+
558
+ /*###################################################################
559
+ ' Temp [C]
560
+ ' Kelvin [K]
561
+ */
562
+ static double Kelvin(double Temp)
563
+ {
564
+ /*' http://en.wikipedia.org/wiki/Kelvin*/
565
+ return Temp + C2K;
566
+ }
567
+
568
+ /*###################################################################
569
+ ' AppAlt [deg]
570
+ ' TempE [C]
571
+ ' PresE [mbar]
572
+ ' TopoAltitudefromAppAlt [deg]
573
+ */
574
+ static double TopoAltfromAppAlt(double AppAlt, double TempE, double PresE)
575
+ {
576
+ double R = 0;
577
+ double retalt = 0;
578
+ if (AppAlt >= LowestAppAlt) {
579
+ if (AppAlt > 17.904104638432)
580
+ R = 0.97 / tan(AppAlt * DEGTORAD);
581
+ else
582
+ R = (34.46 + 4.23 * AppAlt + 0.004 * AppAlt * AppAlt) / (1 + 0.505 * AppAlt + 0.0845 * AppAlt * AppAlt);
583
+ R = (PresE - 80) / 930 / (1 + 0.00008 * (R + 39) * (TempE - 10)) * R;
584
+ retalt = AppAlt - R * Min2Deg;
585
+ } else {
586
+ retalt = AppAlt;
587
+ }
588
+ return retalt;
589
+ }
590
+
591
+ /*###################################################################
592
+ ' TopoAlt [deg]
593
+ ' TempE [C]
594
+ ' PresE [mbar]
595
+ ' AppAltfromTopoAlt [deg]
596
+ ' call this instead of swe_azalt(), because it is faster (lower precision
597
+ ' is required)
598
+ */
599
+ static double AppAltfromTopoAlt(double TopoAlt, double TempE, double PresE, int32 helflag)
600
+ {
601
+ /* using methodology of Newtown derivatives (analogue to what Swiss Emphemeris uses)*/
602
+ int i, nloop = 2;
603
+ double newAppAlt = TopoAlt;
604
+ double newTopoAlt = 0.0;
605
+ double oudAppAlt = newAppAlt;
606
+ double oudTopoAlt = newTopoAlt;
607
+ double verschil, retalt;
608
+ if (helflag & SE_HELFLAG_HIGH_PRECISION)
609
+ nloop = 5;
610
+ for (i = 0; i <= nloop; i++) {
611
+ newTopoAlt = newAppAlt - TopoAltfromAppAlt(newAppAlt, TempE, PresE);
612
+ /*newTopoAlt = newAppAlt - swe_refrac(newAppAlt, PresE, TempE, SE_CALC_APP_TO_TRUE);*/
613
+ verschil = newAppAlt - oudAppAlt;
614
+ oudAppAlt = newTopoAlt - oudTopoAlt - verschil;
615
+ if ((verschil != 0) && (oudAppAlt != 0))
616
+ verschil = newAppAlt - verschil * (TopoAlt + newTopoAlt - newAppAlt) / oudAppAlt;
617
+ else
618
+ verschil = TopoAlt + newTopoAlt;
619
+ oudAppAlt = newAppAlt;
620
+ oudTopoAlt = newTopoAlt;
621
+ newAppAlt = verschil;
622
+ }
623
+ retalt = TopoAlt + newTopoAlt;
624
+ if (retalt < LowestAppAlt)
625
+ retalt = TopoAlt;
626
+ return retalt;
627
+ }
628
+
629
+ /*###################################################################
630
+ ' TopoAlt [deg]
631
+ ' TopoDecl [deg]
632
+ ' Lat [deg]
633
+ ' HourAngle [hour]
634
+ */
635
+ static double HourAngle(double TopoAlt, double TopoDecl, double Lat)
636
+ {
637
+ double Alti = TopoAlt * DEGTORAD;
638
+ double decli = TopoDecl * DEGTORAD;
639
+ double Lati = Lat * DEGTORAD;
640
+ double ha = (sin(Alti) - sin(Lati) * sin(decli)) / cos(Lati) / cos(decli);
641
+ if (ha < -1) ha = -1;
642
+ if (ha > 1) ha = 1;
643
+ /* from http://star-www.st-and.ac.uk/~fv/webnotes/chapt12.htm*/
644
+ return acos(ha) / DEGTORAD / 15.0;
645
+ }
646
+
647
+ /*###################################################################
648
+ ' JDNDays [Days]
649
+ ' COD [msec/cy]
650
+ ' DeltaTSE [Sec]
651
+ */
652
+ static double DeltaTSE(double JDNDays, int COD)
653
+ {
654
+ double OffSetYear;
655
+ int gregflag = SE_GREG_CAL;
656
+ if (StartYear < 1583)
657
+ gregflag = SE_JUL_CAL;
658
+ /* from Swiss Emphemeris */
659
+ if (COD != 0) {
660
+ /* Determined by V. Reijs*/
661
+ OffSetYear = (swe_julday((int) StartYear, 1, 1, 0, gregflag) - JDNDays) / 365.25;
662
+ return (OffSetYear * OffSetYear / 100.0 / 2.0 * COD * Y2D) / 1000.0;
663
+ }
664
+ return swe_deltat(JDNDays) * D2S;
665
+ }
666
+
667
+ /*###################################################################
668
+ ' JDNDays [Day]
669
+ ' COD [msec/cy]
670
+ ' DeltaTVR [Sec]
671
+ */
672
+ static double DeltaTVR(double JDNDays, int COD)
673
+ {
674
+ /* Determined by V. Reijs */
675
+ double DeltaTVR;
676
+ int gregflag = SE_GREG_CAL;
677
+ double OffSetYear;
678
+ if (StartYear < 1583)
679
+ gregflag = SE_JUL_CAL;
680
+ OffSetYear = (swe_julday((int) StartYear, 1, 1, 0, gregflag) - JDNDays) / 365.25;
681
+ if (COD == 0) {
682
+ DeltaTVR = (OffSetYear * OffSetYear / 100.0 / 2.0 * Average + Periodicy / 2.0 / PI * Amplitude * (cos((2 * PI * OffSetYear / Periodicy)) - 1)) * Y2D;
683
+ } else {
684
+ DeltaTVR = OffSetYear * OffSetYear / 100.0 / 2.0 * COD * Y2D;
685
+ }
686
+ return DeltaTVR / 1000.0;
687
+ }
688
+
689
+ /*###################################################################
690
+ ' JDNDays [Days]
691
+ ' COD [msec/cy]
692
+ ' DeltaT [Sec]
693
+ */
694
+ static double DeltaT(double JDNDays, int COD)
695
+ {
696
+ if (USE_DELTA_T_VR)
697
+ return DeltaTVR(JDNDays, COD);
698
+ return DeltaTSE(JDNDays, COD);
699
+ }
700
+
701
+ /*###################################################################
702
+ ' JDNDaysUT [Days]
703
+ ' dgeo [array: longitude, latitude, eye height above sea m]
704
+ ' TempE [C]
705
+ ' PresE [mbar]
706
+ ' ObjectName [-]
707
+ ' Angle (0 = TopoAlt, 1 = Azi, 2=Topo Declination, 3=Topo Rectascension, 4=AppAlt,5=Geo Declination, 6=Geo Rectascension)
708
+ ' ObjectLoc [deg]
709
+ */
710
+ static int32 ObjectLoc(double JDNDaysUT, double *dgeo, double *datm, char *ObjectName, int32 Angle, int32 helflag, double *dret, char *serr)
711
+ {
712
+ double x[6], xin[3], xaz[3], tjd_tt;
713
+ int32 Planet;
714
+ int32 epheflag;
715
+ int32 iflag = SEFLG_EQUATORIAL;
716
+ epheflag = helflag & (SEFLG_JPLEPH|SEFLG_SWIEPH|SEFLG_MOSEPH);
717
+ iflag |= epheflag;
718
+ if (!(helflag & SE_HELFLAG_HIGH_PRECISION))
719
+ iflag |= SEFLG_NONUT | SEFLG_TRUEPOS;
720
+ if (Angle < 5) iflag = iflag | SEFLG_TOPOCTR;
721
+ if (Angle == 7) Angle = 0;
722
+ tjd_tt = JDNDaysUT + DeltaT(JDNDaysUT, 0) / D2S;
723
+ Planet = DeterObject(ObjectName);
724
+ if (Planet != -1) {
725
+ if (swe_calc(tjd_tt, Planet, iflag, x, serr) == ERR)
726
+ return ERR;
727
+ } else {
728
+ if (call_swe_fixstar(ObjectName, tjd_tt, iflag, x, serr) == ERR)
729
+ return ERR;
730
+ }
731
+ if (Angle == 2 || Angle == 5) {
732
+ *dret = x[1];
733
+ } else {
734
+ if (Angle == 3 || Angle == 6) {
735
+ *dret = x[0];
736
+ } else {
737
+ xin[0] = x[0];
738
+ xin[1] = x[1];
739
+ swe_azalt(JDNDaysUT, SE_EQU2HOR, dgeo, datm[0], datm[1], xin, xaz);
740
+ if (Angle == 0)
741
+ *dret = xaz[1];
742
+ if (Angle == 4)
743
+ *dret = AppAltfromTopoAlt(xaz[1], datm[0], datm[1], helflag);
744
+ if (Angle == 1) {
745
+ xaz[0] += 180;
746
+ if (xaz[0] >= 360)
747
+ xaz[0] -= 360;
748
+ *dret = xaz[0];
749
+ }
750
+ }
751
+ }
752
+ return OK;
753
+ }
754
+
755
+ /*###################################################################
756
+ ' JDNDaysUT [Days]
757
+ ' dgeo [array: longitude, latitude, eye height above sea m]
758
+ ' TempE [C]
759
+ ' PresE [mbar]
760
+ ' ObjectName [-]
761
+ ' Angle (0 = TopoAlt, 1 = Azi, 2=Topo Declination, 3=Topo Rectascension, 4=AppAlt,5=Geo Declination, 6=Geo Rectascension)
762
+ ' ObjectLoc [deg]
763
+ */
764
+ static int32 azalt_cart(double JDNDaysUT, double *dgeo, double *datm, char *ObjectName, int32 helflag, double *dret, char *serr)
765
+ {
766
+ double x[6], xin[3], xaz[3], tjd_tt;
767
+ int32 Planet;
768
+ int32 epheflag;
769
+ int32 iflag = SEFLG_EQUATORIAL;
770
+ epheflag = helflag & (SEFLG_JPLEPH|SEFLG_SWIEPH|SEFLG_MOSEPH);
771
+ iflag |= epheflag;
772
+ if (!(helflag & SE_HELFLAG_HIGH_PRECISION))
773
+ iflag |= SEFLG_NONUT | SEFLG_TRUEPOS;
774
+ iflag = iflag | SEFLG_TOPOCTR;
775
+ tjd_tt = JDNDaysUT + DeltaT(JDNDaysUT, 0) / D2S;
776
+ Planet = DeterObject(ObjectName);
777
+ if (Planet != -1) {
778
+ if (swe_calc(tjd_tt, Planet, iflag, x, serr) == ERR)
779
+ return ERR;
780
+ } else {
781
+ if (call_swe_fixstar(ObjectName, tjd_tt, iflag, x, serr) == ERR)
782
+ return ERR;
783
+ }
784
+ xin[0] = x[0];
785
+ xin[1] = x[1];
786
+ swe_azalt(JDNDaysUT, SE_EQU2HOR, dgeo, datm[0], datm[1], xin, xaz);
787
+ dret[0] = xaz[0];
788
+ dret[1] = xaz[1]; /* true altitude */
789
+ dret[2] = xaz[2]; /* apparent altitude */
790
+ /* also return cartesian coordinates, for apparent altitude */
791
+ xaz[1] = xaz[2];
792
+ xaz[2] = 1;
793
+ swi_polcart(xaz, xaz);
794
+ dret[3] = xaz[0];
795
+ dret[4] = xaz[1];
796
+ dret[5] = xaz[2];
797
+ return OK;
798
+ }
799
+
800
+ /*###################################################################
801
+ ' LatA [rad]
802
+ ' LongA [rad]
803
+ ' LatB [rad]
804
+ ' LongB [rad]
805
+ ' DistanceAngle [rad]
806
+ */
807
+ static double DistanceAngle(double LatA, double LongA, double LatB, double LongB)
808
+ {
809
+ double dlon = LongB - LongA;
810
+ double dlat = LatB - LatA;
811
+ /* Haversine formula
812
+ * http://www.movable-type.co.uk/scripts/GIS-FAQ-5.1.html
813
+ * R.W. Sinnott, Virtues of the Haversine, Sky and Telescope, vol. 68, no. 2, 1984, p. 159
814
+ */
815
+ double sindlat2 = sin(dlat / 2);
816
+ double sindlon2 = sin(dlon / 2);
817
+ double corde = sindlat2 * sindlat2 + cos(LatA) * cos(LatB) * sindlon2 *sindlon2;
818
+ if (corde > 1) corde = 1;
819
+ return 2 * asin(sqrt(corde));
820
+ }
821
+
822
+ /*###################################################################
823
+ ' heighteye [m]
824
+ ' TempS [C]
825
+ ' RH [%]
826
+ ' kW [-]
827
+ */
828
+ static double kW(double HeightEye, double TempS, double RH)
829
+ {
830
+ /* From Schaefer , Archaeoastronomy, XV, 2000, page 128*/
831
+ double WT = 0.031;
832
+ WT *= 0.94 * (RH / 100.0) * exp(TempS / 15) * exp(-1 * HeightEye / scaleHwater);
833
+ return WT;
834
+ }
835
+
836
+ /*###################################################################
837
+ ' JDNDaysUT [-]
838
+ ' AltS [deg]
839
+ ' lat [deg]
840
+ ' kOZ [-]
841
+ */
842
+ static double kOZ(double AltS, double sunra, double Lat)
843
+ {
844
+ double CHANGEKO, OZ, LT, kOZret;
845
+ static double koz_last, alts_last, sunra_last;
846
+ if (AltS == alts_last && sunra == sunra_last)
847
+ return koz_last;
848
+ alts_last = AltS; sunra_last = sunra;
849
+ OZ = 0.031;
850
+ LT = Lat * DEGTORAD;
851
+ /* From Schaefer , Archaeoastronomy, XV, 2000, page 128*/
852
+ kOZret = OZ * (3.0 + 0.4 * (LT * cos(sunra * DEGTORAD) - cos(3 * LT))) / 3.0;
853
+ /* depending on day/night vision (altitude of sun < start astronomical twilight), KO changes from 100% to 30%
854
+ * see extinction section of Vistas in Astronomy page 343*/
855
+ CHANGEKO = (100 - 11.6 * mymin(6, mymax(-AltS - 12, 0))) / 100;
856
+ koz_last = kOZret * CHANGEKO;
857
+ return koz_last;
858
+ }
859
+
860
+ /*###################################################################
861
+ ' AltS [deg]
862
+ ' heighteye [m]
863
+ ' kR [-]
864
+ */
865
+ static double kR(double AltS, double HeightEye)
866
+ {
867
+ /* depending on day/night vision (altitude of sun < start astronomical twilight),
868
+ * lambda eye sensibility changes
869
+ * see extinction section of Vistas in Astronomy page 343*/
870
+ double CHANGEK, LAMBDA;
871
+ double val = -AltS - 12;
872
+ if (val < 0) val = 0;
873
+ if (val > 6) val = 6;
874
+ /*CHANGEK = (1 - 0.166667 * Min(6, Max(-AltS - 12, 0)));*/
875
+ CHANGEK = (1 - 0.166667 * val );
876
+ LAMBDA = 0.55 + (CHANGEK - 1) * 0.04;
877
+ /* From Schaefer , Archaeoastronomy, XV, 2000, page 128 */
878
+ return 0.1066 * exp(-1 * HeightEye / scaleHrayleigh) * pow(LAMBDA / 0.55 , -4);
879
+ }
880
+
881
+ static int Sgn(double x)
882
+ {
883
+ if (x < 0)
884
+ return -1;
885
+ return 1;
886
+ }
887
+
888
+ /*###################################################################
889
+ ' JDNDaysUT [-]
890
+ ' AltS [deg]
891
+ ' lat [deg]
892
+ ' heighteye [m]
893
+ ' TempS [C]
894
+ ' RH [%]
895
+ ' VR [km]
896
+ ' ka [-]
897
+ */
898
+ static double ka(double AltS, double sunra, double Lat, double HeightEye, double TempS, double RH, double VR, char *serr)
899
+ {
900
+ double CHANGEKA, LAMBDA, BetaVr, Betaa, kaact;
901
+ double SL = Sgn(Lat);
902
+ /* depending on day/night vision (altitude of sun < start astronomical twilight),
903
+ * lambda eye sensibility changes
904
+ * see extinction section of Vistas in Astronomy page 343 */
905
+ static double alts_last, sunra_last, ka_last;
906
+ if (AltS == alts_last && sunra == sunra_last)
907
+ return ka_last;
908
+ alts_last = AltS; sunra_last = sunra;
909
+ CHANGEKA = (1 - 0.166667 * mymin(6, mymax(-AltS - 12, 0)));
910
+ LAMBDA = 0.55 + (CHANGEKA - 1) * 0.04;
911
+ if (VR != 0) {
912
+ if (VR >= 1) {
913
+ /* Visbility range from http://www1.cs.columbia.edu/CAVE/publications/pdfs/Narasimhan_CVPR03.pdf
914
+ * http://www.icao.int/anb/SG/AMOSSG/meetings/amossg3/wp/SN11Rev.pdf where MOR=2.995/ke
915
+ * factor 1.3 is the relation between "prevailing visibility" and
916
+ * meteorological range was derived by Koshmeider in the 1920's */
917
+ BetaVr = 3.912 / VR;
918
+ Betaa = BetaVr - (kW(HeightEye, TempS, RH) / scaleHwater + kR(AltS, HeightEye) / scaleHrayleigh) * 1000 * astr2tau;
919
+ kaact = Betaa * scaleHaerosol / 1000 * tau2astr;
920
+ if (kaact < 0) {
921
+ if (serr != NULL)
922
+ strcpy(serr, "The provided Meteorological range is too long, when taking into acount other atmospheric parameters"); /* is a warning */
923
+ /* return 0; * return "#HIGHVR"; */
924
+ }
925
+ } else {
926
+ kaact = VR - kW(HeightEye, TempS, RH) - kR(AltS, HeightEye) - kOZ(AltS, sunra, Lat);
927
+ if (kaact < 0) {
928
+ if (serr != NULL)
929
+ strcpy(serr, "The provided atmosphic coeefficent (ktot) is too low, when taking into acount other atmospheric parameters"); /* is a warning */
930
+ /* return 0; * "#LOWktot"; */
931
+ }
932
+ }
933
+ } else {
934
+ /* From Schaefer , Archaeoastronomy, XV, 2000, page 128 */
935
+ #ifdef SIMULATE_VICTORVB
936
+ if (RH <= 0.00000001) RH = 0.00000001;
937
+ if (RH >= 99.99999999) RH = 99.99999999;
938
+ #endif
939
+ kaact = 0.1 * exp(-1 * HeightEye / scaleHaerosol) * pow(1 - 0.32 / log(RH / 100.0), 1.33) * (1 + 0.33 * SL * sin(sunra * DEGTORAD));
940
+ kaact = kaact * pow(LAMBDA / 0.55, -1.3);
941
+ }
942
+ ka_last = kaact;
943
+ return kaact;
944
+ }
945
+
946
+ /*###################################################################
947
+ ' JDNDaysUT [-]
948
+ ' AltS [deg]
949
+ ' lat [deg]
950
+ ' heighteye [m]
951
+ ' TempS [C]
952
+ ' RH [%]
953
+ ' VR [km]
954
+ ' ExtType [0=ka,1=kW,2=kR,3=kOZ,4=ktot]
955
+ ' kt [-]
956
+ */
957
+ static double kt(double AltS, double sunra, double Lat, double HeightEye, double TempS, double RH, double VR, int32 ExtType, char *serr)
958
+ {
959
+ double kRact = 0;
960
+ double kWact = 0;
961
+ double kOZact = 0;
962
+ double kaact = 0;
963
+ if (ExtType == 2 || ExtType == 4)
964
+ kRact = kR(AltS, HeightEye);
965
+ if (ExtType == 1 || ExtType == 4)
966
+ kWact = kW(HeightEye, TempS, RH);
967
+ if (ExtType == 3 || ExtType == 4)
968
+ kOZact = kOZ(AltS, sunra, Lat);
969
+ if (ExtType == 0 || ExtType == 4)
970
+ kaact = ka(AltS, sunra, Lat, HeightEye, TempS, RH, VR, serr);
971
+ if (kaact < 0)
972
+ kaact = 0;
973
+ return kWact + kRact + kOZact + kaact;
974
+ }
975
+
976
+ /*###################################################################
977
+ ' AppAlt0 [deg]
978
+ ' PresS [mbar]
979
+ ' Airmass [??]
980
+ */
981
+ static double Airmass(double AppAltO, double Press)
982
+ {
983
+ double airm, zend;
984
+ zend = (90 - AppAltO) * DEGTORAD;
985
+ if (zend > PI / 2)
986
+ zend = PI / 2;
987
+ airm = 1 / (cos(zend) + 0.025 * exp(-11 * cos(zend)));
988
+ return Press / 1013 * airm;
989
+ }
990
+
991
+ /*###################################################################
992
+ ' scaleH '[m]
993
+ ' zend [rad]
994
+ ' PresS [mbar]
995
+ ' Xext [-]
996
+ */
997
+ static double Xext(double scaleH, double zend, double Press)
998
+ {
999
+ return Press / 1013.0 / (cos(zend) + 0.01 * sqrt(scaleH / 1000.0) * exp(-30.0 / sqrt(scaleH / 1000.0) * cos(zend)));
1000
+ }
1001
+
1002
+ /*###################################################################
1003
+ ' scaleH '[m]
1004
+ ' zend [rad]
1005
+ ' PresS [mbar]
1006
+ ' Xlay [-]
1007
+ */
1008
+ static double Xlay(double scaleH, double zend, double Press)
1009
+ {
1010
+ /*return Press / 1013.0 / sqrt(1.0 - pow(sin(zend) / (1.0 + (scaleH / Ra)), 2));*/
1011
+ double a = sin(zend) / (1.0 + (scaleH / Ra));
1012
+ return Press / 1013.0 / sqrt(1.0 - a * a);
1013
+ }
1014
+
1015
+ /*###################################################################
1016
+ ' Meteorological formula
1017
+ '###################################################################
1018
+ ' TempS [C]
1019
+ ' HeightEye [m]
1020
+ ' TempEfromTempS [C]
1021
+ */
1022
+ static double TempEfromTempS(double TempS, double HeightEye, double Lapse)
1023
+ {
1024
+ return TempS - Lapse * HeightEye;
1025
+ }
1026
+
1027
+ /*###################################################################
1028
+ ' TempS [C]
1029
+ ' PresS [mbar]
1030
+ ' HeightEye [m]
1031
+ ' PresEfromPresS [mbar]
1032
+ */
1033
+ static double PresEfromPresS(double TempS, double Press, double HeightEye)
1034
+ {
1035
+ return Press * exp(-9.80665 * 0.0289644 / (Kelvin(TempS) + 3.25 * HeightEye / 1000) / 8.31441 * HeightEye);
1036
+ }
1037
+
1038
+ /*###################################################################
1039
+ ' AltO [deg]
1040
+ ' JDNDaysUT [-]
1041
+ ' AltS [deg]
1042
+ ' lat [deg]
1043
+ ' heighteye [m]
1044
+ ' TempS [C]
1045
+ ' PresS [mbar]
1046
+ ' RH [%]
1047
+ ' VR [km]
1048
+ ' Deltam [-]
1049
+ */
1050
+ static double Deltam(double AltO, double AltS, double sunra, double Lat, double HeightEye, double *datm, int32 helflag, char *serr)
1051
+ {
1052
+ double zend, xR, XW, Xa, XOZ;
1053
+ double PresE = PresEfromPresS(datm[1], datm[0], HeightEye);
1054
+ double TempE = TempEfromTempS(datm[1], HeightEye, LapseSA);
1055
+ double AppAltO = AppAltfromTopoAlt(AltO, TempE, PresE, helflag);
1056
+ double deltam;
1057
+ static double alts_last, alto_last, sunra_last, deltam_last;
1058
+ if (AltS == alts_last && AltO == alto_last && sunra == sunra_last)
1059
+ return deltam_last;
1060
+ alts_last = AltS; alto_last = AltO; sunra_last = sunra;
1061
+ if (staticAirmass == 0) {
1062
+ zend = (90 - AppAltO) * DEGTORAD;
1063
+ if (zend > PI / 2)
1064
+ zend = PI / 2;
1065
+ /* From Schaefer , Archaeoastronomy, XV, 2000, page 128*/
1066
+ xR = Xext(scaleHrayleigh, zend, datm[0]);
1067
+ XW = Xext(scaleHwater, zend, datm[0]);
1068
+ Xa = Xext(scaleHaerosol, zend, datm[0]);
1069
+ XOZ = Xlay(scaleHozone, zend, datm[0]);
1070
+ deltam = kR(AltS, HeightEye) * xR + kt(AltS, sunra, Lat, HeightEye, datm[1], datm[2], datm[3], 0, serr) * Xa + kOZ(AltS, sunra, Lat) * XOZ + kW(HeightEye, datm[1], datm[2]) * XW;
1071
+ } else {
1072
+ deltam = kt(AltS, sunra, Lat, HeightEye, datm[1], datm[2], datm[3], 4, serr) * Airmass(AppAltO, datm[0]);
1073
+ }
1074
+ deltam_last = deltam;
1075
+ return deltam;
1076
+ }
1077
+
1078
+ /*###################################################################
1079
+ ' AltO [deg]
1080
+ ' JDNDaysUT [-]
1081
+ ' AltS [deg]
1082
+ ' lat [deg]
1083
+ ' heighteye [m]
1084
+ ' TempS [C]
1085
+ ' PresS [mbar]
1086
+ ' RH [%]
1087
+ ' VR [km]
1088
+ ' Bn [nL]
1089
+ */
1090
+ static double Bn(double AltO, double JDNDayUT, double AltS, double sunra, double Lat, double HeightEye, double *datm, int32 helflag, char *serr)
1091
+ {
1092
+ double PresE = PresEfromPresS(datm[1], datm[0], HeightEye);
1093
+ double TempE = TempEfromTempS(datm[1], HeightEye, LapseSA);
1094
+ double AppAltO = AppAltfromTopoAlt(AltO, TempE, PresE, helflag);
1095
+ double zend, YearB, MonthB, DayB, Bna, kX, Bnb;
1096
+ double B0 = 0.0000000000001, dut;
1097
+ int iyar, imon, iday;
1098
+ /* Below altitude of 10 degrees, the Bn stays the same (see page 343 Vistas in Astronomy) */
1099
+ if (AppAltO < 10)
1100
+ AppAltO = 10;
1101
+ zend = (90 - AppAltO) * DEGTORAD;
1102
+ /* From Schaefer , Archaeoastronomy, XV, 2000, page 128 and adjusted for sunspot period*/
1103
+ /*YearB = DatefromJDut(JDNDayUT, 1);
1104
+ MonthB = DatefromJDut(JDNDayUT, 2);
1105
+ DayB = DatefromJDut(JDNDayUT, 3);*/
1106
+ swe_revjul(JDNDayUT, SE_GREG_CAL, &iyar, &imon, &iday, &dut);
1107
+ YearB = iyar; MonthB = imon; DayB = iday;
1108
+ Bna = B0 * (1 + 0.3 * cos(6.283 * (YearB + ((DayB - 1) / 30.4 + MonthB - 1) / 12 - 1990.33) / 11.1));
1109
+ kX = Deltam(AltO, AltS, sunra, Lat, HeightEye, datm, helflag, serr);
1110
+ /* From Schaefer , Archaeoastronomy, XV, 2000, page 129 */
1111
+ Bnb = Bna * (0.4 + 0.6 / sqrt(1 - 0.96 * pow(sin(zend), 2))) * pow(10, -0.4 * kX);
1112
+ return mymax(Bnb, 0) * erg2nL;
1113
+ }
1114
+
1115
+ /*###################################################################
1116
+ ' JDNDaysUT [-]
1117
+ ' dgeo [array: longitude, latitude, eye height above sea m]
1118
+ ' TempE [C]
1119
+ ' PresE [mbar]
1120
+ ' ObjectName [-]
1121
+ ' Magnitude [-]
1122
+ */
1123
+ static int32 Magnitude(double JDNDaysUT, double *dgeo, char *ObjectName, int32 helflag, double *dmag, char *serr)
1124
+ {
1125
+ double x[20];
1126
+ int32 Planet, iflag, epheflag;
1127
+ epheflag = helflag & (SEFLG_JPLEPH|SEFLG_SWIEPH|SEFLG_MOSEPH);
1128
+ *dmag = -99.0;
1129
+ Planet = DeterObject(ObjectName);
1130
+ iflag = SEFLG_TOPOCTR | SEFLG_EQUATORIAL | epheflag;
1131
+ if (!(helflag & SE_HELFLAG_HIGH_PRECISION))
1132
+ iflag |= SEFLG_NONUT|SEFLG_TRUEPOS;
1133
+ if (Planet != -1) {
1134
+ /**dmag = Phenomena(JDNDaysUT, Lat, Longitude, HeightEye, TempE, PresE, ObjectName, 4);*/
1135
+ swe_set_topo(dgeo[0], dgeo[1], dgeo[2]);
1136
+ if (swe_pheno_ut(JDNDaysUT, Planet, iflag, x, serr) == ERR)
1137
+ return ERR;
1138
+ *dmag = x[4];
1139
+ } else {
1140
+ if (call_swe_fixstar_mag(ObjectName, dmag, serr) == ERR)
1141
+ return ERR;
1142
+ }
1143
+ return OK;
1144
+ }
1145
+
1146
+ #if 0
1147
+ static int32 fast_magnitude(double tjd, double *dgeo, char *ObjectName, int32 helflag, double *dmag, char *serr)
1148
+ {
1149
+ int32 retval = OK, ipl, ipli;
1150
+ double dtjd;
1151
+ static double tjdsv[3];
1152
+ static double dmagsv[3];
1153
+ static int32 helflagsv[3];
1154
+ ipl = DeterObject(ObjectName);
1155
+ ipli = ipl;
1156
+ if (ipli > SE_MOON)
1157
+ ipli = 2;
1158
+ dtjd = tjd - tjdsv[ipli];
1159
+ if (tjdsv[ipli] != 0 && helflag == helflagsv[ipli] && fabs(dtjd) < 5.0 / 1440.0) {
1160
+ *dmag = dmagsv[ipli];
1161
+ } else {
1162
+ retval = Magnitude(tjd, dgeo, ObjectName, helflag, dmag, serr);
1163
+ tjdsv[ipli] = tjd;
1164
+ helflagsv[ipli] = helflag;
1165
+ dmagsv[ipli] = *dmag;
1166
+ }
1167
+ return retval;
1168
+ }
1169
+ #endif
1170
+
1171
+ /*###################################################################
1172
+ ' dist [km]
1173
+ ' phasemoon [-]
1174
+ ' MoonsBrightness [-]
1175
+ */
1176
+ static double MoonsBrightness(double dist, double phasemoon)
1177
+ {
1178
+ double log10 = 2.302585092994;
1179
+ /*Moon's brightness changes with distance: http://hem.passagen.se/pausch/comp/ppcomp.html#15 */
1180
+ return -21.62 + 5 * log(dist / (Ra / 1000)) / log10 + 0.026 * fabs(phasemoon) + 0.000000004 * pow(phasemoon, 4);
1181
+ }
1182
+
1183
+ /*###################################################################
1184
+ ' AltM [deg]
1185
+ ' AziM [deg]
1186
+ ' AziS [deg]
1187
+ ' MoonPhase [deg]
1188
+ */
1189
+ static double MoonPhase(double AltM, double AziM, double AziS)
1190
+ {
1191
+ double AltMi = AltM * DEGTORAD;
1192
+ double AziMi = AziM * DEGTORAD;
1193
+ double AziSi = AziS * DEGTORAD;
1194
+ return 180 - acos(cos(AziSi - AziMi) * cos(AltMi + 0.95 * DEGTORAD)) / DEGTORAD;
1195
+ }
1196
+
1197
+ /*###################################################################
1198
+ ' Pressure [mbar]
1199
+ */
1200
+ static double Bm(double AltO, double AziO, double AltM, double AziM, double AltS, double AziS, double sunra, double Lat, double HeightEye, double *datm, int32 helflag, char *serr)
1201
+ {
1202
+ double M0 = -11.05;
1203
+ double Bm = 0;
1204
+ double RM, kXM, kX, C3, FM, phasemoon, MM;
1205
+ if (AltM > -0.26) {
1206
+ /* moon only adds light when (partly) above horizon
1207
+ * From Schaefer , Archaeoastronomy, XV, 2000, page 129*/
1208
+ RM = DistanceAngle(AltO * DEGTORAD, AziO * DEGTORAD, AltM * DEGTORAD, AziM * DEGTORAD) / DEGTORAD;
1209
+ kXM = Deltam(AltM, AltS, sunra, Lat, HeightEye, datm, helflag, serr);
1210
+ kX = Deltam(AltO, AltS, sunra, Lat, HeightEye, datm, helflag, serr);
1211
+ C3 = pow(10, -0.4 * kXM);
1212
+ FM = (62000000.0) / RM / RM + pow(10, 6.15 - RM / 40) + pow(10, 5.36) * (1.06 + pow(cos(RM * DEGTORAD), 2));
1213
+ Bm = FM * C3 + 440000 * (1 - C3);
1214
+ phasemoon = MoonPhase(AltM, AziM, AziS);
1215
+ MM = MoonsBrightness(MoonDistance, phasemoon);
1216
+ Bm = Bm * pow(10, -0.4 * (MM - M0 + 43.27));
1217
+ Bm = Bm * (1 - pow(10, -0.4 * kX));
1218
+ }
1219
+ Bm = mymax(Bm, 0) * erg2nL;
1220
+ return Bm;
1221
+ }
1222
+
1223
+ /*###################################################################
1224
+ ' Pressure [mbar]
1225
+ */
1226
+ static double Btwi(double AltO, double AziO, double AltS, double AziS, double sunra, double Lat, double HeightEye, double *datm, int32 helflag, char *serr)
1227
+ {
1228
+ double M0 = -11.05;
1229
+ double MS = -26.74;
1230
+ double PresE = PresEfromPresS(datm[1], datm[0], HeightEye);
1231
+ double TempE = TempEfromTempS(datm[1], HeightEye, LapseSA);
1232
+ double AppAltO = AppAltfromTopoAlt(AltO, TempE, PresE, helflag);
1233
+ double ZendO = 90 - AppAltO;
1234
+ double RS = DistanceAngle(AltO * DEGTORAD, AziO * DEGTORAD, AltS * DEGTORAD, AziS * DEGTORAD) / DEGTORAD;
1235
+ double kX = Deltam(AltO, AltS, sunra, Lat, HeightEye, datm, helflag, serr);
1236
+ double k = kt(AltS, sunra, Lat, HeightEye, datm[1], datm[2], datm[3], 4, serr);
1237
+ /* From Schaefer , Archaeoastronomy, XV, 2000, page 129*/
1238
+ double Btwi = pow(10, -0.4 * (MS - M0 + 32.5 - AltS - (ZendO / (360 * k))));
1239
+ Btwi = Btwi * (100 / RS) * (1 - pow(10, -0.4 * kX));
1240
+ Btwi = mymax(Btwi, 0) * erg2nL;
1241
+ return Btwi;
1242
+ }
1243
+
1244
+ /*###################################################################
1245
+ ' Pressure [mbar]
1246
+ */
1247
+ static double Bday(double AltO, double AziO, double AltS, double AziS, double sunra, double Lat, double HeightEye, double *datm, int32 helflag, char *serr)
1248
+ {
1249
+ double M0 = -11.05;
1250
+ double MS = -26.74;
1251
+ double RS = DistanceAngle(AltO * DEGTORAD, AziO * DEGTORAD, AltS * DEGTORAD, AziS * DEGTORAD) / DEGTORAD;
1252
+ double kXS = Deltam(AltS, AltS, sunra, Lat, HeightEye, datm, helflag, serr);
1253
+ double kX = Deltam(AltO, AltS, sunra, Lat, HeightEye, datm, helflag, serr);
1254
+ /* From Schaefer , Archaeoastronomy, XV, 2000, page 129*/
1255
+ double C4 = pow(10, -0.4 * kXS);
1256
+ double FS = (62000000.0) / RS / RS + pow(10, (6.15 - RS / 40)) + pow(10, 5.36) * (1.06 + pow(cos(RS * DEGTORAD), 2));
1257
+ double Bday = FS * C4 + 440000.0 * (1 - C4);
1258
+ Bday = Bday * pow(10, (-0.4 * (MS - M0 + 43.27)));
1259
+ Bday = Bday * (1 - pow(10, -0.4 * kX));
1260
+ Bday = mymax(Bday, 0) * erg2nL;
1261
+ return Bday;
1262
+ }
1263
+
1264
+ /*###################################################################
1265
+ ' Value [nL]
1266
+ ' PresS [mbar]
1267
+ ' Bcity [nL]
1268
+ */
1269
+ static double Bcity(double Value, double Press)
1270
+ {
1271
+ double Bcity = Value;
1272
+ Bcity = mymax(Bcity, 0);
1273
+ return Bcity;
1274
+ }
1275
+
1276
+ /*###################################################################
1277
+ ' Pressure [mbar]
1278
+ */
1279
+ static double Bsky(double AltO, double AziO, double AltM, double AziM, double JDNDaysUT, double AltS, double AziS, double sunra, double Lat, double HeightEye, double *datm, int32 helflag, char *serr)
1280
+ {
1281
+ double Bsky = 0;
1282
+ if (AltS < -3) {
1283
+ Bsky += Btwi(AltO, AziO, AltS, AziS, sunra, Lat, HeightEye, datm, helflag, serr);
1284
+ } else {
1285
+ if (AltS > 4) {
1286
+ Bsky += Bday(AltO, AziO, AltS, AziS, sunra, Lat, HeightEye, datm, helflag, serr);
1287
+ } else {
1288
+ Bsky += mymin(Bday(AltO, AziO, AltS, AziS, sunra, Lat, HeightEye, datm, helflag, serr), Btwi(AltO, AziO, AltS, AziS, sunra, Lat, HeightEye, datm, helflag, serr));
1289
+ }
1290
+ }
1291
+ /* if max. Bm [1E7] <5% of Bsky don't add Bm*/
1292
+ if (Bsky < 200000000.0)
1293
+ Bsky += Bm(AltO, AziO, AltM, AziM, AltS, AziS, sunra, Lat, HeightEye, datm, helflag, serr);
1294
+ if (AltS <= 0)
1295
+ Bsky += Bcity(0, datm[0]);
1296
+ /* if max. Bn [250] <5% of Bsky don't add Bn*/
1297
+ if (Bsky < 5000)
1298
+ Bsky = Bsky + Bn(AltO, JDNDaysUT, AltS, sunra, Lat, HeightEye, datm, helflag, serr);
1299
+ /* if max. Bm [1E7] <5% of Bsky don't add Bm*/
1300
+ return Bsky;
1301
+ }
1302
+
1303
+ /* default handling:
1304
+ * 1. datm (atmospheric conditions):
1305
+ * datm consists of
1306
+ * [0] atmospheric pressure
1307
+ * [1] temperature
1308
+ * [2] relative humidity
1309
+ * [3] extinction coefficient
1310
+ * In order to get default values for [0..2], set datm[0] = 0.
1311
+ * Default values for [1-2] are only provided if [0] == 0.
1312
+ * [3] defaults outside this function, depending on [0-2].
1313
+ *
1314
+ * 2. dobs (observer definition):
1315
+ * [0] age (default 36)
1316
+ * [1] Snellen ratio or visual acuity of observer (default 1)
1317
+ */
1318
+ static void default_heliacal_parameters(double *datm, double *dgeo, double *dobs, int helflag)
1319
+ {
1320
+ int i;
1321
+ if (datm[0] <= 0) {
1322
+ /* estimate atmospheric pressure, according to the
1323
+ * International Standard Atmosphere (ISA) */
1324
+ datm[0] = 1013.25 * pow(1 - 0.0065 * dgeo[2] / 288, 5.255);
1325
+ /* temperature */
1326
+ if (datm[1] == 0)
1327
+ datm[1] = 15 - 0.0065 * dgeo[2];
1328
+ /* relative humidity, independent of atmospheric pressure and altitude */
1329
+ if (datm[2] == 0)
1330
+ datm[2] = 40;
1331
+ /* note: datm[3] / VR defaults outside this function */
1332
+ } else {
1333
+ #ifndef SIMULATE_VICTORVB
1334
+ if (datm[2] <= 0.00000001) datm[2] = 0.00000001;
1335
+ if (datm[2] >= 99.99999999) datm[2] = 99.99999999;
1336
+ #endif
1337
+ }
1338
+ /* age of observer */
1339
+ if (dobs[0] == 0)
1340
+ dobs[0] = 36;
1341
+ /* SN Snellen factor of the visual acuity of the observer */
1342
+ if (dobs[1] == 0)
1343
+ dobs[1] = 1;
1344
+ if (!(helflag & SE_HELFLAG_OPTICAL_PARAMS)) {
1345
+ for (i = 2; i <= 5; i++)
1346
+ dobs[i] = 0;
1347
+ }
1348
+ /* OpticMagn undefined -> use eye */
1349
+ if (dobs[3] == 0) {
1350
+ dobs[2] = 1; /* Binocular = 1 */
1351
+ dobs[3] = 1; /* OpticMagn = 1: use eye */
1352
+ /* dobs[4] and dobs[5] (OpticDia and OpticTrans) will be defaulted in
1353
+ * OpticFactor() */
1354
+ }
1355
+ }
1356
+
1357
+ /*###################################################################
1358
+ ' age [Year]
1359
+ ' SN [-]
1360
+ ' AltO [deg]
1361
+ ' AziO [deg]
1362
+ ' AltM [deg]
1363
+ ' AziM [deg]
1364
+ ' MoonDistance [km]
1365
+ ' JDNDaysUT [-]
1366
+ ' AltS [deg]
1367
+ ' AziS [deg]
1368
+ ' lat [deg]
1369
+ ' heighteye [m]
1370
+ ' TempS [C]
1371
+ ' PresS [mbar]
1372
+ ' RH [%]
1373
+ ' VR [km]
1374
+ ' VisLimMagn [-]
1375
+ */
1376
+ static double VisLimMagn(double *dobs, double AltO, double AziO, double AltM, double AziM, double JDNDaysUT, double AltS, double AziS, double sunra, double Lat, double HeightEye, double *datm, int32 helflag, int32 *scotopic_flag, char *serr)
1377
+ {
1378
+ double C1, C2, Th, kX, Bsk, CorrFactor1, CorrFactor2;
1379
+ double log10 = 2.302585092994;
1380
+ /*double Age = dobs[0];*/
1381
+ /*double SN = dobs[1];*/
1382
+ Bsk = Bsky(AltO, AziO, AltM, AziM, JDNDaysUT, AltS, AziS, sunra, Lat, HeightEye, datm, helflag, serr);
1383
+ /* Schaefer, Astronomy and the limits of vision, Archaeoastronomy, 1993 Verder:*/
1384
+ kX = Deltam(AltO, AltS, sunra, Lat, HeightEye, datm, helflag, serr);
1385
+ /* influence of age*/
1386
+ /*Fa = mymax(1, pow(p(23, Bsk) / p(Age, Bsk), 2)); */
1387
+ CorrFactor1 = OpticFactor(Bsk, kX, dobs, JDNDaysUT, "", 1, helflag);
1388
+ CorrFactor2 = OpticFactor(Bsk, kX, dobs, JDNDaysUT, "", 0, helflag);
1389
+ /* From Schaefer , Archaeoastronomy, XV, 2000, page 129*/
1390
+ if (Bsk < BNIGHT && !(helflag & SE_HELFLAG_VISLIM_PHOTOPIC)) {
1391
+ C1 = 1.5848931924611e-10; /*pow(10, -9.8);*/ /* C1 = 10 ^ (-9.8);*/
1392
+ C2 = 0.012589254117942; /*pow(10, -1.9);*/ /* C2 = 10 ^ (-1.9);*/
1393
+ if (scotopic_flag != NULL)
1394
+ *scotopic_flag = 1;
1395
+ } else {
1396
+ C1 = 4.4668359215096e-9; /*pow(10, -8.35);*/ /* C1 = 10 ^ (-8.35);*/
1397
+ C2 = 1.2589254117942e-6; /*pow(10, -5.9);*/ /* C2 = 10 ^ (-5.9);*/
1398
+ if (scotopic_flag != NULL)
1399
+ *scotopic_flag = 0;
1400
+ }
1401
+ if (scotopic_flag != NULL) {
1402
+ if (BNIGHT * BNIGHT_FACTOR > Bsk && BNIGHT / BNIGHT_FACTOR < Bsk)
1403
+ *scotopic_flag |= 2;
1404
+ }
1405
+ /*Th = C1 * pow(1 + sqrt(C2 * Bsk), 2) * Fa;*/
1406
+ Bsk = Bsk / CorrFactor1;
1407
+ Th = C1 * pow(1 + sqrt(C2 * Bsk), 2) * CorrFactor2;
1408
+ #if DEBUG
1409
+ fprintf(stderr, "Bsk=%f\n", Bsk);
1410
+ fprintf(stderr, "kX =%f\n", kX);
1411
+ fprintf(stderr, "Th =%f\n", Th);
1412
+ fprintf(stderr, "CorrFactor1=%f\n", CorrFactor1);
1413
+ fprintf(stderr, "CorrFactor2=%f\n", CorrFactor2);
1414
+ #endif
1415
+ /* Visual limiting magnitude of point source*/
1416
+ #if 0
1417
+ if (SN <= 0.00000001)
1418
+ SN = 0.00000001;
1419
+ return -16.57 - 2.5 * (log(Th) / log10) - kX + 5.0 * (log(SN) / log10);*/
1420
+ #endif
1421
+ return -16.57 - 2.5 * (log(Th) / log10);
1422
+ }
1423
+
1424
+ /* Limiting magnitude in dark skies
1425
+ * function returns:
1426
+ * -1 Error
1427
+ * -2 Object is below horizon
1428
+ * 0 OK, photopic vision
1429
+ * |1 OK, scotopic vision
1430
+ * |2 OK, near limit photopic/scotopic
1431
+ */
1432
+ int32 FAR PASCAL_CONV swe_vis_limit_mag(double tjdut, double *dgeo, double *datm, double *dobs, char *ObjectName, int32 helflag, double *dret, char *serr)
1433
+ {
1434
+ int32 retval = OK, i, scotopic_flag = 0;
1435
+ double AltO, AziO, AltM, AziM, AltS, AziS;
1436
+ double sunra = SunRA(tjdut, helflag, serr);
1437
+ default_heliacal_parameters(datm, dgeo, dobs, helflag);
1438
+ swe_set_topo(dgeo[0], dgeo[1], dgeo[2]);
1439
+ for (i = 0; i < 7; i++)
1440
+ dret[i] = 0;
1441
+ if (ObjectLoc(tjdut, dgeo, datm, ObjectName, 0, helflag, &AltO, serr) == ERR)
1442
+ return ERR;
1443
+ if (AltO < 0 && serr != NULL) {
1444
+ strcpy(serr, "object is below local horizon");
1445
+ *dret = -100;
1446
+ return -2;
1447
+ }
1448
+ if (ObjectLoc(tjdut, dgeo, datm, ObjectName, 1, helflag, &AziO, serr) == ERR)
1449
+ return ERR;
1450
+ if (helflag & SE_HELFLAG_VISLIM_DARK) {
1451
+ AltS = -90;
1452
+ AziS = 0;
1453
+ } else {
1454
+ if (ObjectLoc(tjdut, dgeo, datm, "sun", 0, helflag, &AltS, serr) == ERR)
1455
+ return ERR;
1456
+ if (ObjectLoc(tjdut, dgeo, datm, "sun", 1, helflag, &AziS, serr) == ERR)
1457
+ return ERR;
1458
+ }
1459
+ if (strncmp(ObjectName, "moon", 4) == 0 ||
1460
+ (helflag & SE_HELFLAG_VISLIM_DARK) ||
1461
+ (helflag & SE_HELFLAG_VISLIM_NOMOON)
1462
+ ) {
1463
+ AltM = -90; AziM = 0;
1464
+ } else {
1465
+ if (ObjectLoc(tjdut, dgeo, datm, "moon", 0, helflag, &AltM, serr) == ERR)
1466
+ return ERR;
1467
+ if (ObjectLoc(tjdut, dgeo, datm, "moon", 1, helflag, &AziM, serr) == ERR)
1468
+ return ERR;
1469
+ }
1470
+ #if DEBUG
1471
+ {
1472
+ int i;
1473
+ for (i = 0; i < 6;i++)
1474
+ printf("dobs[%d] = %f\n", i, dobs[i]);
1475
+ printf("AltO = %.10f, AziO = %.10f\n", AltO, AziO);
1476
+ printf("AltM = %.10f, AziM = %.10f\n", AltM, AziM);
1477
+ printf("AltS = %.10f, AziS = %.10f\n", AltS, AziS);
1478
+ printf("JD = %.10f\n", tjdut);
1479
+ printf("lat = %f, eyeh = %f\n", dgeo[1], dgeo[2]);
1480
+ for (i = 0; i < 4;i++)
1481
+ printf("datm[%d] = %f\n", i, datm[i]);
1482
+ printf("helflag = %d\n", helflag);
1483
+ }
1484
+ #endif
1485
+ dret[0] = VisLimMagn(dobs, AltO, AziO, AltM, AziM, tjdut, AltS, AziS, sunra, dgeo[1], dgeo[2], datm, helflag, &scotopic_flag, serr);
1486
+ dret[1] = AltO;
1487
+ dret[2] = AziO;
1488
+ dret[3] = AltS;
1489
+ dret[4] = AziS;
1490
+ dret[5] = AltM;
1491
+ dret[6] = AziM;
1492
+ if (Magnitude(tjdut, dgeo, ObjectName, helflag, &(dret[7]), serr) == ERR)
1493
+ return ERR;
1494
+ retval = scotopic_flag;
1495
+ /*dret[8] = (double) is_scotopic;*/
1496
+ /*if (*serr != '\0') * in VisLimMagn(), serr is only a warning *
1497
+ retval = ERR; */
1498
+ return retval;
1499
+ }
1500
+
1501
+ /*###################################################################
1502
+ ' Magn [-]
1503
+ ' age [Year]
1504
+ ' SN [-]
1505
+ ' AltO [deg]
1506
+ ' AziO [deg]
1507
+ ' AltM [deg]
1508
+ ' AziM [deg]
1509
+ ' MoonDistance [km]
1510
+ ' JDNDaysUT [-]
1511
+ ' AziS [deg]
1512
+ ' lat [deg]
1513
+ ' heighteye [m]
1514
+ ' Temperature [C]
1515
+ ' Pressure [mbar]
1516
+ ' RH [%]
1517
+ ' VR [km]
1518
+ ' TopoArcVisionis [deg]
1519
+ */
1520
+ static int32 TopoArcVisionis(double Magn, double *dobs, double AltO, double AziO, double AltM, double AziM, double JDNDaysUT, double AziS, double sunra, double Lat, double HeightEye, double *datm, int32 helflag, double *dret, char *serr)
1521
+ {
1522
+ double Xm, Ym, AltSi, AziSi;
1523
+ double xR = 0;
1524
+ double Xl = 45;
1525
+ double Yl, Yr;
1526
+ Yl = Magn - VisLimMagn(dobs, AltO, AziO, AltM, AziM, JDNDaysUT, AltO - Xl, AziS, sunra, Lat, HeightEye, datm, helflag, NULL, serr);
1527
+ /* if (*serr != '\0') return ERR; * serr is only a warning */
1528
+ Yr = Magn - VisLimMagn(dobs, AltO, AziO, AltM, AziM, JDNDaysUT, AltO - xR, AziS, sunra, Lat, HeightEye, datm, helflag, NULL, serr);
1529
+ /* if (*serr != '\0') return ERR; * serr is only a warning */
1530
+ /* http://en.wikipedia.org/wiki/Bisection_method*/
1531
+ if ((Yl * Yr) <= 0) {
1532
+ while(fabs(xR - Xl) > epsilon) {
1533
+ /*Calculate midpoint of domain*/
1534
+ Xm = (xR + Xl) / 2.0;
1535
+ AltSi = AltO - Xm;
1536
+ AziSi = AziS;
1537
+ Ym = Magn - VisLimMagn(dobs, AltO, AziO, AltM, AziM, JDNDaysUT, AltSi, AziSi, sunra, Lat, HeightEye, datm, helflag, NULL, serr);
1538
+ /* if (*serr != '\0') return ERR; * serr is only a warning */
1539
+ if ((Yl * Ym) > 0) {
1540
+ /* Throw away left half*/
1541
+ Xl = Xm;
1542
+ Yl = Ym;
1543
+ } else {
1544
+ /* Throw away right half */
1545
+ xR = Xm;
1546
+ Yr = Ym;
1547
+ }
1548
+ }
1549
+ Xm = (xR + Xl) / 2.0;
1550
+ } else {
1551
+ Xm = 99;
1552
+ }
1553
+ if (Xm < AltO)
1554
+ Xm = AltO;
1555
+ *dret = Xm;
1556
+ return OK;
1557
+ }
1558
+
1559
+ int32 FAR PASCAL_CONV swe_topo_arcus_visionis(double tjdut, double *dgeo, double *datm, double *dobs, int32 helflag, double mag, double azi_obj, double alt_obj, double azi_sun, double azi_moon, double alt_moon, double *dret, char *serr)
1560
+ {
1561
+ double sunra = SunRA(tjdut, helflag, serr);
1562
+ if (serr != NULL && *serr != '\0')
1563
+ return ERR;
1564
+ return TopoArcVisionis(mag, dobs, alt_obj, azi_obj, alt_moon, azi_moon, tjdut, azi_sun, sunra, dgeo[1], dgeo[2], datm, helflag, dret, serr);
1565
+ }
1566
+
1567
+ /*###################################################################*/
1568
+ /*' Magn [-]
1569
+ ' age [Year]
1570
+ ' SN Snellen factor of the visual aquity of the observer
1571
+ see: http://www.i-see.org/eyecharts.html#make-your-own
1572
+ ' AziO [deg]
1573
+ ' AltM [deg]
1574
+ ' AziM [deg]
1575
+ ' MoonDistance [km]
1576
+ ' JDNDaysUT [-]
1577
+ ' AziS [deg]
1578
+ ' Lat [deg]
1579
+ ' HeightEye [m]
1580
+ ' Temperature [C]
1581
+ ' Pressure [mbar]
1582
+ ' RH [%] relative humidity
1583
+ ' VR [km] Meteorological Range,
1584
+ see http://www.iol.ie/~geniet/eng/atmoastroextinction.htm
1585
+ ' TypeAngle
1586
+ ' [0=Object's altitude,
1587
+ ' 1=Arcus Visonis (Object's altitude - Sun's altitude),
1588
+ ' 2=Sun's altitude]
1589
+ ' HeliacalAngle [deg]
1590
+ */
1591
+ static int32 HeliacalAngle(double Magn, double *dobs, double AziO, double AltM, double AziM, double JDNDaysUT, double AziS, double *dgeo, double *datm, int32 helflag, double *dangret, char *serr)
1592
+ {
1593
+ double x, minx, maxx, xmin, ymin, Xl, xR, Yr, Yl, Xm, Ym, xmd, ymd;
1594
+ double Arc, DELTAx;
1595
+ double sunra = SunRA(JDNDaysUT, helflag, serr);
1596
+ double Lat = dgeo[1];
1597
+ double HeightEye = dgeo[2];
1598
+ if (PLSV == 1) {
1599
+ dangret[0] = criticalangle;
1600
+ dangret[1] = criticalangle + Magn * 2.492 + 13.447;
1601
+ dangret[2] = -(Magn * 2.492 + 13.447); /* Magn * 1.1 + 8.9;*/
1602
+ return OK;
1603
+ }
1604
+ minx = 2;
1605
+ maxx = 20;
1606
+ xmin = 0;
1607
+ ymin = 10000;
1608
+ for (x = minx; x <= maxx; x++) {
1609
+ if (TopoArcVisionis(Magn, dobs, x, AziO, AltM, AziM, JDNDaysUT, AziS, sunra, Lat, HeightEye, datm, helflag, &Arc, serr) == ERR)
1610
+ return ERR;
1611
+ if (Arc < ymin) {
1612
+ ymin = Arc;
1613
+ xmin = x;
1614
+ }
1615
+ }
1616
+ Xl = xmin - 1;
1617
+ xR = xmin + 1;
1618
+ if (TopoArcVisionis(Magn, dobs, xR, AziO, AltM, AziM, JDNDaysUT, AziS, sunra, Lat, HeightEye, datm, helflag, &Yr, serr) == ERR)
1619
+ return ERR;
1620
+ if (TopoArcVisionis(Magn, dobs, Xl, AziO, AltM, AziM, JDNDaysUT, AziS, sunra, Lat, HeightEye, datm, helflag, &Yl, serr) == ERR)
1621
+ return ERR;
1622
+ /* http://en.wikipedia.org/wiki/Bisection_method*/
1623
+ while(fabs(xR - Xl) > 0.1) {
1624
+ /* Calculate midpoint of domain */
1625
+ Xm = (xR + Xl) / 2.0;
1626
+ DELTAx = 0.025;
1627
+ xmd = Xm + DELTAx;
1628
+ if (TopoArcVisionis(Magn, dobs, Xm, AziO, AltM, AziM, JDNDaysUT, AziS, sunra, Lat, HeightEye, datm, helflag, &Ym, serr) == ERR)
1629
+ return ERR;
1630
+ if (TopoArcVisionis(Magn, dobs, xmd, AziO, AltM, AziM, JDNDaysUT, AziS, sunra, Lat, HeightEye, datm, helflag, &ymd, serr) == ERR)
1631
+ return ERR;
1632
+ if (Ym >= ymd) {
1633
+ /* Throw away left half */
1634
+ Xl = Xm;
1635
+ Yl = Ym;
1636
+ } else {
1637
+ /*Throw away right half */
1638
+ xR = Xm;
1639
+ Yr = Ym;
1640
+ }
1641
+ }
1642
+ Xm = (xR + Xl) / 2.0;
1643
+ Ym = (Yr + Yl) / 2.0;
1644
+ dangret[1] = Ym;
1645
+ dangret[2] = Xm - Ym;
1646
+ dangret[0] = Xm;
1647
+ return OK;
1648
+ }
1649
+
1650
+ int32 FAR PASCAL_CONV swe_heliacal_angle(double tjdut, double *dgeo, double *datm, double *dobs, int32 helflag, double mag, double azi_obj, double azi_sun, double azi_moon, double alt_moon, double *dret, char *serr)
1651
+ {
1652
+ return HeliacalAngle(mag, dobs, azi_obj, alt_moon, azi_moon, tjdut, azi_sun, dgeo, datm, helflag, dret, serr);
1653
+ }
1654
+
1655
+ /*###################################################################
1656
+ ' AltO [deg]
1657
+ ' AziO [deg]
1658
+ ' AltS [deg]
1659
+ ' AziS [deg]
1660
+ ' parallax [deg]
1661
+ ' WidthMoon [deg]
1662
+ */
1663
+ static double WidthMoon(double AltO, double AziO, double AltS, double AziS, double parallax)
1664
+ {
1665
+ /* Yallop 1998, page 3*/
1666
+ double GeoAltO = AltO + parallax;
1667
+ return 0.27245 * parallax * (1 + sin(GeoAltO * DEGTORAD) * sin(parallax * DEGTORAD)) * (1 - cos((AltS - GeoAltO) * DEGTORAD) * cos((AziS - AziO) * DEGTORAD));
1668
+ }
1669
+
1670
+ /*###################################################################
1671
+ ' W [deg]
1672
+ ' LengthMoon [deg]
1673
+ */
1674
+ static double LengthMoon(double W, double Diamoon)
1675
+ {
1676
+ double Wi, D;
1677
+ if (Diamoon == 0) Diamoon = AvgRadiusMoon * 2;
1678
+ Wi = W * 60;
1679
+ D = Diamoon * 60;
1680
+ /* Crescent length according: http://calendar.ut.ac.ir/Fa/Crescent/Data/Sultan2005.pdf*/
1681
+ return (D - 0.3 * (D + Wi) / 2.0 / Wi) / 60.0;
1682
+ }
1683
+
1684
+ /*###################################################################
1685
+ ' W [deg]
1686
+ ' GeoARCVact [deg]
1687
+ ' q [-]
1688
+ */
1689
+ static double qYallop(double W, double GeoARCVact)
1690
+ {
1691
+ double Wi = W * 60;
1692
+ return (GeoARCVact - (11.8371 - 6.3226 * Wi + 0.7319 * Wi * Wi - 0.1018 * Wi * Wi * Wi)) / 10;
1693
+ }
1694
+
1695
+ /*###################################################################
1696
+ 'A (0,p)
1697
+ 'B (1,q)
1698
+ 'C (0,r)
1699
+ 'D (1,s)
1700
+ */
1701
+ static double crossing(double A, double B, double C, double D)
1702
+ {
1703
+ return (C - A) / ((B - A) - (D - C));
1704
+ }
1705
+
1706
+ /*###################################################################*/
1707
+ static int32 DeterTAV(double *dobs, double JDNDaysUT, double *dgeo, double *datm, char *ObjectName, int32 helflag, double *dret, char *serr)
1708
+ {
1709
+ double Magn, AltO, AziS, AziO, AziM, AltM;
1710
+ double sunra = SunRA(JDNDaysUT, helflag, serr);
1711
+ if (Magnitude(JDNDaysUT, dgeo, ObjectName, helflag, &Magn, serr) == ERR)
1712
+ return ERR;
1713
+ if (ObjectLoc(JDNDaysUT, dgeo, datm, ObjectName, 0, helflag, &AltO, serr) == ERR)
1714
+ return ERR;
1715
+ if (ObjectLoc(JDNDaysUT, dgeo, datm, ObjectName, 1, helflag, &AziO, serr) == ERR)
1716
+ return ERR;
1717
+ if (strncmp(ObjectName, "moon", 4) == 0) {
1718
+ AltM = -90;
1719
+ AziM = 0;
1720
+ } else {
1721
+ if (ObjectLoc(JDNDaysUT, dgeo, datm, "moon", 0, helflag, &AltM, serr) == ERR)
1722
+ return ERR;
1723
+ if (ObjectLoc(JDNDaysUT, dgeo, datm, "moon", 1, helflag, &AziM, serr) == ERR)
1724
+ return ERR;
1725
+ }
1726
+ if (ObjectLoc(JDNDaysUT, dgeo, datm, "sun", 1, helflag, &AziS, serr) == ERR)
1727
+ return ERR;
1728
+ if (TopoArcVisionis(Magn, dobs, AltO, AziO, AltM, AziM, JDNDaysUT, AziS, sunra, dgeo[1], dgeo[2], datm, helflag, dret, serr) == ERR)
1729
+ return ERR;
1730
+ return OK;
1731
+ }
1732
+
1733
+ /*###################################################################
1734
+ ' A y-value at x=1
1735
+ ' B y-value at x=0
1736
+ ' C y-value at x=-1
1737
+ ' x2min minimum for the quadratic function
1738
+ */
1739
+ static double x2min(double A, double B, double C)
1740
+ {
1741
+ double term = A + C - 2 * B;
1742
+ if (term == 0)
1743
+ return 0;
1744
+ return -(A - C) / 2.0 / term;
1745
+ }
1746
+
1747
+
1748
+ /*###################################################################
1749
+ ' A y-value at x=1
1750
+ ' B y-value at x=0
1751
+ ' C y-value at x=-1
1752
+ ' x
1753
+ ' y is y-value of quadratic function
1754
+ */
1755
+ static double funct2(double A, double B, double C, double x)
1756
+ {
1757
+ return (A + C - 2 * B) / 2.0 * x * x + (A - C) / 2.0 * x + B;
1758
+ }
1759
+
1760
+ static void strcpy_VBsafe(char *sout, char *sin)
1761
+ {
1762
+ char *sp, *sp2;
1763
+ int iw = 0;
1764
+ sp = sin;
1765
+ sp2 = sout;
1766
+ while((isalnum(*sp) || *sp == ' ' || *sp == '-') && iw < 30) {
1767
+ *sp2 = *sp;
1768
+ sp++; sp2++; iw++;
1769
+ }
1770
+ *sp2 = '\0';
1771
+ }
1772
+
1773
+ /*###################################################################
1774
+ ' JDNDaysUT [JDN]
1775
+ ' HPheno
1776
+ '0=AltO [deg] topocentric altitude of object (unrefracted)
1777
+ '1=AppAltO [deg] apparent altitude of object (refracted)
1778
+ '2=GeoAltO [deg] geocentric altitude of object
1779
+ '3=AziO [deg] azimuth of object
1780
+ '4=AltS [deg] topocentric altitude of Sun
1781
+ '5=AziS [deg] azimuth of Sun
1782
+ '6=TAVact [deg] actual topocentric arcus visionis
1783
+ '7=ARCVact [deg] actual (geocentric) arcus visionis
1784
+ '8=DAZact [deg] actual difference between object's and sun's azimuth
1785
+ '9=ARCLact [deg] actual longitude difference between object and sun
1786
+ '10=kact [-] extinction coefficient
1787
+ '11=minTAV [deg] smallest topocentric arcus visionis
1788
+ '12=TfistVR [JDN] first time object is visible, according to VR
1789
+ '13=TbVR [JDN] optimum time the object is visible, according to VR
1790
+ '14=TlastVR [JDN] last time object is visible, according to VR
1791
+ '15=TbYallop[JDN] best time the object is visible, according to Yallop
1792
+ '16=WMoon [deg] cresent width of moon
1793
+ '17=qYal [-] q-test value of Yallop
1794
+ '18=qCrit [-] q-test criterion of Yallop
1795
+ '19=ParO [deg] parallax of object
1796
+ '20 Magn [-] magnitude of object
1797
+ '21=RiseO [JDN] rise/set time of object
1798
+ '22=RiseS [JDN] rise/set time of sun
1799
+ '23=Lag [JDN] rise/set time of object minus rise/set time of sun
1800
+ '24=TvisVR [JDN] visibility duration
1801
+ '25=LMoon [deg] cresent length of moon
1802
+ '26=CVAact [deg]
1803
+ '27=Illum [%] 'new
1804
+ '28=CVAact [deg] 'new
1805
+ '29=MSk [-]
1806
+ */
1807
+ int32 FAR PASCAL_CONV swe_heliacal_pheno_ut(double JDNDaysUT, double *dgeo, double *datm, double *dobs, char *ObjectNameIn, int32 TypeEvent, int32 helflag, double *darr, char *serr)
1808
+ {
1809
+ double AziS, AltS, AltS2, AziO, AltO, AltO2, GeoAltO, AppAltO, DAZact, TAVact, ParO, MagnO;
1810
+ double ARCVact, ARCLact, kact, WMoon, LMoon = 0, qYal, qCrit;
1811
+ double RiseSetO, RiseSetS, Lag, TbYallop, TfirstVR, TlastVR, TbVR;
1812
+ double MinTAV, MinTAVact, Ta, Tc, TimeStep, TimePointer, MinTAVoud = 0, DeltaAltoud = 0, DeltaAlt, TvisVR, crosspoint;
1813
+ double OldestDeltaAlt, OldestMinTAV, extrax, illum;
1814
+ double elong, attr[30];
1815
+ double TimeCheck, LocalminCheck;
1816
+ int32 retval = OK, RS, Planet;
1817
+ AS_BOOL noriseO = FALSE;
1818
+ char ObjectName[AS_MAXCH];
1819
+ double sunra = SunRA(JDNDaysUT, helflag, serr);
1820
+ int32 iflag = helflag & (SEFLG_JPLEPH|SEFLG_SWIEPH|SEFLG_MOSEPH);
1821
+ /* note, the fixed stars functions rewrite the star name. The input string
1822
+ may be too short, so we have to make sure we have enough space */
1823
+ strcpy_VBsafe(ObjectName, ObjectNameIn);
1824
+ default_heliacal_parameters(datm, dgeo, dobs, helflag);
1825
+ swe_set_topo(dgeo[0], dgeo[1], dgeo[2]);
1826
+ retval = ObjectLoc(JDNDaysUT, dgeo, datm, "sun", 1, helflag, &AziS, serr);
1827
+ if (retval == OK)
1828
+ retval = ObjectLoc(JDNDaysUT, dgeo, datm, "sun", 0, helflag, &AltS, serr);
1829
+ if (retval == OK)
1830
+ retval = ObjectLoc(JDNDaysUT, dgeo, datm, ObjectName, 1, helflag, &AziO, serr);
1831
+ if (retval == OK)
1832
+ retval = ObjectLoc(JDNDaysUT, dgeo, datm, ObjectName, 0, helflag, &AltO, serr);
1833
+ if (retval == OK)
1834
+ retval = ObjectLoc(JDNDaysUT, dgeo, datm, ObjectName, 7, helflag, &GeoAltO, serr);
1835
+ if (retval == ERR)
1836
+ return ERR;
1837
+ AppAltO = AppAltfromTopoAlt(AltO, datm[1], datm[0], helflag);
1838
+ DAZact = AziS - AziO;
1839
+ TAVact = AltO - AltS;
1840
+ /*this parallax seems to be somewhat smaller then in Yallop and SkyMap! Needs to be studied*/
1841
+ ParO = GeoAltO - AltO;
1842
+ if (Magnitude(JDNDaysUT, dgeo, ObjectName, helflag, &MagnO, serr) == ERR)
1843
+ return ERR;
1844
+ ARCVact = TAVact + ParO;
1845
+ ARCLact = acos(cos(ARCVact * DEGTORAD) * cos(DAZact * DEGTORAD)) / DEGTORAD;
1846
+ Planet = DeterObject(ObjectName);
1847
+ if (Planet == -1) {
1848
+ elong = ARCLact;
1849
+ illum = 100;
1850
+ } else {
1851
+ retval = swe_pheno_ut(JDNDaysUT, Planet, iflag|(SEFLG_TOPOCTR|SEFLG_EQUATORIAL), attr, serr);
1852
+ if (retval == ERR) return ERR;
1853
+ elong = attr[2];
1854
+ illum = attr[1] * 100;
1855
+ }
1856
+ kact = kt(AltS, sunra, dgeo[1], dgeo[2], datm[1], datm[2], datm[3], 4, serr);
1857
+ if (0) {
1858
+ darr[26] = kR(AltS, dgeo[2]);
1859
+ darr[27] = kW(dgeo[2], datm[1], datm[2]);
1860
+ darr[28] = kOZ(AltS, sunra, dgeo[1]);
1861
+ darr[29] = ka(AltS, sunra, dgeo[1], dgeo[2], datm[1], datm[2], datm[3], serr);
1862
+ darr[30] = darr[26] + darr[27] + darr[28] + darr[29];
1863
+ }
1864
+ WMoon = 0;
1865
+ qYal = 0;
1866
+ qCrit = 0;
1867
+ LMoon = 0;
1868
+ if (Planet == SE_MOON) {
1869
+ WMoon = WidthMoon(AltO, AziO, AltS, AziS, ParO);
1870
+ LMoon = LengthMoon(WMoon, 0);
1871
+ qYal = qYallop(WMoon, ARCVact);
1872
+ if (qYal > 0.216) qCrit = 1; /* A */
1873
+ if (qYal < 0.216 && qYal > -0.014) qCrit = 2; /* B */
1874
+ if (qYal < -0.014 && qYal > -0.16) qCrit = 3; /* C */
1875
+ if (qYal < -0.16 && qYal > -0.232) qCrit = 4; /* D */
1876
+ if (qYal < -0.232 && qYal > -0.293) qCrit = 5; /* E */
1877
+ if (qYal < -0.293) qCrit = 6; /* F */
1878
+ }
1879
+ /*determine if rise or set event*/
1880
+ RS = 2;
1881
+ if (TypeEvent == 1 || TypeEvent == 4) RS = 1;
1882
+ retval = RiseSet(JDNDaysUT - 4.0 / 24.0, dgeo, datm, "sun", RS, helflag, 0, &RiseSetS, serr);
1883
+ if (retval == ERR)
1884
+ return ERR;
1885
+ retval = RiseSet(JDNDaysUT - 4.0 / 24.0, dgeo, datm, ObjectName, RS, helflag, 0, &RiseSetO, serr);
1886
+ if (retval == ERR)
1887
+ return ERR;
1888
+ TbYallop = TJD_INVALID;
1889
+ if (retval == -2) { /* object does not rise or set */
1890
+ Lag = 0;
1891
+ noriseO = TRUE;
1892
+ } else {
1893
+ Lag = RiseSetO - RiseSetS;
1894
+ if (Planet == SE_MOON)
1895
+ TbYallop = (RiseSetO * 4 + RiseSetS * 5) / 9.0;
1896
+ }
1897
+ if ((TypeEvent == 3 || TypeEvent == 4) && (Planet == -1 || Planet >= SE_MARS)) {
1898
+ TfirstVR = TJD_INVALID;
1899
+ TbVR = TJD_INVALID;
1900
+ TlastVR = TJD_INVALID;
1901
+ TvisVR = 0;
1902
+ MinTAV = 0;
1903
+ goto output_heliacal_pheno;
1904
+ }
1905
+ /* If HPheno >= 11 And HPheno <= 14 Or HPheno = 24 Then*/
1906
+ /*te bepalen m.b.v. walkthrough*/
1907
+ MinTAVact = 199;
1908
+ DeltaAlt = 0;
1909
+ OldestDeltaAlt = 0;
1910
+ OldestMinTAV = 0;
1911
+ Ta = 0;
1912
+ Tc = 0;
1913
+ TbVR = 0;
1914
+ TimeStep = -TimeStepDefault / 24.0 / 60.0;
1915
+ if (RS == 2) TimeStep = -TimeStep;
1916
+ TimePointer = RiseSetS - TimeStep;
1917
+ do {
1918
+ TimePointer = TimePointer + TimeStep;
1919
+ OldestDeltaAlt = DeltaAltoud;
1920
+ OldestMinTAV = MinTAVoud;
1921
+ MinTAVoud = MinTAVact;
1922
+ DeltaAltoud = DeltaAlt;
1923
+ retval = ObjectLoc(TimePointer, dgeo, datm, "sun", 0, helflag, &AltS2, serr);
1924
+ if (retval == OK)
1925
+ retval = ObjectLoc(TimePointer, dgeo, datm, ObjectName, 0, helflag, &AltO2, serr);
1926
+ if (retval != OK)
1927
+ return ERR;
1928
+ DeltaAlt = AltO2 - AltS2;
1929
+ if (DeterTAV(dobs, TimePointer, dgeo, datm, ObjectName, helflag, &MinTAVact, serr) == ERR)
1930
+ return ERR;
1931
+ if (MinTAVoud < MinTAVact && TbVR == 0) {
1932
+ /* determine if this is a local minimum with object still above horizon*/
1933
+ TimeCheck = TimePointer + Sgn(TimeStep) * LocalMinStep / 24.0 / 60.0;
1934
+ if (RiseSetO != 0) {
1935
+ if (TimeStep > 0)
1936
+ TimeCheck = mymin(TimeCheck, RiseSetO);
1937
+ else
1938
+ TimeCheck = mymax(TimeCheck, RiseSetO);
1939
+ }
1940
+ if (DeterTAV(dobs, TimeCheck, dgeo, datm, ObjectName, helflag, &LocalminCheck, serr) == ERR)
1941
+ return ERR;
1942
+ if (LocalminCheck > MinTAVact) {
1943
+ extrax = x2min(MinTAVact, MinTAVoud, OldestMinTAV);
1944
+ TbVR = TimePointer - (1 - extrax) * TimeStep;
1945
+ MinTAV = funct2(MinTAVact, MinTAVoud, OldestMinTAV, extrax);
1946
+ }
1947
+ }
1948
+ if (DeltaAlt > MinTAVact && Tc == 0 && TbVR == 0) {
1949
+ crosspoint = crossing(DeltaAltoud, DeltaAlt, MinTAVoud, MinTAVact);
1950
+ Tc = TimePointer - TimeStep * (1 - crosspoint);
1951
+ }
1952
+ if (DeltaAlt < MinTAVact && Ta == 0 && Tc != 0) {
1953
+ crosspoint = crossing(DeltaAltoud, DeltaAlt, MinTAVoud, MinTAVact);
1954
+ Ta = TimePointer - TimeStep * (1 - crosspoint);
1955
+ }
1956
+ } while (fabs(TimePointer - RiseSetS) <= MaxTryHours / 24.0 && Ta == 0 && !((TbVR != 0 && (TypeEvent == 3 || TypeEvent == 4) && (strncmp(ObjectName, "moon", 4) != 0 && strncmp(ObjectName, "venus", 5) != 0 && strncmp(ObjectName, "mercury", 7) != 0))));
1957
+ if (RS == 2) {
1958
+ TfirstVR = Tc;
1959
+ TlastVR = Ta;
1960
+ } else {
1961
+ TfirstVR = Ta;
1962
+ TlastVR = Tc;
1963
+ }
1964
+ if (TfirstVR == 0 && TlastVR == 0) {
1965
+ if (RS == 1)
1966
+ TfirstVR = TbVR - 0.000001;
1967
+ else
1968
+ TlastVR = TbVR + 0.000001;
1969
+ }
1970
+ if (!noriseO) {
1971
+ if (RS == 1)
1972
+ TfirstVR = mymax(TfirstVR, RiseSetO);
1973
+ else
1974
+ TlastVR = mymin(TlastVR, RiseSetO);
1975
+ }
1976
+ TvisVR = TJD_INVALID; /*"#NA!" */
1977
+ if (TlastVR != 0 && TfirstVR != 0)
1978
+ TvisVR = TlastVR - TfirstVR;
1979
+ if (TlastVR == 0) TlastVR = TJD_INVALID; /*"#NA!" */
1980
+ if (TbVR == 0) TbVR = TJD_INVALID; /*"#NA!" */
1981
+ if (TfirstVR == 0) TfirstVR = TJD_INVALID; /*"#NA!" */
1982
+ output_heliacal_pheno:
1983
+ /*End If*/
1984
+ darr[0] = AltO;
1985
+ darr[1] = AppAltO;
1986
+ darr[2] = GeoAltO;
1987
+ darr[3] = AziO;
1988
+ darr[4] = AltS;
1989
+ darr[5] = AziS;
1990
+ darr[6] = TAVact;
1991
+ darr[7] = ARCVact;
1992
+ darr[8] = DAZact;
1993
+ darr[9] = ARCLact;
1994
+ darr[10] = kact;
1995
+ darr[11] = MinTAV;
1996
+ darr[12] = TfirstVR;
1997
+ darr[13] = TbVR;
1998
+ darr[14] = TlastVR;
1999
+ darr[15] = TbYallop;
2000
+ darr[16] = WMoon;
2001
+ darr[17] = qYal;
2002
+ darr[18] = qCrit;
2003
+ darr[19] = ParO;
2004
+ darr[20] = MagnO;
2005
+ darr[21] = RiseSetO;
2006
+ darr[22] = RiseSetS;
2007
+ darr[23] = Lag;
2008
+ darr[24] = TvisVR;
2009
+ darr[25] = LMoon;
2010
+ darr[26] = elong;
2011
+ darr[27] = illum;
2012
+ return OK;
2013
+ }
2014
+
2015
+ #if 0
2016
+ int32 FAR PASCAL_CONV HeliacalJDut(double JDNDaysUTStart, double Age, double SN, double Lat, double Longitude, double HeightEye, double Temperature, double Pressure, double RH, double VR, char *ObjectName, int TypeEvent, char *AVkind, double *dret, char *serr)
2017
+ {
2018
+ double dgeo[3], datm[4], dobs[6];
2019
+ int32 helflag = SE_HELFLAG_HIGH_PRECISION;
2020
+ helflag |= SE_HELFLAG_AVKIND_VR;
2021
+ dgeo[0] = Longitude;
2022
+ dgeo[1] = Lat;
2023
+ dgeo[2] = HeightEye;
2024
+ datm[0] = Pressure;
2025
+ datm[1] = Temperature;
2026
+ datm[2] = RH;
2027
+ datm[3] = VR;
2028
+ dobs[0] = Age;
2029
+ dobs[1] = SN;
2030
+ return swe_heliacal_ut(JDNDaysUTStart, dgeo, datm, dobs, ObjectName, TypeEvent, helflag, dret, serr);
2031
+ }
2032
+ #endif
2033
+
2034
+ static double get_synodic_period(int Planet)
2035
+ {
2036
+ /* synodic periods from:
2037
+ * Kelley/Milone/Aveni, "Exploring ancient Skies", p. 43. */
2038
+ switch(Planet) {
2039
+ case SE_MOON: return 29.530588853;
2040
+ case SE_MERCURY: return 115.8775;
2041
+ case SE_VENUS: return 583.9214;
2042
+ case SE_MARS: return 779.9361;
2043
+ case SE_JUPITER: return 398.8840;
2044
+ case SE_SATURN: return 378.0919;
2045
+ case SE_URANUS: return 369.6560;
2046
+ case SE_NEPTUNE: return 367.4867;
2047
+ case SE_PLUTO: return 366.7207;
2048
+ }
2049
+ return 366; /* for stars and default for far away planets */
2050
+ }
2051
+
2052
+ /*###################################################################*/
2053
+ static int32 moon_event_arc_vis(double JDNDaysUTStart, double *dgeo, double *datm, double *dobs, int32 TypeEvent, int32 helflag, double *dret, char *serr)
2054
+ {
2055
+ double x[20], MinTAV, MinTAVoud, OldestMinTAV;
2056
+ double phase1, phase2, JDNDaysUT, JDNDaysUTi;
2057
+ double tjd_moonevent, tjd_moonevent_start;
2058
+ double DeltaAltoud, TimeCheck, LocalminCheck;
2059
+ double AltS, AltO, DeltaAlt = 90;
2060
+ char ObjectName[30];
2061
+ int32 iflag, Daystep, eventtype, goingup, Planet, i, retval;
2062
+ int32 avkind = helflag & SE_HELFLAG_AVKIND;
2063
+ int32 epheflag = helflag & (SEFLG_JPLEPH|SEFLG_SWIEPH|SEFLG_MOSEPH);
2064
+ dret[0] = JDNDaysUTStart; /* will be returned in error case */
2065
+ if (avkind == 0)
2066
+ avkind = SE_HELFLAG_AVKIND_VR;
2067
+ if (avkind != SE_HELFLAG_AVKIND_VR) {
2068
+ if (serr != NULL)
2069
+ strcpy(serr, "error: in valid AV kind for the moon");
2070
+ return ERR;
2071
+ }
2072
+ if (TypeEvent == 1 || TypeEvent == 2) {
2073
+ if (serr != NULL)
2074
+ strcpy(serr, "error: the moon has no morning first or evening last");
2075
+ return ERR;
2076
+ }
2077
+ strcpy(ObjectName, "moon");
2078
+ Planet = SE_MOON;
2079
+ iflag = SEFLG_TOPOCTR | SEFLG_EQUATORIAL | epheflag;
2080
+ if (!(helflag & SE_HELFLAG_HIGH_PRECISION))
2081
+ iflag |= SEFLG_NONUT|SEFLG_TRUEPOS;
2082
+ Daystep = 1;
2083
+ if (TypeEvent == 3) {
2084
+ /*morning last */
2085
+ TypeEvent = 2;
2086
+ } else {
2087
+ /*evening first*/
2088
+ TypeEvent = 1;
2089
+ Daystep = -Daystep;
2090
+ }
2091
+ eventtype = TypeEvent + SE_BIT_DISC_CENTER;
2092
+ /* check Synodic/phase Period */
2093
+ JDNDaysUT = JDNDaysUTStart;
2094
+ /* start 30 days later if TypeEvent=4 (1) */
2095
+ if (TypeEvent == 1) JDNDaysUT = JDNDaysUT + 30;
2096
+ /* determination of new moon date */
2097
+ i = swe_pheno_ut(JDNDaysUT, Planet, iflag, x, serr);
2098
+ phase2 = x[0];
2099
+ goingup = 0;
2100
+ do {
2101
+ JDNDaysUT = JDNDaysUT + Daystep;
2102
+ phase1 = phase2;
2103
+ i = swe_pheno_ut(JDNDaysUT, Planet, iflag, x, serr);
2104
+ phase2 = x[0];
2105
+ if (phase2 > phase1)
2106
+ goingup = 1;
2107
+ } while (goingup == 0 || (goingup == 1 && (phase2 > phase1)));
2108
+ /* fix the date to get the day with the smallest phase (nwest moon) */
2109
+ JDNDaysUT = JDNDaysUT - Daystep;
2110
+ /* initialize the date to look for set */
2111
+ JDNDaysUTi = JDNDaysUT;
2112
+ JDNDaysUT = JDNDaysUT - Daystep;
2113
+ MinTAVoud = 199;
2114
+ do {
2115
+ JDNDaysUT = JDNDaysUT + Daystep;
2116
+ if ((retval = RiseSet(JDNDaysUT, dgeo, datm, ObjectName, TypeEvent, helflag, 0, &tjd_moonevent, serr)) != OK)
2117
+ return retval;
2118
+ tjd_moonevent_start = tjd_moonevent;
2119
+ MinTAV = 199;
2120
+ OldestMinTAV = MinTAV;
2121
+ do {
2122
+ OldestMinTAV = MinTAVoud;
2123
+ MinTAVoud = MinTAV;
2124
+ DeltaAltoud = DeltaAlt;
2125
+ tjd_moonevent = tjd_moonevent - 1.0 / 60.0 / 24.0 * Sgn(Daystep);
2126
+ if (ObjectLoc(tjd_moonevent, dgeo, datm, "sun", 0, helflag, &AltS, serr) == ERR)
2127
+ return ERR;
2128
+ if (ObjectLoc(tjd_moonevent, dgeo, datm, ObjectName, 0, helflag, &AltO, serr) == ERR)
2129
+ return ERR;
2130
+ DeltaAlt = AltO - AltS;
2131
+ if (DeterTAV(dobs, tjd_moonevent, dgeo, datm, ObjectName, helflag, &MinTAV, serr) == ERR)
2132
+ return ERR;
2133
+ TimeCheck = tjd_moonevent - LocalMinStep / 60.0 / 24.0 * Sgn(Daystep);
2134
+ if (DeterTAV(dobs, TimeCheck, dgeo, datm, ObjectName, helflag, &LocalminCheck, serr) == ERR)
2135
+ return ERR;
2136
+ /*printf("%f, %f <= %f\n", tjd_moonevent, MinTAV, MinTAVoud);*/
2137
+ /* while (MinTAV <= MinTAVoud && fabs(tjd_moonevent - tjd_moonevent_start) < 120.0 / 60.0 / 24.0);*/
2138
+ } while ((MinTAV <= MinTAVoud || LocalminCheck < MinTAV) && fabs(tjd_moonevent - tjd_moonevent_start) < 120.0 / 60.0 / 24.0);
2139
+ /* while (DeltaAlt < MinTAVoud && fabs(JDNDaysUT - JDNDaysUTi) < 15);*/
2140
+ } while (DeltaAltoud < MinTAVoud && fabs(JDNDaysUT - JDNDaysUTi) < 15);
2141
+ if (fabs(JDNDaysUT - JDNDaysUTi) < 15) {
2142
+ tjd_moonevent += (1 - x2min(MinTAV, MinTAVoud, OldestMinTAV)) * Sgn(Daystep) / 60.0 / 24.0;
2143
+ } else {
2144
+ strcpy(serr, "no date found for lunar event");
2145
+ return ERR;
2146
+ }
2147
+ dret[0] = tjd_moonevent;
2148
+ return OK;
2149
+ }
2150
+
2151
+ static int32 heliacal_ut_arc_vis(double JDNDaysUTStart, double *dgeo, double *datm, double *dobs, char *ObjectName, int32 TypeEventIn, int32 helflag, double *dret, char *serr_ret)
2152
+ {
2153
+ double x[6];
2154
+ double xin[2];
2155
+ double xaz[2];
2156
+ double dang[3];
2157
+ double objectmagn = 0, maxlength, DayStep, DayStep0;
2158
+ double JDNDaysUT, JDNDaysUTfinal, JDNDaysUTstep, JDNDaysUTstepoud, JDNarcvisUT, tjd_tt, tret, OudeDatum, JDNDaysUTinp = JDNDaysUTStart, JDNDaysUTtijd;
2159
+ double ArcusVis, ArcusVisDelta, ArcusVisPto, ArcusVisDeltaoud;
2160
+ double Trise, sunsangle, Theliacal, Tdelta, Angle;
2161
+ double TimeStep, TimePointer, OldestMinTAV, MinTAVoud, MinTAVact, extrax, TbVR = 0;
2162
+ double AziS, AltS, AziO, AltO, DeltaAlt;
2163
+ double direct, Pressure, Temperature, RH, VR, d;
2164
+ int32 epheflag, retval = OK;
2165
+ int32 iflag, Planet, eventtype;
2166
+ int32 TypeEvent = TypeEventIn;
2167
+ int doneoneday;
2168
+ char serr[AS_MAXCH];
2169
+ *dret = JDNDaysUTStart;
2170
+ *serr = '\0';
2171
+ Planet = DeterObject(ObjectName);
2172
+ Pressure = datm[0];
2173
+ Temperature = datm[1];
2174
+ RH = datm[2];
2175
+ VR = datm[3];
2176
+ /* determine Magnitude of star*/
2177
+ if ((retval = Magnitude(JDNDaysUTStart, dgeo, ObjectName, helflag, &objectmagn, serr)) == ERR)
2178
+ goto swe_heliacal_err;
2179
+ epheflag = helflag & (SEFLG_JPLEPH|SEFLG_SWIEPH|SEFLG_MOSEPH);
2180
+ iflag = SEFLG_TOPOCTR | SEFLG_EQUATORIAL | epheflag;
2181
+ if (!(helflag & SE_HELFLAG_HIGH_PRECISION))
2182
+ iflag |= SEFLG_NONUT | SEFLG_TRUEPOS;
2183
+ /* start values for search of heliacal rise
2184
+ * maxlength = phase period in days, smaller than minimal synodic period */
2185
+ /* days per step (for heliacal rise) in power of two */
2186
+ switch(Planet) {
2187
+ case SE_MERCURY:
2188
+ DayStep = 1; maxlength = 100; break;
2189
+ case SE_VENUS:
2190
+ DayStep = 64; maxlength = 384; break;
2191
+ case SE_MARS:
2192
+ DayStep = 128; maxlength = 640; break;
2193
+ case SE_JUPITER:
2194
+ DayStep = 64; maxlength = 384; break;
2195
+ case SE_SATURN:
2196
+ DayStep = 64; maxlength = 256; break;
2197
+ default:
2198
+ DayStep = 64; maxlength = 256; break;
2199
+ }
2200
+ DayStep0 = DayStep;
2201
+ /* heliacal setting */
2202
+ eventtype = TypeEvent;
2203
+ if (eventtype == 2) DayStep = -DayStep;
2204
+ /* acronychal setting */
2205
+ if (eventtype == 4) {
2206
+ eventtype = 1;
2207
+ DayStep = -DayStep;
2208
+ }
2209
+ /* acronychal rising */
2210
+ if (eventtype == 3) eventtype = 2;
2211
+ eventtype |= SE_BIT_DISC_CENTER;
2212
+ /* normalize the maxlength to the step size */
2213
+ {
2214
+ /* check each Synodic/phase Period */
2215
+ JDNDaysUT = JDNDaysUTStart;
2216
+ /* make sure one can find an event on the just after the JDNDaysUTStart */
2217
+ JDNDaysUTfinal = JDNDaysUT + maxlength;
2218
+ JDNDaysUT = JDNDaysUT - 1;
2219
+ if (DayStep < 0) {
2220
+ JDNDaysUTtijd = JDNDaysUT;
2221
+ JDNDaysUT = JDNDaysUTfinal;
2222
+ JDNDaysUTfinal = JDNDaysUTtijd;
2223
+ }
2224
+ /* prepair the search */
2225
+ JDNDaysUTstep = JDNDaysUT - DayStep;
2226
+ doneoneday = 0;
2227
+ ArcusVisDelta = 199;
2228
+ ArcusVisPto = -5.55;
2229
+ do { /* this is a do {} while() loop */
2230
+ if (fabs(DayStep) == 1) doneoneday = 1;
2231
+ do { /* this is a do {} while() loop */
2232
+ /* init search for heliacal rise */
2233
+ JDNDaysUTstepoud = JDNDaysUTstep;
2234
+ ArcusVisDeltaoud = ArcusVisDelta;
2235
+ JDNDaysUTstep = JDNDaysUTstep + DayStep;
2236
+ /* determine rise/set time */
2237
+ if ((retval = my_rise_trans(JDNDaysUTstep, SE_SUN, "", eventtype, helflag, dgeo, datm, &tret, serr)) == ERR)
2238
+ goto swe_heliacal_err;
2239
+ /* determine time compensation to get Sun's altitude at heliacal rise */
2240
+ tjd_tt = tret + DeltaT(tret, 0) / D2S;
2241
+ if ((retval = swe_calc(tjd_tt, SE_SUN, iflag, x, serr)) == ERR)
2242
+ goto swe_heliacal_err;
2243
+ xin[0] = x[0];
2244
+ xin[1] = x[1];
2245
+ swe_azalt(tret, SE_EQU2HOR, dgeo, Pressure, Temperature, xin, xaz);
2246
+ Trise = HourAngle(xaz[1], x[1], dgeo[1]);
2247
+ sunsangle = ArcusVisPto;
2248
+ if (helflag & SE_HELFLAG_AVKIND_MIN7) sunsangle = -7;
2249
+ if (helflag & SE_HELFLAG_AVKIND_MIN9) sunsangle = -9;
2250
+ Theliacal = HourAngle(sunsangle, x[1], dgeo[1]);
2251
+ Tdelta = Theliacal - Trise;
2252
+ if (TypeEvent == 2 || TypeEvent== 3) Tdelta = -Tdelta;
2253
+ /* determine appr.time when sun is at the wanted Sun's altitude */
2254
+ JDNarcvisUT = tret - Tdelta / 24;
2255
+ tjd_tt = JDNarcvisUT + DeltaT(JDNarcvisUT, 0) / D2S;
2256
+ /* determine Sun's position */
2257
+ if ((retval = swe_calc(tjd_tt, SE_SUN, iflag, x, serr)) == ERR)
2258
+ goto swe_heliacal_err;
2259
+ xin[0] = x[0];
2260
+ xin[1] = x[1];
2261
+ swe_azalt(JDNarcvisUT, SE_EQU2HOR, dgeo, Pressure, Temperature, xin, xaz);
2262
+ AziS = xaz[0] + 180;
2263
+ if (AziS >= 360) AziS = AziS - 360;
2264
+ AltS = xaz[1];
2265
+ /* determine Moon's position */
2266
+ #if 0
2267
+ double AltM, AziM;
2268
+ if ((retval = swe_calc(tjd_tt, SE_MOON, iflag, x, serr)) == ERR)
2269
+ goto swe_heliacal_err;
2270
+ xin[0] = x[0];
2271
+ xin[1] = x[1];
2272
+ swe_azalt(JDNarcvisUT, SE_EQU2HOR, dgeo, Pressure, Temperature, xin, xaz);
2273
+ AziM = xaz[0] + 180;
2274
+ if (AziM >= 360) AziM = AziM - 360;
2275
+ AltM = xaz[1];
2276
+ #endif
2277
+ /* determine object's position */
2278
+ if (Planet != -1) {
2279
+ if ((retval = swe_calc(tjd_tt, Planet, iflag, x, serr)) == ERR)
2280
+ goto swe_heliacal_err;
2281
+ /* determine magnitude of Planet */
2282
+ if ((retval = Magnitude(JDNarcvisUT, dgeo, ObjectName, helflag, &objectmagn, serr)) == ERR)
2283
+ goto swe_heliacal_err;
2284
+ } else {
2285
+ if ((retval = call_swe_fixstar(ObjectName, tjd_tt, iflag, x, serr)) == ERR)
2286
+ goto swe_heliacal_err;
2287
+ }
2288
+ xin[0] = x[0];
2289
+ xin[1] = x[1];
2290
+ swe_azalt(JDNarcvisUT, SE_EQU2HOR, dgeo, Pressure, Temperature, xin, xaz);
2291
+ AziO = xaz[0] + 180;
2292
+ if (AziO >= 360) AziO = AziO - 360;
2293
+ AltO = xaz[1];
2294
+ /* determine arcusvisionis */
2295
+ DeltaAlt = AltO - AltS;
2296
+ /*if ((retval = HeliacalAngle(objectmagn, dobs, AziO, AltM, AziM, JDNarcvisUT, AziS, dgeo, datm, helflag, dang, serr)) == ERR)*/
2297
+ if ((retval = HeliacalAngle(objectmagn, dobs, AziO, -1, 0, JDNarcvisUT, AziS, dgeo, datm, helflag, dang, serr)) == ERR)
2298
+ goto swe_heliacal_err;
2299
+ ArcusVis = dang[1];
2300
+ ArcusVisPto = dang[2];
2301
+ ArcusVisDelta = DeltaAlt - ArcusVis;
2302
+ /*} while (((ArcusVisDeltaoud > 0 && ArcusVisDelta < 0) || ArcusVisDelta < 0) && (JDNDaysUTfinal - JDNDaysUTstep) * Sgn(DayStep) > 0);*/
2303
+ } while ((ArcusVisDeltaoud > 0 || ArcusVisDelta < 0) && (JDNDaysUTfinal - JDNDaysUTstep) * Sgn(DayStep) > 0);
2304
+ if (doneoneday == 0 && (JDNDaysUTfinal - JDNDaysUTstep) * Sgn(DayStep) > 0) {
2305
+ /* go back to date before heliacal altitude */
2306
+ ArcusVisDelta = ArcusVisDeltaoud;
2307
+ DayStep = ((int) (fabs(DayStep) / 2.0)) * Sgn(DayStep);
2308
+ JDNDaysUTstep = JDNDaysUTstepoud;
2309
+ }
2310
+ } while (doneoneday == 0 && (JDNDaysUTfinal - JDNDaysUTstep) * Sgn(DayStep) > 0);
2311
+ }
2312
+ d = (JDNDaysUTfinal - JDNDaysUTstep) * Sgn(DayStep);
2313
+ if (d <= 0 || d >= maxlength) {
2314
+ dret[0] = JDNDaysUTinp; /* no date found, just return input */
2315
+ retval = -2; /* marks "not found" within synodic period */
2316
+ sprintf(serr, "heliacal event not found within maxlength %f\n", maxlength);
2317
+ goto swe_heliacal_err;
2318
+ }
2319
+ #if 0
2320
+ if (helflag & SE_HELFLAG_AVKIND_VR) {
2321
+ double darr[40];
2322
+ if (swe_heliacal_pheno_ut(JDNarcvisUT, dgeo, datm, dobs, ObjectName, TypeEvent, helflag, darr, serr) != OK)
2323
+ return ERR;
2324
+ JDNarcvisUT = darr[13];
2325
+ }
2326
+ }
2327
+ #endif
2328
+ direct = TimeStepDefault / 24.0 / 60.0;
2329
+ if (DayStep < 0) direct = -direct;
2330
+ if (helflag & SE_HELFLAG_AVKIND_VR) {
2331
+ /*te bepalen m.b.v. walkthrough*/
2332
+ TimeStep = direct;
2333
+ TbVR = 0;
2334
+ TimePointer = JDNarcvisUT;
2335
+ if (DeterTAV(dobs, TimePointer, dgeo, datm, ObjectName, helflag, &OldestMinTAV, serr) == ERR)
2336
+ return ERR;
2337
+ TimePointer = TimePointer + TimeStep;
2338
+ if (DeterTAV(dobs, TimePointer, dgeo, datm, ObjectName, helflag, &MinTAVoud, serr) == ERR)
2339
+ return ERR;
2340
+ if (MinTAVoud > OldestMinTAV) {
2341
+ TimePointer = JDNarcvisUT;
2342
+ TimeStep = -TimeStep;
2343
+ MinTAVact = OldestMinTAV;
2344
+ } else {
2345
+ MinTAVact = MinTAVoud;
2346
+ MinTAVoud = OldestMinTAV;
2347
+ }
2348
+ /*TimePointer = TimePointer - Timestep*/
2349
+ do {
2350
+ TimePointer = TimePointer + TimeStep;
2351
+ OldestMinTAV = MinTAVoud;
2352
+ MinTAVoud = MinTAVact;
2353
+ if (DeterTAV(dobs, TimePointer, dgeo, datm, ObjectName, helflag, &MinTAVact, serr) == ERR)
2354
+ return ERR;
2355
+ if (MinTAVoud < MinTAVact) {
2356
+ extrax = x2min(MinTAVact, MinTAVoud, OldestMinTAV);
2357
+ TbVR = TimePointer - (1 - extrax) * TimeStep;
2358
+ }
2359
+ } while (TbVR == 0);
2360
+ JDNarcvisUT = TbVR;
2361
+ }
2362
+ /*if (strncmp(AVkind, "pto", 3) == 0) */
2363
+ if (helflag & SE_HELFLAG_AVKIND_PTO) {
2364
+ do {
2365
+ OudeDatum = JDNarcvisUT;
2366
+ JDNarcvisUT = JDNarcvisUT - direct;
2367
+ tjd_tt = JDNarcvisUT + DeltaT(JDNarcvisUT, 0) / D2S;
2368
+ if (Planet != -1) {
2369
+ if ((retval = swe_calc(tjd_tt, Planet, iflag, x, serr)) == ERR)
2370
+ goto swe_heliacal_err;
2371
+ } else {
2372
+ if ((retval = call_swe_fixstar(ObjectName, tjd_tt, iflag, x, serr)) == ERR)
2373
+ goto swe_heliacal_err;
2374
+ }
2375
+ xin[0] = x[0];
2376
+ xin[1] = x[1];
2377
+ swe_azalt(JDNarcvisUT, SE_EQU2HOR, dgeo, Pressure, Temperature, xin, xaz);
2378
+ Angle = xaz[1];
2379
+ } while (Angle > 0);
2380
+ JDNarcvisUT = (JDNarcvisUT + OudeDatum) / 2.0;
2381
+ }
2382
+ if (JDNarcvisUT < -9999999 || JDNarcvisUT > 9999999) {
2383
+ dret[0] = JDNDaysUT; /* no date found, just return input */
2384
+ strcpy(serr, "no heliacal date found");
2385
+ retval = ERR;
2386
+ goto swe_heliacal_err;
2387
+ }
2388
+ dret[0] = JDNarcvisUT;
2389
+ swe_heliacal_err:
2390
+ if (serr_ret != NULL && *serr != '\0')
2391
+ strcpy(serr_ret, serr);
2392
+ return retval;
2393
+ }
2394
+
2395
+ static int32 get_asc_obl(double tjd, int32 ipl, char *star, int32 iflag, double
2396
+ *dgeo, AS_BOOL desc_obl, double *daop, char *serr)
2397
+ {
2398
+ int32 retval;
2399
+ int32 epheflag = iflag & (SEFLG_JPLEPH|SEFLG_SWIEPH|SEFLG_MOSEPH);
2400
+ double x[6], adp;
2401
+ char s[AS_MAXCH];
2402
+ char star2[AS_MAXCH];
2403
+ strcpy(star2, star);
2404
+ if (ipl == -1) {
2405
+ if ((retval = swe_fixstar(star2, tjd, epheflag | SEFLG_EQUATORIAL, x, serr)) == ERR)
2406
+ return ERR;
2407
+ } else {
2408
+ if ((retval = swe_calc(tjd, ipl, epheflag | SEFLG_EQUATORIAL, x, serr)) == ERR)
2409
+ return ERR;
2410
+ }
2411
+ adp = tan(dgeo[1] * DEGTORAD) * tan(x[1] * DEGTORAD);
2412
+ if (fabs(adp) > 1) {
2413
+ if (star != NULL && *star != '\0')
2414
+ strcpy(s, star);
2415
+ else
2416
+ swe_get_planet_name(ipl, s);
2417
+ sprintf(serr, "%s is circumpolar, cannot calculate heliacal event", s);
2418
+ return -2;
2419
+ }
2420
+ adp = asin(adp) / DEGTORAD;
2421
+ if (desc_obl)
2422
+ *daop = x[0] + adp;
2423
+ else
2424
+ *daop = x[0] - adp;
2425
+ *daop = swe_degnorm(*daop);
2426
+ return OK;
2427
+ }
2428
+
2429
+ #if 0
2430
+ static int32 get_asc_obl_old(double tjd, int32 ipl, char *star, int32 iflag, double *dgeo, AS_BOOL desc_obl, double *daop, char *serr)
2431
+ {
2432
+ int32 retval;
2433
+ int32 epheflag = iflag & (SEFLG_JPLEPH|SEFLG_SWIEPH|SEFLG_MOSEPH);
2434
+ double x[6], adp;
2435
+ char s[AS_MAXCH];
2436
+ if (star != NULL && *star != '\0') {
2437
+ if ((retval = call_swe_fixstar(star, tjd, epheflag | SEFLG_EQUATORIAL, x, serr)) == ERR)
2438
+ return ERR;
2439
+ } else {
2440
+ if ((retval = swe_calc(tjd, ipl, epheflag | SEFLG_EQUATORIAL, x, serr)) == ERR)
2441
+ return ERR;
2442
+ }
2443
+ adp = tan(dgeo[1] * DEGTORAD) * tan(x[1] * DEGTORAD);
2444
+ if (fabs(adp) > 1) {
2445
+ if (star != NULL && *star != '\0')
2446
+ strcpy(s, star);
2447
+ else
2448
+ swe_get_planet_name(ipl, s);
2449
+ sprintf(serr, "%s is circumpolar, cannot calculate heliacal event", s);
2450
+ return -2;
2451
+ }
2452
+ adp = asin(adp) / DEGTORAD;
2453
+ if (desc_obl)
2454
+ *daop = x[0] + adp;
2455
+ else
2456
+ *daop = x[0] - adp;
2457
+ *daop = swe_degnorm(*daop);
2458
+ return OK;
2459
+ }
2460
+ #endif
2461
+
2462
+ static int32 get_asc_obl_diff(double tjd, int32 ipl, char *star, int32 iflag, double *dgeo, AS_BOOL desc_obl, AS_BOOL is_acronychal, double *dsunpl, char *serr)
2463
+ {
2464
+ int32 retval = OK;
2465
+ double aosun, aopl;
2466
+ /* ascensio obliqua of sun */
2467
+ retval = get_asc_obl(tjd, SE_SUN, "", iflag, dgeo, desc_obl, &aosun, serr);
2468
+ if (retval != OK)
2469
+ return retval;
2470
+ if (is_acronychal) {
2471
+ if (desc_obl == TRUE)
2472
+ desc_obl = FALSE;
2473
+ else
2474
+ desc_obl = TRUE;
2475
+ }
2476
+ /* ascensio obliqua of body */
2477
+ retval = get_asc_obl(tjd, ipl, star, iflag, dgeo, desc_obl, &aopl, serr);
2478
+ if (retval != OK)
2479
+ return retval;
2480
+ *dsunpl = swe_degnorm(aosun - aopl);
2481
+ if (is_acronychal)
2482
+ *dsunpl = swe_degnorm(*dsunpl - 180);
2483
+ if (*dsunpl > 180) *dsunpl -= 360;
2484
+ return OK;
2485
+ }
2486
+
2487
+ #if 0
2488
+ static int32 get_asc_obl_diff_old(double tjd, int32 ipl, char *star, int32 iflag, double *dgeo, AS_BOOL desc_obl, double *dsunpl, char *serr)
2489
+ {
2490
+ int32 retval = OK;
2491
+ double aosun, aopl;
2492
+ /* ascensio obliqua of sun */
2493
+ retval = get_asc_obl(tjd, SE_SUN, "", iflag, dgeo, desc_obl, &aosun, serr);
2494
+ if (retval != OK)
2495
+ return retval;
2496
+ /* ascensio obliqua of body */
2497
+ retval = get_asc_obl(tjd, ipl, star, iflag, dgeo, desc_obl, &aopl, serr);
2498
+ if (retval != OK)
2499
+ return retval;
2500
+ *dsunpl = swe_degnorm(aosun - aopl);
2501
+ return OK;
2502
+ }
2503
+ #endif
2504
+
2505
+ /* times of
2506
+ * - superior and inferior conjunction (Mercury and Venus)
2507
+ * - conjunction and opposition (ipl >= Mars)
2508
+ */
2509
+ static double tcon[] =
2510
+ {
2511
+ 0, 0,
2512
+ 2451550, 2451550, /* Moon */
2513
+ 2451604, 2451670, /* Mercury */
2514
+ 2451980, 2452280, /* Venus */
2515
+ 2451727, 2452074, /* Mars */
2516
+ 2451673, 2451877, /* Jupiter */
2517
+ 2451675, 2451868, /* Saturn */
2518
+ 2451581, 2451768, /* Uranus */
2519
+ 2451568, 2451753, /* Neptune */
2520
+ };
2521
+
2522
+ static int32 find_conjunct_sun(double tjd_start, int32 ipl, int32 helflag, int32 TypeEvent, double *tjd, char *serr)
2523
+ {
2524
+ int32 epheflag = helflag & (SEFLG_JPLEPH|SEFLG_SWIEPH|SEFLG_MOSEPH);
2525
+ int i;
2526
+ double tjdcon, tjd0, ds, dsynperiod, x[6], xs[6], daspect = 0;
2527
+ if (ipl >= SE_MARS && TypeEvent >= 3)
2528
+ daspect = 180;
2529
+ i = (TypeEvent - 1) / 2 + ipl * 2;
2530
+ tjd0 = tcon[i];
2531
+ dsynperiod = get_synodic_period(ipl);
2532
+ tjdcon = tjd0 + ((floor) ((tjd_start - tjd0) / dsynperiod) + 1) * dsynperiod;
2533
+ ds = 100;
2534
+ while (ds > 0.5) {
2535
+ if (swe_calc(tjdcon, ipl, epheflag|SEFLG_SPEED, x, serr) == ERR)
2536
+ return ERR;
2537
+ if (swe_calc(tjdcon, SE_SUN, epheflag|SEFLG_SPEED, xs, serr) == ERR)
2538
+ return ERR;
2539
+ ds = swe_degnorm(x[0] - xs[0] - daspect);
2540
+ if (ds > 180) ds -= 360;
2541
+ tjdcon -= ds / (x[3] - xs[3]);
2542
+ }
2543
+ *tjd = tjdcon;
2544
+ return OK;
2545
+ }
2546
+
2547
+ static int32 get_asc_obl_with_sun(double tjd_start, int32 ipl, char *star, int32 helflag, int32 evtyp, double dperiod, double *dgeo, double *tjdret, char *serr)
2548
+ {
2549
+ int i, retval;
2550
+ int32 is_acronychal = FALSE;
2551
+ int32 epheflag = helflag & (SEFLG_JPLEPH|SEFLG_SWIEPH|SEFLG_MOSEPH);
2552
+ double dsunpl = 1, dsunpl_save, dsunpl_test, tjd, daystep;
2553
+ AS_BOOL desc_obl = FALSE, retro = FALSE;
2554
+ if (evtyp == SE_EVENING_LAST || evtyp == SE_EVENING_FIRST)
2555
+ desc_obl = TRUE;
2556
+ if (evtyp == SE_MORNING_FIRST || evtyp == SE_EVENING_LAST)
2557
+ retro = TRUE;
2558
+ if (evtyp == SE_ACRONYCHAL_RISING)
2559
+ desc_obl = TRUE;
2560
+ if (evtyp == SE_ACRONYCHAL_RISING || evtyp == SE_ACRONYCHAL_SETTING) {
2561
+ is_acronychal = TRUE;
2562
+ if (ipl != SE_MOON)
2563
+ retro = TRUE;
2564
+ }
2565
+ // if (evtyp == 3 || evtyp == 4)
2566
+ // dangsearch = 180;
2567
+ /* find date when sun and object have the same ascensio obliqua */
2568
+ tjd = tjd_start;
2569
+ dsunpl_save = -999999999;
2570
+ retval = get_asc_obl_diff(tjd, ipl, star, epheflag, dgeo, desc_obl, is_acronychal, &dsunpl, serr);
2571
+ if (retval != OK) /* retval may be ERR or -2 */
2572
+ return retval;
2573
+ daystep = 20;
2574
+ i = 0;
2575
+ while (dsunpl_save == -999999999 ||
2576
+ /*fabs(dsunpl - dsunpl_save) > 180 ||*/
2577
+ fabs(dsunpl) + fabs(dsunpl_save) > 180 ||
2578
+ (retro && !(dsunpl_save < 0 && dsunpl >= 0)) ||
2579
+ (!retro && !(dsunpl_save >= 0 && dsunpl < 0))) {
2580
+ i++;
2581
+ if (i > 5000) {
2582
+ sprintf(serr, "loop in get_asc_obl_with_sun() (1)");
2583
+ return ERR;
2584
+ }
2585
+ dsunpl_save = dsunpl;
2586
+ tjd += 10.0;
2587
+ if (dperiod > 0 && tjd - tjd_start > dperiod)
2588
+ return -2;
2589
+ retval = get_asc_obl_diff(tjd, ipl, star, epheflag, dgeo, desc_obl, is_acronychal, &dsunpl, serr);
2590
+ if (retval != OK) /* retval may be ERR or -2 */
2591
+ return retval;
2592
+ }
2593
+ tjd_start = tjd - daystep;
2594
+ daystep /= 2.0;
2595
+ tjd = tjd_start + daystep;
2596
+ retval = get_asc_obl_diff(tjd, ipl, star, epheflag, dgeo, desc_obl, is_acronychal, &dsunpl_test, serr);
2597
+ if (retval != OK) /* retval may be ERR or -2 */
2598
+ return retval;
2599
+ i = 0;
2600
+ while (fabs(dsunpl) > 0.00001) {
2601
+ i++;
2602
+ if (i > 5000) {
2603
+ sprintf(serr, "loop in get_asc_obl_with_sun() (2)");
2604
+ return ERR;
2605
+ }
2606
+ if (dsunpl_save * dsunpl_test >= 0) {
2607
+ dsunpl_save = dsunpl_test;
2608
+ tjd_start = tjd;
2609
+ } else {
2610
+ dsunpl = dsunpl_test;
2611
+ }
2612
+ daystep /= 2.0;
2613
+ tjd = tjd_start + daystep;
2614
+ retval = get_asc_obl_diff(tjd, ipl, star, epheflag, dgeo, desc_obl, is_acronychal, &dsunpl_test, serr);
2615
+ if (retval != OK) /* retval may be ERR or -2 */
2616
+ return retval;
2617
+ }
2618
+ *tjdret = tjd;
2619
+ return OK;
2620
+ }
2621
+
2622
+ #if 0
2623
+ /* works only for fixed stars */
2624
+ static int32 get_asc_obl_with_sun_old(double tjd_start, int32 ipl, char *star, int32 helflag, int32 TypeEvent, double *dgeo, double *tjdret, char *serr)
2625
+ {
2626
+ int retval;
2627
+ int32 epheflag = helflag & (SEFLG_JPLEPH|SEFLG_SWIEPH|SEFLG_MOSEPH);
2628
+ double dsunpl = 1, tjd, daystep, dsunpl_save;
2629
+ double dsynperiod = 367;
2630
+ double dangsearch = 0;
2631
+ AS_BOOL desc_obl = FALSE;
2632
+ if (TypeEvent == 2 || TypeEvent == 3)
2633
+ desc_obl = TRUE;
2634
+ if (TypeEvent == 3 || TypeEvent == 4)
2635
+ dangsearch = 180;
2636
+ /* find date when sun and object have the same ascensio obliqua */
2637
+ daystep = dsynperiod;
2638
+ tjd = tjd_start;
2639
+ retval = get_asc_obl_diff(tjd, ipl, star, epheflag, dgeo, desc_obl, &dsunpl, serr);
2640
+ if (retval != OK) /* retval may be ERR or -2 */
2641
+ return retval;
2642
+ while (dsunpl < 359.99999) {
2643
+ dsunpl_save = dsunpl;
2644
+ daystep /= 2.0;
2645
+ retval = get_asc_obl_diff(tjd + daystep, ipl, star, epheflag, dgeo, desc_obl, &dsunpl, serr);
2646
+ if (retval != OK) /* retval may be ERR or -2 */
2647
+ return retval;
2648
+ if (dsunpl > dsunpl_save)
2649
+ tjd += daystep;
2650
+ else
2651
+ dsunpl = dsunpl_save;
2652
+ }
2653
+ *tjdret = tjd;
2654
+ return OK;
2655
+ }
2656
+ #endif
2657
+
2658
+ #if 0
2659
+ /* works only for fixed stars */
2660
+ static int32 get_asc_obl_acronychal(double tjd_start, int32 ipl, char *star, int32 helflag, int32 TypeEvent, double *dgeo, double *tjdret, char *serr)
2661
+ {
2662
+ int retval;
2663
+ int32 epheflag = helflag & (SEFLG_JPLEPH|SEFLG_SWIEPH|SEFLG_MOSEPH);
2664
+ double dsunpl = 1, tjd, daystep, dsunpl_save;
2665
+ double dsynperiod = 367;
2666
+ double aosun, aopl;
2667
+ AS_BOOL sun_desc = TRUE, obj_desc = FALSE;
2668
+ daystep = dsynperiod;
2669
+ tjd = tjd_start;
2670
+ if (TypeEvent == 4) {
2671
+ sun_desc = FALSE;
2672
+ obj_desc = TRUE;
2673
+ }
2674
+ /* ascensio (descensio) obliqua of sun */
2675
+ retval = get_asc_obl(tjd, SE_SUN, "", epheflag, dgeo, sun_desc, &aosun, serr);
2676
+ if (retval != OK) /* retval may be ERR or -2 */
2677
+ return retval;
2678
+ /* ascensio (descensio) obliqua of body */
2679
+ retval = get_asc_obl(tjd, ipl, star, epheflag, dgeo, obj_desc, &aopl, serr);
2680
+ if (retval != OK) /* retval may be ERR or -2 */
2681
+ return retval;
2682
+ dsunpl = swe_degnorm(aosun - aopl + 180);
2683
+ while (dsunpl < 359.99999) {
2684
+ dsunpl_save = dsunpl;
2685
+ daystep /= 2.0;
2686
+ /* ascensio (descensio) obliqua of sun */
2687
+ retval = get_asc_obl(tjd+daystep, SE_SUN, "", epheflag, dgeo, sun_desc, &aosun, serr);
2688
+ if (retval != OK) /* retval may be ERR or -2 */
2689
+ return retval;
2690
+ /* ascensio (descensio) obliqua of body */
2691
+ retval = get_asc_obl(tjd+daystep, ipl, star, epheflag, dgeo, obj_desc, &aopl, serr);
2692
+ if (retval != OK) /* retval may be ERR or -2 */
2693
+ return retval;
2694
+ dsunpl = swe_degnorm(aosun - aopl + 180);
2695
+ if (dsunpl > dsunpl_save)
2696
+ tjd += daystep;
2697
+ else
2698
+ dsunpl = dsunpl_save;
2699
+ }
2700
+ *tjdret = tjd;
2701
+ return OK;
2702
+ }
2703
+ #endif
2704
+
2705
+ static int32 get_heliacal_day(double tjd, double *dgeo, double *datm, double *dobs, char *ObjectName, int32 helflag, int32 TypeEvent, double *thel, char *serr)
2706
+ {
2707
+ int32 is_rise_or_set, ndays, retval, retval_old;
2708
+ double direct_day, direct_time, tfac, tend, daystep, tday, vdelta, tret;
2709
+ double darr[30], tsave, vd, dmag;
2710
+ int32 ipl = DeterObject(ObjectName);
2711
+ /*
2712
+ * find the day and minute on which the object becomes visible
2713
+ */
2714
+ switch (TypeEvent) {
2715
+ /* morning first */
2716
+ case 1: is_rise_or_set = SE_CALC_RISE;
2717
+ direct_day = 1; direct_time = -1;
2718
+ break;
2719
+ /* evening last */
2720
+ case 2: is_rise_or_set = SE_CALC_SET;
2721
+ direct_day = -1; direct_time = 1;
2722
+ break;
2723
+ /* evening first */
2724
+ case 3: is_rise_or_set = SE_CALC_SET;
2725
+ direct_day = 1; direct_time = 1;
2726
+ break;
2727
+ /* morning last */
2728
+ case 4: is_rise_or_set = SE_CALC_RISE;
2729
+ direct_day = -1; direct_time = -1;
2730
+ break;
2731
+ }
2732
+ tfac = 1;
2733
+ switch (ipl) {
2734
+ case SE_MOON:
2735
+ ndays = 6;
2736
+ daystep = 1;
2737
+ break;
2738
+ case SE_MERCURY:
2739
+ ndays = 60; tjd -= 0 * direct_day;
2740
+ daystep = 5;
2741
+ tfac = 5;
2742
+ break;
2743
+ case SE_VENUS:
2744
+ ndays = 300; tjd -= 30 * direct_day;
2745
+ daystep = 5;
2746
+ if (TypeEvent >= 3) {
2747
+ daystep = 15;
2748
+ tfac = 3;
2749
+ }
2750
+ break;
2751
+ case SE_MARS:
2752
+ ndays = 400;
2753
+ daystep = 15;
2754
+ tfac = 5;
2755
+ break;
2756
+ case SE_SATURN:
2757
+ ndays = 300;
2758
+ daystep = 20;
2759
+ tfac = 5;
2760
+ break;
2761
+ case -1:
2762
+ ndays = 300;
2763
+ if (call_swe_fixstar_mag(ObjectName, &dmag, serr) == ERR)
2764
+ return ERR;
2765
+ daystep = 15;
2766
+ tfac = 10;
2767
+ if (dmag > 2) {
2768
+ daystep = 15;
2769
+ }
2770
+ break;
2771
+ default:
2772
+ ndays = 300;
2773
+ daystep = 15;
2774
+ tfac = 3;
2775
+ break;
2776
+ }
2777
+ tend = tjd + ndays * direct_day;
2778
+ retval_old = -2;
2779
+ for (tday = tjd;
2780
+ (direct_day > 0 && tday < tend) || (direct_day < 0 && tday > tend);
2781
+ tday += daystep * direct_day) {
2782
+ vdelta = -100;
2783
+ if ((retval = my_rise_trans(tday, SE_SUN, "", is_rise_or_set, helflag, dgeo, datm, &tret, serr)) == ERR)
2784
+ return ERR;
2785
+ /* sun does not rise: try next day */
2786
+ if (retval == -2) {
2787
+ retval_old = retval;
2788
+ continue;
2789
+ }
2790
+ retval = swe_vis_limit_mag(tret, dgeo, datm, dobs, ObjectName, helflag, darr, serr);
2791
+ if (retval == ERR)
2792
+ return ERR;
2793
+ #if 1
2794
+ /* object has appeared above horizon: reduce daystep */
2795
+ if (retval_old == -2 && retval >= 0 && daystep > 1) {
2796
+ retval_old = retval;
2797
+ tday -= daystep * direct_day;
2798
+ daystep = 1;
2799
+ /* Note: beyond latitude 55N (?), Mars can have a morning last.
2800
+ * If the period of visibility is less than 5 days, we may miss the
2801
+ * event. I don't know if this happens */
2802
+ if (ipl >= SE_MARS || ipl == -1)
2803
+ daystep = 5;
2804
+ continue;
2805
+ }
2806
+ retval_old = retval;
2807
+ #endif
2808
+ /* object below horizon: try next day */
2809
+ if (retval == -2)
2810
+ continue;
2811
+ vdelta = darr[0] - darr[7];
2812
+ /* find minute of object's becoming visible */
2813
+ tsave = tret;
2814
+ while (retval != -2 && (vd = darr[0] - darr[7]) < 0) {
2815
+ if (vd < -1.0)
2816
+ tret += 5.0 / 1440.0 * direct_time * tfac;
2817
+ else if (vd < -0.5)
2818
+ tret += 2.0 / 1440.0 * direct_time * tfac;
2819
+ else if (vd < -0.1)
2820
+ tret += 1.0 / 1440.0 * direct_time * tfac;
2821
+ else
2822
+ tret += 1.0 / 1440.0 * direct_time;
2823
+ retval = swe_vis_limit_mag(tret, dgeo, datm, dobs, ObjectName, helflag, darr, serr);
2824
+ if (retval == ERR)
2825
+ return ERR;
2826
+ }
2827
+ vdelta = darr[0] - darr[7];
2828
+ /* object is visible, save time of appearance */
2829
+ if (vdelta > 0) {
2830
+ if ((ipl >= SE_MARS || ipl == -1) && daystep > 1) {
2831
+ tday -= daystep * direct_day;
2832
+ daystep = 1;
2833
+ } else {
2834
+ *thel = tret;
2835
+ return OK;
2836
+ }
2837
+ }
2838
+ }
2839
+ sprintf(serr, "heliacal event does not happen");
2840
+ return -2;
2841
+ }
2842
+
2843
+ #if 0
2844
+ static int32 get_acronychal_day_new(double tjd, double *dgeo, double *datm, double *dobs, char *ObjectName, int32 helflag, int32 TypeEvent, double *thel, char *serr) {
2845
+ double tjdc = tjd, tret, x[6], xaz[6], AltO = -10;
2846
+ int32 retval, is_rise_or_set, iter_day;
2847
+ int32 ipl = DeterObject(ObjectName);
2848
+ int32 epheflag = helflag & (SEFLG_JPLEPH|SEFLG_SWIEPH|SEFLG_MOSEPH);
2849
+ int32 iflag = epheflag | SEFLG_EQUATORIAL | SEFLG_TOPOCTR;
2850
+ if ((retval = my_rise_trans(tret, 0, ObjectName, SE_CALC_RISE, helflag, dgeo, datm, &tret, serr)) == ERR) return ERR;
2851
+ trise = tret;
2852
+ tret += 0.01
2853
+ if ((retval = my_rise_trans(tret, 0, ObjectName, SE_CALC_SET, helflag, dgeo, datm, &tret, serr)) == ERR) return ERR;
2854
+ trise = tset;
2855
+
2856
+ *thel = tret;
2857
+ return OK;
2858
+ }
2859
+ #endif
2860
+
2861
+ #if 0
2862
+ static int32 get_acronychal_day_old(double tjd, double *dgeo, double *datm, double *dobs, char *ObjectName, int32 helflag, int32 TypeEvent, double *thel, char *serr) {
2863
+ double tjdc = tjd, tret, x[6], xaz[6], AltO = -10;
2864
+ int32 retval, is_rise_or_set, iter_day;
2865
+ int32 ipl = DeterObject(ObjectName);
2866
+ int32 epheflag = helflag & (SEFLG_JPLEPH|SEFLG_SWIEPH|SEFLG_MOSEPH);
2867
+ int32 iflag = epheflag | SEFLG_EQUATORIAL | SEFLG_TOPOCTR;
2868
+ if (TypeEvent == 3) {
2869
+ is_rise_or_set = SE_CALC_SET;
2870
+ tret = tjdc - 3;
2871
+ if (ipl >= SE_MARS)
2872
+ tret = tjdc - 3;
2873
+ iter_day = 1;
2874
+ } else {
2875
+ is_rise_or_set = SE_CALC_RISE;
2876
+ tret = tjdc + 3;
2877
+ if (ipl >= SE_MARS)
2878
+ tret = tjdc + 3;
2879
+ iter_day = -1;
2880
+ }
2881
+ while (AltO < 0) {
2882
+ tret += 0.3 * iter_day;
2883
+ if (iter_day == -1)
2884
+ tret -= 1;
2885
+ retval = my_rise_trans(tret, SE_SUN, "", is_rise_or_set, helflag, dgeo, datm, &tret, serr);
2886
+ if (retval != OK)
2887
+ return retval;
2888
+ /* determine object's position */
2889
+ if (ipl == -1)
2890
+ retval = call_swe_fixstar(ObjectName, tret+swe_deltat(tret), iflag, x, serr);
2891
+ else
2892
+ retval = swe_calc(tret+swe_deltat(tret), ipl, iflag, x, serr);
2893
+ if (retval == ERR) return ERR;
2894
+ swe_azalt(tret, SE_EQU2HOR, dgeo, datm[0], datm[1], x, xaz);
2895
+ AltO = xaz[2];
2896
+ }
2897
+ *thel = tret;
2898
+ return OK;
2899
+ }
2900
+ #endif
2901
+
2902
+ static int32 time_optimum_visibility(double tjd, double *dgeo, double *datm, double *dobs, char *ObjectName, int32 helflag, double *tret, char *serr)
2903
+ {
2904
+ int32 retval, retval_sv, i;
2905
+ double d, vl, darr[10], phot_scot_opic, phot_scot_opic_sv;
2906
+ *tret = tjd;
2907
+ retval = swe_vis_limit_mag(tjd, dgeo, datm, dobs, ObjectName, helflag, darr, serr);
2908
+ if (retval == ERR) return ERR;
2909
+ retval_sv = retval;
2910
+ vl = darr[0] - darr[7];
2911
+ phot_scot_opic_sv = retval & SE_SCOTOPIC_FLAG;
2912
+ for (i = 0, d = 100.0 / 86400.0; i < 3; i++, d /= 10.0) {
2913
+ while((retval = swe_vis_limit_mag(tjd - d, dgeo, datm, dobs, ObjectName, helflag, darr, serr)) >= 0
2914
+ && darr[0] > darr[7]
2915
+ && darr[0] - darr[7] > vl) {
2916
+ tjd -= d; vl = darr[0] - darr[7];
2917
+ retval_sv = retval;
2918
+ phot_scot_opic_sv = retval & SE_SCOTOPIC_FLAG;
2919
+ /* printf("1: %f\n", darr[8]);*/
2920
+ }
2921
+ if (retval == ERR) return ERR;
2922
+ while((retval = swe_vis_limit_mag(tjd + d, dgeo, datm, dobs, ObjectName, helflag, darr, serr)) >= 0
2923
+ && darr[0] > darr[7]
2924
+ && darr[0] - darr[7] > vl) {
2925
+ tjd += d; vl = darr[0] - darr[7];
2926
+ retval_sv = retval;
2927
+ phot_scot_opic_sv = retval & SE_SCOTOPIC_FLAG;
2928
+ /* printf("2: %f\n", darr[8]);*/
2929
+ }
2930
+ if (retval == ERR) return ERR;
2931
+ }
2932
+ /* printf("3: %f <-> %f\n", darr[8], phot_scot_opic_sv);*/
2933
+ *tret = tjd;
2934
+ if (retval >= 0) {
2935
+ /* search for optimum came to an end because change scotopic/photopic: */
2936
+ phot_scot_opic = (retval & SE_SCOTOPIC_FLAG);
2937
+ if (phot_scot_opic_sv != phot_scot_opic) {
2938
+ /* calling function writes warning into serr */
2939
+ return -2;
2940
+ }
2941
+ /* valid result found but it is close to the scotopic/photopic limit */
2942
+ if (retval_sv & SE_MIXEDOPIC_FLAG) {
2943
+ return -2;
2944
+ }
2945
+ }
2946
+ return OK;
2947
+ }
2948
+
2949
+ static int32 time_limit_invisible(double tjd, double *dgeo, double *datm, double *dobs, char *ObjectName, int32 helflag, int32 direct, double *tret, char *serr)
2950
+ {
2951
+ int32 retval, retval_sv, i, ncnt = 3;
2952
+ double d = 0, darr[10], phot_scot_opic, phot_scot_opic_sv;
2953
+ double d0 = 100.0 / 86400.0, tjd_save;
2954
+ *tret = tjd;
2955
+ tjd_save = tjd;
2956
+ if (strcmp(ObjectName, "moon") == 0) {
2957
+ d0 *= 10;
2958
+ ncnt = 4;
2959
+ }
2960
+ retval = swe_vis_limit_mag(tjd + d * direct, dgeo, datm, dobs, ObjectName, helflag, darr, serr);
2961
+ if (retval == ERR) return ERR;
2962
+ retval_sv = retval;
2963
+ phot_scot_opic_sv = retval & SE_SCOTOPIC_FLAG;
2964
+ for (i = 0, d = d0; i < ncnt; i++, d /= 10.0) {
2965
+ while((retval = swe_vis_limit_mag(tjd + d * direct, dgeo, datm, dobs, ObjectName, helflag, darr, serr)) >= 0
2966
+ && darr[0] > darr[7]) {
2967
+ tjd += d * direct;
2968
+ retval_sv = retval;
2969
+ phot_scot_opic_sv = retval & SE_SCOTOPIC_FLAG;
2970
+ /* printf("%d: %f\n", direct, darr[8]); */
2971
+ }
2972
+ }
2973
+ /* printf("4: %f, %f/%f %f <-> %f\n", darr[8], darr[0], darr[7], tjd, phot_scot_opic_sv); */
2974
+ *tret = tjd;
2975
+ /* if object disappears at setting, retval is -2, but we want it OK, and
2976
+ * also suppress the warning "object is below local horizon" */
2977
+ *serr = '\0';
2978
+ if (retval >= 0) {
2979
+ /* search for limit came to an end because change scotopic/photopic: */
2980
+ phot_scot_opic = (retval & SE_SCOTOPIC_FLAG);
2981
+ if (phot_scot_opic_sv != phot_scot_opic) {
2982
+ /* calling function writes warning into serr */
2983
+ return -2;
2984
+ }
2985
+ /* valid result found but it is close to the scotopic/photopic limit */
2986
+ if (retval_sv & SE_MIXEDOPIC_FLAG) {
2987
+ return -2;
2988
+ }
2989
+ }
2990
+ return OK;
2991
+ }
2992
+
2993
+ static int32 get_acronychal_day(double tjd, double *dgeo, double *datm, double *dobs, char *ObjectName, int32 helflag, int32 TypeEvent, double *thel, char *serr) {
2994
+ double tret, tret_dark, darr[30], dtret, dtret_save;
2995
+ /* x[6], xaz[6], alto, azio, alto_dark, azio_dark;*/
2996
+ int32 retval, is_rise_or_set, direct;
2997
+ int32 ipl = DeterObject(ObjectName);
2998
+ helflag |= SE_HELFLAG_VISLIM_PHOTOPIC;
2999
+ /*int32 epheflag = helflag & (SEFLG_JPLEPH|SEFLG_SWIEPH|SEFLG_MOSEPH);*/
3000
+ /* int32 iflag = epheflag | SEFLG_EQUATORIAL | SEFLG_TOPOCTR;*/
3001
+ if (TypeEvent == 3 || TypeEvent == 5) {
3002
+ is_rise_or_set = SE_CALC_RISE;
3003
+ /* tret = tjdc - 3;
3004
+ if (ipl >= SE_MARS)
3005
+ tret = tjdc - 3;*/
3006
+ direct = -1;
3007
+ } else {
3008
+ is_rise_or_set = SE_CALC_SET;
3009
+ /*tret = tjdc + 3;
3010
+ if (ipl >= SE_MARS)
3011
+ tret = tjdc + 3;*/
3012
+ direct = 1;
3013
+ }
3014
+ dtret = 999;
3015
+ #if 0
3016
+ while (fabs(dtret) > 0.5) {
3017
+ #else
3018
+ while (fabs(dtret) > 0.5 / 1440.0) {
3019
+ #endif
3020
+ tjd += 0.7 * direct;
3021
+ if (direct < 0) tjd -= 1;
3022
+ retval = my_rise_trans(tjd, ipl, ObjectName, is_rise_or_set, helflag, dgeo, datm, &tjd, serr);
3023
+ if (retval == ERR) return ERR;
3024
+ retval = swe_vis_limit_mag(tjd, dgeo, datm, dobs, ObjectName, helflag, darr, serr);
3025
+ while(darr[0] < darr[7]) {
3026
+ tjd += 10.0 / 1440.0 * -direct;
3027
+ retval = swe_vis_limit_mag(tjd, dgeo, datm, dobs, ObjectName, helflag, darr, serr);
3028
+ }
3029
+ retval = time_limit_invisible(tjd, dgeo, datm, dobs, ObjectName, helflag | SE_HELFLAG_VISLIM_DARK, direct, &tret_dark, serr);
3030
+ if (retval == ERR) return ERR;
3031
+ retval = time_limit_invisible(tjd, dgeo, datm, dobs, ObjectName, helflag | SE_HELFLAG_VISLIM_NOMOON, direct, &tret, serr);
3032
+ if (retval == ERR) return ERR;
3033
+ dtret_save = dtret;
3034
+ #if 0
3035
+ if (azalt_cart(tret_dark, dgeo, datm, ObjectName, helflag, darr, serr) == ERR)
3036
+ return ERR;
3037
+ if (azalt_cart(tret, dgeo, datm, ObjectName, helflag, darr+6, serr) == ERR)
3038
+ return ERR;
3039
+ dtret = acos(swi_dot_prod_unit(darr+3, darr+9)) / DEGTORAD;
3040
+ #else
3041
+ dtret = fabs(tret - tret_dark);
3042
+ #endif
3043
+ /*printf("dtret = %f - %f\n", dtret * 1440, fabs(dtret - dtret_save) * 1440);*/
3044
+ }
3045
+ if (azalt_cart(tret, dgeo, datm, "sun", helflag, darr, serr) == ERR)
3046
+ return ERR;
3047
+ *thel = tret;
3048
+ if (darr[1] < -12) {
3049
+ sprintf(serr, "acronychal rising/setting not available, %f", darr[1]);
3050
+ return OK;
3051
+ } else {
3052
+ sprintf(serr, "solar altitude, %f", darr[1]);
3053
+ }
3054
+ return OK;
3055
+ }
3056
+
3057
+ static int32 get_heliacal_details(double tday, double *dgeo, double *datm, double *dobs, char *ObjectName, int32 TypeEvent, int32 helflag, double *dret, char *serr)
3058
+ {
3059
+ int32 i, retval, direct;
3060
+ AS_BOOL optimum_undefined, limit_1_undefined, limit_2_undefined;
3061
+ /* find next optimum visibility */
3062
+ optimum_undefined = FALSE;
3063
+ retval = time_optimum_visibility(tday, dgeo, datm, dobs, ObjectName, helflag, &(dret[1]), serr);
3064
+ if (retval == ERR) return ERR;
3065
+ if (retval == -2) {
3066
+ retval = OK;
3067
+ optimum_undefined = TRUE; /* change photopic <-> scotopic vision */
3068
+ }
3069
+ /* find moment of becoming visible */
3070
+ direct = 1;
3071
+ if (TypeEvent == 1 || TypeEvent == 4)
3072
+ direct = -1;
3073
+ limit_1_undefined = FALSE;
3074
+ retval = time_limit_invisible(tday, dgeo, datm, dobs, ObjectName, helflag, direct, &(dret[0]), serr);
3075
+ if (retval == ERR) return ERR;
3076
+ if (retval == -2) {
3077
+ retval = OK;
3078
+ limit_1_undefined = TRUE; /* change photopic <-> scotopic vision */
3079
+ }
3080
+ /* find moment of end of visibility */
3081
+ direct *= -1;
3082
+ limit_2_undefined = FALSE;
3083
+ retval = time_limit_invisible(dret[1], dgeo, datm, dobs, ObjectName, helflag, direct, &(dret[2]), serr);
3084
+ if (retval == ERR) return ERR;
3085
+ if (retval == -2) {
3086
+ retval = OK;
3087
+ limit_2_undefined = TRUE; /* change photopic <-> scotopic vision */
3088
+ }
3089
+ /* correct sequence of times:
3090
+ * with event types 2 and 3 swap dret[0] and dret[2] */
3091
+ if (TypeEvent == 2 || TypeEvent == 3) {
3092
+ tday = dret[2];
3093
+ dret[2] = dret[0];
3094
+ dret[0] = tday;
3095
+ i = (int) limit_1_undefined;
3096
+ limit_1_undefined = limit_2_undefined;
3097
+ limit_2_undefined = (AS_BOOL) i;
3098
+ }
3099
+ /*if (retval == OK && dret[0] == dret[1]) */
3100
+ if (optimum_undefined || limit_1_undefined || limit_2_undefined) {
3101
+ sprintf(serr, "return values [");
3102
+ if (limit_1_undefined)
3103
+ strcat(serr, "0,");
3104
+ if (optimum_undefined)
3105
+ strcat(serr, "1,");
3106
+ if (limit_2_undefined)
3107
+ strcat(serr, "2,");
3108
+ strcat(serr, "] are uncertain due to change between photopic and scotopic vision");
3109
+ }
3110
+ return OK;
3111
+ }
3112
+
3113
+ static int32 heliacal_ut_vis_lim(double tjd_start, double *dgeo, double *datm, double *dobs, char *ObjectName, int32 TypeEventIn, int32 helflag, double *dret, char *serr_ret)
3114
+ {
3115
+ int i;
3116
+ double d, darr[10], direct = 1, tjd, tday;
3117
+ int32 epheflag, retval = OK, helflag2;
3118
+ int32 iflag, ipl;
3119
+ int32 TypeEvent = TypeEventIn;
3120
+ char serr[AS_MAXCH];
3121
+ for (i = 0; i < 10; i++)
3122
+ dret[i] = 0;
3123
+ *dret = tjd_start;
3124
+ *serr = '\0';
3125
+ ipl = DeterObject(ObjectName);
3126
+ epheflag = helflag & (SEFLG_JPLEPH|SEFLG_SWIEPH|SEFLG_MOSEPH);
3127
+ iflag = SEFLG_TOPOCTR | SEFLG_EQUATORIAL | epheflag;
3128
+ if (!(helflag & SE_HELFLAG_HIGH_PRECISION))
3129
+ iflag |= SEFLG_NONUT | SEFLG_TRUEPOS;
3130
+ if (ipl == SE_MERCURY)
3131
+ tjd = tjd_start - 30;
3132
+ else
3133
+ tjd = tjd_start - 50; /* -50 makes sure, that no event is missed,
3134
+ * but may return an event before start date */
3135
+ helflag2 = helflag;
3136
+ /*helflag2 &= ~SE_HELFLAG_HIGH_PRECISION;*/
3137
+ /*
3138
+ * heliacal event
3139
+ */
3140
+ if (ipl == SE_MERCURY || ipl == SE_VENUS || TypeEvent <= 2) {
3141
+ if (ipl == -1) {
3142
+ /* find date when star rises with sun (cosmic rising) */
3143
+ retval = get_asc_obl_with_sun(tjd, ipl, ObjectName, helflag, TypeEvent, 0, dgeo, &tjd, serr);
3144
+ if (retval != OK)
3145
+ goto swe_heliacal_err; /* retval may be -2 or ERR */
3146
+ } else {
3147
+ /* find date of conjunction of object with sun */
3148
+ if ((retval = find_conjunct_sun(tjd, ipl, helflag, TypeEvent, &tjd, serr)) == ERR)
3149
+ goto swe_heliacal_err;
3150
+ }
3151
+ /* find the day and minute on which the object becomes visible */
3152
+ retval = get_heliacal_day(tjd, dgeo, datm, dobs, ObjectName, helflag2, TypeEvent, &tday, serr);
3153
+ if (retval != OK)
3154
+ goto swe_heliacal_err;
3155
+ /*
3156
+ * acronychal event
3157
+ */
3158
+ } else {
3159
+ if (1 || ipl == -1) {
3160
+ /*retval = get_asc_obl_acronychal(tjd, ipl, ObjectName, helflag2, TypeEvent, dgeo, &tjd, serr);*/
3161
+ retval = get_asc_obl_with_sun(tjd, ipl, ObjectName, helflag, TypeEvent, 0, dgeo, &tjd, serr);
3162
+ if (retval != OK)
3163
+ goto swe_heliacal_err;
3164
+ } else {
3165
+ /* find date of conjunction of object with sun */
3166
+ if ((retval = find_conjunct_sun(tjd, ipl, helflag, TypeEvent, &tjd, serr)) == ERR)
3167
+ goto swe_heliacal_err;
3168
+ }
3169
+ tday = tjd;
3170
+ retval = get_acronychal_day(tjd, dgeo, datm, dobs, ObjectName, helflag2, TypeEvent, &tday, serr);
3171
+ if (retval != OK)
3172
+ goto swe_heliacal_err;
3173
+ }
3174
+ dret[0] = tday;
3175
+ if (!(helflag & SE_HELFLAG_NO_DETAILS)) {
3176
+ /* more precise event times for
3177
+ * - morning first, evening last
3178
+ * - venus and mercury's evening first and morning last
3179
+ */
3180
+ if (ipl == SE_MERCURY || ipl == SE_VENUS || TypeEvent <= 2) {
3181
+ retval = get_heliacal_details(tday, dgeo, datm, dobs, ObjectName, TypeEvent, helflag2, dret, serr);
3182
+ if (retval == ERR) goto swe_heliacal_err;
3183
+ } else if (0) {
3184
+ if (TypeEvent == 4 || TypeEvent == 6) direct = -1;
3185
+ for (i = 0, d = 100.0 / 86400.0; i < 3; i++, d /= 10.0) {
3186
+ while((retval = swe_vis_limit_mag(*dret + d * direct, dgeo, datm, dobs, ObjectName, helflag, darr, serr)) == -2 || (retval >= 0 && darr[0] < darr[7])) {
3187
+ *dret += d * direct;
3188
+ }
3189
+ }
3190
+ /* the last time step must be added */
3191
+ if (retval == OK)
3192
+ *dret += 1.0 / 86400.0 * direct;
3193
+ }
3194
+ } /* if (1) */
3195
+ swe_heliacal_err:
3196
+ if (serr_ret != NULL && *serr != '\0')
3197
+ strcpy(serr_ret, serr);
3198
+ return retval;
3199
+ }
3200
+
3201
+ /*###################################################################*/
3202
+ static int32 moon_event_vis_lim(double tjdstart, double *dgeo, double *datm, double *dobs, int32 TypeEvent, int32 helflag, double *dret, char *serr_ret)
3203
+ {
3204
+ double tjd, trise;
3205
+ char serr[AS_MAXCH];
3206
+ char ObjectName[30];
3207
+ int32 iflag, Daystep, eventtype, ipl, retval, helflag2, direct;
3208
+ int32 epheflag = helflag & (SEFLG_JPLEPH|SEFLG_SWIEPH|SEFLG_MOSEPH);
3209
+ dret[0] = tjdstart; /* will be returned in error case */
3210
+ if (TypeEvent == 1 || TypeEvent == 2) {
3211
+ if (serr != NULL)
3212
+ strcpy(serr, "error: the moon has no morning first or evening last");
3213
+ return ERR;
3214
+ }
3215
+ strcpy(ObjectName, "moon");
3216
+ ipl = SE_MOON;
3217
+ iflag = SEFLG_TOPOCTR | SEFLG_EQUATORIAL | epheflag;
3218
+ if (!(helflag & SE_HELFLAG_HIGH_PRECISION))
3219
+ iflag |= SEFLG_NONUT|SEFLG_TRUEPOS;
3220
+ helflag2 = helflag;
3221
+ helflag2 &= ~SE_HELFLAG_HIGH_PRECISION;
3222
+ Daystep = 1;
3223
+ eventtype = TypeEvent + SE_BIT_DISC_CENTER;
3224
+ /* check Synodic/phase Period */
3225
+ tjd = tjdstart - 30; /* -50 makes sure, that no event is missed,
3226
+ * but may return an event before start date */
3227
+ if ((retval = find_conjunct_sun(tjd, ipl, helflag, TypeEvent, &tjd, serr)) == ERR)
3228
+ return ERR;
3229
+ /* find the day and minute on which the object becomes visible */
3230
+ retval = get_heliacal_day(tjd, dgeo, datm, dobs, ObjectName, helflag2, TypeEvent, &tjd, serr);
3231
+ if (retval != OK)
3232
+ goto moon_event_err;
3233
+ dret[0] = tjd;
3234
+ /* find next optimum visibility */
3235
+ retval = time_optimum_visibility(tjd, dgeo, datm, dobs, ObjectName, helflag, &tjd, serr);
3236
+ if (retval == ERR) goto moon_event_err;
3237
+ dret[1] = tjd;
3238
+ /* find moment of becoming visible */
3239
+ /* Note: The on the day of fist light the moon may become visible
3240
+ * already during day. It also may appear during day, disappear again
3241
+ * and then reappear after sunset */
3242
+ direct = 1;
3243
+ if (TypeEvent == 4)
3244
+ direct = -1;
3245
+ retval = time_limit_invisible(tjd, dgeo, datm, dobs, ObjectName, helflag, direct, &tjd, serr);
3246
+ if (retval == ERR) goto moon_event_err;
3247
+ dret[2] = tjd;
3248
+ /* find moment of end of visibility */
3249
+ direct *= -1;
3250
+ retval = time_limit_invisible(dret[1], dgeo, datm, dobs, ObjectName, helflag, direct, &tjd, serr);
3251
+ dret[0] = tjd;
3252
+ if (retval == ERR) goto moon_event_err;
3253
+ /* if the moon is visible before sunset, we return sunset as start time */
3254
+ if (TypeEvent == 3) {
3255
+ if ((retval = my_rise_trans(tjd, SE_SUN, "", SE_CALC_SET, helflag, dgeo, datm, &trise, serr)) == ERR)
3256
+ return ERR;
3257
+ if (trise < dret[1]) {
3258
+ dret[0] = trise;
3259
+ /* do not warn, it happens too often */
3260
+ /*strcpy(serr, "start time given is sunset, but moon is observable before that");*/
3261
+ }
3262
+ /* if the moon is visible after sunrise, we return sunrise as end time */
3263
+ } else {
3264
+ if ((retval = my_rise_trans(dret[1], SE_SUN, "", SE_CALC_RISE, helflag, dgeo, datm, &trise, serr)) == ERR)
3265
+ return ERR;
3266
+ if (dret[0] > trise) {
3267
+ dret[0] = trise;
3268
+ /* do not warn, it happens too often */
3269
+ /*strcpy(serr, "end time given is sunrise, but moon is observable after that");*/
3270
+ }
3271
+ }
3272
+ /* correct order of the three times: */
3273
+ if (TypeEvent == 4) {
3274
+ tjd = dret[0];
3275
+ dret[0] = dret[2];
3276
+ dret[2] = tjd;
3277
+ }
3278
+ moon_event_err:
3279
+ if (serr_ret != NULL && *serr != '\0')
3280
+ strcpy(serr_ret, serr);
3281
+ return retval;
3282
+ }
3283
+
3284
+ static int32 MoonEventJDut(double JDNDaysUTStart, double *dgeo, double *datm, double *dobs, int32 TypeEvent, int32 helflag, double *dret, char *serr)
3285
+ {
3286
+ int32 avkind = helflag & SE_HELFLAG_AVKIND;
3287
+ if (avkind)
3288
+ return moon_event_arc_vis(JDNDaysUTStart, dgeo, datm, dobs, TypeEvent, helflag, dret, serr);
3289
+ else
3290
+ return moon_event_vis_lim(JDNDaysUTStart, dgeo, datm, dobs, TypeEvent, helflag, dret, serr);
3291
+ }
3292
+
3293
+ static int32 heliacal_ut(double JDNDaysUTStart, double *dgeo, double *datm, double *dobs, char *ObjectName, int32 TypeEventIn, int32 helflag, double *dret, char *serr_ret)
3294
+ {
3295
+ int32 avkind = helflag & SE_HELFLAG_AVKIND;
3296
+ if (avkind)
3297
+ return heliacal_ut_arc_vis(JDNDaysUTStart, dgeo, datm, dobs, ObjectName, TypeEventIn, helflag, dret, serr_ret);
3298
+ else
3299
+ return heliacal_ut_vis_lim(JDNDaysUTStart, dgeo, datm, dobs, ObjectName, TypeEventIn, helflag, dret, serr_ret);
3300
+ }
3301
+
3302
+ /*' Magn [-]
3303
+ ' tjd_ut start date (JD) for event search
3304
+ ' dgeo[3] geogr. longitude, latitude, eye height (m above sea level)
3305
+ ' datm[4] atm. pressure, temperature, RH, and VR
3306
+ ' - pressure atmospheric pressure (mbar, =hPa) default 1013.25hPa
3307
+ ' - temperature deg C, default 15 deg C (if at
3308
+ ' If both attemp and atpress are 0, a temperature and
3309
+ ' atmospheric pressure are estimated from the above-mentioned
3310
+ ' default values and the height above sea level.
3311
+ ' - RH relative humidity in %
3312
+ ' - VR VR>=1: the Meteorological range: default 40 km
3313
+ ' 1>VR>0: the ktot (so the total atmospheric coefficient):
3314
+ ' a good default would be 0.25
3315
+ ' VR=-1: the ktot is calculated from the other atmospheric
3316
+ ' constants.
3317
+ ' age [Year] default 36, experienced sky observer in ancient times
3318
+ ' optimum age is 23
3319
+ ' SN Snellen factor of the visual aquity of the observer
3320
+ ' default 1
3321
+ ' see: http://www.i-see.org/eyecharts.html#make-your-own
3322
+ ' TypeEvent 1 morning first
3323
+ ' 2 evening last
3324
+ ' 3 evening first
3325
+ ' 4 morning last
3326
+ ' dret output: time (tjd_ut) of heliacal event
3327
+ ' see http://www.iol.ie/~geniet/eng/atmoastroextinction.htm
3328
+ */
3329
+ int32 FAR PASCAL_CONV swe_heliacal_ut(double JDNDaysUTStart, double *dgeo, double *datm, double *dobs, char *ObjectNameIn, int32 TypeEvent, int32 helflag, double *dret, char *serr_ret)
3330
+ {
3331
+ int32 retval, Planet, itry;
3332
+ char ObjectName[AS_MAXCH], serr[AS_MAXCH], s[AS_MAXCH];
3333
+ double tjd0 = JDNDaysUTStart, tjd, dsynperiod, tjdmax, tadd;
3334
+ int32 MaxCountSynodicPeriod = MAX_COUNT_SYNPER;
3335
+ char *sevent[7] = {"", "morning first", "evening last", "evening first", "morning last", "acronychal rising", "acronychal setting"};
3336
+ if (helflag & SE_HELFLAG_LONG_SEARCH)
3337
+ MaxCountSynodicPeriod = MAX_COUNT_SYNPER_MAX;
3338
+ /* if (helflag & SE_HELFLAG_SEARCH_1_PERIOD)
3339
+ MaxCountSynodicPeriod = 1; */
3340
+ *serr = '\0';
3341
+ if (serr_ret != NULL)
3342
+ *serr_ret = '\0';
3343
+ /* note, the fixed stars functions rewrite the star name. The input string
3344
+ may be too short, so we have to make sure we have enough space */
3345
+ strcpy_VBsafe(ObjectName, ObjectNameIn);
3346
+ default_heliacal_parameters(datm, dgeo, dobs, helflag);
3347
+ swe_set_topo(dgeo[0], dgeo[1], dgeo[2]);
3348
+ Planet = DeterObject(ObjectName);
3349
+ /*
3350
+ * Moon events
3351
+ */
3352
+ if (Planet == SE_MOON) {
3353
+ if (TypeEvent == 1 || TypeEvent == 2) {
3354
+ if (serr_ret != NULL)
3355
+ sprintf(serr_ret, "%s (event type %d) does not exist for the moon\n", sevent[TypeEvent], TypeEvent);
3356
+ return ERR;
3357
+ }
3358
+ tjd = tjd0;
3359
+ retval = MoonEventJDut(tjd, dgeo, datm, dobs, TypeEvent, helflag, dret, serr);
3360
+ while (retval != -2 && *dret < tjd0) {
3361
+ tjd += 15;
3362
+ *serr = '\0';
3363
+ retval = MoonEventJDut(tjd, dgeo, datm, dobs, TypeEvent, helflag, dret, serr);
3364
+ }
3365
+ if (serr_ret != NULL && *serr != '\0')
3366
+ strcpy(serr_ret, serr);
3367
+ return retval;
3368
+ }
3369
+ /*
3370
+ * planets and fixed stars
3371
+ */
3372
+ if (!(helflag & SE_HELFLAG_AVKIND)) {
3373
+ if (Planet == -1 || Planet >= SE_MARS) {
3374
+ if (TypeEvent == 3 || TypeEvent == 4) {
3375
+ if (serr_ret != NULL) {
3376
+ if (Planet == -1)
3377
+ strcpy(s, ObjectName);
3378
+ else
3379
+ swe_get_planet_name(Planet, s);
3380
+ sprintf(serr_ret, "%s (event type %d) does not exist for %s\n", sevent[TypeEvent], TypeEvent, s);
3381
+ }
3382
+ return ERR;
3383
+ }
3384
+ }
3385
+ }
3386
+ /* arcus visionis method: set the TypeEvent for acronychal events */
3387
+ if (helflag & SE_HELFLAG_AVKIND) {
3388
+ if (Planet == -1 || Planet >= SE_MARS) {
3389
+ if (TypeEvent == SE_ACRONYCHAL_RISING)
3390
+ TypeEvent = 3;
3391
+ if (TypeEvent == SE_ACRONYCHAL_SETTING)
3392
+ TypeEvent = 4;
3393
+ }
3394
+ /* acronychal rising and setting (cosmic setting) are ill-defined.
3395
+ * We do not calculate them with the "visibility limit method" */
3396
+ } else if (1) {
3397
+ if (TypeEvent == SE_ACRONYCHAL_RISING || TypeEvent == SE_ACRONYCHAL_SETTING) {
3398
+ if (serr_ret != NULL) {
3399
+ if (Planet == -1)
3400
+ strcpy(s, ObjectName);
3401
+ else
3402
+ swe_get_planet_name(Planet, s);
3403
+ sprintf(serr_ret, "%s (event type %d) is not provided for %s\n", sevent[TypeEvent], TypeEvent, s);
3404
+ }
3405
+ return ERR;
3406
+ }
3407
+ }
3408
+ dsynperiod = get_synodic_period(Planet);
3409
+ tjdmax = tjd0 + dsynperiod * MaxCountSynodicPeriod;
3410
+ tadd = dsynperiod * 0.6;
3411
+ if (Planet == SE_MERCURY)
3412
+ tadd = 30;
3413
+ /*
3414
+ * this is the outer loop over n synodic periods
3415
+ */
3416
+ tjd = tjd0;
3417
+ retval = -2; /* indicates that another synodic period has to be done */
3418
+ for (itry = 0;
3419
+ tjd < tjdmax && retval == -2;
3420
+ itry++, tjd += tadd) {
3421
+ *serr = '\0';
3422
+ retval = heliacal_ut(tjd, dgeo, datm, dobs, ObjectName, TypeEvent, helflag, dret, serr);
3423
+ /* if resulting event date < start date for search (tjd0): retry starting
3424
+ * from half a period later. The event must be found now, unless there
3425
+ * is none, as is often the case with Mercury */
3426
+ while (retval != -2 && *dret < tjd0) {
3427
+ tjd += tadd;
3428
+ *serr = '\0';
3429
+ retval = heliacal_ut(tjd, dgeo, datm, dobs, ObjectName, TypeEvent, helflag, dret, serr);
3430
+ }
3431
+ }
3432
+ /*
3433
+ * no event was found within MaxCountSynodicPeriod, return error
3434
+ */
3435
+ if ((helflag & SE_HELFLAG_SEARCH_1_PERIOD) && (retval == -2 || dret[0] > tjd0 + dsynperiod * 1.5)) {
3436
+ strcpy(serr, "no heliacal date found within this synodic period");
3437
+ retval = -2;
3438
+ } else if (retval == -2) {
3439
+ sprintf(serr, "no heliacal date found within %d synodic periods", MaxCountSynodicPeriod);
3440
+ retval = ERR;
3441
+ }
3442
+ if (serr_ret != NULL && *serr != '\0')
3443
+ strcpy(serr_ret, serr);
3444
+ return retval;
3445
+ }