@typescriptify/sweph 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (211) hide show
  1. package/README.md +422 -0
  2. package/ephe/semo_18.se1 +0 -0
  3. package/ephe/sepl_18.se1 +0 -0
  4. package/originalCode/.eslintrc.json +124 -0
  5. package/originalCode/.gitattributes +2 -0
  6. package/originalCode/.github/FUNDING.yml +5 -0
  7. package/originalCode/.github/workflows/test.yml +35 -0
  8. package/originalCode/LICENSE +840 -0
  9. package/originalCode/README.md +91 -0
  10. package/originalCode/binding.gyp +41 -0
  11. package/originalCode/constants.js +366 -0
  12. package/originalCode/docs.gif +0 -0
  13. package/originalCode/index.d.ts +5115 -0
  14. package/originalCode/index.js +7 -0
  15. package/originalCode/index.mjs +109 -0
  16. package/originalCode/package.json +55 -0
  17. package/originalCode/src/functions/azalt.cpp +39 -0
  18. package/originalCode/src/functions/azalt_rev.cpp +35 -0
  19. package/originalCode/src/functions/calc.cpp +29 -0
  20. package/originalCode/src/functions/calc_pctr.cpp +31 -0
  21. package/originalCode/src/functions/calc_ut.cpp +29 -0
  22. package/originalCode/src/functions/close.cpp +6 -0
  23. package/originalCode/src/functions/cotrans.cpp +26 -0
  24. package/originalCode/src/functions/cotrans_sp.cpp +26 -0
  25. package/originalCode/src/functions/cs2degstr.cpp +19 -0
  26. package/originalCode/src/functions/cs2lonlatstr.cpp +23 -0
  27. package/originalCode/src/functions/cs2timestr.cpp +23 -0
  28. package/originalCode/src/functions/csnorm.cpp +15 -0
  29. package/originalCode/src/functions/csroundsec.cpp +15 -0
  30. package/originalCode/src/functions/d2l.cpp +15 -0
  31. package/originalCode/src/functions/date_conversion.cpp +30 -0
  32. package/originalCode/src/functions/day_of_week.cpp +15 -0
  33. package/originalCode/src/functions/degnorm.cpp +15 -0
  34. package/originalCode/src/functions/deltat.cpp +15 -0
  35. package/originalCode/src/functions/deltat_ex.cpp +24 -0
  36. package/originalCode/src/functions/difcs2n.cpp +19 -0
  37. package/originalCode/src/functions/difcsn.cpp +19 -0
  38. package/originalCode/src/functions/difdeg2n.cpp +19 -0
  39. package/originalCode/src/functions/difdegn.cpp +19 -0
  40. package/originalCode/src/functions/fixstar.cpp +32 -0
  41. package/originalCode/src/functions/fixstar2.cpp +32 -0
  42. package/originalCode/src/functions/fixstar2_mag.cpp +28 -0
  43. package/originalCode/src/functions/fixstar2_ut.cpp +32 -0
  44. package/originalCode/src/functions/fixstar_mag.cpp +28 -0
  45. package/originalCode/src/functions/fixstar_ut.cpp +32 -0
  46. package/originalCode/src/functions/gauquelin_sector.cpp +44 -0
  47. package/originalCode/src/functions/get_ayanamsa.cpp +15 -0
  48. package/originalCode/src/functions/get_ayanamsa_ex.cpp +27 -0
  49. package/originalCode/src/functions/get_ayanamsa_ex_ut.cpp +27 -0
  50. package/originalCode/src/functions/get_ayanamsa_name.cpp +19 -0
  51. package/originalCode/src/functions/get_ayanamsa_ut.cpp +15 -0
  52. package/originalCode/src/functions/get_current_file_data.cpp +28 -0
  53. package/originalCode/src/functions/get_library_path.cpp +8 -0
  54. package/originalCode/src/functions/get_orbital_elements.cpp +29 -0
  55. package/originalCode/src/functions/get_planet_name.cpp +19 -0
  56. package/originalCode/src/functions/get_tid_acc.cpp +7 -0
  57. package/originalCode/src/functions/heliacal_pheno_ut.cpp +52 -0
  58. package/originalCode/src/functions/heliacal_ut.cpp +52 -0
  59. package/originalCode/src/functions/helio_cross.cpp +33 -0
  60. package/originalCode/src/functions/helio_cross_ut.cpp +33 -0
  61. package/originalCode/src/functions/house_name.cpp +20 -0
  62. package/originalCode/src/functions/house_pos.cpp +36 -0
  63. package/originalCode/src/functions/houses.cpp +35 -0
  64. package/originalCode/src/functions/houses_armc.cpp +38 -0
  65. package/originalCode/src/functions/houses_armc_ex2.cpp +47 -0
  66. package/originalCode/src/functions/houses_ex.cpp +37 -0
  67. package/originalCode/src/functions/houses_ex2.cpp +46 -0
  68. package/originalCode/src/functions/jdet_to_utc.cpp +38 -0
  69. package/originalCode/src/functions/jdut1_to_utc.cpp +38 -0
  70. package/originalCode/src/functions/julday.cpp +25 -0
  71. package/originalCode/src/functions/lat_to_lmt.cpp +27 -0
  72. package/originalCode/src/functions/lmt_to_lat.cpp +27 -0
  73. package/originalCode/src/functions/lun_eclipse_how.cpp +34 -0
  74. package/originalCode/src/functions/lun_eclipse_when.cpp +31 -0
  75. package/originalCode/src/functions/lun_eclipse_when_loc.cpp +39 -0
  76. package/originalCode/src/functions/lun_occult_when_glob.cpp +35 -0
  77. package/originalCode/src/functions/lun_occult_when_loc.cpp +43 -0
  78. package/originalCode/src/functions/lun_occult_where.cpp +34 -0
  79. package/originalCode/src/functions/mooncross.cpp +26 -0
  80. package/originalCode/src/functions/mooncross_node.cpp +30 -0
  81. package/originalCode/src/functions/mooncross_node_ut.cpp +30 -0
  82. package/originalCode/src/functions/mooncross_ut.cpp +26 -0
  83. package/originalCode/src/functions/nod_aps.cpp +42 -0
  84. package/originalCode/src/functions/nod_aps_ut.cpp +42 -0
  85. package/originalCode/src/functions/orbit_max_min_true_distance.cpp +37 -0
  86. package/originalCode/src/functions/pheno.cpp +29 -0
  87. package/originalCode/src/functions/pheno_ut.cpp +29 -0
  88. package/originalCode/src/functions/radnorm.cpp +15 -0
  89. package/originalCode/src/functions/refrac.cpp +23 -0
  90. package/originalCode/src/functions/refrac_extended.cpp +32 -0
  91. package/originalCode/src/functions/revjul.cpp +33 -0
  92. package/originalCode/src/functions/rise_trans.cpp +44 -0
  93. package/originalCode/src/functions/rise_trans_true_hor.cpp +46 -0
  94. package/originalCode/src/functions/set_delta_t_userdef.cpp +14 -0
  95. package/originalCode/src/functions/set_ephe_path.cpp +14 -0
  96. package/originalCode/src/functions/set_jpl_file.cpp +14 -0
  97. package/originalCode/src/functions/set_sid_mode.cpp +20 -0
  98. package/originalCode/src/functions/set_tid_acc.cpp +14 -0
  99. package/originalCode/src/functions/set_topo.cpp +20 -0
  100. package/originalCode/src/functions/sidtime.cpp +15 -0
  101. package/originalCode/src/functions/sidtime0.cpp +21 -0
  102. package/originalCode/src/functions/sol_eclipse_how.cpp +34 -0
  103. package/originalCode/src/functions/sol_eclipse_when_glob.cpp +31 -0
  104. package/originalCode/src/functions/sol_eclipse_when_loc.cpp +39 -0
  105. package/originalCode/src/functions/sol_eclipse_where.cpp +30 -0
  106. package/originalCode/src/functions/solcross.cpp +26 -0
  107. package/originalCode/src/functions/solcross_ut.cpp +26 -0
  108. package/originalCode/src/functions/split_deg.cpp +35 -0
  109. package/originalCode/src/functions/time_equ.cpp +25 -0
  110. package/originalCode/src/functions/utc_time_zone.cpp +48 -0
  111. package/originalCode/src/functions/utc_to_jd.cpp +37 -0
  112. package/originalCode/src/functions/version.cpp +8 -0
  113. package/originalCode/src/functions/vis_limit_mag.cpp +50 -0
  114. package/originalCode/src/sweph.cpp +150 -0
  115. package/originalCode/src/sweph.h +119 -0
  116. package/originalCode/swisseph/swecl.c +6428 -0
  117. package/originalCode/swisseph/swedate.c +588 -0
  118. package/originalCode/swisseph/swedate.h +81 -0
  119. package/originalCode/swisseph/swehel.c +3511 -0
  120. package/originalCode/swisseph/swehouse.c +3143 -0
  121. package/originalCode/swisseph/swehouse.h +98 -0
  122. package/originalCode/swisseph/swejpl.c +958 -0
  123. package/originalCode/swisseph/swejpl.h +103 -0
  124. package/originalCode/swisseph/swemmoon.c +1930 -0
  125. package/originalCode/swisseph/swemplan.c +967 -0
  126. package/originalCode/swisseph/swemptab.h +10640 -0
  127. package/originalCode/swisseph/swenut2000a.h +2819 -0
  128. package/originalCode/swisseph/sweodef.h +326 -0
  129. package/originalCode/swisseph/sweph.c +8614 -0
  130. package/originalCode/swisseph/sweph.h +849 -0
  131. package/originalCode/swisseph/swephexp.h +1020 -0
  132. package/originalCode/swisseph/swephlib.c +4634 -0
  133. package/originalCode/swisseph/swephlib.h +189 -0
  134. package/package.json +28 -0
  135. package/scripts/gen-swemptab.js +177 -0
  136. package/scripts/gen-swenut2000a.js +106 -0
  137. package/src/SwissEph/README.md +268 -0
  138. package/src/SwissEph/UseCases/Ayanamsa.md +363 -0
  139. package/src/SwissEph/UseCases/AzimuthAltitude.md +408 -0
  140. package/src/SwissEph/UseCases/CoordinateSystems.md +337 -0
  141. package/src/SwissEph/UseCases/DateAndTime.md +368 -0
  142. package/src/SwissEph/UseCases/DeltaT.md +258 -0
  143. package/src/SwissEph/UseCases/EphemerisFiles.md +338 -0
  144. package/src/SwissEph/UseCases/FixedStars.md +300 -0
  145. package/src/SwissEph/UseCases/GauquelinSectors.md +304 -0
  146. package/src/SwissEph/UseCases/HeliacalEvents.md +396 -0
  147. package/src/SwissEph/UseCases/HelioCrossings.md +325 -0
  148. package/src/SwissEph/UseCases/HousePosition.md +254 -0
  149. package/src/SwissEph/UseCases/HouseSystems.md +279 -0
  150. package/src/SwissEph/UseCases/LunarEclipse.md +326 -0
  151. package/src/SwissEph/UseCases/MeridianTransit.md +279 -0
  152. package/src/SwissEph/UseCases/MoonCrossings.md +373 -0
  153. package/src/SwissEph/UseCases/NodesAndApsides.md +307 -0
  154. package/src/SwissEph/UseCases/Occultation.md +352 -0
  155. package/src/SwissEph/UseCases/OrbitalElements.md +469 -0
  156. package/src/SwissEph/UseCases/Phenomena.md +328 -0
  157. package/src/SwissEph/UseCases/PlanetPositions.md +366 -0
  158. package/src/SwissEph/UseCases/Planetocentric.md +278 -0
  159. package/src/SwissEph/UseCases/Refraction.md +314 -0
  160. package/src/SwissEph/UseCases/RiseAndSet.md +433 -0
  161. package/src/SwissEph/UseCases/SiderealTime.md +302 -0
  162. package/src/SwissEph/UseCases/SolarEclipse.md +379 -0
  163. package/src/SwissEph/UseCases/SunCrossings.md +275 -0
  164. package/src/SwissEph/UseCases/TopocentricCorrection.md +335 -0
  165. package/src/SwissEph/errors.ts +10 -0
  166. package/src/SwissEph/index.ts +823 -0
  167. package/src/SwissEph/types.ts +291 -0
  168. package/src/constants.ts +762 -0
  169. package/src/file-reader.ts +147 -0
  170. package/src/index.ts +10 -0
  171. package/src/swecl.ts +4526 -0
  172. package/src/swedate.ts +376 -0
  173. package/src/swehel.ts +1939 -0
  174. package/src/swehouse.ts +2167 -0
  175. package/src/swejpl.ts +470 -0
  176. package/src/swemmoon.ts +1318 -0
  177. package/src/swemplan.ts +585 -0
  178. package/src/swemptab.ts +4448 -0
  179. package/src/swenut2000a.ts +2763 -0
  180. package/src/sweph.ts +3993 -0
  181. package/src/swephlib.ts +2720 -0
  182. package/src/types.ts +490 -0
  183. package/tests/c-style/ayanamsa.test.ts +63 -0
  184. package/tests/c-style/config.test.ts +96 -0
  185. package/tests/c-style/crossings.test.ts +81 -0
  186. package/tests/c-style/date-time.test.ts +114 -0
  187. package/tests/c-style/eclipses.test.ts +84 -0
  188. package/tests/c-style/fixed-stars.test.ts +66 -0
  189. package/tests/c-style/heliacal.test.ts +34 -0
  190. package/tests/c-style/houses.test.ts +135 -0
  191. package/tests/c-style/math-utils.test.ts +160 -0
  192. package/tests/c-style/orbital.test.ts +78 -0
  193. package/tests/c-style/phenomena.test.ts +42 -0
  194. package/tests/c-style/planetocentric.test.ts +26 -0
  195. package/tests/c-style/planets.test.ts +117 -0
  196. package/tests/c-style/rise-set.test.ts +71 -0
  197. package/tests/helpers.ts +21 -0
  198. package/tests/modern/ayanamsa.test.ts +47 -0
  199. package/tests/modern/calc.test.ts +113 -0
  200. package/tests/modern/config.test.ts +46 -0
  201. package/tests/modern/crossings.test.ts +45 -0
  202. package/tests/modern/eclipses.test.ts +81 -0
  203. package/tests/modern/errors.test.ts +71 -0
  204. package/tests/modern/heliacal.test.ts +30 -0
  205. package/tests/modern/houses.test.ts +87 -0
  206. package/tests/modern/orbital.test.ts +79 -0
  207. package/tests/modern/phenomena.test.ts +41 -0
  208. package/tests/modern/rise-set.test.ts +60 -0
  209. package/tests/modern/statics.test.ts +99 -0
  210. package/tests/modern/utilities.test.ts +70 -0
  211. package/tsconfig.json +20 -0
