Bestimmung der Zeitpunkte von Ereignissen
ulrich
2023-03-19 2f6b9a6d698d70893d6d56ba0736910c14d44214
commit | author | age
66d68b 1 /*
U 2   Zeitrechnung - a class library to determine calendar events
3   Copyright (c) 1984-2023 Ulrich Hilger, http://uhilger.de
4
5   This program is free software: you can redistribute it and/or modify
6   it under the terms of the GNU Affero General Public License as published by
7   the Free Software Foundation, either version 3 of the License, or
8   (at your option) any later version.
9
10   This program is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   GNU Affero General Public License for more details.
14
15   You should have received a copy of the GNU Affero General Public License
16   along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 package de.uhilger.zeitrechnung.kalender;
19
20 import de.uhilger.zeitrechnung.Definition;
21 import de.uhilger.zeitrechnung.Ort;
22 import de.uhilger.zeitrechnung.Zeit;
23
24 /**
25  * Abstrakte Basisklasse fuer Klassen, die ein Kalendersystem implementieren
26  * 
27  * @author Ulrich Hilger
28  * @version 2, 1.10.2022
29  */
30 public abstract class BasisKalender implements Zeitrechnung {
31   
32   /* Implementierung der Schnittstelle Zeitrechnung */
33   
34   @Override
35   public long ganzzahlQuotient(double x, double y) {
36     return (long) Math.floor(x / y);
37   }
38
39   @Override
40   public long modulo(long x, long y) {
41     return (long) (x - y * Math.floor((double) x / y));
42   }
43   
44     public double modulo(double x, double y) {
45         return x - y * Math.floor(x / y);
46     }
47
48   @Override
49   public long tagNach(long datum, int t) {
50     return tagAmOderNach(datum + 7, t);
51   }
52
53   @Override
54   public long tagAmOderNach(long datum, int t) {
55     return datum - wochentagVonGenerisch(datum - t);
56   }
57
58   @Override
59   public long wochentagVonGenerisch(long datum) {
60     return modulo(datum, 7);
61   }
62     
63   @Override
64     public long nterTag(int n, int t, long datum) {
65         return n > 0 ?
66             tagVor(datum, t) + 7 * n :
67             tagNach(datum, t) + 7 * n;
68     }
69   
70   @Override
71     public long tagVor(long datum, int t) {
72         return tagAmOderVor(datum - 1, t);
73     }
74
75   @Override
76     public long tagAmOderVor(long datum, int t) {
77         return datum - wochentagVonGenerisch(datum - t);
78     }
79
80   @Override
81     public long letzterTag(int t, long datum) {
82         return nterTag(-1, t, datum);
83     }
84   
85   /* ---- Zeit ----- */
86   
87     public double zuMoment(int stunde, int minute, double sekunde) {
88         return stunde / 24d + minute / (24d * 60) + sekunde / (24d * 60 * 60);
89     }
90   
91   public double zuMoment(Zeit z) {
92     return BasisKalender.this.zuMoment(z.getStunde(), z.getMinute(), z.getSekunde());
93   }
94
95     public Zeit vonMoment(double t) {
96     Zeit z = new Zeit();
97         z.setStunde((int)Math.floor(modulo(t * 24, 24)));
98         z.setMinute((int)Math.floor(modulo(t * 24 * 60, 60)));
99         z.setSekunde(modulo(t * 24 * 60 * 60, 60));
100     return z;
101     }  
102     
103   /* ----------- Mondphase ----------- */
104   
105     public double mondphase(double t) {
106         return modulo(mondLaenge(t) - solareLaenge(t), 360);
107     }
108     
109     public double mondHoehe(double t, Ort ort) {
110         double phi = ort.getBreite();
111         double psi = ort.getLaenge();
112         double varepsilon = obliquity(t);
113         double lambda = mondLaenge(t);
114         double beta = mondBreite(t);
115         double alpha = arcTanGrad(
116             (sinGrad(lambda) * kosGrad(varepsilon) - tanGrad(beta) * sinGrad(varepsilon)) /
117             kosGrad(lambda),
118             (int)ganzzahlQuotient(lambda, (double) (90)) + 1
119         );
120         double delta = arcSinGrad(sinGrad(beta) * kosGrad(varepsilon) +
121             kosGrad(beta) * sinGrad(varepsilon) * sinGrad(lambda));
122         double theta0 = siderischVonMoment(t);
123         double capH = modulo(theta0 + psi - alpha, 360);
124         double altitude = arcSinGrad(sinGrad(phi) * sinGrad(delta) + kosGrad(phi) * kosGrad(delta) * kosGrad(capH));
125         return modulo(altitude + (double) (180), 360) - (double) (180);
126     }
127   
128     public double mondLaenge(double t) {
129         double c = julJahrhunderte(t);
130         double meanMoon = grad(poly(c, llon.coeffMeanMoon));
131         double elongation = grad(poly(c, llon.coeffElongation));
132         double solarAnomaly = grad(poly(c, llon.coeffSolarAnomaly));
133         double lunarAnomaly = grad(poly(c, llon.coeffLunarAnomaly));
134         double moonNode = grad(poly(c, llon.coeffMoonNode));
135         double capE = poly(c, llon.coeffCapE);
136         double sigma = 0;
137         for(int i = 0; i < llon.argsLunarElongation.length; ++i) {
138             double x = llon.argsSolarAnomaly[i];
139             sigma += llon.sineCoefficients[i] *
140                 Math.pow(capE, Math.abs(x)) *
141                 sinGrad(    llon.argsLunarElongation[i] * elongation + 
142                     x * solarAnomaly +
143                     llon.argsLunarAnomaly[i] * lunarAnomaly +
144                     llon.argsMoonFromNode[i] * moonNode);
145         }
146         double correction = ((double) (1) / 1000000) * sigma;
147         double venus = ((double) (3958) / 1000000) * sinGrad(119.75 + c * 131.849);
148         double jupiter = ((double) (318) / 1000000) * sinGrad(53.09 + c * 479264.29);
149         double flatEarth = ((double) (1962) / 1000000) * sinGrad(meanMoon - moonNode);
150         return modulo(meanMoon + correction + venus + jupiter + flatEarth + nutation(t), 360);
151     }
152     private static class llon {
153         private static final double[] coeffMeanMoon = new double[] {218.3164591, 481267.88134236, -0.0013268, 1d/538841, -1d/65194000};
154         private static final double[] coeffElongation = new double[] {297.8502042, 445267.1115168, -0.00163, 1d/545868, -1d/113065000};
155         private static final double[] coeffSolarAnomaly = new double[] {357.5291092, 35999.0502909, -0.0001536, 1d/24490000};
156         private static final double[] coeffLunarAnomaly = new double[] {134.9634114, 477198.8676313, 0.008997, 1d/69699, -1d/14712000};
157         private static final double[] coeffMoonNode = new double[] {93.2720993, 483202.0175273, -0.0034029, -1d/3526000, 1d/863310000};
158         private static final double[] coeffCapE = new double[] {1, -0.002516, -0.0000074};
159         private static final byte[] argsLunarElongation = new byte[] {
160             0, 2, 2, 0, 0, 0, 2, 2, 2, 2, 0, 1, 0, 2, 0, 0, 4, 0, 4, 2, 2, 1,
161             1, 2, 2, 4, 2, 0, 2, 2, 1, 2, 0, 0, 2, 2, 2, 4, 0, 3, 2, 4, 0, 2,
162             2, 2, 4, 0, 4, 1, 2, 0, 1, 3, 4, 2, 0, 1, 2
163         };
164         private static final byte[] argsSolarAnomaly = new byte[] {
165             0, 0, 0, 0, 1, 0, 0, -1, 0, -1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1,
166             0, 1, -1, 0, 0, 0, 1, 0, -1, 0, -2, 1, 2, -2, 0, 0, -1, 0, 0, 1,
167             -1, 2, 2, 1, -1, 0, 0, -1, 0, 1, 0, 1, 0, 0, -1, 2, 1, 0
168         };
169         private static final byte[] argsLunarAnomaly = new byte[] {
170             1, -1, 0, 2, 0, 0, -2, -1, 1, 0, -1, 0, 1, 0, 1, 1, -1, 3, -2,
171             -1, 0, -1, 0, 1, 2, 0, -3, -2, -1, -2, 1, 0, 2, 0, -1, 1, 0,
172             -1, 2, -1, 1, -2, -1, -1, -2, 0, 1, 4, 0, -2, 0, 2, 1, -2, -3,
173             2, 1, -1, 3
174         };
175         private static final byte[] argsMoonFromNode = new byte[] {
176             0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, -2, 2, -2, 0, 0, 0, 0, 0,
177             0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, -2, 2, 0, 2, 0, 0, 0, 0,
178             0, 0, -2, 0, 0, 0, 0, -2, -2, 0, 0, 0, 0, 0, 0, 0
179         };
180         private static final int[] sineCoefficients = new int[] {
181             6288774, 1274027, 658314, 213618, -185116, -114332,
182             58793, 57066, 53322, 45758, -40923, -34720, -30383,
183             15327, -12528, 10980, 10675, 10034, 8548, -7888,
184             -6766, -5163, 4987, 4036, 3994, 3861, 3665, -2689,
185             -2602, 2390, -2348, 2236, -2120, -2069, 2048, -1773,
186             -1595, 1215, -1110, -892, -810, 759, -713, -700, 691,
187             596, 549, 537, 520, -487, -399, -381, 351, -340, 330,
188             327, -323, 299, 294
189         };
190     }
191
192     // aus "Astronomical Algorithms" von Jean Meeus,
193     // Willmann-Bell, Inc., 1998.
194
195     public double mondBreite(double t) {
196         double c = julJahrhunderte(t);
197         double longitude = grad(poly(c, llat.coeffLongitude));
198         double elongation = grad(poly(c, llat.coeffElongation));
199         double solarAnomaly = grad(poly(c, llat.coeffSolarAnomaly));
200         double lunarAnomaly = grad(poly(c, llat.coeffLunarAnomaly));
201         double moonNode = grad(poly(c, llat.coeffMoonNode));
202         double capE = poly(c, llat.coeffCapE);
203         double latitude = 0;
204         for(int i = 0; i < llat.argsLunarElongation.length; ++i) {
205             double x = llat.argsSolarAnomaly[i];
206             latitude += llat.sineCoefficients[i] *
207                 Math.pow(capE, Math.abs(x)) *
208                 sinGrad(    llat.argsLunarElongation[i] * elongation + 
209                     x * solarAnomaly +
210                     llat.argsLunarAnomaly[i] * lunarAnomaly +
211                     llat.argsMoonNode[i] * moonNode);
212         }
213         latitude *= (double) (1) / 1000000;
214         double venus = ((double) (175) / 1000000) * (sinGrad((double) (119.75) + c * 131.849 + moonNode) + sinGrad((double) (119.75) + c * 131.849 - moonNode));
215         double flatEarth = ((double) (-2235) / 1000000) * sinGrad(longitude) +
216             ((double) (127) / 1000000) * sinGrad(longitude - lunarAnomaly) +
217             ((double) (-115) / 1000000) * sinGrad(longitude + lunarAnomaly);
218         double extra = ((double) (382) / 1000000) * sinGrad((double) (313.45) + c * (double) (481266.484));
219         return modulo(latitude + venus + flatEarth + extra, 360);
220     }
221     private static class llat {
222         private static final double[] coeffLongitude = new double[] {218.3164591, 481267.88134236, -0.0013268, 1d/538841, -1d/65194000};
223         private static final double[] coeffElongation = new double[] {297.8502042, 445267.1115168, -0.00163, 1d/545868, -1d/113065000};
224         private static final double[] coeffSolarAnomaly = new double[] {357.5291092, 35999.0502909, -0.0001536, 1d/24490000};
225         private static final double[] coeffLunarAnomaly = new double[] {134.9634114, 477198.8676313, 0.008997, 1d/69699, -1d/14712000};
226         private static final double[] coeffMoonNode = new double[] {93.2720993, 483202.0175273, -0.0034029, -1d/3526000, 1d/863310000};
227         private static final double[] coeffCapE = new double[] {1, -0.002516, -0.0000074};
228         private static final byte[] argsLunarElongation = new byte[] {
229             0, 0, 0, 2, 2, 2, 2, 0, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 4, 0, 0, 0,
230             1, 0, 0, 0, 1, 0, 4, 4, 0, 4, 2, 2, 2, 2, 0, 2, 2, 2, 2, 4, 2, 2,
231             0, 2, 1, 1, 0, 2, 1, 2, 0, 4, 4, 1, 4, 1, 4, 2};
232         private static final byte[] argsSolarAnomaly = new byte[] {
233             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 1, -1, -1, -1, 1, 0, 1,
234             0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 1,
235             0, -1, -2, 0, 1, 1, 1, 1, 1, 0, -1, 1, 0, -1, 0, 0, 0, -1, -2};
236         private static final byte[] argsLunarAnomaly = new byte[] {
237             0, 1, 1, 0, -1, -1, 0, 2, 1, 2, 0, -2, 1, 0, -1, 0, -1, -1, -1,
238             0, 0, -1, 0, 1, 1, 0, 0, 3, 0, -1, 1, -2, 0, 2, 1, -2, 3, 2, -3,
239             -1, 0, 0, 1, 0, 1, 1, 0, 0, -2, -1, 1, -2, 2, -2, -1, 1, 1, -2,
240             0, 0};
241         private static final byte[] argsMoonNode = new byte[] {
242             1, 1, -1, -1, 1, -1, 1, 1, -1, -1, -1, -1, 1, -1, 1, 1, -1, -1,
243             -1, 1, 3, 1, 1, 1, -1, -1, -1, 1, -1, 1, -3, 1, -3, -1, -1, 1,
244             -1, 1, -1, 1, 1, 1, 1, -1, 3, -1, -1, 1, -1, -1, 1, -1, 1, -1,
245             -1, -1, -1, -1, -1, 1};
246         private static final int[] sineCoefficients = new int[] {
247             5128122, 280602, 277693, 173237, 55413, 46271, 32573,
248             17198, 9266, 8822, 8216, 4324, 4200, -3359, 2463, 2211,
249             2065, -1870, 1828, -1794, -1749, -1565, -1491, -1475,
250             -1410, -1344, -1335, 1107, 1021, 833, 777, 671, 607,
251             596, 491, -451, 439, 422, 421, -366, -351, 331, 315,
252             302, -283, -229, 223, 223, -220, -220, -185, 181,
253             -177, 176, 166, -164, 132, -119, 115, 107};
254     }
255   
256     public double arcTanGrad(double x, int quad) {
257         double alpha = bogenmassZuGrad(Math.atan(x));
258         return modulo(quad == 1 || quad == 4 ? alpha : alpha + (double) (180), 360);
259     }
260   
261     public double siderischVonMoment(double t) {
262         double c = (t - j2000()) / 36525;
263         return modulo(poly(c, sfm.siderealCoeff), 360);
264     }
265     private static class sfm {
266         private static final double[] siderealCoeff = new double[] {280.46061837, 36525 * 360.98564736629, 0.000387933, 1d/38710000};
267     }
268
269   /* ----------- Sonnenauf- und -untergang ----------- */
270   
271     public double sonnenaufgang(long date, Ort ort) throws Exception {
272         return morgen(date, ort, alpha(ort));
273     }
274   
275     public double sonnenuntergang(long date, Ort ort)
276         throws Exception
277     {
278         return abend(date, ort, alpha(ort));
279     }
280   
281   public double alpha(Ort ort) {
282         double h = Math.max(0, ort.getHoehe());
283         final double capR = (double) 6.372E+6;
284         double dip = arcKosGrad(capR / (capR + h));
285         return winkel(0, 50, 0) + dip;
286   }
287   
288     public double morgen(long date, Ort ort, double alpha) throws Exception {
289         double approx;
290         try {
291             approx = zeitVonHorizont(date + .25, ort, alpha);
292         } catch(Exception ex) {
293             approx = date;
294         }
295         double result = zeitVonHorizont(approx, ort, alpha);
296         return standardVonLokal(result, ort);
297     }
298     
299     public double abend(long date, Ort ort, double alpha)
300         throws Exception
301     {
302         double approx;
303         try {
304             approx = zeitVonHorizont(date + .75, ort, alpha);
305         } catch(Exception ex) {
306             approx = date + .99d;
307         }
308         double result = zeitVonHorizont(approx, ort, alpha);
309         return standardVonLokal(result, ort);
310     }
311
312     public double zeitVonHorizont(double approx, Ort ort, double alpha) throws Exception {
313         double phi = ort.getBreite();
314         double t = universalVonLokal(approx, ort);
315         double delta = arcSinGrad(sinGrad(obliquity(t)) * sinGrad(solareLaenge(t)));
316         boolean morgen = modulo(approx, 1) < 0.5;
317         double sinusAbstand = tanGrad(phi) * tanGrad(delta) +
318             sinGrad(alpha) / (kosGrad(delta) * kosGrad(phi));
319         double offset = modulo(0.5 + arcSinGrad(sinusAbstand) / (double) 360, 1) - 0.5;
320         if(Math.abs(sinusAbstand) > 1) {
321             throw new Exception();
322         }
323         return lokalVonScheinbar(Math.floor(approx) + (morgen ? .25 - offset : .75 + offset));
324     }
325     
326     public double universalVonLokal(double tl, Ort ort) {
327         return tl - ort.getLaenge() / (double) 360;
328     }
329
330     public double standardVonLokal(double tl, Ort ort) {
331         return standardVonUniversal(universalVonLokal(tl, ort), ort);
332     }
333     
334     public double lokalVonScheinbar(double t) {
335         return t - zeitgleichung(t);
336     }
337
338     public double zeitgleichung(double t) {
339         double c = julJahrhunderte(t);
340         double laenge = poly(c, et.koeffLaenge);
341         double anomalie = poly(c, et.koeffAnomalie);
342         double exzentrizitaet = poly(c, et.koeffExzentrizitaet);
343         double varepsilon = obliquity(t);
344         double y = quadrat(tanGrad(varepsilon / 2));
345         double equation = (1d / 2d / Math.PI) * (y * sinGrad(2 * laenge) +
346         -2 * exzentrizitaet * sinGrad(anomalie) +
347         4 * exzentrizitaet * y * sinGrad(anomalie) * kosGrad(2 * laenge) +
348         -0.5 * y * y * sinGrad(4 * laenge) +
349         -1.25 * exzentrizitaet * exzentrizitaet * sinGrad(2 * anomalie));
350         return signum(equation) * Math.min(Math.abs(equation), stunde(12));
351     }
352     private static class et {
353         private static final double[] koeffLaenge = new double[] {280.46645, 36000.76983, 0.0003032};
354         private static final double[] koeffAnomalie = new double[] {357.52910, 35999.05030, -0.0001559, -0.00000048};
355         private static final double[] koeffExzentrizitaet = new double[] {0.016708617, -0.000042037, -0.0000001236};
356     }
357
358     public double obliquity(double t) {
359         double c = julJahrhunderte(t);
360         return winkel(23, 26, 21.448) + poly(c, coeffObliquity);
361     }
362     private final double[] coeffObliquity = new double[] {0, winkel(0, 0, -46.8150), winkel(0, 0, -0.00059), winkel(0, 0, 0.001813)};
363   
364     public int signum(double x) {
365         if(x < 0)
366             return -1;
367         else if(x > 0)
368             return 1;
369         else
370             return 0;
371     }
372     
373     public double quadrat(double x) {
374         return x * x;
375     }
376
377     public double kosGrad(double theta) {
378         return Math.cos(gradZuBogenmass(theta));
379     }
380
381     public double arcSinGrad(double x) {
382         return bogenmassZuGrad(Math.asin(x));
383     }
384     
385     public double tanGrad(double theta) {
386         return Math.tan(gradZuBogenmass(theta));
387     }
388
389     public double arcKosGrad(double x) {
390         return bogenmassZuGrad(Math.acos(x));
391     }
392     
393     public double bogenmassZuGrad(double theta) {
394         return grad(theta / Math.PI * 180);
395     }
396
397     public double winkel(double d, double m, double s) {
398         return d + (m + s / 60) / 60;
399     }
400   
401   /* ---------------- Jahreszeiten ----- */
402
403     public static final double TROPISCHES_JAHR = 365.242189;
404     
405     public double standardVonUniversal(double t, Ort ort) {
406         return t + ort.getZeitzone() / 24;
407     }
408   
409     public double solareLaengeNach(double t, double phi) {
410         double varepsilon = 0.00001;
411     double rate = TROPISCHES_JAHR / (double) 360;
412         double tau = t + rate * modulo(phi - solareLaenge(t), 360);
413         double l = Math.max(t, tau - 5);
414         double u = tau + 5;
415         
416         double lo = l, hi = u, x = (hi + lo) / 2;
417         while(hi - lo > varepsilon) {
418             if(modulo(solareLaenge(x) - phi, 360) < (double) 180)
419                 hi = x;
420             else
421                 lo = x;
422
423             x = (hi + lo) / 2;
424         }
425         return x;
426     }
427   
428     public double solareLaenge(double t) {
429         double c = julJahrhunderte(t);
430         double sigma = 0;
431         for(int i = 0; i < sLaenge.koeffizienten.length; ++i) {
432             sigma += sLaenge.koeffizienten[i] * sinGrad(sLaenge.multiplikatoren[i] * c + sLaenge.summanden[i]);
433         }
434     double laenge = (double) 282.7771834 +            
435             36000.76953744 * c +
436             0.000005729577951308232 * sigma;
437         return modulo(laenge + aberration(t) + nutation(t), 360);
438     }
439
440     public double julJahrhunderte(double t) {
441         return (dynamischVonUniversal(t) - j2000()) / 36525;
442     }
443
444     public double dynamischVonUniversal(double tee) {
445         return tee + ephemeridenKorrektur(tee);
446     }
447
448     public double ephemeridenKorrektur(double t) {
449     double[] koeffizient17tes = new double[] {196.58333, -4.0675, 0.0219167};
450         double[] koeffizient19tes = new double[] {-0.00002, 0.000297, 0.025184, -0.181133, 0.553040, -0.861938, 0.677066, -0.212591};
451         double[] koeffizient18tes = new double[] {-0.000009, 0.003844, 0.083563, 0.865736, 4.867575, 15.845535, 31.332267, 38.291999, 28.316289, 11.636204, 2.043794};
452     ISOKalender w = new ISOKalender();
453         long jahr = w.jahrVonTagen((long)Math.floor(t));
454         double c = differenz(w.zuTagen(1900, Definition.JANUAR, 1), 
455             w.zuTagen(jahr, Definition.JULI, 1)) / 36525d;
456         double result;
457         if(1988 <= jahr && jahr <= 2019) {
458             result = (jahr - 1933) / (24d * 60 * 60);
459         } else if (1900 <= jahr && jahr <= 1987) {
460             result = poly(c, koeffizient19tes);
461         } else if (1800 <= jahr && jahr <= 1899) {
462             result = poly(c, koeffizient18tes);
463         } else if (1620 <= jahr && jahr <= 1799) {
464             result = poly(jahr - 1600, koeffizient17tes) / (24 * 60 * 60);
465         } else {
466             double x = stunde(12) + differenz(w.zuTagen(1810, Definition.JANUAR, 1), 
467               w.zuTagen(jahr, Definition.JANUAR, 1));
468             return (x * x / 41048480 - 15) / (24 * 60 * 60);
469         }
470         return result;
471     }
472   
473     public double nutation(double t) {
474         double[] koeffa = new double[] {124.90, -1934.134, 0.002063};
475         double[] koeffb = new double[] {201.11, 72001.5377, 0.00057};
476         double c = julJahrhunderte(t);
477         double capA = poly(c, koeffa);
478         double capB = poly(c, koeffb);
479         return (double) -0.004778 * sinGrad(capA) +
480             (double) -0.0003667 * sinGrad(capB);
481     }
482
483     public static long differenz(long datum1, long datum2) {
484         return datum2 - datum1;
485     }
486   
487     public double stunde(double x) {
488         return x / 24;
489     }
490   
491   public double j2000() {
492     ISOKalender w = new ISOKalender();
493     return stunde(12) + w.zuTagen(2000, Definition.JANUAR, 1);
494   }
495   
496     public double sinGrad(double theta) {
497         return Math.sin(gradZuBogenmass(theta));
498     }
499
500     public double gradZuBogenmass(double theta) {
501         return grad(theta) * Math.PI / 180;
502     }
503
504     public double grad(double theta) {
505         return modulo(theta, 360);
506     }
507
508     public double aberration(double t) {
509         double c = julJahrhunderte(t);
510     return (double) 0.0000974 * gradKosinus((double) 177.63 + (double) 35999.01848 * c) - (double) 0.005575;
511     }
512
513     public double gradKosinus(double theta) {
514         return Math.cos(gradZuBogenmass(theta));
515     }
516
517     public double poly(double x, double[] a) {
518         double ergebnis = a[0];
519         for(int i = 1; i < a.length; ++i) {
520             ergebnis += a[i] * Math.pow(x, i);
521         }
522         return ergebnis;
523     }
524   
525     private static class sLaenge {
526         private static final int[] koeffizienten = new int[] {
527             403406, 195207, 119433, 112392, 3891, 2819, 1721,
528             660, 350, 334, 314, 268, 242, 234, 158, 132, 129, 114,
529             99, 93, 86, 78, 72, 68, 64, 46, 38, 37, 32, 29, 28, 27, 27,
530             25, 24, 21, 21, 20, 18, 17, 14, 13, 13, 13, 12, 10, 10, 10,
531             10
532         };
533         private static final double[] multiplikatoren = new double[] {
534             0.9287892, 35999.1376958, 35999.4089666,
535             35998.7287385, 71998.20261, 71998.4403,
536             36000.35726, 71997.4812, 32964.4678,
537             -19.4410, 445267.1117, 45036.8840, 3.1008,
538             22518.4434, -19.9739, 65928.9345,
539             9038.0293, 3034.7684, 33718.148, 3034.448,
540             -2280.773, 29929.992, 31556.493, 149.588,
541             9037.750, 107997.405, -4444.176, 151.771,
542             67555.316, 31556.080, -4561.540,
543             107996.706, 1221.655, 62894.167,
544             31437.369, 14578.298, -31931.757,
545             34777.243, 1221.999, 62894.511,
546             -4442.039, 107997.909, 119.066, 16859.071,
547             -4.578, 26895.292, -39.127, 12297.536,
548             90073.778
549         };
550         private static final double[] summanden = new double[] {
551             270.54861, 340.19128, 63.91854, 331.26220,
552             317.843, 86.631, 240.052, 310.26, 247.23,
553             260.87, 297.82, 343.14, 166.79, 81.53,
554             3.50, 132.75, 182.95, 162.03, 29.8,
555             266.4, 249.2, 157.6, 257.8, 185.1, 69.9,
556             8.0, 197.1, 250.4, 65.3, 162.7, 341.5,
557             291.6, 98.5, 146.7, 110.0, 5.2, 342.6,
558             230.9, 256.1, 45.3, 242.9, 115.2, 151.8,
559             285.3, 53.3, 126.6, 205.7, 85.9,
560             146.1
561         };
562     } 
563 }