package/src/swehel.ts ADDED
@@ -0,0 +1,1939 @@
1
+ /*************************************************************
2
+ * Swiss Ephemeris — Heliacal risings and related calculations
3
+ * Translated from swehel.c
4
+ *
5
+ * Author: Victor Reijs
6
+ * Translation from VB into C by Dieter Koch
7
+ * Translation from C to TypeScript
8
+ *
9
+ * Copyright (c) Victor Reijs, 2008
10
+ * Copyright (C) 1997 - 2021 Astrodienst AG, Switzerland.
11
+ * All rights reserved. (AGPL)
12
+ *************************************************************/
13
+
14
+ import {
15
+ PI, DEGTORAD, RADTODEG,
16
+ SE_SUN, SE_MOON, SE_MERCURY, SE_VENUS, SE_MARS,
17
+ SE_JUPITER, SE_SATURN, SE_URANUS, SE_NEPTUNE, SE_PLUTO,
18
+ SE_AST_OFFSET, SE_GREG_CAL,
19
+ SE_CALC_RISE, SE_CALC_SET, SE_BIT_DISC_CENTER, SE_EQU2HOR,
20
+ SEFLG_JPLEPH, SEFLG_SWIEPH, SEFLG_MOSEPH,
21
+ SEFLG_EQUATORIAL, SEFLG_TOPOCTR, SEFLG_NONUT, SEFLG_TRUEPOS, SEFLG_SPEED,
22
+ OK, ERR, TJD_INVALID,
23
+ SE_HELFLAG_HIGH_PRECISION, SE_HELFLAG_OPTICAL_PARAMS,
24
+ SE_HELFLAG_NO_DETAILS, SE_HELFLAG_LONG_SEARCH,
25
+ SE_HELFLAG_SEARCH_1_PERIOD,
26
+ SE_HELFLAG_VISLIM_DARK, SE_HELFLAG_VISLIM_NOMOON,
27
+ SE_HELFLAG_VISLIM_PHOTOPIC, SE_HELFLAG_VISLIM_SCOTOPIC,
28
+ SE_HELFLAG_AVKIND, SE_HELFLAG_AVKIND_VR,
29
+ SE_HELFLAG_AVKIND_PTO, SE_HELFLAG_AVKIND_MIN7, SE_HELFLAG_AVKIND_MIN9,
30
+ SE_SCOTOPIC_FLAG, SE_MIXEDOPIC_FLAG,
31
+ SE_MORNING_FIRST, SE_EVENING_LAST, SE_EVENING_FIRST, SE_MORNING_LAST,
32
+ SE_ACRONYCHAL_RISING, SE_ACRONYCHAL_SETTING,
33
+ SEI_ECL_GEOALT_MIN, SEI_ECL_GEOALT_MAX,
34
+ } from './constants';
35
+ import { sweDegnorm } from './swephlib';
36
+ import { sweDeltatEx } from './swephlib';
37
+ import { swiPolcart } from './swephlib';
38
+ import { revJul } from './swedate';
39
+ import { sweCalc, sweCalcUt, sweFixstar, sweFixstarMag, sweSetTopo, sweGetPlanetName } from './sweph';
40
+ import { sweRiseTrans, sweAzalt, swePhenoUt } from './swecl';
41
+ import type { SweData } from './types';
42
+
43
+ /* ---- Module-level constants ---- */
44
+ const PLSV = 0;
45
+ const criticalangle = 0.0;
46
+ const BNIGHT = 1479.0;
47
+ const BNIGHT_FACTOR = 1.0;
48
+ const Min2Deg = 1.0 / 60.0;
49
+ const MaxTryHours = 4;
50
+ const TimeStepDefault = 1;
51
+ const LocalMinStep = 8;
52
+
53
+ /* time constants */
54
+ const D2H = 24.0;
55
+ const H2S = 3600.0;
56
+ const D2S = D2H * H2S;
57
+
58
+ /* refraction algorithm choice */
59
+ const REFR_SINCLAIR = 0;
60
+ const FormAstroRefrac = REFR_SINCLAIR;
61
+ const GravitySource = 2;
62
+ const REarthSource = 1;
63
+
64
+ const MAX_COUNT_SYNPER = 5;
65
+ const MAX_COUNT_SYNPER_MAX = 1000000;
66
+ const AvgRadiusMoon = 15.541 / 60;
67
+
68
+ /* WGS84 */
69
+ const Ra = 6378136.6;
70
+
71
+ /* Schaefer model */
72
+ const nL2erg = 1.02e-15;
73
+ const erg2nL = 1 / nL2erg;
74
+ const scaleHwater = 3000.0;
75
+ const scaleHrayleigh = 8515.0;
76
+ const scaleHaerosol = 3745.0;
77
+ const scaleHozone = 20000.0;
78
+ const astr2tau = 0.921034037197618;
79
+ const tau2astr = 1 / astr2tau;
80
+
81
+ /* meteorological */
82
+ const C2K = 273.15;
83
+ const LapseSA = 0.0065;
84
+
85
+ const LowestAppAlt = -3.5;
86
+ const epsilon = 0.001;
87
+ const staticAirmass = 0;
88
+
89
+ /* optic defaults */
90
+ const GOpticMag = 1;
91
+ const GOpticTrans = 0.8;
92
+ const GBinocular = 1;
93
+ const GOpticDia = 50;
94
+
95
+ /* conjunction reference table */
96
+ const tcon = [
97
+ 0, 0,
98
+ 2451550, 2451550, /* Moon */
99
+ 2451604, 2451670, /* Mercury */
100
+ 2451980, 2452280, /* Venus */
101
+ 2451727, 2452074, /* Mars */
102
+ 2451673, 2451877, /* Jupiter */
103
+ 2451675, 2451868, /* Saturn */
104
+ 2451581, 2451768, /* Uranus */
105
+ 2451568, 2451753, /* Neptune */
106
+ ];
107
+
108
+ /* ---- Module-level caches (replacing C static TLS) ---- */
109
+ let sunRA_tjdlast = 0;
110
+ let sunRA_ralast = 0;
111
+ let kOZ_alts_last = -99999;
112
+ let kOZ_sunra_last = -99999;
113
+ let kOZ_last = 0;
114
+ let ka_alts_last = -99999;
115
+ let ka_sunra_last = -99999;
116
+ let ka_last = 0;
117
+ let deltam_alts_last = -99999;
118
+ let deltam_alto_last = -99999;
119
+ let deltam_sunra_last = -99999;
120
+ let deltam_last = 0;
121
+ let fixstarMag_star_save = '';
122
+ let fixstarMag_dmag = 0;
123
+
124
+ /* ================================================================
125
+ * A. Pure math functions (no swed)
126
+ * ================================================================ */
127
+
128
+ function Sgn(x: number): number {
129
+ if (x < 0) return -1;
130
+ return 1;
131
+ }
132
+
133
+ function Kelvin(Temp: number): number {
134
+ return Temp + C2K;
135
+ }
136
+
137
+ function HourAngle(TopoAlt: number, TopoDecl: number, Lat: number): number {
138
+ const Alti = TopoAlt * DEGTORAD;
139
+ const decli = TopoDecl * DEGTORAD;
140
+ const Lati = Lat * DEGTORAD;
141
+ let ha = (Math.sin(Alti) - Math.sin(Lati) * Math.sin(decli)) / Math.cos(Lati) / Math.cos(decli);
142
+ if (ha < -1) ha = -1;
143
+ if (ha > 1) ha = 1;
144
+ return Math.acos(ha) / DEGTORAD / 15.0;
145
+ }
146
+
147
+ function DistanceAngle(LatA: number, LongA: number, LatB: number, LongB: number): number {
148
+ const dlon = LongB - LongA;
149
+ const dlat = LatB - LatA;
150
+ const sindlat2 = Math.sin(dlat / 2);
151
+ const sindlon2 = Math.sin(dlon / 2);
152
+ let corde = sindlat2 * sindlat2 + Math.cos(LatA) * Math.cos(LatB) * sindlon2 * sindlon2;
153
+ if (corde > 1) corde = 1;
154
+ return 2 * Math.asin(Math.sqrt(corde));
155
+ }
156
+
157
+ function TopoAltfromAppAlt(AppAlt: number, TempE: number, PresE: number): number {
158
+ let R = 0;
159
+ let retalt = 0;
160
+ if (AppAlt >= LowestAppAlt) {
161
+ if (AppAlt > 17.904104638432)
162
+ R = 0.97 / Math.tan(AppAlt * DEGTORAD);
163
+ else
164
+ R = (34.46 + 4.23 * AppAlt + 0.004 * AppAlt * AppAlt) / (1 + 0.505 * AppAlt + 0.0845 * AppAlt * AppAlt);
165
+ R = (PresE - 80) / 930 / (1 + 0.00008 * (R + 39) * (TempE - 10)) * R;
166
+ retalt = AppAlt - R * Min2Deg;
167
+ } else {
168
+ retalt = AppAlt;
169
+ }
170
+ return retalt;
171
+ }
172
+
173
+ function AppAltfromTopoAlt(TopoAlt: number, TempE: number, PresE: number, helflag: number): number {
174
+ let nloop = 2;
175
+ let newAppAlt = TopoAlt;
176
+ let newTopoAlt = 0.0;
177
+ let oudAppAlt = newAppAlt;
178
+ let oudTopoAlt = newTopoAlt;
179
+ let verschil: number;
180
+ if (helflag & SE_HELFLAG_HIGH_PRECISION)
181
+ nloop = 5;
182
+ for (let i = 0; i <= nloop; i++) {
183
+ newTopoAlt = newAppAlt - TopoAltfromAppAlt(newAppAlt, TempE, PresE);
184
+ verschil = newAppAlt - oudAppAlt;
185
+ oudAppAlt = newTopoAlt - oudTopoAlt - verschil;
186
+ if (verschil !== 0 && oudAppAlt !== 0)
187
+ verschil = newAppAlt - verschil * (TopoAlt + newTopoAlt - newAppAlt) / oudAppAlt;
188
+ else
189
+ verschil = TopoAlt + newTopoAlt;
190
+ oudAppAlt = newAppAlt;
191
+ oudTopoAlt = newTopoAlt;
192
+ newAppAlt = verschil;
193
+ }
194
+ const retalt = TopoAlt + newTopoAlt;
195
+ if (retalt < LowestAppAlt)
196
+ return TopoAlt;
197
+ return retalt;
198
+ }
199
+
200
+ function TempEfromTempS(TempS: number, HeightEye: number, Lapse: number): number {
201
+ return TempS - Lapse * HeightEye;
202
+ }
203
+
204
+ function PresEfromPresS(TempS: number, Press: number, HeightEye: number): number {
205
+ return Press * Math.exp(-9.80665 * 0.0289644 / (Kelvin(TempS) + 3.25 * HeightEye / 1000) / 8.31441 * HeightEye);
206
+ }
207
+
208
+ function Airmass(AppAltO: number, Press: number): number {
209
+ let zend = (90 - AppAltO) * DEGTORAD;
210
+ if (zend > PI / 2) zend = PI / 2;
211
+ const airm = 1 / (Math.cos(zend) + 0.025 * Math.exp(-11 * Math.cos(zend)));
212
+ return Press / 1013 * airm;
213
+ }
214
+
215
+ function Xext(scaleH: number, zend: number, Press: number): number {
216
+ return Press / 1013.0 / (Math.cos(zend) + 0.01 * Math.sqrt(scaleH / 1000.0) * Math.exp(-30.0 / Math.sqrt(scaleH / 1000.0) * Math.cos(zend)));
217
+ }
218
+
219
+ function Xlay(scaleH: number, zend: number, Press: number): number {
220
+ const a = Math.sin(zend) / (1.0 + scaleH / Ra);
221
+ return Press / 1013.0 / Math.sqrt(1.0 - a * a);
222
+ }
223
+
224
+ function MoonsBrightness(dist: number, phasemoon: number): number {
225
+ const log10 = 2.302585092994;
226
+ return -21.62 + 5 * Math.log(dist / (Ra / 1000)) / log10 + 0.026 * Math.abs(phasemoon) + 0.000000004 * Math.pow(phasemoon, 4);
227
+ }
228
+
229
+ function MoonPhase(AltM: number, AziM: number, AltS: number, AziS: number): number {
230
+ const AltMi = AltM * DEGTORAD;
231
+ const AltSi = AltS * DEGTORAD;
232
+ const AziMi = AziM * DEGTORAD;
233
+ const AziSi = AziS * DEGTORAD;
234
+ const MoonAvgPar = 0.95;
235
+ return 180 - Math.acos(Math.cos(AziSi - AziMi - MoonAvgPar * DEGTORAD) * Math.cos(AltMi + MoonAvgPar * DEGTORAD) * Math.cos(AltSi) + Math.sin(AltSi) * Math.sin(AltMi + MoonAvgPar * DEGTORAD)) / DEGTORAD;
236
+ }
237
+
238
+ function WidthMoon(AltO: number, AziO: number, AltS: number, AziS: number, parallax: number): number {
239
+ const GeoAltO = AltO + parallax;
240
+ return 0.27245 * parallax * (1 + Math.sin(GeoAltO * DEGTORAD) * Math.sin(parallax * DEGTORAD)) * (1 - Math.cos((AltS - GeoAltO) * DEGTORAD) * Math.cos((AziS - AziO) * DEGTORAD));
241
+ }
242
+
243
+ function LengthMoon(W: number, Diamoon: number): number {
244
+ let D = Diamoon;
245
+ if (D === 0) D = AvgRadiusMoon * 2;
246
+ const Wi = W * 60;
247
+ D = D * 60;
248
+ return (D - 0.3 * (D + Wi) / 2.0 / Wi) / 60.0;
249
+ }
250
+
251
+ function qYallop(W: number, GeoARCVact: number): number {
252
+ const Wi = W * 60;
253
+ return (GeoARCVact - (11.8371 - 6.3226 * Wi + 0.7319 * Wi * Wi - 0.1018 * Wi * Wi * Wi)) / 10;
254
+ }
255
+
256
+ function crossing(A: number, B: number, C: number, D: number): number {
257
+ return (C - A) / ((B - A) - (D - C));
258
+ }
259
+
260
+ function x2min(A: number, B: number, C: number): number {
261
+ const term = A + C - 2 * B;
262
+ if (term === 0) return 0;
263
+ return -(A - C) / 2.0 / term;
264
+ }
265
+
266
+ function funct2(A: number, B: number, C: number, x: number): number {
267
+ return (A + C - 2 * B) / 2.0 * x * x + (A - C) / 2.0 * x + B;
268
+ }
269
+
270
+ function CVA(B: number, SN: number, helflag: number): number {
271
+ let is_scotopic = false;
272
+ if (B < 1394) is_scotopic = true;
273
+ if (helflag & SE_HELFLAG_VISLIM_PHOTOPIC) is_scotopic = false;
274
+ if (helflag & SE_HELFLAG_VISLIM_SCOTOPIC) is_scotopic = true;
275
+ if (is_scotopic)
276
+ return Math.min(900, 380 / SN * Math.pow(10, 0.3 * Math.pow(B, -0.29))) / 60.0 / 60.0;
277
+ else
278
+ return (40.0 / SN) * Math.pow(10, 8.28 * Math.pow(B, -0.29)) / 60.0 / 60.0;
279
+ }
280
+
281
+ function PupilDia(Age: number, B: number): number {
282
+ return (0.534 - 0.00211 * Age - (0.236 - 0.00127 * Age) * Math.tanh(0.4 * Math.log(B) / Math.log(10) - 2.2)) * 10;
283
+ }
284
+
285
+ function getSynodicPeriod(Planet: number): number {
286
+ switch (Planet) {
287
+ case SE_MOON: return 29.530588853;
288
+ case SE_MERCURY: return 115.8775;
289
+ case SE_VENUS: return 583.9214;
290
+ case SE_MARS: return 779.9361;
291
+ case SE_JUPITER: return 398.8840;
292
+ case SE_SATURN: return 378.0919;
293
+ case SE_URANUS: return 369.6560;
294
+ case SE_NEPTUNE: return 367.4867;
295
+ case SE_PLUTO: return 366.7207;
296
+ }
297
+ return 366;
298
+ }
299
+
300
+ function DeterObject(ObjectName: string): number {
301
+ const s = ObjectName.toLowerCase();
302
+ if (s.startsWith('sun')) return SE_SUN;
303
+ if (s.startsWith('venus')) return SE_VENUS;
304
+ if (s.startsWith('mars')) return SE_MARS;
305
+ if (s.startsWith('mercur')) return SE_MERCURY;
306
+ if (s.startsWith('jupiter')) return SE_JUPITER;
307
+ if (s.startsWith('saturn')) return SE_SATURN;
308
+ if (s.startsWith('uranus')) return SE_URANUS;
309
+ if (s.startsWith('neptun')) return SE_NEPTUNE;
310
+ if (s.startsWith('moon')) return SE_MOON;
311
+ const ipl = parseInt(s, 10);
312
+ if (ipl > 0) return ipl + SE_AST_OFFSET;
313
+ return -1;
314
+ }
315
+
316
+ function strcpyVBsafe(sin: string): string {
317
+ let out = '';
318
+ for (let i = 0; i < sin.length && out.length < 30; i++) {
319
+ const c = sin[i];
320
+ if (/[a-zA-Z0-9 ,\-]/.test(c)) out += c;
321
+ else break;
322
+ }
323
+ return out;
324
+ }
325
+
326
+ function tolowerStringStar(str: string): string {
327
+ const commaIdx = str.indexOf(',');
328
+ if (commaIdx === -1) return str.toLowerCase();
329
+ return str.substring(0, commaIdx).toLowerCase() + str.substring(commaIdx);
330
+ }
331
+
332
+ function defaultHeliacalParameters(datm: number[], dgeo: number[], dobs: number[], helflag: number): void {
333
+ if (datm[0] <= 0) {
334
+ datm[0] = 1013.25 * Math.pow(1 - 0.0065 * dgeo[2] / 288, 5.255);
335
+ if (datm[1] === 0) datm[1] = 15 - 0.0065 * dgeo[2];
336
+ if (datm[2] === 0) datm[2] = 40;
337
+ } else {
338
+ if (datm[2] <= 0.00000001) datm[2] = 0.00000001;
339
+ if (datm[2] >= 99.99999999) datm[2] = 99.99999999;
340
+ }
341
+ if (dobs[0] === 0) dobs[0] = 36;
342
+ if (dobs[1] === 0) dobs[1] = 1;
343
+ if (!(helflag & SE_HELFLAG_OPTICAL_PARAMS)) {
344
+ for (let i = 2; i <= 5; i++) dobs[i] = 0;
345
+ }
346
+ if (dobs[3] === 0) {
347
+ dobs[2] = 1;
348
+ dobs[3] = 1;
349
+ }
350
+ }
351
+
352
+ /* ================================================================
353
+ * B. Atmospheric extinction (with caches)
354
+ * ================================================================ */
355
+
356
+ function kW(HeightEye: number, TempS: number, RH: number): number {
357
+ let WT = 0.031;
358
+ WT *= 0.94 * (RH / 100.0) * Math.exp(TempS / 15) * Math.exp(-1 * HeightEye / scaleHwater);
359
+ return WT;
360
+ }
361
+
362
+ function kR(AltS: number, HeightEye: number): number {
363
+ let val = -AltS - 12;
364
+ if (val < 0) val = 0;
365
+ if (val > 6) val = 6;
366
+ const CHANGEK = 1 - 0.166667 * val;
367
+ const LAMBDA = 0.55 + (CHANGEK - 1) * 0.04;
368
+ return 0.1066 * Math.exp(-1 * HeightEye / scaleHrayleigh) * Math.pow(LAMBDA / 0.55, -4);
369
+ }
370
+
371
+ function kOZ(AltS: number, sunra: number, Lat: number): number {
372
+ if (AltS === kOZ_alts_last && sunra === kOZ_sunra_last) return kOZ_last;
373
+ kOZ_alts_last = AltS;
374
+ kOZ_sunra_last = sunra;
375
+ const OZ = 0.031;
376
+ const LT = Lat * DEGTORAD;
377
+ let kOZret = OZ * (3.0 + 0.4 * (LT * Math.cos(sunra * DEGTORAD) - Math.cos(3 * LT))) / 3.0;
378
+ let altslim = -AltS - 12;
379
+ if (altslim < 0) altslim = 0;
380
+ const CHANGEKO = (100 - 11.6 * Math.min(6, altslim)) / 100;
381
+ kOZ_last = kOZret * CHANGEKO;
382
+ return kOZ_last;
383
+ }
384
+
385
+ function ka(AltS: number, sunra: number, Lat: number, HeightEye: number, TempS: number, RH: number, VR: number, serrRef: { value: string }): number {
386
+ const SL = Sgn(Lat);
387
+ if (AltS === ka_alts_last && sunra === ka_sunra_last) return ka_last;
388
+ ka_alts_last = AltS;
389
+ ka_sunra_last = sunra;
390
+ const CHANGEKA = 1 - 0.166667 * Math.min(6, Math.max(-AltS - 12, 0));
391
+ const LAMBDA = 0.55 + (CHANGEKA - 1) * 0.04;
392
+ let kaact: number;
393
+ if (VR !== 0) {
394
+ if (VR >= 1) {
395
+ const BetaVr = 3.912 / VR;
396
+ const Betaa = BetaVr - (kW(HeightEye, TempS, RH) / scaleHwater + kR(AltS, HeightEye) / scaleHrayleigh) * 1000 * astr2tau;
397
+ kaact = Betaa * scaleHaerosol / 1000 * tau2astr;
398
+ if (kaact < 0) {
399
+ serrRef.value = 'The provided Meteorological range is too long, when taking into acount other atmospheric parameters';
400
+ }
401
+ } else {
402
+ kaact = VR - kW(HeightEye, TempS, RH) - kR(AltS, HeightEye) - kOZ(AltS, sunra, Lat);
403
+ if (kaact < 0) {
404
+ serrRef.value = 'The provided atmosphic coeefficent (ktot) is too low, when taking into acount other atmospheric parameters';
405
+ }
406
+ }
407
+ } else {
408
+ kaact = 0.1 * Math.exp(-1 * HeightEye / scaleHaerosol) * Math.pow(1 - 0.32 / Math.log(RH / 100.0), 1.33) * (1 + 0.33 * SL * Math.sin(sunra * DEGTORAD));
409
+ kaact = kaact * Math.pow(LAMBDA / 0.55, -1.3);
410
+ }
411
+ ka_last = kaact;
412
+ return kaact;
413
+ }
414
+
415
+ function kt(AltS: number, sunra: number, Lat: number, HeightEye: number, TempS: number, RH: number, VR: number, ExtType: number, serrRef: { value: string }): number {
416
+ let kRact = 0, kWact = 0, kOZact = 0, kaact = 0;
417
+ if (ExtType === 2 || ExtType === 4) kRact = kR(AltS, HeightEye);
418
+ if (ExtType === 1 || ExtType === 4) kWact = kW(HeightEye, TempS, RH);
419
+ if (ExtType === 3 || ExtType === 4) kOZact = kOZ(AltS, sunra, Lat);
420
+ if (ExtType === 0 || ExtType === 4) kaact = ka(AltS, sunra, Lat, HeightEye, TempS, RH, VR, serrRef);
421
+ if (kaact < 0) kaact = 0;
422
+ return kWact + kRact + kOZact + kaact;
423
+ }
424
+
425
+ function Deltam(AltO: number, AltS: number, sunra: number, Lat: number, HeightEye: number, datm: number[], helflag: number, serrRef: { value: string }): number {
426
+ if (AltS === deltam_alts_last && AltO === deltam_alto_last && sunra === deltam_sunra_last) return deltam_last;
427
+ deltam_alts_last = AltS;
428
+ deltam_alto_last = AltO;
429
+ deltam_sunra_last = sunra;
430
+ const PresE = PresEfromPresS(datm[1], datm[0], HeightEye);
431
+ const TempE = TempEfromTempS(datm[1], HeightEye, LapseSA);
432
+ const AppAltO = AppAltfromTopoAlt(AltO, TempE, PresE, helflag);
433
+ let deltam: number;
434
+ if (staticAirmass === 0) {
435
+ let zend = (90 - AppAltO) * DEGTORAD;
436
+ if (zend > PI / 2) zend = PI / 2;
437
+ const xR = Xext(scaleHrayleigh, zend, datm[0]);
438
+ const XW = Xext(scaleHwater, zend, datm[0]);
439
+ const Xa = Xext(scaleHaerosol, zend, datm[0]);
440
+ const XOZ = Xlay(scaleHozone, zend, datm[0]);
441
+ deltam = kR(AltS, HeightEye) * xR + kt(AltS, sunra, Lat, HeightEye, datm[1], datm[2], datm[3], 0, serrRef) * Xa + kOZ(AltS, sunra, Lat) * XOZ + kW(HeightEye, datm[1], datm[2]) * XW;
442
+ } else {
443
+ deltam = kt(AltS, sunra, Lat, HeightEye, datm[1], datm[2], datm[3], 4, serrRef) * Airmass(AppAltO, datm[0]);
444
+ }
445
+ deltam_last = deltam;
446
+ return deltam;
447
+ }
448
+
449
+ /* ================================================================
450
+ * C. Sky brightness
451
+ * ================================================================ */
452
+
453
+ function Bn(AltO: number, JDNDayUT: number, AltS: number, sunra: number, Lat: number, HeightEye: number, datm: number[], helflag: number, serrRef: { value: string }): number {
454
+ const PresE = PresEfromPresS(datm[1], datm[0], HeightEye);
455
+ const TempE = TempEfromTempS(datm[1], HeightEye, LapseSA);
456
+ let AppAltO = AppAltfromTopoAlt(AltO, TempE, PresE, helflag);
457
+ const B0 = 0.0000000000001;
458
+ if (AppAltO < 10) AppAltO = 10;
459
+ const zend = (90 - AppAltO) * DEGTORAD;
460
+ const r = revJul(JDNDayUT, SE_GREG_CAL);
461
+ const YearB = r.year;
462
+ const MonthB = r.month;
463
+ const DayB = r.day;
464
+ const Bna = B0 * (1 + 0.3 * Math.cos(6.283 * (YearB + ((DayB - 1) / 30.4 + MonthB - 1) / 12 - 1990.33) / 11.1));
465
+ const kX = Deltam(AltO, AltS, sunra, Lat, HeightEye, datm, helflag, serrRef);
466
+ const Bnb = Bna * (0.4 + 0.6 / Math.sqrt(1 - 0.96 * Math.pow(Math.sin(zend), 2))) * Math.pow(10, -0.4 * kX);
467
+ return Math.max(Bnb, 0) * erg2nL;
468
+ }
469
+
470
+ function Bm(AltO: number, AziO: number, AltM: number, AziM: number, AltS: number, AziS: number, sunra: number, Lat: number, HeightEye: number, datm: number[], helflag: number, serrRef: { value: string }): number {
471
+ const M0 = -11.05;
472
+ let BmVal = 0;
473
+ const lunar_radius = 0.25 * DEGTORAD;
474
+ const object_is_moon = (AltO === AltM && AziO === AziM);
475
+ if (AltM > -0.26 && !object_is_moon) {
476
+ let RM = DistanceAngle(AltO * DEGTORAD, AziO * DEGTORAD, AltM * DEGTORAD, AziM * DEGTORAD) / DEGTORAD;
477
+ if (RM <= lunar_radius / DEGTORAD) RM = lunar_radius / DEGTORAD;
478
+ const kXM = Deltam(AltM, AltS, sunra, Lat, HeightEye, datm, helflag, serrRef);
479
+ const kX = Deltam(AltO, AltS, sunra, Lat, HeightEye, datm, helflag, serrRef);
480
+ const C3 = Math.pow(10, -0.4 * kXM);
481
+ const FM = 62000000.0 / RM / RM + Math.pow(10, 6.15 - RM / 40) + Math.pow(10, 5.36) * (1.06 + Math.pow(Math.cos(RM * DEGTORAD), 2));
482
+ BmVal = FM * C3 + 440000 * (1 - C3);
483
+ const phasemoon = MoonPhase(AltM, AziM, AltS, AziS);
484
+ const MM = MoonsBrightness(384410.4978, phasemoon);
485
+ BmVal = BmVal * Math.pow(10, -0.4 * (MM - M0 + 43.27));
486
+ BmVal = BmVal * (1 - Math.pow(10, -0.4 * kX));
487
+ }
488
+ BmVal = Math.max(BmVal, 0) * erg2nL;
489
+ return BmVal;
490
+ }
491
+
492
+ function Btwi(AltO: number, AziO: number, AltS: number, AziS: number, sunra: number, Lat: number, HeightEye: number, datm: number[], helflag: number, serrRef: { value: string }): number {
493
+ const M0 = -11.05;
494
+ const MS = -26.74;
495
+ const PresE = PresEfromPresS(datm[1], datm[0], HeightEye);
496
+ const TempE = TempEfromTempS(datm[1], HeightEye, LapseSA);
497
+ const AppAltO = AppAltfromTopoAlt(AltO, TempE, PresE, helflag);
498
+ const ZendO = 90 - AppAltO;
499
+ const RS = DistanceAngle(AltO * DEGTORAD, AziO * DEGTORAD, AltS * DEGTORAD, AziS * DEGTORAD) / DEGTORAD;
500
+ const kX = Deltam(AltO, AltS, sunra, Lat, HeightEye, datm, helflag, serrRef);
501
+ const k = kt(AltS, sunra, Lat, HeightEye, datm[1], datm[2], datm[3], 4, serrRef);
502
+ let BtwiVal = Math.pow(10, -0.4 * (MS - M0 + 32.5 - AltS - (ZendO / (360 * k))));
503
+ BtwiVal = BtwiVal * (100 / RS) * (1 - Math.pow(10, -0.4 * kX));
504
+ BtwiVal = Math.max(BtwiVal, 0) * erg2nL;
505
+ return BtwiVal;
506
+ }
507
+
508
+ function Bday(AltO: number, AziO: number, AltS: number, AziS: number, sunra: number, Lat: number, HeightEye: number, datm: number[], helflag: number, serrRef: { value: string }): number {
509
+ const M0 = -11.05;
510
+ const MS = -26.74;
511
+ const RS = DistanceAngle(AltO * DEGTORAD, AziO * DEGTORAD, AltS * DEGTORAD, AziS * DEGTORAD) / DEGTORAD;
512
+ const kXS = Deltam(AltS, AltS, sunra, Lat, HeightEye, datm, helflag, serrRef);
513
+ const kX = Deltam(AltO, AltS, sunra, Lat, HeightEye, datm, helflag, serrRef);
514
+ const C4 = Math.pow(10, -0.4 * kXS);
515
+ const FS = 62000000.0 / RS / RS + Math.pow(10, 6.15 - RS / 40) + Math.pow(10, 5.36) * (1.06 + Math.pow(Math.cos(RS * DEGTORAD), 2));
516
+ let BdayVal = FS * C4 + 440000.0 * (1 - C4);
517
+ BdayVal = BdayVal * Math.pow(10, -0.4 * (MS - M0 + 43.27));
518
+ BdayVal = BdayVal * (1 - Math.pow(10, -0.4 * kX));
519
+ BdayVal = Math.max(BdayVal, 0) * erg2nL;
520
+ return BdayVal;
521
+ }
522
+
523
+ function Bcity(Value: number, _Press: number): number {
524
+ return Math.max(Value, 0);
525
+ }
526
+
527
+ function Bsky(AltO: number, AziO: number, AltM: number, AziM: number, JDNDaysUT: number, AltS: number, AziS: number, sunra: number, Lat: number, HeightEye: number, datm: number[], helflag: number, serrRef: { value: string }): number {
528
+ let BskyVal = 0;
529
+ if (AltS < -3) {
530
+ BskyVal += Btwi(AltO, AziO, AltS, AziS, sunra, Lat, HeightEye, datm, helflag, serrRef);
531
+ } else {
532
+ if (AltS > 4) {
533
+ BskyVal += Bday(AltO, AziO, AltS, AziS, sunra, Lat, HeightEye, datm, helflag, serrRef);
534
+ } else {
535
+ BskyVal += Math.min(Bday(AltO, AziO, AltS, AziS, sunra, Lat, HeightEye, datm, helflag, serrRef), Btwi(AltO, AziO, AltS, AziS, sunra, Lat, HeightEye, datm, helflag, serrRef));
536
+ }
537
+ }
538
+ if (BskyVal < 200000000.0)
539
+ BskyVal += Bm(AltO, AziO, AltM, AziM, AltS, AziS, sunra, Lat, HeightEye, datm, helflag, serrRef);
540
+ if (AltS <= 0)
541
+ BskyVal += Bcity(0, datm[0]);
542
+ if (BskyVal < 5000)
543
+ BskyVal += Bn(AltO, JDNDaysUT, AltS, sunra, Lat, HeightEye, datm, helflag, serrRef);
544
+ return BskyVal;
545
+ }
546
+
547
+ /* ================================================================
548
+ * D. Optic factor and visual limit magnitude
549
+ * ================================================================ */
550
+
551
+ function OpticFactor(Bback: number, kX: number, dobs: number[], JDNDaysUT: number, ObjectName: string, TypeFactor: number, helflag: number): number {
552
+ const Age = dobs[0];
553
+ const SN = dobs[1];
554
+ let SNi = SN;
555
+ const Binocular = dobs[2];
556
+ let OpticMag = dobs[3];
557
+ let OpticDia = dobs[4];
558
+ let OpticTrans = dobs[5];
559
+ let is_scotopic = false;
560
+ if (SNi <= 0.00000001) SNi = 0.00000001;
561
+ const Pst = PupilDia(23, Bback);
562
+ if (OpticMag === 1) {
563
+ OpticTrans = 1;
564
+ OpticDia = Pst;
565
+ }
566
+ const CIb = 0.7;
567
+ const CIi = 0.5;
568
+ const ObjectSize = 0;
569
+ let Fb = 1;
570
+ if (Binocular === 0) Fb = 1.41;
571
+ if (Bback < 1645) is_scotopic = true;
572
+ if (helflag & SE_HELFLAG_VISLIM_PHOTOPIC) is_scotopic = false;
573
+ if (helflag & SE_HELFLAG_VISLIM_SCOTOPIC) is_scotopic = true;
574
+ let Fe: number, Fsc: number, Fci: number, Fcb: number;
575
+ if (is_scotopic) {
576
+ Fe = Math.pow(10, 0.48 * kX);
577
+ Fsc = Math.min(1, (1 - Math.pow(Pst / 124.4, 4)) / (1 - Math.pow(OpticDia / OpticMag / 124.4, 4)));
578
+ Fci = Math.pow(10, -0.4 * (1 - CIi / 2.0));
579
+ Fcb = Math.pow(10, -0.4 * (1 - CIb / 2.0));
580
+ } else {
581
+ Fe = Math.pow(10, 0.4 * kX);
582
+ Fsc = Math.min(1, Math.pow(OpticDia / OpticMag / Pst, 2) * (1 - Math.exp(-Math.pow(Pst / 6.2, 2))) / (1 - Math.exp(-Math.pow(OpticDia / OpticMag / 6.2, 2))));
583
+ Fci = 1;
584
+ Fcb = 1;
585
+ }
586
+ const Ft = 1 / OpticTrans;
587
+ const Fp = Math.max(1, Math.pow(Pst / (OpticMag * PupilDia(Age, Bback)), 2));
588
+ const Fa = Math.pow(Pst / OpticDia, 2);
589
+ const Fr = (1 + 0.03 * Math.pow(OpticMag * ObjectSize / CVA(Bback, SNi, helflag), 2)) / Math.pow(SNi, 2);
590
+ const Fm = Math.pow(OpticMag, 2);
591
+ if (TypeFactor === 0)
592
+ return Fb * Fe * Ft * Fp * Fa * Fr * Fsc * Fci;
593
+ else
594
+ return Fb * Ft * Fp * Fa * Fm * Fsc * Fcb;
595
+ }
596
+
597
+ function VisLimMagn(dobs: number[], AltO: number, AziO: number, AltM: number, AziM: number, JDNDaysUT: number, AltS: number, AziS: number, sunra: number, Lat: number, HeightEye: number, datm: number[], helflag: number, scotopic_flag: { value: number } | null, serrRef: { value: string }): number {
598
+ const log10 = 2.302585092994;
599
+ let is_scotopic = false;
600
+ let Bsk = Bsky(AltO, AziO, AltM, AziM, JDNDaysUT, AltS, AziS, sunra, Lat, HeightEye, datm, helflag, serrRef);
601
+ const kX = Deltam(AltO, AltS, sunra, Lat, HeightEye, datm, helflag, serrRef);
602
+ const CorrFactor1 = OpticFactor(Bsk, kX, dobs, JDNDaysUT, '', 1, helflag);
603
+ const CorrFactor2 = OpticFactor(Bsk, kX, dobs, JDNDaysUT, '', 0, helflag);
604
+ if (Bsk < 1645) is_scotopic = true;
605
+ if (helflag & SE_HELFLAG_VISLIM_PHOTOPIC) is_scotopic = false;
606
+ if (helflag & SE_HELFLAG_VISLIM_SCOTOPIC) is_scotopic = true;
607
+ let C1: number, C2: number;
608
+ if (is_scotopic) {
609
+ C1 = 1.5848931924611e-10;
610
+ C2 = 0.012589254117942;
611
+ if (scotopic_flag !== null) scotopic_flag.value = 1;
612
+ } else {
613
+ C1 = 4.4668359215096e-9;
614
+ C2 = 1.2589254117942e-6;
615
+ if (scotopic_flag !== null) scotopic_flag.value = 0;
616
+ }
617
+ if (scotopic_flag !== null) {
618
+ if (BNIGHT * BNIGHT_FACTOR > Bsk && BNIGHT / BNIGHT_FACTOR < Bsk)
619
+ scotopic_flag.value |= 2;
620
+ }
621
+ Bsk = Bsk * CorrFactor1;
622
+ const Th = C1 * Math.pow(1 + Math.sqrt(C2 * Bsk), 2) * CorrFactor2;
623
+ return -16.57 - 2.5 * (Math.log(Th) / log10);
624
+ }
625
+
626
+ /* ================================================================
627
+ * E. Swiss Ephemeris wrappers (need swed)
628
+ * ================================================================ */
629
+
630
+ function callSweFixstar(swed: SweData, star: string, tjd: number, iflag: number): { retval: number; xx: Float64Array; serr: string } {
631
+ const r = sweFixstar(swed, star, tjd, iflag);
632
+ return { retval: r.flags === ERR ? ERR : OK, xx: r.xx, serr: r.serr };
633
+ }
634
+
635
+ function callSweFixstarMag(swed: SweData, star: string): { retval: number; mag: number; serr: string } {
636
+ if (star === fixstarMag_star_save) {
637
+ return { retval: OK, mag: fixstarMag_dmag, serr: '' };
638
+ }
639
+ fixstarMag_star_save = star;
640
+ const r = sweFixstarMag(swed, star);
641
+ fixstarMag_dmag = r.mag;
642
+ return { retval: r.serr ? ERR : OK, mag: r.mag, serr: r.serr };
643
+ }
644
+
645
+ function callSweRiseTrans(swed: SweData, tjd: number, ipl: number, star: string, helflag: number, eventtype: number, dgeo: number[], atpress: number, attemp: number): { retval: number; tret: number; serr: string } {
646
+ const iflag = helflag & (SEFLG_JPLEPH | SEFLG_SWIEPH | SEFLG_MOSEPH);
647
+ const serrRef = { value: '' };
648
+ const r = sweRiseTrans(swed, tjd, ipl, star || null, iflag, eventtype, dgeo, atpress, attemp, serrRef);
649
+ return { retval: r.retval, tret: r.tret, serr: serrRef.value };
650
+ }
651
+
652
+ function SunRA(swed: SweData, JDNDaysUT: number, helflag: number): { ra: number; serr: string } {
653
+ let serr = '';
654
+ if (JDNDaysUT === sunRA_tjdlast) return { ra: sunRA_ralast, serr: '' };
655
+ const epheflag = helflag & (SEFLG_JPLEPH | SEFLG_SWIEPH | SEFLG_MOSEPH);
656
+ const iflag = epheflag | SEFLG_EQUATORIAL | SEFLG_NONUT | SEFLG_TRUEPOS;
657
+ const tjd_tt = JDNDaysUT + sweDeltatEx(JDNDaysUT, epheflag, swed);
658
+ const r = sweCalc(swed, tjd_tt, SE_SUN, iflag);
659
+ if (r.flags !== ERR) {
660
+ sunRA_ralast = r.xx[0];
661
+ sunRA_tjdlast = JDNDaysUT;
662
+ return { ra: sunRA_ralast, serr: r.serr };
663
+ }
664
+ /* fallback approximation */
665
+ const rv = revJul(JDNDaysUT, SE_GREG_CAL);
666
+ sunRA_tjdlast = JDNDaysUT;
667
+ sunRA_ralast = sweDegnorm((rv.month + (rv.day - 1) / 30.4 - 3.69) * 30);
668
+ return { ra: sunRA_ralast, serr };
669
+ }
670
+
671
+ function Magnitude(swed: SweData, JDNDaysUT: number, dgeo: number[], ObjectName: string, helflag: number): { retval: number; dmag: number; serr: string } {
672
+ const epheflag = helflag & (SEFLG_JPLEPH | SEFLG_SWIEPH | SEFLG_MOSEPH);
673
+ let dmag = -99.0;
674
+ const Planet = DeterObject(ObjectName);
675
+ let iflag = SEFLG_TOPOCTR | SEFLG_EQUATORIAL | epheflag;
676
+ if (!(helflag & SE_HELFLAG_HIGH_PRECISION))
677
+ iflag |= SEFLG_NONUT | SEFLG_TRUEPOS;
678
+ if (Planet !== -1) {
679
+ sweSetTopo(swed, dgeo[0], dgeo[1], dgeo[2]);
680
+ const serrRef = { value: '' };
681
+ const r = swePhenoUt(swed, JDNDaysUT, Planet, iflag, serrRef);
682
+ if (r.retval === ERR) return { retval: ERR, dmag, serr: serrRef.value };
683
+ dmag = r.attr[4];
684
+ return { retval: OK, dmag, serr: serrRef.value };
685
+ } else {
686
+ const r = callSweFixstarMag(swed, ObjectName);
687
+ if (r.retval === ERR) return { retval: ERR, dmag, serr: r.serr };
688
+ dmag = r.mag;
689
+ return { retval: OK, dmag, serr: r.serr };
690
+ }
691
+ }
692
+
693
+ function ObjectLoc(swed: SweData, JDNDaysUT: number, dgeo: number[], datm: number[], ObjectName: string, Angle: number, helflag: number): { retval: number; dret: number; serr: string } {
694
+ const epheflag = helflag & (SEFLG_JPLEPH | SEFLG_SWIEPH | SEFLG_MOSEPH);
695
+ let iflag = SEFLG_EQUATORIAL | epheflag;
696
+ if (!(helflag & SE_HELFLAG_HIGH_PRECISION))
697
+ iflag |= SEFLG_NONUT | SEFLG_TRUEPOS;
698
+ let AngleAdj = Angle;
699
+ if (AngleAdj < 5) iflag |= SEFLG_TOPOCTR;
700
+ if (AngleAdj === 7) AngleAdj = 0;
701
+ const tjd_tt = JDNDaysUT + sweDeltatEx(JDNDaysUT, epheflag, swed);
702
+ const Planet = DeterObject(ObjectName);
703
+ let x: Float64Array;
704
+ let serr = '';
705
+ if (Planet !== -1) {
706
+ const r = sweCalc(swed, tjd_tt, Planet, iflag);
707
+ if (r.flags === ERR) return { retval: ERR, dret: 0, serr: r.serr };
708
+ x = r.xx;
709
+ serr = r.serr;
710
+ } else {
711
+ const r = callSweFixstar(swed, ObjectName, tjd_tt, iflag);
712
+ if (r.retval === ERR) return { retval: ERR, dret: 0, serr: r.serr };
713
+ x = r.xx;
714
+ serr = r.serr;
715
+ }
716
+ if (AngleAdj === 2 || AngleAdj === 5) {
717
+ return { retval: OK, dret: x[1], serr };
718
+ } else if (AngleAdj === 3 || AngleAdj === 6) {
719
+ return { retval: OK, dret: x[0], serr };
720
+ } else {
721
+ const xin = [x[0], x[1]];
722
+ const xaz = [0, 0, 0];
723
+ sweAzalt(swed, JDNDaysUT, SE_EQU2HOR, dgeo, datm[0], datm[1], xin, xaz);
724
+ if (AngleAdj === 0) return { retval: OK, dret: xaz[1], serr };
725
+ if (AngleAdj === 4) return { retval: OK, dret: AppAltfromTopoAlt(xaz[1], datm[0], datm[1], helflag), serr };
726
+ if (AngleAdj === 1) {
727
+ let azi = xaz[0] + 180;
728
+ if (azi >= 360) azi -= 360;
729
+ return { retval: OK, dret: azi, serr };
730
+ }
731
+ return { retval: OK, dret: xaz[1], serr };
732
+ }
733
+ }
734
+
735
+ function azaltCart(swed: SweData, JDNDaysUT: number, dgeo: number[], datm: number[], ObjectName: string, helflag: number): { retval: number; dret: number[]; serr: string } {
736
+ const epheflag = helflag & (SEFLG_JPLEPH | SEFLG_SWIEPH | SEFLG_MOSEPH);
737
+ let iflag = SEFLG_EQUATORIAL | epheflag;
738
+ if (!(helflag & SE_HELFLAG_HIGH_PRECISION))
739
+ iflag |= SEFLG_NONUT | SEFLG_TRUEPOS;
740
+ iflag |= SEFLG_TOPOCTR;
741
+ const tjd_tt = JDNDaysUT + sweDeltatEx(JDNDaysUT, epheflag, swed);
742
+ const Planet = DeterObject(ObjectName);
743
+ let x: Float64Array;
744
+ let serr = '';
745
+ if (Planet !== -1) {
746
+ const r = sweCalc(swed, tjd_tt, Planet, iflag);
747
+ if (r.flags === ERR) return { retval: ERR, dret: [0, 0, 0, 0, 0, 0], serr: r.serr };
748
+ x = r.xx; serr = r.serr;
749
+ } else {
750
+ const r = callSweFixstar(swed, ObjectName, tjd_tt, iflag);
751
+ if (r.retval === ERR) return { retval: ERR, dret: [0, 0, 0, 0, 0, 0], serr: r.serr };
752
+ x = r.xx; serr = r.serr;
753
+ }
754
+ const xin = [x[0], x[1]];
755
+ const xaz = [0, 0, 0];
756
+ sweAzalt(swed, JDNDaysUT, SE_EQU2HOR, dgeo, datm[0], datm[1], xin, xaz);
757
+ const dret = [xaz[0], xaz[1], xaz[2], 0, 0, 0];
758
+ const xazCart = [xaz[0], xaz[2], 1];
759
+ const cart = [0, 0, 0];
760
+ swiPolcart(xazCart, cart);
761
+ dret[3] = cart[0]; dret[4] = cart[1]; dret[5] = cart[2];
762
+ return { retval: OK, dret, serr };
763
+ }
764
+
765
+ function calcRiseAndSet(swed: SweData, tjd_start: number, ipl: number, dgeo: number[], datm: number[], eventflag: number, helflag: number): { retval: number; tret: number; serr: string } {
766
+ const dfac = 1 / 365.25;
767
+ const epheflag = helflag & (SEFLG_JPLEPH | SEFLG_SWIEPH | SEFLG_MOSEPH);
768
+ let iflag = epheflag | SEFLG_EQUATORIAL;
769
+ if (!(helflag & SE_HELFLAG_HIGH_PRECISION))
770
+ iflag |= SEFLG_NONUT | SEFLG_TRUEPOS;
771
+ const rs = sweCalcUt(swed, tjd_start, SE_SUN, iflag);
772
+ if (rs.flags === ERR) return { retval: ERR, tret: 0, serr: 'error in calc_rise_and_set(): calc(sun) failed' };
773
+ const xs = rs.xx;
774
+ const rx = sweCalcUt(swed, tjd_start, ipl, iflag);
775
+ if (rx.flags === ERR) return { retval: ERR, tret: 0, serr: 'error in calc_rise_and_set(): calc failed' };
776
+ const xx = rx.xx;
777
+ let tjdnoon = Math.trunc(tjd_start) - dgeo[0] / 15.0 / 24.0;
778
+ tjdnoon -= sweDegnorm(xs[0] - xx[0]) / 360.0;
779
+ const xaz = [0, 0, 0];
780
+ sweAzalt(swed, tjd_start, SE_EQU2HOR, dgeo, datm[0], datm[1], [xx[0], xx[1]], xaz);
781
+ if (eventflag & SE_CALC_RISE) {
782
+ if (xaz[2] > 0) {
783
+ while (tjdnoon - tjd_start < 0.5) tjdnoon += 1;
784
+ while (tjdnoon - tjd_start > 1.5) tjdnoon -= 1;
785
+ } else {
786
+ while (tjdnoon - tjd_start < 0.0) tjdnoon += 1;
787
+ while (tjdnoon - tjd_start > 1.0) tjdnoon -= 1;
788
+ }
789
+ } else {
790
+ if (xaz[2] > 0) {
791
+ while (tjd_start - tjdnoon > 0.5) tjdnoon += 1;
792
+ while (tjd_start - tjdnoon < -0.5) tjdnoon -= 1;
793
+ } else {
794
+ while (tjd_start - tjdnoon > 0.0) tjdnoon += 1;
795
+ while (tjd_start - tjdnoon < -1.0) tjdnoon -= 1;
796
+ }
797
+ }
798
+ let iflag2 = epheflag | SEFLG_EQUATORIAL;
799
+ const rn = sweCalcUt(swed, tjdnoon, ipl, iflag2);
800
+ if (rn.flags === ERR) return { retval: ERR, tret: 0, serr: 'error in calc_rise_and_set(): calc failed' };
801
+ const xxn = rn.xx;
802
+ let rdi = 0;
803
+ if (ipl === SE_SUN)
804
+ rdi = Math.asin(696000000.0 / 1.49597870691e+11 / xxn[2]) / DEGTORAD;
805
+ else if (ipl === SE_MOON)
806
+ rdi = Math.asin(1737000.0 / 1.49597870691e+11 / xxn[2]) / DEGTORAD;
807
+ if (eventflag & SE_BIT_DISC_CENTER) rdi = 0;
808
+ const rh = -(34.5 / 60.0 + rdi);
809
+ const sda = Math.acos(-Math.tan(dgeo[1] * DEGTORAD) * Math.tan(xxn[1] * DEGTORAD)) * RADTODEG;
810
+ let tjdrise: number;
811
+ if (eventflag & SE_CALC_RISE)
812
+ tjdrise = tjdnoon - sda / 360.0;
813
+ else
814
+ tjdrise = tjdnoon + sda / 360.0;
815
+ iflag2 = epheflag | SEFLG_SPEED | SEFLG_EQUATORIAL;
816
+ if (ipl === SE_MOON) iflag2 |= SEFLG_TOPOCTR;
817
+ if (!(helflag & SE_HELFLAG_HIGH_PRECISION))
818
+ iflag2 |= SEFLG_NONUT | SEFLG_TRUEPOS;
819
+ for (let i = 0; i < 2; i++) {
820
+ const rc = sweCalcUt(swed, tjdrise, ipl, iflag2);
821
+ if (rc.flags === ERR) return { retval: ERR, tret: 0, serr: rc.serr };
822
+ const xxi = rc.xx;
823
+ const xazi = [0, 0, 0];
824
+ sweAzalt(swed, tjdrise, SE_EQU2HOR, dgeo, datm[0], datm[1], [xxi[0], xxi[1]], xazi);
825
+ const xxPrev = [xxi[0] - xxi[3] * dfac, xxi[1] - xxi[4] * dfac];
826
+ const xaz2 = [0, 0, 0];
827
+ sweAzalt(swed, tjdrise - dfac, SE_EQU2HOR, dgeo, datm[0], datm[1], xxPrev, xaz2);
828
+ tjdrise -= (xazi[1] - rh) / (xazi[1] - xaz2[1]) * dfac;
829
+ }
830
+ return { retval: OK, tret: tjdrise, serr: '' };
831
+ }
832
+
833
+ function myRiseTrans(swed: SweData, tjd: number, ipl: number, starname: string, eventtype: number, helflag: number, dgeo: number[], datm: number[]): { retval: number; tret: number; serr: string } {
834
+ let iplAdj = ipl;
835
+ if (starname !== '' && starname !== null) iplAdj = DeterObject(starname);
836
+ if (iplAdj !== -1 && Math.abs(dgeo[1]) < 63) {
837
+ return calcRiseAndSet(swed, tjd, iplAdj, dgeo, datm, eventtype, helflag);
838
+ } else {
839
+ return callSweRiseTrans(swed, tjd, ipl, starname, helflag, eventtype, dgeo, datm[0], datm[1]);
840
+ }
841
+ }
842
+
843
+ function RiseSet(swed: SweData, JDNDaysUT: number, dgeo: number[], datm: number[], ObjectName: string, RSEvent: number, helflag: number, Rim: number): { retval: number; tret: number; serr: string } {
844
+ let eventtype = RSEvent;
845
+ if (Rim === 0) eventtype |= SE_BIT_DISC_CENTER;
846
+ const Planet = DeterObject(ObjectName);
847
+ if (Planet !== -1)
848
+ return myRiseTrans(swed, JDNDaysUT, Planet, '', eventtype, helflag, dgeo, datm);
849
+ else
850
+ return myRiseTrans(swed, JDNDaysUT, -1, ObjectName, eventtype, helflag, dgeo, datm);
851
+ }
852
+
853
+ function TopoArcVisionis(swed: SweData, Magn: number, dobs: number[], AltO: number, AziO: number, AltM: number, AziM: number, JDNDaysUT: number, AziS: number, sunra: number, Lat: number, HeightEye: number, datm: number[], helflag: number): { retval: number; dret: number; serr: string } {
854
+ const serrRef = { value: '' };
855
+ let xR = 0;
856
+ let Xl = 45;
857
+ const Yl = Magn - VisLimMagn(dobs, AltO, AziO, AltM, AziM, JDNDaysUT, AltO - Xl, AziS, sunra, Lat, HeightEye, datm, helflag, null, serrRef);
858
+ let Yr = Magn - VisLimMagn(dobs, AltO, AziO, AltM, AziM, JDNDaysUT, AltO - xR, AziS, sunra, Lat, HeightEye, datm, helflag, null, serrRef);
859
+ let Xm: number;
860
+ if (Yl * Yr <= 0) {
861
+ let YlMut = Yl;
862
+ while (Math.abs(xR - Xl) > epsilon) {
863
+ Xm = (xR + Xl) / 2.0;
864
+ const AltSi = AltO - Xm;
865
+ const Ym = Magn - VisLimMagn(dobs, AltO, AziO, AltM, AziM, JDNDaysUT, AltSi, AziS, sunra, Lat, HeightEye, datm, helflag, null, serrRef);
866
+ if (YlMut * Ym > 0) { Xl = Xm; YlMut = Ym; }
867
+ else { xR = Xm; Yr = Ym; }
868
+ }
869
+ Xm = (xR + Xl) / 2.0;
870
+ } else {
871
+ Xm = 99;
872
+ }
873
+ if (Xm < AltO) Xm = AltO;
874
+ return { retval: OK, dret: Xm, serr: serrRef.value };
875
+ }
876
+
877
+ function HeliacalAngle(swed: SweData, Magn: number, dobs: number[], AziO: number, AltM: number, AziM: number, JDNDaysUT: number, AziS: number, dgeo: number[], datm: number[], helflag: number): { retval: number; dangret: number[]; serr: string } {
878
+ const serrRef = { value: '' };
879
+ const sunra = SunRA(swed, JDNDaysUT, helflag).ra;
880
+ const Lat = dgeo[1];
881
+ const HeightEye = dgeo[2];
882
+ const dangret = [0, 0, 0];
883
+ if (PLSV as number === 1) {
884
+ dangret[0] = criticalangle;
885
+ dangret[1] = criticalangle + Magn * 2.492 + 13.447;
886
+ dangret[2] = -(Magn * 2.492 + 13.447);
887
+ return { retval: OK, dangret, serr: '' };
888
+ }
889
+ const minx = 2, maxx = 20;
890
+ let xmin = 0, ymin = 10000;
891
+ for (let x = minx; x <= maxx; x++) {
892
+ const r = TopoArcVisionis(swed, Magn, dobs, x, AziO, AltM, AziM, JDNDaysUT, AziS, sunra, Lat, HeightEye, datm, helflag);
893
+ if (r.retval === ERR) return { retval: ERR, dangret, serr: r.serr };
894
+ if (r.dret < ymin) { ymin = r.dret; xmin = x; }
895
+ }
896
+ let XlH = xmin - 1;
897
+ let xRH = xmin + 1;
898
+ let rr = TopoArcVisionis(swed, Magn, dobs, xRH, AziO, AltM, AziM, JDNDaysUT, AziS, sunra, Lat, HeightEye, datm, helflag);
899
+ if (rr.retval === ERR) return { retval: ERR, dangret, serr: rr.serr };
900
+ let Yr = rr.dret;
901
+ let rl = TopoArcVisionis(swed, Magn, dobs, XlH, AziO, AltM, AziM, JDNDaysUT, AziS, sunra, Lat, HeightEye, datm, helflag);
902
+ if (rl.retval === ERR) return { retval: ERR, dangret, serr: rl.serr };
903
+ let Yl = rl.dret;
904
+ while (Math.abs(xRH - XlH) > 0.1) {
905
+ const Xm = (xRH + XlH) / 2.0;
906
+ const DELTAx = 0.025;
907
+ const rm = TopoArcVisionis(swed, Magn, dobs, Xm, AziO, AltM, AziM, JDNDaysUT, AziS, sunra, Lat, HeightEye, datm, helflag);
908
+ if (rm.retval === ERR) return { retval: ERR, dangret, serr: rm.serr };
909
+ const Ym = rm.dret;
910
+ const rmd = TopoArcVisionis(swed, Magn, dobs, Xm + DELTAx, AziO, AltM, AziM, JDNDaysUT, AziS, sunra, Lat, HeightEye, datm, helflag);
911
+ if (rmd.retval === ERR) return { retval: ERR, dangret, serr: rmd.serr };
912
+ if (Ym >= rmd.dret) { XlH = Xm; Yl = Ym; }
913
+ else { xRH = Xm; Yr = Ym; }
914
+ }
915
+ const XmF = (xRH + XlH) / 2.0;
916
+ const YmF = (Yr + Yl) / 2.0;
917
+ dangret[1] = YmF;
918
+ dangret[2] = XmF - YmF;
919
+ dangret[0] = XmF;
920
+ return { retval: OK, dangret, serr: serrRef.value };
921
+ }
922
+
923
+ function DeterTAV(swed: SweData, dobs: number[], JDNDaysUT: number, dgeo: number[], datm: number[], ObjectName: string, helflag: number): { retval: number; dret: number; serr: string } {
924
+ const sunra = SunRA(swed, JDNDaysUT, helflag).ra;
925
+ const mr = Magnitude(swed, JDNDaysUT, dgeo, ObjectName, helflag);
926
+ if (mr.retval === ERR) return { retval: ERR, dret: 0, serr: mr.serr };
927
+ const altO = ObjectLoc(swed, JDNDaysUT, dgeo, datm, ObjectName, 0, helflag);
928
+ if (altO.retval === ERR) return { retval: ERR, dret: 0, serr: altO.serr };
929
+ const aziO = ObjectLoc(swed, JDNDaysUT, dgeo, datm, ObjectName, 1, helflag);
930
+ if (aziO.retval === ERR) return { retval: ERR, dret: 0, serr: aziO.serr };
931
+ let AltM: number, AziM: number;
932
+ if (ObjectName.startsWith('moon')) {
933
+ AltM = -90; AziM = 0;
934
+ } else {
935
+ const rm = ObjectLoc(swed, JDNDaysUT, dgeo, datm, 'moon', 0, helflag);
936
+ if (rm.retval === ERR) return { retval: ERR, dret: 0, serr: rm.serr };
937
+ AltM = rm.dret;
938
+ const rma = ObjectLoc(swed, JDNDaysUT, dgeo, datm, 'moon', 1, helflag);
939
+ if (rma.retval === ERR) return { retval: ERR, dret: 0, serr: rma.serr };
940
+ AziM = rma.dret;
941
+ }
942
+ const aziS = ObjectLoc(swed, JDNDaysUT, dgeo, datm, 'sun', 1, helflag);
943
+ if (aziS.retval === ERR) return { retval: ERR, dret: 0, serr: aziS.serr };
944
+ return TopoArcVisionis(swed, mr.dmag, dobs, altO.dret, aziO.dret, AltM, AziM, JDNDaysUT, aziS.dret, sunra, dgeo[1], dgeo[2], datm, helflag);
945
+ }
946
+
947
+ /* ================================================================
948
+ * F. Event search functions
949
+ * ================================================================ */
950
+
951
+ function getAscObl(swed: SweData, tjd: number, ipl: number, star: string, iflag: number, dgeo: number[], desc_obl: boolean): { retval: number; daop: number; serr: string } {
952
+ const epheflag = iflag & (SEFLG_JPLEPH | SEFLG_SWIEPH | SEFLG_MOSEPH);
953
+ let x: Float64Array;
954
+ let serr = '';
955
+ if (ipl === -1) {
956
+ const star2 = star;
957
+ const r = sweFixstar(swed, star2, tjd, epheflag | SEFLG_EQUATORIAL);
958
+ if (r.flags === ERR) return { retval: ERR, daop: 0, serr: r.serr };
959
+ x = r.xx; serr = r.serr;
960
+ } else {
961
+ const r = sweCalc(swed, tjd, ipl, epheflag | SEFLG_EQUATORIAL);
962
+ if (r.flags === ERR) return { retval: ERR, daop: 0, serr: r.serr };
963
+ x = r.xx; serr = r.serr;
964
+ }
965
+ const adpRaw = Math.tan(dgeo[1] * DEGTORAD) * Math.tan(x[1] * DEGTORAD);
966
+ if (Math.abs(adpRaw) > 1) {
967
+ let s: string;
968
+ if (star !== '') s = star;
969
+ else s = sweGetPlanetName(ipl, swed);
970
+ return { retval: -2, daop: 0, serr: `${s} is circumpolar, cannot calculate heliacal event` };
971
+ }
972
+ const adp = Math.asin(adpRaw) / DEGTORAD;
973
+ let daop: number;
974
+ if (desc_obl) daop = x[0] + adp;
975
+ else daop = x[0] - adp;
976
+ daop = sweDegnorm(daop);
977
+ return { retval: OK, daop, serr };
978
+ }
979
+
980
+ function getAscOblDiff(swed: SweData, tjd: number, ipl: number, star: string, iflag: number, dgeo: number[], desc_obl: boolean, is_acronychal: boolean): { retval: number; dsunpl: number; serr: string } {
981
+ const r1 = getAscObl(swed, tjd, SE_SUN, '', iflag, dgeo, desc_obl);
982
+ if (r1.retval !== OK) return { retval: r1.retval, dsunpl: 0, serr: r1.serr };
983
+ let desc_obl2 = desc_obl;
984
+ if (is_acronychal) desc_obl2 = !desc_obl2;
985
+ const r2 = getAscObl(swed, tjd, ipl, star, iflag, dgeo, desc_obl2);
986
+ if (r2.retval !== OK) return { retval: r2.retval, dsunpl: 0, serr: r2.serr };
987
+ let dsunpl = sweDegnorm(r1.daop - r2.daop);
988
+ if (is_acronychal) dsunpl = sweDegnorm(dsunpl - 180);
989
+ if (dsunpl > 180) dsunpl -= 360;
990
+ return { retval: OK, dsunpl, serr: '' };
991
+ }
992
+
993
+ function getAscOblWithSun(swed: SweData, tjd_start: number, ipl: number, star: string, helflag: number, evtyp: number, dperiod: number, dgeo: number[]): { retval: number; tjdret: number; serr: string } {
994
+ const epheflag = helflag & (SEFLG_JPLEPH | SEFLG_SWIEPH | SEFLG_MOSEPH);
995
+ let is_acronychal = false;
996
+ let desc_obl = false;
997
+ let retro = false;
998
+ if (evtyp === SE_EVENING_LAST || evtyp === SE_EVENING_FIRST) desc_obl = true;
999
+ if (evtyp === SE_MORNING_FIRST || evtyp === SE_EVENING_LAST) retro = true;
1000
+ if (evtyp === SE_ACRONYCHAL_RISING) desc_obl = true;
1001
+ if (evtyp === SE_ACRONYCHAL_RISING || evtyp === SE_ACRONYCHAL_SETTING) {
1002
+ is_acronychal = true;
1003
+ if (ipl !== SE_MOON) retro = true;
1004
+ }
1005
+ let tjd = tjd_start;
1006
+ let dsunpl_save = -999999999;
1007
+ let r = getAscOblDiff(swed, tjd, ipl, star, epheflag, dgeo, desc_obl, is_acronychal);
1008
+ if (r.retval !== OK) return { retval: r.retval, tjdret: 0, serr: r.serr };
1009
+ let dsunpl = r.dsunpl;
1010
+ let daystep = 20;
1011
+ let i = 0;
1012
+ while (dsunpl_save === -999999999 ||
1013
+ Math.abs(dsunpl) + Math.abs(dsunpl_save) > 180 ||
1014
+ (retro && !(dsunpl_save < 0 && dsunpl >= 0)) ||
1015
+ (!retro && !(dsunpl_save >= 0 && dsunpl < 0))) {
1016
+ i++;
1017
+ if (i > 5000) return { retval: ERR, tjdret: 0, serr: 'loop in get_asc_obl_with_sun() (1)' };
1018
+ dsunpl_save = dsunpl;
1019
+ tjd += 10.0;
1020
+ if (dperiod > 0 && tjd - tjd_start > dperiod) return { retval: -2, tjdret: 0, serr: '' };
1021
+ r = getAscOblDiff(swed, tjd, ipl, star, epheflag, dgeo, desc_obl, is_acronychal);
1022
+ if (r.retval !== OK) return { retval: r.retval, tjdret: 0, serr: r.serr };
1023
+ dsunpl = r.dsunpl;
1024
+ }
1025
+ let tjd_s = tjd - daystep;
1026
+ daystep /= 2.0;
1027
+ tjd = tjd_s + daystep;
1028
+ let rt = getAscOblDiff(swed, tjd, ipl, star, epheflag, dgeo, desc_obl, is_acronychal);
1029
+ if (rt.retval !== OK) return { retval: rt.retval, tjdret: 0, serr: rt.serr };
1030
+ let dsunpl_test = rt.dsunpl;
1031
+ i = 0;
1032
+ while (Math.abs(dsunpl) > 0.00001) {
1033
+ i++;
1034
+ if (i > 5000) return { retval: ERR, tjdret: 0, serr: 'loop in get_asc_obl_with_sun() (2)' };
1035
+ if (dsunpl_save * dsunpl_test >= 0) {
1036
+ dsunpl_save = dsunpl_test;
1037
+ tjd_s = tjd;
1038
+ } else {
1039
+ dsunpl = dsunpl_test;
1040
+ }
1041
+ daystep /= 2.0;
1042
+ tjd = tjd_s + daystep;
1043
+ rt = getAscOblDiff(swed, tjd, ipl, star, epheflag, dgeo, desc_obl, is_acronychal);
1044
+ if (rt.retval !== OK) return { retval: rt.retval, tjdret: 0, serr: rt.serr };
1045
+ dsunpl_test = rt.dsunpl;
1046
+ }
1047
+ return { retval: OK, tjdret: tjd, serr: '' };
1048
+ }
1049
+
1050
+ function findConjunctSun(swed: SweData, tjd_start: number, ipl: number, helflag: number, TypeEvent: number): { retval: number; tjd: number; serr: string } {
1051
+ const epheflag = helflag & (SEFLG_JPLEPH | SEFLG_SWIEPH | SEFLG_MOSEPH);
1052
+ let daspect = 0;
1053
+ if (ipl >= SE_MARS && TypeEvent >= 3) daspect = 180;
1054
+ const i = Math.trunc((TypeEvent - 1) / 2) + ipl * 2;
1055
+ const tjd0 = tcon[i];
1056
+ const dsynperiod = getSynodicPeriod(ipl);
1057
+ let tjdcon = tjd0 + (Math.floor((tjd_start - tjd0) / dsynperiod) + 1) * dsynperiod;
1058
+ let ds = 100;
1059
+ while (ds > 0.5) {
1060
+ const rx = sweCalc(swed, tjdcon, ipl, epheflag | SEFLG_SPEED);
1061
+ if (rx.flags === ERR) return { retval: ERR, tjd: 0, serr: rx.serr };
1062
+ const rs = sweCalc(swed, tjdcon, SE_SUN, epheflag | SEFLG_SPEED);
1063
+ if (rs.flags === ERR) return { retval: ERR, tjd: 0, serr: rs.serr };
1064
+ ds = sweDegnorm(rx.xx[0] - rs.xx[0] - daspect);
1065
+ if (ds > 180) ds -= 360;
1066
+ tjdcon -= ds / (rx.xx[3] - rs.xx[3]);
1067
+ }
1068
+ return { retval: OK, tjd: tjdcon, serr: '' };
1069
+ }
1070
+
1071
+ function moonEventArcVis(swed: SweData, JDNDaysUTStart: number, dgeo: number[], datm: number[], dobs: number[], TypeEventIn: number, helflag: number): { retval: number; dret: number; serr: string } {
1072
+ const epheflag = helflag & (SEFLG_JPLEPH | SEFLG_SWIEPH | SEFLG_MOSEPH);
1073
+ const avkind = helflag & SE_HELFLAG_AVKIND;
1074
+ if (avkind === 0 || avkind !== SE_HELFLAG_AVKIND_VR)
1075
+ return { retval: ERR, dret: JDNDaysUTStart, serr: 'error: in valid AV kind for the moon' };
1076
+ if (TypeEventIn === 1 || TypeEventIn === 2)
1077
+ return { retval: ERR, dret: JDNDaysUTStart, serr: 'error: the moon has no morning first or evening last' };
1078
+ const ObjectName = 'moon';
1079
+ const Planet = SE_MOON;
1080
+ let iflag = SEFLG_TOPOCTR | SEFLG_EQUATORIAL | epheflag;
1081
+ if (!(helflag & SE_HELFLAG_HIGH_PRECISION))
1082
+ iflag |= SEFLG_NONUT | SEFLG_TRUEPOS;
1083
+ let Daystep = 1;
1084
+ let TypeEvent: number;
1085
+ if (TypeEventIn === 3) { TypeEvent = 2; }
1086
+ else { TypeEvent = 1; Daystep = -Daystep; }
1087
+ let JDNDaysUT = JDNDaysUTStart;
1088
+ if (TypeEvent === 1) JDNDaysUT += 30;
1089
+ const serrObj = { value: '' };
1090
+ let pr = swePhenoUt(swed, JDNDaysUT, Planet, iflag, serrObj);
1091
+ let phase2 = pr.attr[0];
1092
+ let goingup = 0;
1093
+ let phase1: number;
1094
+ do {
1095
+ JDNDaysUT += Daystep;
1096
+ phase1 = phase2;
1097
+ pr = swePhenoUt(swed, JDNDaysUT, Planet, iflag, serrObj);
1098
+ phase2 = pr.attr[0];
1099
+ if (phase2 > phase1) goingup = 1;
1100
+ } while (goingup === 0 || (goingup === 1 && phase2 > phase1));
1101
+ JDNDaysUT -= Daystep;
1102
+ const JDNDaysUTi = JDNDaysUT;
1103
+ JDNDaysUT -= Daystep;
1104
+ let MinTAVoud = 199;
1105
+ let MinTAV: number, OldestMinTAV: number;
1106
+ let DeltaAlt = 90;
1107
+ let DeltaAltoud = 0;
1108
+ let tjd_moonevent = 0;
1109
+ do {
1110
+ JDNDaysUT += Daystep;
1111
+ const rrs = RiseSet(swed, JDNDaysUT, dgeo, datm, ObjectName, TypeEvent, helflag, 0);
1112
+ if (rrs.retval !== OK) return { retval: rrs.retval, dret: JDNDaysUTStart, serr: rrs.serr };
1113
+ tjd_moonevent = rrs.tret;
1114
+ const tjd_moonevent_start = tjd_moonevent;
1115
+ MinTAV = 199;
1116
+ OldestMinTAV = MinTAV;
1117
+ let LocalminCheck = 0;
1118
+ do {
1119
+ OldestMinTAV = MinTAVoud;
1120
+ MinTAVoud = MinTAV;
1121
+ DeltaAltoud = DeltaAlt;
1122
+ tjd_moonevent -= 1.0 / 60.0 / 24.0 * Sgn(Daystep);
1123
+ const rAltS = ObjectLoc(swed, tjd_moonevent, dgeo, datm, 'sun', 0, helflag);
1124
+ if (rAltS.retval === ERR) return { retval: ERR, dret: JDNDaysUTStart, serr: rAltS.serr };
1125
+ const rAltO = ObjectLoc(swed, tjd_moonevent, dgeo, datm, ObjectName, 0, helflag);
1126
+ if (rAltO.retval === ERR) return { retval: ERR, dret: JDNDaysUTStart, serr: rAltO.serr };
1127
+ DeltaAlt = rAltO.dret - rAltS.dret;
1128
+ const rTAV = DeterTAV(swed, dobs, tjd_moonevent, dgeo, datm, ObjectName, helflag);
1129
+ if (rTAV.retval === ERR) return { retval: ERR, dret: JDNDaysUTStart, serr: rTAV.serr };
1130
+ MinTAV = rTAV.dret;
1131
+ const TimeCheck = tjd_moonevent - LocalMinStep / 60.0 / 24.0 * Sgn(Daystep);
1132
+ const rLC = DeterTAV(swed, dobs, TimeCheck, dgeo, datm, ObjectName, helflag);
1133
+ if (rLC.retval === ERR) return { retval: ERR, dret: JDNDaysUTStart, serr: rLC.serr };
1134
+ LocalminCheck = rLC.dret;
1135
+ } while ((MinTAV <= MinTAVoud || LocalminCheck < MinTAV) && Math.abs(tjd_moonevent - tjd_moonevent_start) < 120.0 / 60.0 / 24.0);
1136
+ } while (DeltaAltoud < MinTAVoud && Math.abs(JDNDaysUT - JDNDaysUTi) < 15);
1137
+ if (Math.abs(JDNDaysUT - JDNDaysUTi) < 15) {
1138
+ tjd_moonevent += (1 - x2min(MinTAV, MinTAVoud, OldestMinTAV)) * Sgn(Daystep) / 60.0 / 24.0;
1139
+ } else {
1140
+ return { retval: ERR, dret: JDNDaysUTStart, serr: 'no date found for lunar event' };
1141
+ }
1142
+ return { retval: OK, dret: tjd_moonevent, serr: '' };
1143
+ }
1144
+
1145
+ function heliacalUtArcVis(swed: SweData, JDNDaysUTStart: number, dgeo: number[], datm: number[], dobs: number[], ObjectName: string, TypeEventIn: number, helflag: number): { retval: number; dret: number; serr: string } {
1146
+ let serr = '';
1147
+ let retval: number = OK;
1148
+ const Planet = DeterObject(ObjectName);
1149
+ const Pressure = datm[0];
1150
+ const Temperature = datm[1];
1151
+ let objectmagn = 0;
1152
+ const mr = Magnitude(swed, JDNDaysUTStart, dgeo, ObjectName, helflag);
1153
+ if (mr.retval === ERR) return { retval: ERR, dret: JDNDaysUTStart, serr: mr.serr };
1154
+ objectmagn = mr.dmag;
1155
+ const epheflag = helflag & (SEFLG_JPLEPH | SEFLG_SWIEPH | SEFLG_MOSEPH);
1156
+ let iflag = SEFLG_TOPOCTR | SEFLG_EQUATORIAL | epheflag;
1157
+ if (!(helflag & SE_HELFLAG_HIGH_PRECISION))
1158
+ iflag |= SEFLG_NONUT | SEFLG_TRUEPOS;
1159
+ let DayStep: number, maxlength: number;
1160
+ switch (Planet) {
1161
+ case SE_MERCURY: DayStep = 1; maxlength = 100; break;
1162
+ case SE_VENUS: DayStep = 64; maxlength = 384; break;
1163
+ case SE_MARS: DayStep = 128; maxlength = 640; break;
1164
+ case SE_JUPITER: DayStep = 64; maxlength = 384; break;
1165
+ case SE_SATURN: DayStep = 64; maxlength = 256; break;
1166
+ default: DayStep = 64; maxlength = 256; break;
1167
+ }
1168
+ let TypeEvent = TypeEventIn;
1169
+ let eventtype = TypeEvent;
1170
+ if (eventtype === 2) DayStep = -DayStep;
1171
+ if (eventtype === 4) { eventtype = 1; DayStep = -DayStep; }
1172
+ if (eventtype === 3) eventtype = 2;
1173
+ eventtype |= SE_BIT_DISC_CENTER;
1174
+ let JDNDaysUT = JDNDaysUTStart;
1175
+ let JDNDaysUTfinal = JDNDaysUT + maxlength;
1176
+ JDNDaysUT -= 1;
1177
+ if (DayStep < 0) {
1178
+ const tmp = JDNDaysUT; JDNDaysUT = JDNDaysUTfinal; JDNDaysUTfinal = tmp;
1179
+ }
1180
+ let JDNDaysUTstep = JDNDaysUT - DayStep;
1181
+ let doneoneday = 0;
1182
+ let ArcusVisDelta = 199;
1183
+ let ArcusVisPto = -5.55;
1184
+ let JDNarcvisUT = 0;
1185
+ let JDNDaysUTstepoud: number, ArcusVisDeltaoud: number;
1186
+ do {
1187
+ if (Math.abs(DayStep) === 1) doneoneday = 1;
1188
+ do {
1189
+ JDNDaysUTstepoud = JDNDaysUTstep;
1190
+ ArcusVisDeltaoud = ArcusVisDelta;
1191
+ JDNDaysUTstep += DayStep;
1192
+ const rrt = myRiseTrans(swed, JDNDaysUTstep, SE_SUN, '', eventtype, helflag, dgeo, datm);
1193
+ if (rrt.retval === ERR) return { retval: ERR, dret: JDNDaysUTStart, serr: rrt.serr };
1194
+ const tret = rrt.tret;
1195
+ const tjd_tt = tret + sweDeltatEx(tret, epheflag, swed);
1196
+ let rc = sweCalc(swed, tjd_tt, SE_SUN, iflag);
1197
+ if (rc.flags === ERR) return { retval: ERR, dret: JDNDaysUTStart, serr: rc.serr };
1198
+ const xin = [rc.xx[0], rc.xx[1]];
1199
+ const xaz = [0, 0, 0];
1200
+ sweAzalt(swed, tret, SE_EQU2HOR, dgeo, Pressure, Temperature, xin, xaz);
1201
+ const Trise = HourAngle(xaz[1], rc.xx[1], dgeo[1]);
1202
+ let sunsangle = ArcusVisPto;
1203
+ if (helflag & SE_HELFLAG_AVKIND_MIN7) sunsangle = -7;
1204
+ if (helflag & SE_HELFLAG_AVKIND_MIN9) sunsangle = -9;
1205
+ const Theliacal = HourAngle(sunsangle, rc.xx[1], dgeo[1]);
1206
+ let Tdelta = Theliacal - Trise;
1207
+ if (TypeEvent === 2 || TypeEvent === 3) Tdelta = -Tdelta;
1208
+ JDNarcvisUT = tret - Tdelta / 24;
1209
+ const tjd_tt2 = JDNarcvisUT + sweDeltatEx(JDNarcvisUT, epheflag, swed);
1210
+ rc = sweCalc(swed, tjd_tt2, SE_SUN, iflag);
1211
+ if (rc.flags === ERR) return { retval: ERR, dret: JDNDaysUTStart, serr: rc.serr };
1212
+ const xin2 = [rc.xx[0], rc.xx[1]];
1213
+ const xaz2 = [0, 0, 0];
1214
+ sweAzalt(swed, JDNarcvisUT, SE_EQU2HOR, dgeo, Pressure, Temperature, xin2, xaz2);
1215
+ let AziS = xaz2[0] + 180; if (AziS >= 360) AziS -= 360;
1216
+ const AltS = xaz2[1];
1217
+ let x: Float64Array;
1218
+ if (Planet !== -1) {
1219
+ const rp = sweCalc(swed, tjd_tt2, Planet, iflag);
1220
+ if (rp.flags === ERR) return { retval: ERR, dret: JDNDaysUTStart, serr: rp.serr };
1221
+ x = rp.xx;
1222
+ const mm = Magnitude(swed, JDNarcvisUT, dgeo, ObjectName, helflag);
1223
+ if (mm.retval === ERR) return { retval: ERR, dret: JDNDaysUTStart, serr: mm.serr };
1224
+ objectmagn = mm.dmag;
1225
+ } else {
1226
+ const rf = callSweFixstar(swed, ObjectName, tjd_tt2, iflag);
1227
+ if (rf.retval === ERR) return { retval: ERR, dret: JDNDaysUTStart, serr: rf.serr };
1228
+ x = rf.xx;
1229
+ }
1230
+ const xin3 = [x[0], x[1]];
1231
+ const xaz3 = [0, 0, 0];
1232
+ sweAzalt(swed, JDNarcvisUT, SE_EQU2HOR, dgeo, Pressure, Temperature, xin3, xaz3);
1233
+ let AziO = xaz3[0] + 180; if (AziO >= 360) AziO -= 360;
1234
+ const AltO = xaz3[1];
1235
+ const DeltaAlt = AltO - AltS;
1236
+ const rha = HeliacalAngle(swed, objectmagn, dobs, AziO, -1, 0, JDNarcvisUT, AziS, dgeo, datm, helflag);
1237
+ if (rha.retval === ERR) return { retval: ERR, dret: JDNDaysUTStart, serr: rha.serr };
1238
+ ArcusVisPto = rha.dangret[2];
1239
+ ArcusVisDelta = DeltaAlt - rha.dangret[1];
1240
+ } while ((ArcusVisDeltaoud > 0 || ArcusVisDelta < 0) && (JDNDaysUTfinal - JDNDaysUTstep) * Sgn(DayStep) > 0);
1241
+ if (doneoneday === 0 && (JDNDaysUTfinal - JDNDaysUTstep) * Sgn(DayStep) > 0) {
1242
+ ArcusVisDelta = ArcusVisDeltaoud;
1243
+ DayStep = Math.trunc(Math.abs(DayStep) / 2.0) * Sgn(DayStep);
1244
+ JDNDaysUTstep = JDNDaysUTstepoud;
1245
+ }
1246
+ } while (doneoneday === 0 && (JDNDaysUTfinal - JDNDaysUTstep) * Sgn(DayStep) > 0);
1247
+ const d = (JDNDaysUTfinal - JDNDaysUTstep) * Sgn(DayStep);
1248
+ if (d <= 0 || d >= maxlength) {
1249
+ return { retval: -2, dret: JDNDaysUTStart, serr: `heliacal event not found within maxlength ${maxlength}` };
1250
+ }
1251
+ const direct = DayStep < 0 ? -TimeStepDefault / 24.0 / 60.0 : TimeStepDefault / 24.0 / 60.0;
1252
+ if (helflag & SE_HELFLAG_AVKIND_VR) {
1253
+ let TimeStep = direct;
1254
+ let TbVR = 0;
1255
+ let TimePointer = JDNarcvisUT;
1256
+ let rOld = DeterTAV(swed, dobs, TimePointer, dgeo, datm, ObjectName, helflag);
1257
+ if (rOld.retval === ERR) return { retval: ERR, dret: JDNDaysUTStart, serr: rOld.serr };
1258
+ let OldestMinTAV = rOld.dret;
1259
+ TimePointer += TimeStep;
1260
+ let rNew = DeterTAV(swed, dobs, TimePointer, dgeo, datm, ObjectName, helflag);
1261
+ if (rNew.retval === ERR) return { retval: ERR, dret: JDNDaysUTStart, serr: rNew.serr };
1262
+ let MinTAVoud: number, MinTAVact: number;
1263
+ if (rNew.dret > OldestMinTAV) {
1264
+ TimePointer = JDNarcvisUT; TimeStep = -TimeStep;
1265
+ MinTAVact = OldestMinTAV;
1266
+ } else {
1267
+ MinTAVact = rNew.dret; MinTAVoud = OldestMinTAV;
1268
+ }
1269
+ MinTAVoud = OldestMinTAV;
1270
+ do {
1271
+ TimePointer += TimeStep;
1272
+ OldestMinTAV = MinTAVoud;
1273
+ MinTAVoud = MinTAVact;
1274
+ const rr = DeterTAV(swed, dobs, TimePointer, dgeo, datm, ObjectName, helflag);
1275
+ if (rr.retval === ERR) return { retval: ERR, dret: JDNDaysUTStart, serr: rr.serr };
1276
+ MinTAVact = rr.dret;
1277
+ if (MinTAVoud < MinTAVact) {
1278
+ const extrax = x2min(MinTAVact, MinTAVoud, OldestMinTAV);
1279
+ TbVR = TimePointer - (1 - extrax) * TimeStep;
1280
+ }
1281
+ } while (TbVR === 0);
1282
+ JDNarcvisUT = TbVR;
1283
+ }
1284
+ if (helflag & SE_HELFLAG_AVKIND_PTO) {
1285
+ let OudeDatum: number;
1286
+ do {
1287
+ OudeDatum = JDNarcvisUT;
1288
+ JDNarcvisUT -= direct;
1289
+ const tjd_tt = JDNarcvisUT + sweDeltatEx(JDNarcvisUT, epheflag, swed);
1290
+ let x: Float64Array;
1291
+ if (Planet !== -1) {
1292
+ const rp = sweCalc(swed, tjd_tt, Planet, iflag);
1293
+ if (rp.flags === ERR) return { retval: ERR, dret: JDNDaysUTStart, serr: rp.serr };
1294
+ x = rp.xx;
1295
+ } else {
1296
+ const rf = callSweFixstar(swed, ObjectName, tjd_tt, iflag);
1297
+ if (rf.retval === ERR) return { retval: ERR, dret: JDNDaysUTStart, serr: rf.serr };
1298
+ x = rf.xx;
1299
+ }
1300
+ const xin = [x[0], x[1]];
1301
+ const xaz = [0, 0, 0];
1302
+ sweAzalt(swed, JDNarcvisUT, SE_EQU2HOR, dgeo, Pressure, Temperature, xin, xaz);
1303
+ if (xaz[1] <= 0) break;
1304
+ } while (true);
1305
+ JDNarcvisUT = (JDNarcvisUT + OudeDatum!) / 2.0;
1306
+ }
1307
+ if (JDNarcvisUT < -9999999 || JDNarcvisUT > 9999999) {
1308
+ return { retval: ERR, dret: JDNDaysUT, serr: 'no heliacal date found' };
1309
+ }
1310
+ return { retval: OK, dret: JDNarcvisUT, serr };
1311
+ }
1312
+
1313
+ function getHeliacalDay(swed: SweData, tjd: number, dgeo: number[], datm: number[], dobs: number[], ObjectName: string, helflag: number, TypeEvent: number): { retval: number; thel: number; serr: string } {
1314
+ let is_rise_or_set = 0, direct_day = 0, direct_time = 0;
1315
+ const ipl = DeterObject(ObjectName);
1316
+ switch (TypeEvent) {
1317
+ case 1: is_rise_or_set = SE_CALC_RISE; direct_day = 1; direct_time = -1; break;
1318
+ case 2: is_rise_or_set = SE_CALC_SET; direct_day = -1; direct_time = 1; break;
1319
+ case 3: is_rise_or_set = SE_CALC_SET; direct_day = 1; direct_time = 1; break;
1320
+ case 4: is_rise_or_set = SE_CALC_RISE; direct_day = -1; direct_time = -1; break;
1321
+ }
1322
+ let tfac = 1;
1323
+ let ndays: number, daystep: number;
1324
+ let dmag: number;
1325
+ switch (ipl) {
1326
+ case SE_MOON: ndays = 16; daystep = 1; break;
1327
+ case SE_MERCURY: ndays = 60; daystep = 5; tfac = 5; break;
1328
+ case SE_VENUS: ndays = 300; tjd -= 30 * direct_day; daystep = 5;
1329
+ if (TypeEvent >= 3) { daystep = 15; tfac = 3; } break;
1330
+ case SE_MARS: ndays = 400; daystep = 15; tfac = 5; break;
1331
+ case SE_SATURN: ndays = 300; daystep = 20; tfac = 5; break;
1332
+ case -1:
1333
+ ndays = 300; daystep = 15; tfac = 10;
1334
+ const rmag = callSweFixstarMag(swed, ObjectName);
1335
+ if (rmag.retval === ERR) return { retval: ERR, thel: 0, serr: rmag.serr };
1336
+ dmag = rmag.mag;
1337
+ if (dmag > 2) daystep = 15;
1338
+ if (dmag < 0) tfac = 3;
1339
+ break;
1340
+ default: ndays = 300; daystep = 15; tfac = 3; break;
1341
+ }
1342
+ const tend = tjd + ndays * direct_day;
1343
+ let retval_old = -2;
1344
+ for (let tday = tjd, i = 0;
1345
+ (direct_day > 0 && tday < tend) || (direct_day < 0 && tday > tend);
1346
+ tday += daystep * direct_day, i++) {
1347
+ if (i > 0) tday -= 0.3 * direct_day;
1348
+ const rrt = myRiseTrans(swed, tday, SE_SUN, '', is_rise_or_set, helflag, dgeo, datm);
1349
+ if (rrt.retval === ERR) return { retval: ERR, thel: 0, serr: rrt.serr };
1350
+ if (rrt.retval === -2) { retval_old = -2; continue; }
1351
+ let tret = rrt.tret;
1352
+ let rv = sweVisLimitMag(swed, tret, dgeo, datm, dobs, ObjectName, helflag);
1353
+ if (rv.retval === ERR) return { retval: ERR, thel: 0, serr: rv.serr };
1354
+ if (retval_old === -2 && rv.retval >= 0 && daystep > 1) {
1355
+ retval_old = rv.retval;
1356
+ tday -= daystep * direct_day;
1357
+ daystep = 1;
1358
+ if (ipl >= SE_MARS || ipl === -1) daystep = 5;
1359
+ continue;
1360
+ }
1361
+ retval_old = rv.retval;
1362
+ if (rv.retval === -2) continue;
1363
+ const div = 1440.0;
1364
+ let vd = -1;
1365
+ let visible_at_sunsetrise = 1;
1366
+ while (rv.retval !== -2 && (vd = rv.dret[0] - rv.dret[7]) < 0) {
1367
+ visible_at_sunsetrise = 0;
1368
+ if (vd < -1.0) tret += 5.0 / div * direct_time * tfac;
1369
+ else if (vd < -0.5) tret += 2.0 / div * direct_time * tfac;
1370
+ else if (vd < -0.1) tret += 1.0 / div * direct_time * tfac;
1371
+ else tret += 1.0 / div * direct_time;
1372
+ rv = sweVisLimitMag(swed, tret, dgeo, datm, dobs, ObjectName, helflag);
1373
+ if (rv.retval === ERR) return { retval: ERR, thel: 0, serr: rv.serr };
1374
+ }
1375
+ if (visible_at_sunsetrise) {
1376
+ for (let j = 0; j < 10; j++) {
1377
+ const rvn = sweVisLimitMag(swed, tret + 1.0 / div * direct_time, dgeo, datm, dobs, ObjectName, helflag);
1378
+ if (rvn.retval >= 0 && rvn.dret[0] - rvn.dret[7] > vd) {
1379
+ vd = rvn.dret[0] - rvn.dret[7];
1380
+ tret += 1.0 / div * direct_time;
1381
+ }
1382
+ }
1383
+ }
1384
+ const vdelta = rv.dret[0] - rv.dret[7];
1385
+ if (vdelta > 0) {
1386
+ if ((ipl >= SE_MARS || ipl === -1) && daystep > 1) {
1387
+ tday -= daystep * direct_day;
1388
+ daystep = 1;
1389
+ } else {
1390
+ return { retval: OK, thel: tret, serr: '' };
1391
+ }
1392
+ }
1393
+ }
1394
+ return { retval: -2, thel: 0, serr: 'heliacal event does not happen' };
1395
+ }
1396
+
1397
+ function timeOptimumVisibility(swed: SweData, tjd: number, dgeo: number[], datm: number[], dobs: number[], ObjectName: string, helflag: number): { retval: number; tret: number; serr: string } {
1398
+ let rv = sweVisLimitMag(swed, tjd, dgeo, datm, dobs, ObjectName, helflag);
1399
+ if (rv.retval === ERR) return { retval: ERR, tret: tjd, serr: rv.serr };
1400
+ let retval_sv = rv.retval;
1401
+ let t1 = tjd, t2 = tjd, vl1 = -1, vl2 = -1;
1402
+ let phot_scot_opic_sv = retval_sv & SE_SCOTOPIC_FLAG;
1403
+ for (let i = 0, d = 100.0 / 86400.0; i < 3; i++, d /= 10.0) {
1404
+ t1 += d;
1405
+ let t_has_changed = 0;
1406
+ while (true) {
1407
+ rv = sweVisLimitMag(swed, t1 - d, dgeo, datm, dobs, ObjectName, helflag);
1408
+ if (rv.retval < 0 || rv.dret[0] <= rv.dret[7] || rv.dret[0] - rv.dret[7] <= vl1) break;
1409
+ t1 -= d; vl1 = rv.dret[0] - rv.dret[7]; t_has_changed = 1;
1410
+ retval_sv = rv.retval;
1411
+ phot_scot_opic_sv = rv.retval & SE_SCOTOPIC_FLAG;
1412
+ }
1413
+ if (t_has_changed === 0) t1 -= d;
1414
+ if (rv.retval === ERR) return { retval: ERR, tret: tjd, serr: rv.serr };
1415
+ }
1416
+ for (let i = 0, d = 100.0 / 86400.0; i < 3; i++, d /= 10.0) {
1417
+ t2 -= d;
1418
+ let t_has_changed = 0;
1419
+ while (true) {
1420
+ rv = sweVisLimitMag(swed, t2 + d, dgeo, datm, dobs, ObjectName, helflag);
1421
+ if (rv.retval < 0 || rv.dret[0] <= rv.dret[7] || rv.dret[0] - rv.dret[7] <= vl2) break;
1422
+ t2 += d; vl2 = rv.dret[0] - rv.dret[7]; t_has_changed = 1;
1423
+ retval_sv = rv.retval;
1424
+ phot_scot_opic_sv = rv.retval & SE_SCOTOPIC_FLAG;
1425
+ }
1426
+ if (t_has_changed === 0) t2 += d;
1427
+ if (rv.retval === ERR) return { retval: ERR, tret: tjd, serr: rv.serr };
1428
+ }
1429
+ const tret = vl2 > vl1 ? t2 : t1;
1430
+ if (rv.retval >= 0) {
1431
+ const phot_scot_opic = rv.retval & SE_SCOTOPIC_FLAG;
1432
+ if (phot_scot_opic_sv !== phot_scot_opic) return { retval: -2, tret, serr: '' };
1433
+ if (retval_sv & SE_MIXEDOPIC_FLAG) return { retval: -2, tret, serr: '' };
1434
+ }
1435
+ return { retval: OK, tret, serr: '' };
1436
+ }
1437
+
1438
+ function timeLimitInvisible(swed: SweData, tjd: number, dgeo: number[], datm: number[], dobs: number[], ObjectName: string, helflag: number, direct: number): { retval: number; tret: number; serr: string } {
1439
+ let ncnt = 3;
1440
+ let d0 = 100.0 / 86400.0;
1441
+ let tjdAdj = tjd;
1442
+ if (ObjectName === 'moon') { d0 *= 10; ncnt = 4; }
1443
+ let rv = sweVisLimitMag(swed, tjdAdj, dgeo, datm, dobs, ObjectName, helflag);
1444
+ if (rv.retval === ERR) return { retval: ERR, tret: tjd, serr: rv.serr };
1445
+ let retval_sv = rv.retval;
1446
+ let phot_scot_opic_sv = rv.retval & SE_SCOTOPIC_FLAG;
1447
+ for (let i = 0, d = d0; i < ncnt; i++, d /= 10.0) {
1448
+ while (true) {
1449
+ rv = sweVisLimitMag(swed, tjdAdj + d * direct, dgeo, datm, dobs, ObjectName, helflag);
1450
+ if (rv.retval < 0 || rv.dret[0] <= rv.dret[7]) break;
1451
+ tjdAdj += d * direct;
1452
+ retval_sv = rv.retval;
1453
+ phot_scot_opic_sv = rv.retval & SE_SCOTOPIC_FLAG;
1454
+ }
1455
+ }
1456
+ if (rv.retval >= 0) {
1457
+ const phot_scot_opic = rv.retval & SE_SCOTOPIC_FLAG;
1458
+ if (phot_scot_opic_sv !== phot_scot_opic) return { retval: -2, tret: tjdAdj, serr: '' };
1459
+ if (retval_sv & SE_MIXEDOPIC_FLAG) return { retval: -2, tret: tjdAdj, serr: '' };
1460
+ }
1461
+ return { retval: OK, tret: tjdAdj, serr: '' };
1462
+ }
1463
+
1464
+ function getAcronchalDay(swed: SweData, tjd: number, dgeo: number[], datm: number[], dobs: number[], ObjectName: string, helflag: number, TypeEvent: number): { retval: number; thel: number; serr: string } {
1465
+ const ipl = DeterObject(ObjectName);
1466
+ const helflagP = helflag | SE_HELFLAG_VISLIM_PHOTOPIC;
1467
+ let is_rise_or_set: number, direct: number;
1468
+ if (TypeEvent === 3 || TypeEvent === 5) { is_rise_or_set = SE_CALC_RISE; direct = -1; }
1469
+ else { is_rise_or_set = SE_CALC_SET; direct = 1; }
1470
+ let dtret = 999;
1471
+ let tjdAdj = tjd;
1472
+ while (Math.abs(dtret) > 0.5 / 1440.0) {
1473
+ tjdAdj += 0.7 * direct;
1474
+ if (direct < 0) tjdAdj -= 1;
1475
+ const rrt = myRiseTrans(swed, tjdAdj, ipl, ObjectName, is_rise_or_set, helflagP, dgeo, datm);
1476
+ if (rrt.retval === ERR) return { retval: ERR, thel: 0, serr: rrt.serr };
1477
+ tjdAdj = rrt.tret;
1478
+ let rv = sweVisLimitMag(swed, tjdAdj, dgeo, datm, dobs, ObjectName, helflagP);
1479
+ if (rv.retval === ERR) return { retval: ERR, thel: 0, serr: rv.serr };
1480
+ while (rv.dret[0] < rv.dret[7]) {
1481
+ tjdAdj += 10.0 / 1440.0 * -direct;
1482
+ rv = sweVisLimitMag(swed, tjdAdj, dgeo, datm, dobs, ObjectName, helflagP);
1483
+ if (rv.retval === ERR) return { retval: ERR, thel: 0, serr: rv.serr };
1484
+ }
1485
+ const rd = timeLimitInvisible(swed, tjdAdj, dgeo, datm, dobs, ObjectName, helflagP | SE_HELFLAG_VISLIM_DARK, direct);
1486
+ if (rd.retval === ERR) return { retval: ERR, thel: 0, serr: rd.serr };
1487
+ const tret_dark = rd.tret;
1488
+ const rn = timeLimitInvisible(swed, tjdAdj, dgeo, datm, dobs, ObjectName, helflagP | SE_HELFLAG_VISLIM_NOMOON, direct);
1489
+ if (rn.retval === ERR) return { retval: ERR, thel: 0, serr: rn.serr };
1490
+ const tret = rn.tret;
1491
+ dtret = Math.abs(tret - tret_dark);
1492
+ }
1493
+ const rsun = azaltCart(swed, tjdAdj, dgeo, datm, 'sun', helflag);
1494
+ if (rsun.retval === ERR) return { retval: ERR, thel: 0, serr: rsun.serr };
1495
+ let serr = '';
1496
+ if (rsun.dret[1] < -12) serr = `acronychal rising/setting not available, ${rsun.dret[1]}`;
1497
+ else serr = `solar altitude, ${rsun.dret[1]}`;
1498
+ return { retval: OK, thel: tjdAdj, serr };
1499
+ }
1500
+
1501
+ function getHeliacalDetails(swed: SweData, tday: number, dgeo: number[], datm: number[], dobs: number[], ObjectName: string, TypeEvent: number, helflag: number): { retval: number; dret: number[]; serr: string } {
1502
+ const dret = [0, 0, 0];
1503
+ let optimum_undefined = false, limit_1_undefined = false, limit_2_undefined = false;
1504
+ let r = timeOptimumVisibility(swed, tday, dgeo, datm, dobs, ObjectName, helflag);
1505
+ if (r.retval === ERR) return { retval: ERR, dret, serr: r.serr };
1506
+ if (r.retval === -2) optimum_undefined = true;
1507
+ dret[1] = r.tret;
1508
+ let direct = 1;
1509
+ if (TypeEvent === 1 || TypeEvent === 4) direct = -1;
1510
+ r = timeLimitInvisible(swed, tday, dgeo, datm, dobs, ObjectName, helflag, direct);
1511
+ if (r.retval === ERR) return { retval: ERR, dret, serr: r.serr };
1512
+ if (r.retval === -2) limit_1_undefined = true;
1513
+ dret[0] = r.tret;
1514
+ direct *= -1;
1515
+ r = timeLimitInvisible(swed, dret[1], dgeo, datm, dobs, ObjectName, helflag, direct);
1516
+ if (r.retval === ERR) return { retval: ERR, dret, serr: r.serr };
1517
+ if (r.retval === -2) limit_2_undefined = true;
1518
+ dret[2] = r.tret;
1519
+ if (TypeEvent === 2 || TypeEvent === 3) {
1520
+ const tmp = dret[2]; dret[2] = dret[0]; dret[0] = tmp;
1521
+ const tmpB = limit_1_undefined; limit_1_undefined = limit_2_undefined; limit_2_undefined = tmpB;
1522
+ }
1523
+ let serr = '';
1524
+ if (optimum_undefined || limit_1_undefined || limit_2_undefined) {
1525
+ serr = 'return values [';
1526
+ if (limit_1_undefined) serr += '0,';
1527
+ if (optimum_undefined) serr += '1,';
1528
+ if (limit_2_undefined) serr += '2,';
1529
+ serr += '] are uncertain due to change between photopic and scotopic vision';
1530
+ }
1531
+ return { retval: OK, dret, serr };
1532
+ }
1533
+
1534
+ function heliacalUtVisLim(swed: SweData, tjd_start: number, dgeo: number[], datm: number[], dobs: number[], ObjectName: string, TypeEventIn: number, helflag: number): { retval: number; dret: number[]; serr: string } {
1535
+ const dret = new Array(10).fill(0);
1536
+ dret[0] = tjd_start;
1537
+ let serr = '';
1538
+ const ipl = DeterObject(ObjectName);
1539
+ let tjd = ipl === SE_MERCURY ? tjd_start - 30 : tjd_start - 50;
1540
+ const helflag2 = helflag;
1541
+ let retval: number;
1542
+ const TypeEvent = TypeEventIn;
1543
+ if (ipl === SE_MERCURY || ipl === SE_VENUS || TypeEvent <= 2) {
1544
+ if (ipl === -1) {
1545
+ const r = getAscOblWithSun(swed, tjd, ipl, ObjectName, helflag, TypeEvent, 0, dgeo);
1546
+ if (r.retval !== OK) return { retval: r.retval, dret, serr: r.serr };
1547
+ tjd = r.tjdret;
1548
+ } else {
1549
+ const r = findConjunctSun(swed, tjd, ipl, helflag, TypeEvent);
1550
+ if (r.retval === ERR) return { retval: ERR, dret, serr: r.serr };
1551
+ tjd = r.tjd;
1552
+ }
1553
+ const r = getHeliacalDay(swed, tjd, dgeo, datm, dobs, ObjectName, helflag2, TypeEvent);
1554
+ if (r.retval !== OK) return { retval: r.retval, dret, serr: r.serr };
1555
+ dret[0] = r.thel;
1556
+ } else {
1557
+ const r = getAscOblWithSun(swed, tjd, ipl, ObjectName, helflag, TypeEvent, 0, dgeo);
1558
+ if (r.retval !== OK) return { retval: r.retval, dret, serr: r.serr };
1559
+ tjd = r.tjdret;
1560
+ const ra = getAcronchalDay(swed, tjd, dgeo, datm, dobs, ObjectName, helflag2, TypeEvent);
1561
+ if (ra.retval !== OK) return { retval: ra.retval, dret, serr: ra.serr };
1562
+ dret[0] = ra.thel;
1563
+ serr = ra.serr;
1564
+ }
1565
+ if (!(helflag & SE_HELFLAG_NO_DETAILS)) {
1566
+ if (ipl === SE_MERCURY || ipl === SE_VENUS || TypeEvent <= 2) {
1567
+ const r = getHeliacalDetails(swed, dret[0], dgeo, datm, dobs, ObjectName, TypeEvent, helflag2);
1568
+ if (r.retval === ERR) return { retval: ERR, dret, serr: r.serr };
1569
+ dret[0] = r.dret[0]; dret[1] = r.dret[1]; dret[2] = r.dret[2];
1570
+ if (r.serr) serr = r.serr;
1571
+ }
1572
+ }
1573
+ return { retval: OK, dret, serr };
1574
+ }
1575
+
1576
+ function moonEventVisLim(swed: SweData, tjdstart: number, dgeo: number[], datm: number[], dobs: number[], TypeEvent: number, helflag: number): { retval: number; dret: number[]; serr: string } {
1577
+ const dret = [tjdstart, 0, 0];
1578
+ if (TypeEvent === 1 || TypeEvent === 2)
1579
+ return { retval: ERR, dret, serr: 'error: the moon has no morning first or evening last' };
1580
+ const ObjectName = 'moon';
1581
+ const ipl = SE_MOON;
1582
+ const helflag2 = helflag & ~SE_HELFLAG_HIGH_PRECISION;
1583
+ let tjd = tjdstart - 30;
1584
+ const rc = findConjunctSun(swed, tjd, ipl, helflag, TypeEvent);
1585
+ if (rc.retval === ERR) return { retval: ERR, dret, serr: rc.serr };
1586
+ tjd = rc.tjd;
1587
+ const rh = getHeliacalDay(swed, tjd, dgeo, datm, dobs, ObjectName, helflag2, TypeEvent);
1588
+ if (rh.retval !== OK) return { retval: rh.retval, dret, serr: rh.serr };
1589
+ tjd = rh.thel;
1590
+ dret[0] = tjd;
1591
+ const ro = timeOptimumVisibility(swed, tjd, dgeo, datm, dobs, ObjectName, helflag);
1592
+ if (ro.retval === ERR) return { retval: ERR, dret, serr: ro.serr };
1593
+ dret[1] = ro.tret;
1594
+ tjd = ro.tret;
1595
+ let direct = 1;
1596
+ if (TypeEvent === 4) direct = -1;
1597
+ const rl = timeLimitInvisible(swed, tjd, dgeo, datm, dobs, ObjectName, helflag, direct);
1598
+ if (rl.retval === ERR) return { retval: ERR, dret, serr: rl.serr };
1599
+ dret[2] = rl.tret;
1600
+ const rl2 = timeLimitInvisible(swed, dret[1], dgeo, datm, dobs, ObjectName, helflag, -direct);
1601
+ if (rl2.retval === ERR) return { retval: ERR, dret, serr: rl2.serr };
1602
+ dret[0] = rl2.tret;
1603
+ if (TypeEvent === 3) {
1604
+ const rs = myRiseTrans(swed, rl2.tret, SE_SUN, '', SE_CALC_SET, helflag, dgeo, datm);
1605
+ if (rs.retval === ERR) return { retval: ERR, dret, serr: rs.serr };
1606
+ if (rs.tret < dret[1]) dret[0] = rs.tret;
1607
+ } else {
1608
+ const rs = myRiseTrans(swed, dret[1], SE_SUN, '', SE_CALC_RISE, helflag, dgeo, datm);
1609
+ if (rs.retval === ERR) return { retval: ERR, dret, serr: rs.serr };
1610
+ if (dret[0] > rs.tret) dret[0] = rs.tret;
1611
+ }
1612
+ if (TypeEvent === 4) {
1613
+ const tmp = dret[0]; dret[0] = dret[2]; dret[2] = tmp;
1614
+ }
1615
+ return { retval: OK, dret, serr: '' };
1616
+ }
1617
+
1618
+ function MoonEventJDut(swed: SweData, JDNDaysUTStart: number, dgeo: number[], datm: number[], dobs: number[], TypeEvent: number, helflag: number): { retval: number; dret: number[]; serr: string } {
1619
+ const avkind = helflag & SE_HELFLAG_AVKIND;
1620
+ if (avkind) {
1621
+ const r = moonEventArcVis(swed, JDNDaysUTStart, dgeo, datm, dobs, TypeEvent, helflag);
1622
+ return { retval: r.retval, dret: [r.dret], serr: r.serr };
1623
+ } else {
1624
+ return moonEventVisLim(swed, JDNDaysUTStart, dgeo, datm, dobs, TypeEvent, helflag);
1625
+ }
1626
+ }
1627
+
1628
+ function heliacalUt(swed: SweData, JDNDaysUTStart: number, dgeo: number[], datm: number[], dobs: number[], ObjectName: string, TypeEventIn: number, helflag: number): { retval: number; dret: number[]; serr: string } {
1629
+ const avkind = helflag & SE_HELFLAG_AVKIND;
1630
+ if (avkind) {
1631
+ const r = heliacalUtArcVis(swed, JDNDaysUTStart, dgeo, datm, dobs, ObjectName, TypeEventIn, helflag);
1632
+ return { retval: r.retval, dret: [r.dret], serr: r.serr };
1633
+ } else {
1634
+ return heliacalUtVisLim(swed, JDNDaysUTStart, dgeo, datm, dobs, ObjectName, TypeEventIn, helflag);
1635
+ }
1636
+ }
1637
+
1638
+ /* ================================================================
1639
+ * G. Public API functions
1640
+ * ================================================================ */
1641
+
1642
+ export function sweVisLimitMag(
1643
+ swed: SweData, tjdut: number, dgeo: number[], datm: number[], dobs: number[],
1644
+ ObjectName: string, helflag: number,
1645
+ ): { retval: number; dret: number[]; serr: string } {
1646
+ const dret = new Array(8).fill(0);
1647
+ const datmC = [...datm];
1648
+ const dobsC = [...dobs];
1649
+ let objectName = tolowerStringStar(ObjectName);
1650
+ if (DeterObject(objectName) === SE_SUN)
1651
+ return { retval: ERR, dret, serr: 'it makes no sense to call swe_vis_limit_mag() for the Sun' };
1652
+ const sunra = SunRA(swed, tjdut, helflag).ra;
1653
+ defaultHeliacalParameters(datmC, dgeo, dobsC, helflag);
1654
+ sweSetTopo(swed, dgeo[0], dgeo[1], dgeo[2]);
1655
+ const rAltO = ObjectLoc(swed, tjdut, dgeo, datmC, objectName, 0, helflag);
1656
+ if (rAltO.retval === ERR) return { retval: ERR, dret, serr: rAltO.serr };
1657
+ if (rAltO.dret < 0) { dret[0] = -100; return { retval: -2, dret, serr: 'object is below local horizon' }; }
1658
+ const rAziO = ObjectLoc(swed, tjdut, dgeo, datmC, objectName, 1, helflag);
1659
+ if (rAziO.retval === ERR) return { retval: ERR, dret, serr: rAziO.serr };
1660
+ let AltS: number, AziS: number;
1661
+ if (helflag & SE_HELFLAG_VISLIM_DARK) { AltS = -90; AziS = 0; }
1662
+ else {
1663
+ const rs = ObjectLoc(swed, tjdut, dgeo, datmC, 'sun', 0, helflag);
1664
+ if (rs.retval === ERR) return { retval: ERR, dret, serr: rs.serr };
1665
+ AltS = rs.dret;
1666
+ const rsa = ObjectLoc(swed, tjdut, dgeo, datmC, 'sun', 1, helflag);
1667
+ if (rsa.retval === ERR) return { retval: ERR, dret, serr: rsa.serr };
1668
+ AziS = rsa.dret;
1669
+ }
1670
+ let AltM: number, AziM: number;
1671
+ if (objectName.startsWith('moon') || (helflag & SE_HELFLAG_VISLIM_DARK) || (helflag & SE_HELFLAG_VISLIM_NOMOON)) {
1672
+ AltM = -90; AziM = 0;
1673
+ } else {
1674
+ const rm = ObjectLoc(swed, tjdut, dgeo, datmC, 'moon', 0, helflag);
1675
+ if (rm.retval === ERR) return { retval: ERR, dret, serr: rm.serr };
1676
+ AltM = rm.dret;
1677
+ const rma = ObjectLoc(swed, tjdut, dgeo, datmC, 'moon', 1, helflag);
1678
+ if (rma.retval === ERR) return { retval: ERR, dret, serr: rma.serr };
1679
+ AziM = rma.dret;
1680
+ }
1681
+ const scotopic_flag = { value: 0 };
1682
+ const serrRef = { value: '' };
1683
+ dret[0] = VisLimMagn(dobsC, rAltO.dret, rAziO.dret, AltM, AziM, tjdut, AltS, AziS, sunra, dgeo[1], dgeo[2], datmC, helflag, scotopic_flag, serrRef);
1684
+ dret[1] = rAltO.dret; dret[2] = rAziO.dret;
1685
+ dret[3] = AltS; dret[4] = AziS; dret[5] = AltM; dret[6] = AziM;
1686
+ const rm = Magnitude(swed, tjdut, dgeo, objectName, helflag);
1687
+ if (rm.retval === ERR) return { retval: ERR, dret, serr: rm.serr };
1688
+ dret[7] = rm.dmag;
1689
+ return { retval: scotopic_flag.value, dret, serr: serrRef.value };
1690
+ }
1691
+
1692
+ export function sweTopoArcusVisionis(
1693
+ swed: SweData, tjdut: number, dgeo: number[], datm: number[], dobs: number[],
1694
+ helflag: number, mag: number, azi_obj: number, alt_obj: number,
1695
+ azi_sun: number, azi_moon: number, alt_moon: number,
1696
+ ): { retval: number; dret: number; serr: string } {
1697
+ const datmC = [...datm]; const dobsC = [...dobs];
1698
+ const sunra = SunRA(swed, tjdut, helflag).ra;
1699
+ defaultHeliacalParameters(datmC, dgeo, dobsC, helflag);
1700
+ return TopoArcVisionis(swed, mag, dobsC, alt_obj, azi_obj, alt_moon, azi_moon, tjdut, azi_sun, sunra, dgeo[1], dgeo[2], datmC, helflag);
1701
+ }
1702
+
1703
+ export function sweHeliacalAngle(
1704
+ swed: SweData, tjdut: number, dgeo: number[], datm: number[], dobs: number[],
1705
+ helflag: number, mag: number, azi_obj: number, azi_sun: number,
1706
+ azi_moon: number, alt_moon: number,
1707
+ ): { retval: number; dret: number[]; serr: string } {
1708
+ if (dgeo[2] < SEI_ECL_GEOALT_MIN || dgeo[2] > SEI_ECL_GEOALT_MAX)
1709
+ return { retval: ERR, dret: [0, 0, 0], serr: `location for heliacal events must be between ${SEI_ECL_GEOALT_MIN} and ${SEI_ECL_GEOALT_MAX} m above sea` };
1710
+ const datmC = [...datm]; const dobsC = [...dobs];
1711
+ defaultHeliacalParameters(datmC, dgeo, dobsC, helflag);
1712
+ const r = HeliacalAngle(swed, mag, dobsC, azi_obj, alt_moon, azi_moon, tjdut, azi_sun, dgeo, datmC, helflag);
1713
+ return { retval: r.retval, dret: r.dangret, serr: r.serr };
1714
+ }
1715
+
1716
+ export function sweHeliacalPhenoUt(
1717
+ swed: SweData, JDNDaysUT: number, dgeo: number[], datm: number[], dobs: number[],
1718
+ ObjectNameIn: string, TypeEvent: number, helflag: number,
1719
+ ): { retval: number; darr: number[]; serr: string } {
1720
+ const darr = new Array(30).fill(0);
1721
+ if (dgeo[2] < SEI_ECL_GEOALT_MIN || dgeo[2] > SEI_ECL_GEOALT_MAX)
1722
+ return { retval: ERR, darr, serr: `location for heliacal events must be between ${SEI_ECL_GEOALT_MIN} and ${SEI_ECL_GEOALT_MAX} m above sea` };
1723
+ const datmC = [...datm]; const dobsC = [...dobs];
1724
+ const ObjectName = tolowerStringStar(strcpyVBsafe(ObjectNameIn));
1725
+ const sunra = SunRA(swed, JDNDaysUT, helflag).ra;
1726
+ defaultHeliacalParameters(datmC, dgeo, dobsC, helflag);
1727
+ sweSetTopo(swed, dgeo[0], dgeo[1], dgeo[2]);
1728
+ const iflag = helflag & (SEFLG_JPLEPH | SEFLG_SWIEPH | SEFLG_MOSEPH);
1729
+ let r = ObjectLoc(swed, JDNDaysUT, dgeo, datmC, 'sun', 1, helflag);
1730
+ if (r.retval === ERR) return { retval: ERR, darr, serr: r.serr };
1731
+ const AziS = r.dret;
1732
+ r = ObjectLoc(swed, JDNDaysUT, dgeo, datmC, 'sun', 0, helflag);
1733
+ if (r.retval === ERR) return { retval: ERR, darr, serr: r.serr };
1734
+ const AltS = r.dret;
1735
+ r = ObjectLoc(swed, JDNDaysUT, dgeo, datmC, ObjectName, 1, helflag);
1736
+ if (r.retval === ERR) return { retval: ERR, darr, serr: r.serr };
1737
+ const AziO = r.dret;
1738
+ r = ObjectLoc(swed, JDNDaysUT, dgeo, datmC, ObjectName, 0, helflag);
1739
+ if (r.retval === ERR) return { retval: ERR, darr, serr: r.serr };
1740
+ const AltO = r.dret;
1741
+ r = ObjectLoc(swed, JDNDaysUT, dgeo, datmC, ObjectName, 7, helflag);
1742
+ if (r.retval === ERR) return { retval: ERR, darr, serr: r.serr };
1743
+ const GeoAltO = r.dret;
1744
+ const AppAltO = AppAltfromTopoAlt(AltO, datmC[1], datmC[0], helflag);
1745
+ const DAZact = AziS - AziO;
1746
+ const TAVact = AltO - AltS;
1747
+ const ParO = GeoAltO - AltO;
1748
+ const mr = Magnitude(swed, JDNDaysUT, dgeo, ObjectName, helflag);
1749
+ if (mr.retval === ERR) return { retval: ERR, darr, serr: mr.serr };
1750
+ const MagnO = mr.dmag;
1751
+ const ARCVact = TAVact + ParO;
1752
+ const ARCLact = Math.acos(Math.cos(ARCVact * DEGTORAD) * Math.cos(DAZact * DEGTORAD)) / DEGTORAD;
1753
+ const Planet = DeterObject(ObjectName);
1754
+ let elong: number, illum: number;
1755
+ if (Planet === -1) { elong = ARCLact; illum = 100; }
1756
+ else {
1757
+ const serrRef = { value: '' };
1758
+ const rp = swePhenoUt(swed, JDNDaysUT, Planet, iflag | SEFLG_TOPOCTR | SEFLG_EQUATORIAL, serrRef);
1759
+ if (rp.retval === ERR) return { retval: ERR, darr, serr: serrRef.value };
1760
+ elong = rp.attr[2]; illum = rp.attr[1] * 100;
1761
+ }
1762
+ const serrRef2 = { value: '' };
1763
+ const kact = kt(AltS, sunra, dgeo[1], dgeo[2], datmC[1], datmC[2], datmC[3], 4, serrRef2);
1764
+ let WMoon = 0, qYal = 0, qCrit = 0, LMoon = 0;
1765
+ if (Planet === SE_MOON) {
1766
+ WMoon = WidthMoon(AltO, AziO, AltS, AziS, ParO);
1767
+ LMoon = LengthMoon(WMoon, 0);
1768
+ qYal = qYallop(WMoon, ARCVact);
1769
+ if (qYal > 0.216) qCrit = 1;
1770
+ if (qYal < 0.216 && qYal > -0.014) qCrit = 2;
1771
+ if (qYal < -0.014 && qYal > -0.16) qCrit = 3;
1772
+ if (qYal < -0.16 && qYal > -0.232) qCrit = 4;
1773
+ if (qYal < -0.232 && qYal > -0.293) qCrit = 5;
1774
+ if (qYal < -0.293) qCrit = 6;
1775
+ }
1776
+ let RS = 2;
1777
+ if (TypeEvent === 1 || TypeEvent === 4) RS = 1;
1778
+ const rrs = RiseSet(swed, JDNDaysUT - 4.0 / 24.0, dgeo, datmC, 'sun', RS, helflag, 0);
1779
+ if (rrs.retval === ERR) return { retval: ERR, darr, serr: rrs.serr };
1780
+ const RiseSetS = rrs.tret;
1781
+ const rro = RiseSet(swed, JDNDaysUT - 4.0 / 24.0, dgeo, datmC, ObjectName, RS, helflag, 0);
1782
+ if (rro.retval === ERR) return { retval: ERR, darr, serr: rro.serr };
1783
+ const RiseSetO = rro.tret;
1784
+ let noriseO = false;
1785
+ let Lag: number;
1786
+ let TbYallop = TJD_INVALID;
1787
+ if (rro.retval === -2) { Lag = 0; noriseO = true; }
1788
+ else {
1789
+ Lag = RiseSetO - RiseSetS;
1790
+ if (Planet === SE_MOON) TbYallop = (RiseSetO * 4 + RiseSetS * 5) / 9.0;
1791
+ }
1792
+ let TfirstVR = TJD_INVALID, TbVR = TJD_INVALID, TlastVR = TJD_INVALID, TvisVR = 0, MinTAV = 0;
1793
+ if (!((TypeEvent === 3 || TypeEvent === 4) && (Planet === -1 || Planet >= SE_MARS))) {
1794
+ let MinTAVact = 199, DeltaAlt = 0, OldestMinTAV = 0, Ta = 0, Tc = 0;
1795
+ let MinTAVoud = 0, DeltaAltoud = 0;
1796
+ TbVR = 0;
1797
+ let TimeStep = -TimeStepDefault / 24.0 / 60.0;
1798
+ if (RS === 2) TimeStep = -TimeStep;
1799
+ let TimePointer = RiseSetS - TimeStep;
1800
+ do {
1801
+ TimePointer += TimeStep;
1802
+ OldestMinTAV = MinTAVoud;
1803
+ MinTAVoud = MinTAVact;
1804
+ DeltaAltoud = DeltaAlt;
1805
+ const rs2 = ObjectLoc(swed, TimePointer, dgeo, datmC, 'sun', 0, helflag);
1806
+ if (rs2.retval !== OK) return { retval: ERR, darr, serr: rs2.serr };
1807
+ const ro2 = ObjectLoc(swed, TimePointer, dgeo, datmC, ObjectName, 0, helflag);
1808
+ if (ro2.retval !== OK) return { retval: ERR, darr, serr: ro2.serr };
1809
+ DeltaAlt = ro2.dret - rs2.dret;
1810
+ const rt = DeterTAV(swed, dobsC, TimePointer, dgeo, datmC, ObjectName, helflag);
1811
+ if (rt.retval === ERR) return { retval: ERR, darr, serr: rt.serr };
1812
+ MinTAVact = rt.dret;
1813
+ if (MinTAVoud < MinTAVact && TbVR === 0) {
1814
+ let TimeCheck = TimePointer + Sgn(TimeStep) * LocalMinStep / 24.0 / 60.0;
1815
+ if (RiseSetO !== 0) {
1816
+ if (TimeStep > 0) TimeCheck = Math.min(TimeCheck, RiseSetO);
1817
+ else TimeCheck = Math.max(TimeCheck, RiseSetO);
1818
+ }
1819
+ const rlc = DeterTAV(swed, dobsC, TimeCheck, dgeo, datmC, ObjectName, helflag);
1820
+ if (rlc.retval === ERR) return { retval: ERR, darr, serr: rlc.serr };
1821
+ if (rlc.dret > MinTAVact) {
1822
+ const extrax = x2min(MinTAVact, MinTAVoud, OldestMinTAV);
1823
+ TbVR = TimePointer - (1 - extrax) * TimeStep;
1824
+ MinTAV = funct2(MinTAVact, MinTAVoud, OldestMinTAV, extrax);
1825
+ }
1826
+ }
1827
+ if (DeltaAlt > MinTAVact && Tc === 0 && TbVR === 0) {
1828
+ const cp = crossing(DeltaAltoud, DeltaAlt, MinTAVoud, MinTAVact);
1829
+ Tc = TimePointer - TimeStep * (1 - cp);
1830
+ }
1831
+ if (DeltaAlt < MinTAVact && Ta === 0 && Tc !== 0) {
1832
+ const cp = crossing(DeltaAltoud, DeltaAlt, MinTAVoud, MinTAVact);
1833
+ Ta = TimePointer - TimeStep * (1 - cp);
1834
+ }
1835
+ } while (Math.abs(TimePointer - RiseSetS) <= MaxTryHours / 24.0 && Ta === 0 &&
1836
+ !((TbVR !== 0 && (TypeEvent === 3 || TypeEvent === 4) && !ObjectName.startsWith('moon') && !ObjectName.startsWith('venus') && !ObjectName.startsWith('mercury'))));
1837
+ if (RS === 2) { TfirstVR = Tc; TlastVR = Ta; }
1838
+ else { TfirstVR = Ta; TlastVR = Tc; }
1839
+ if (TfirstVR === 0 && TlastVR === 0) {
1840
+ if (RS === 1) TfirstVR = TbVR - 0.000001;
1841
+ else TlastVR = TbVR + 0.000001;
1842
+ }
1843
+ if (!noriseO) {
1844
+ if (RS === 1) TfirstVR = Math.max(TfirstVR, RiseSetO);
1845
+ else TlastVR = Math.min(TlastVR, RiseSetO);
1846
+ }
1847
+ TvisVR = TJD_INVALID;
1848
+ if (TlastVR !== 0 && TfirstVR !== 0) TvisVR = TlastVR - TfirstVR;
1849
+ if (TlastVR === 0) TlastVR = TJD_INVALID;
1850
+ if (TbVR === 0) TbVR = TJD_INVALID;
1851
+ if (TfirstVR === 0) TfirstVR = TJD_INVALID;
1852
+ }
1853
+ darr[0] = AltO; darr[1] = AppAltO; darr[2] = GeoAltO; darr[3] = AziO;
1854
+ darr[4] = AltS; darr[5] = AziS; darr[6] = TAVact; darr[7] = ARCVact;
1855
+ darr[8] = DAZact; darr[9] = ARCLact; darr[10] = kact; darr[11] = MinTAV;
1856
+ darr[12] = TfirstVR; darr[13] = TbVR; darr[14] = TlastVR; darr[15] = TbYallop;
1857
+ darr[16] = WMoon; darr[17] = qYal; darr[18] = qCrit; darr[19] = ParO;
1858
+ darr[20] = MagnO; darr[21] = RiseSetO; darr[22] = RiseSetS; darr[23] = Lag;
1859
+ darr[24] = TvisVR; darr[25] = LMoon; darr[26] = elong; darr[27] = illum;
1860
+ return { retval: OK, darr, serr: '' };
1861
+ }
1862
+
1863
+ export function sweHeliacalUt(
1864
+ swed: SweData, JDNDaysUTStart: number, dgeo: number[], datm: number[], dobs: number[],
1865
+ ObjectNameIn: string, TypeEvent: number, helflag: number,
1866
+ ): { retval: number; dret: number[]; serr: string } {
1867
+ const dret = [0, 0, 0];
1868
+ if (dgeo[2] < SEI_ECL_GEOALT_MIN || dgeo[2] > SEI_ECL_GEOALT_MAX)
1869
+ return { retval: ERR, dret, serr: `location for heliacal events must be between ${SEI_ECL_GEOALT_MIN} and ${SEI_ECL_GEOALT_MAX} m above sea` };
1870
+ const datmC = [...datm]; const dobsC = [...dobs];
1871
+ const ObjectName = tolowerStringStar(strcpyVBsafe(ObjectNameIn));
1872
+ defaultHeliacalParameters(datmC, dgeo, dobsC, helflag);
1873
+ sweSetTopo(swed, dgeo[0], dgeo[1], dgeo[2]);
1874
+ const Planet = DeterObject(ObjectName);
1875
+ if (Planet === SE_SUN)
1876
+ return { retval: ERR, dret, serr: 'the sun has no heliacal rising or setting' };
1877
+ let MaxCountSynodicPeriod = MAX_COUNT_SYNPER;
1878
+ if (helflag & SE_HELFLAG_LONG_SEARCH) MaxCountSynodicPeriod = MAX_COUNT_SYNPER_MAX;
1879
+ const sevent = ['', 'morning first', 'evening last', 'evening first', 'morning last', 'acronychal rising', 'acronychal setting'];
1880
+ let TypeEventAdj = TypeEvent;
1881
+ /* Moon events */
1882
+ if (Planet === SE_MOON) {
1883
+ if (TypeEvent === 1 || TypeEvent === 2)
1884
+ return { retval: ERR, dret, serr: `${sevent[TypeEvent]} (event type ${TypeEvent}) does not exist for the moon` };
1885
+ let tjd = JDNDaysUTStart;
1886
+ let r = MoonEventJDut(swed, tjd, dgeo, datmC, dobsC, TypeEvent, helflag);
1887
+ while (r.retval !== -2 && r.dret[0] < JDNDaysUTStart) {
1888
+ tjd += 15;
1889
+ r = MoonEventJDut(swed, tjd, dgeo, datmC, dobsC, TypeEvent, helflag);
1890
+ }
1891
+ dret[0] = r.dret[0]; if (r.dret.length > 1) dret[1] = r.dret[1]; if (r.dret.length > 2) dret[2] = r.dret[2];
1892
+ return { retval: r.retval, dret, serr: r.serr };
1893
+ }
1894
+ /* planets and fixed stars */
1895
+ if (!(helflag & SE_HELFLAG_AVKIND)) {
1896
+ if (Planet === -1 || Planet >= SE_MARS) {
1897
+ if (TypeEvent === 3 || TypeEvent === 4) {
1898
+ const s = Planet === -1 ? ObjectName : sweGetPlanetName(Planet, swed);
1899
+ return { retval: ERR, dret, serr: `${sevent[TypeEvent]} (event type ${TypeEvent}) does not exist for ${s}` };
1900
+ }
1901
+ }
1902
+ }
1903
+ if (helflag & SE_HELFLAG_AVKIND) {
1904
+ if (Planet === -1 || Planet >= SE_MARS) {
1905
+ if (TypeEventAdj === SE_ACRONYCHAL_RISING) TypeEventAdj = 3;
1906
+ if (TypeEventAdj === SE_ACRONYCHAL_SETTING) TypeEventAdj = 4;
1907
+ }
1908
+ } else {
1909
+ if (TypeEventAdj === SE_ACRONYCHAL_RISING || TypeEventAdj === SE_ACRONYCHAL_SETTING) {
1910
+ const s = Planet === -1 ? ObjectName : sweGetPlanetName(Planet, swed);
1911
+ return { retval: ERR, dret, serr: `${sevent[TypeEvent]} (event type ${TypeEvent}) is not provided for ${s}` };
1912
+ }
1913
+ }
1914
+ const dsynperiod = getSynodicPeriod(Planet);
1915
+ const tjdmax = JDNDaysUTStart + dsynperiod * MaxCountSynodicPeriod;
1916
+ let tadd = dsynperiod * 0.6;
1917
+ if (Planet === SE_MERCURY) tadd = 30;
1918
+ let retval = -2;
1919
+ for (let tjd = JDNDaysUTStart; tjd < tjdmax && retval === -2; tjd += tadd) {
1920
+ let r = heliacalUt(swed, tjd, dgeo, datmC, dobsC, ObjectName, TypeEventAdj, helflag);
1921
+ retval = r.retval;
1922
+ dret[0] = r.dret[0]; if (r.dret.length > 1) dret[1] = r.dret[1]; if (r.dret.length > 2) dret[2] = r.dret[2];
1923
+ while (retval !== -2 && dret[0] < JDNDaysUTStart) {
1924
+ tjd += tadd;
1925
+ r = heliacalUt(swed, tjd, dgeo, datmC, dobsC, ObjectName, TypeEventAdj, helflag);
1926
+ retval = r.retval; dret[0] = r.dret[0];
1927
+ if (r.dret.length > 1) dret[1] = r.dret[1]; if (r.dret.length > 2) dret[2] = r.dret[2];
1928
+ }
1929
+ }
1930
+ let serr = '';
1931
+ if ((helflag & SE_HELFLAG_SEARCH_1_PERIOD) && (retval === -2 || dret[0] > JDNDaysUTStart + dsynperiod * 1.5)) {
1932
+ serr = 'no heliacal date found within this synodic period';
1933
+ retval = -2;
1934
+ } else if (retval === -2) {
1935
+ serr = `no heliacal date found within ${MaxCountSynodicPeriod} synodic periods`;
1936
+ retval = ERR;
1937
+ }
1938
+ return { retval, dret, serr };
1939
+ }