package AstroOL; import java.util.*; /** Die Klasse LowPrecCalculator ergänzt die Klasse Calculator um explizite Methoden zur Berechnung der Planeten und Häuser. Die Berechnungen, die von der Calculator-Klasse normalerweise mittels eines Servlets im Backend ausgeführt werden, sind im LowPrecCalculator konkret ausprogrammiert. <p> Wie Calculator hat auch LowPrecCalculator den Zweck, astrologische Berechnungen effizient durchzuführen. Sie ist jedoch als Standalone Version gedacht, die auch offline verwendbar ist.- Um sie dennoch kompakt und schnell zu halten, wurde von den hohen Genauigkeitsansprüchen der Swiss Ephemeris abgerückt: Der LowPrecCalculator rechnet Planetenstände auf die Bogenminute genau, nur die Sonne ist auf die Bogensekunde genau, so dass auch Solarberechnungen möglich sind. <p> LowPrecCalculator erbt von Calculator, so dass keine doppelte Logik programmiert werden musste. Die meisten Hilfsfunktionen existierten bereits in der Nachfolgefunktion oder konnten leicht in diese übernommen werden. @see <a href="./doc-files/LowPrecCalculator.html">Datenmodell und die Kompressionsmethode des LowPrecCalculator</a> */ public class LowPrecCalculator extends Calculator implements ICalculator { /** Umwandlungsfaktor Sternzeit in Weltzeit */ public static final double ST_UT = .10027379093e1; /** Reziprokwert der Lichtgeschwindigkeit in d/AE */ public static final double cInvers = .57755183044121e-2; /** Naibodschlüssel (mittlere Bewegung der Sonne am Tag) */ public static final double naibod = .9856473e0; /** Gibt an, ob Aberration und Lichtlaufzeit berücksichtigt werden sollen. Ist es gesetzt, so werden Aberration und Lichtlaufzeit nicht berücksichtigt. Man erhält die geometrischen Planetenpositionen */ public static boolean geometric = false; /** Verwendetes Häusersystem. */ public static byte hSystem = Mundan.PLACIDUS; /** Julianisches Datum der Instanz (in Ephemeridenzeit) */ public double xjd; /** Weltzeit der Instanz */ public double ut; /** Geographische Länge der Instanz (in Grad). Östliche Längen werden positiv, westliche negativ gerechnet. */ public double lon = 8.55; /** Geographische Breite der Instanz (in Grad). Nördliche Breiten werden positiv, südliche negativ gerechnet. */ public double lat = 47.366; /** Rektaszension des Medium Coeli (RAMC) in Grad. Dies ist derselbe Wert wie die in Grad umgerechnete Ortssternzeit (LST) */ public double ramc; /** Schiefe der Ekliptik zur Instanz in Grad */ public double ee; /** Häuserspitzen. Es ist <table align="center"> <tr><td>h[1] </td><td>= Aszendent,</td></tr> <tr><td>h[4] </td><td>= I.C.,</td></tr> <tr><td>h[7] </td><td>= Deszendent,</td></tr> <tr><td>h[10] </td><td>= M.C.,</td></tr> <tr><td>h[i] </td><td>= i. Häuserspitze</td></tr> </table> in der in der Astrologie üblichen Zählweise. */ public double h[]; /** Ekliptikale Längen der Planeten. Die Indizierung entspricht der Reihenfolge (mit 0 = SO beginnend) im String {@link Calculator#pknam Calculator.pknam}. */ public double pl[]; /** Ekliptikale Breiten der Planeten. Die Indizierung entspricht der Reihenfolge (mit 0 = SO beginnend) im String {@link Calculator#pknam Calculator.pknam}. */ public double pb[]; /** Der leere Konstruktor instanziiert zum aktuellen Datum. Als Ort wird Zürich zugrundegelegt */ public LowPrecCalculator() { xjd = thisjd(); construct(); } /** Konstruktor mit Julianischem Datum, geographischer Länge und Breite @param xjd Julianisches Datum in ET @param lon Geographische Länge @param lat Geographische Breite */ public LowPrecCalculator(double xjd, double lon, double lat) { this.xjd = xjd; this.lon = lon; this.lat = lat; construct(); } /** Konstruktor mit Zeit/Ort String. @param in Eingabestring für Datum, Uhrzeit und Ort. Zum Format des Strings siehe die Methode {@link Calculator#parseTimePlace(String,double[]) Calculator.parseTimePlace()} */ public LowPrecCalculator(String in) { double[] tp = new double[3]; if (!in.equals("") && !in.equalsIgnoreCase("now") && parseTimePlace(in,tp)) { lon = tp[1]; lat = tp[2]; xjd = tp[0]; } else xjd = thisjd(); construct(); } /** Berechnung der Häuser und Planeten. Diese Methode wird aus dem Konstruktor aufgerufen */ private void construct() { pl = new double[10]; pb = new double[10]; h = new double[13]; construct(pl,pb,h); } private void construct(double[] pl, double[] pb, double[] h) { byte i; double[][] lbr = new double[10][3]; Mundan m; compute(xjd, lbr); for (i = 0; i < 10; i++) { pl[i] = lbr[i][0]; pb[i] = lbr[i][1]; } ut = (xjd + .5 - Math.floor(xjd + .5) - deltat(xjd))*24; ee = tilt(); ramc = lst(); m = new Mundan( ramc, lat, ee, hSystem); for (i = 0; i < 12; i++) h[i+1] = m.hauslaenge(i*30d); } /** Implementierung der Methode ICalculator.getPlanetsAndHouses() */ public boolean getPlanetsAndHouses( double iXjd, double iLon, double iLat, double[] cPl, double[] cH) { this.xjd = iXjd; this.lon = iLon; this.lat = iLat; pb = new double[10]; pl = cPl; h = cH; construct(pl,pb,h); return true; } /** Leere Implementierung, da diese Klasse kein Backend benötigt */ public void setServletURL(String iServletURL) { } /** Korrektur zur Umrechnung Weltzeit (UT) in Ephemeridenzeit (ET). Es wird eine Nährungsformel von Stephenson und Morrison (Sun and Planetary System vol. 96 (1982), p.73) verwendet. Es gilt ET = UT + Delta T. @param xjd Julianisches Datum @return Korrektur in Tagen */ public static double deltat(double xjd) { return 2.81961082534138505e-13 * (-2.406934851e6+xjd) * (-2.357307148e6+xjd) ; } /** Ausgabe der Attribute einer Calculator-Instanz */ public String toString() { StringBuffer s = new StringBuffer(); s.append("Julianisches Datum: " + Double.toString(xjd) + "\n"); int[] ymd = calendarDate(xjd); s.append("Kalenderdatum: " + ymd[2]+"."+ymd[1]+"."+ymd[0] + "\n"); s.append("Geographische Laenge: " + dms(lon,LONG) + "\n"); s.append("Geographische Breite: " + dms(lat,LAT) + "\n"); s.append("Aszendent: " + dms(h[1],ECL | SEC) + "\n"); s.append("Medium Coeli: " + dms(h[10],ECL | SEC) + "\n"); s.append("Haus 2: " + dms(h[2],ECL | SEC) + "\n"); s.append("Haus 3: " + dms(h[3],ECL | SEC) + "\n"); s.append("Haus 11: " + dms(h[11],ECL | SEC) + "\n"); s.append("Haus 12: " + dms(h[12],ECL | SEC) + "\n"); for ( int i = 0; i < 10; i++ ) s.append(pknam.substring(2*i,2*i+2) + ": " + dms(pl[i]) + "\n"); return s.toString(); } /** Bogensekundengenaue Sonnenposition nach einer Reihenentwicklung von S. Newcomb. @param jd Julianisches Datum in Ephemeridenzeit @return Polarkoordinaten der Sonne (Länge, Breite, Radius) in dieser Reihenfolge */ public static double[] newcomb (double jd) { double t,t1,dlp,l0,l01,g,g2,g4,g5,g6,d,a_,u,dl,r0,dl2,dl4,dl5,dl6; double dlm,l,dr2,dr4,dr5,dr6,drm,r,lx,bx,rx; double lbr[] = { 0.,0.,0. }; t1 = jd - (double)2415020.; t = t1/(double)36525.; /*c --- long periodic disturbation */ dlp = ((double)1.882e0-(double).016*t)* sin((double)57.24 + (double)150.27*t) + (double) 6.4 *sin(231.19e0 + 20.20*t) + (double)0.266 *sin( 31.8e0 + 119.00*t); /*c --- mean longitude sun */ l0 = 279.6966778e0 + 360.*fract(t1/(double)365.25); l01 = 2768.13*t + 1.089*t*t + 0.202*sin(315.6e0+893.3*t)+dlp; l0 = l0 + l01/3600.e0; /*c --- mean anomaly sun */ g = 358.475833e0 + 360.e0*fract(t1*(double).0027104722792607802874743) + t1*(double).009828884325804243668 + ( 179.1*t - .54*t*t + dlp )/3600.e0; /*c --- mean anomaly venus,mars,jupiter,saturn */ g2 = 212.45e0 + 360.*fract(t1*(double).004435318275154004107) + t1*(double).0054070636650308; g4 = 319.58e0 + t1*(double).524024010951403; g5 = 225.28e0 + t1*(double).0830823545516769336 + (double).3611111111111111111* sin(133.775e0 + 39.804*t); g6 = 175.6e0 + t1*(double).03345089664613278576; /*c --- moon data */ d = 350.737486e0 + t1*(double).00840832900752909 + 360.*fract(t1*(double).033839835728952772); a_ = 296.104608e0 + t1*(double).005444191868583162 + 360.*fract(t1*(double).0362765229295003422); u = 11.250889e0 + t1*(double).00224572621492128 + 360.*fract(t1*(double).03674195756331279945); /*c --- terms of two body motion */ dl = (6910.057e0 - 17.240e0*t)*sin( g ) + ( 72.338e0 - .361e0*t)*sin(2.e0*g) + 1.054e0*t *sin(3.e0*g ); r0 = ( .00003057e0 - 0.00000015*t) + (-.00727412e0 + 0.00001814*t)*cos( g ) + (-.00009138e0 + 0.00000046*t)*cos( 2.e0*g ) - 0.00000145 *cos( 3.e0*g ); /*c --- perturbations in longitude */ dl2 = 4.838*cos(299.102e0 + g2 - g) + 0.116*cos(148.900e0 + 2.*g2 - g) + 5.526*cos(148.313e0 + 2.*g2 - 2.*g) + 2.497*cos(315.943e0 + 2.*g2 - 3.*g) + 0.666*cos(177.710e0 + 3.*g2 - 3.*g) + 1.559*cos(345.243e0 + 3.*g2 - 4.*g) + 1.024*cos(318.150e0 + 3.*g2 - 5.*g) + 0.210*cos(206.200e0 + 4.*g2 - 4.*g) + 0.144*cos(195.400e0 + 4.*g2 - 5.*g) + 0.152*cos(343.800e0 + 4.*g2 - 6.*g) + 0.123*cos(195.300e0 + 5.*g2 - 7.*g) + 0.154*cos(359.600e0 + 5.*g2 - 8.*g); /*c */ dl4 = 0.273*cos(217.700e0 - g4 + g) + 2.043*cos(343.888e0 - 2.*g4 + 2.*g) + 1.770*cos(200.402e0 - 2.*g4 + g) + 0.129*cos(294.200e0 - 3.*g4 + 3.*g) + 0.425*cos(338.800e0 - 3.*g4 + 2.*g) + 0.500*cos(105.180e0 - 4.*g4 + 3.*g) + 0.585*cos(334.060e0 - 4.*g4 + 2.*g) + 0.204*cos(100.800e0 - 5.*g4 + 3.*g) + 0.154*cos(227.400e0 - 6.*g4 + 4.*g) + 0.101*cos( 96.300e0 - 6.*g4 + 3.*g) + 0.106*cos(222.700e0 - 7.*g4 + 4.*g); /*c */ dl5 = 0.163*cos(198.600e0 - g5 + 2.*g) + 7.208*cos(179.532e0 - g5 + g) + 2.600*cos(263.217e0 - g5 ) + 2.731*cos( 87.145e0 - 2.*g5 + 2.*g) + 1.610*cos(109.493e0 - 2.*g5 + g) + 0.164*cos(170.500e0 - 3.*g5 + 3.*g) + 0.556*cos( 82.650e0 - 3.*g5 + 2.*g) + 0.210*cos( 98.500e0 - 3.*g5 + g); /*c */ dl6 = 0.419*cos(100.580e0 - g6 + g) + 0.320*cos(269.460e0 - g6 ) + 0.108*cos(290.600e0 - 2.*g6 + 2.*g) + 0.112*cos(293.600e0 - 2.*g6 + g); /*c */ dlm = 6.454*sin(d) + 0.177*sin(d+a_) - 0.424*sin(d-a_) + 0.172*sin(d-g); /*c c --- now sum up to true longitude c */ l = dl + dl2 + dl4 + dl5 + dl6 + dlm ; lbr[0] = fmod(l/.36e4 + l0,.36e3); /*c c --- ecliptical latitude c */ bx= -0.210*cos(151.800e0 + 3.*g2 - 4.*g ) -0.166*cos(265.500e0 - 2.*g5 + g ) +0.576*sin(u); lbr[1] = bx/3600.; /*c c --- radius vector c */ dr2 = 2359*cos(209.080 + g2 - g) + 160*cos( 58.400 + 2*g2 - g) + 6842*cos( 58.318 + 2*g2 - 2*g) + 869*cos(226.700 + 2*g2 - 3*g) + 1045*cos( 87.570 + 3*g2 - 3*g) + 1497*cos(255.250 + 3*g2 - 4*g) + 194*cos( 49.500 + 3*g2 - 5*g) + 376*cos(116.280 + 4*g2 - 4*g) + 196*cos(105.200 + 4*g2 - 5*g) + 163*cos(145.400 + 5*g2 - 5*g) + 141*cos(105.400 + 5*g2 - 7*g); /*c */ dr4 = 150*cos(127.700 - g4 + g) + 2057*cos(253.828 - 2*g4 + 2*g) + 151*cos(295.000 - 2*g4 + g) + 168*cos(203.500 - 3*g4 + 3*g) + 215*cos(249.000 - 3*g4 + 2*g) + 478*cos( 15.170 - 4*g4 + 3*g) + 105*cos( 65.900 - 4*g4 + 2*g) + 107*cos(324.600 - 5*g4 + 4*g) + 139*cos(137.300 - 6*g4 + 4*g); /*c */ dr5 = 208*cos(112.000 - g5 + 2*g) + 7067*cos( 89.545 - g5 + g) + 244*cos(338.600 - g5 ) + 103*cos(350.500 - 2*g5 + 3*g) + 4026*cos(357.108 - 2*g5 + 2*g) + 1459*cos( 19.467 - 2*g5 + 1*g) + 281*cos( 81.200 - 3*g5 + 3*g) + 803*cos(352.560 - 3*g5 + 2*g) + 174*cos( 8.600 - 3*g5 + 1*g) + 113*cos(347.700 - 4*g5 + 2*g); /*c */ dr6 = 429*cos( 10.600 - g6 + g) + 162*cos(200.600 - 2*g6 + 2*g) + 112*cos(203.100 - 2*g6 + g); /*c */ drm =13360*cos(d) + 370*cos(d+a_) - 1330*cos(d-a_) - 140*cos(d+g) + 360*cos(d-g); r = r0 + 1.e-9*(dr2+dr4+dr5+dr6+drm); lbr[2] = Math.pow(0.1e2,r); return lbr; } /** Mondephemeride nach Brown. Es wird die Mondposition zur Ephemeridenzeit jd berechnet. Das Resultat ist in Länge auf 1-2 Bogenminuten genau. @param jd Julianisches Datum in ET (Ephemeridenzeit) @return Mondposition in Polarkoordinaten (Länge, Breite, Radiusvektor) */ public static double[] brown (double jd) { double w,xnut_,day,xl,yl,xp,yp,xn,al,bl,ap,bp,an, u,v,f,d,dl,e; double lbn[] = { 0., 0., 0. }; w=(jd-2415020.e0)/36525.e0; xnut_ = -17.2327/1296000.*Math.sin((259.18-1934.142*w)*toRad); day=jd-2415020.e0; xl=.751206e0 +day*.0366011014634e0; yl=.776935e0 +day*.0027379092649e0; xp=.928693e0 +day*.0003094557786e0; yp=.781169e0 +day*.0000001307457e0; xn=.719954e0 -day*.0001470942283e0; al=fract(xl)*2*Math.PI; bl=fract(yl)*2*Math.PI; ap=fract(xp)*2*Math.PI; bp=fract(yp)*2*Math.PI; an=fract(xn)*2*Math.PI; u=al-ap; v=bl-bp; f=al-an; d=al-bl; dl=22639*Math.sin(u)-4586*Math.sin(u-d-d)+2370*Math.sin(d+d)+769*Math.sin(u+u) -668*Math.sin(v)-412*Math.sin(f+f)-212*Math.sin(u+u-d-d)-206*Math.sin(u+v-d-d) +192*Math.sin(u+d+d)-165*Math.sin(v-d-d)+148*Math.sin(u-v)-125*Math.sin(d) -110*Math.sin(u+v)-55*Math.sin(f+f-d-d)-45*Math.sin(u+f+f)+40*Math.sin(u-f-f) -38*Math.sin(u-4*d)+36*Math.sin(3*u)-31*Math.sin(u+u-4*d)+28*Math.sin(u-v-d-d) -24*Math.sin(v+d+d)+19*Math.sin(u-d)+18*Math.sin(v+d)+15*Math.sin(u-v+d+d) +14*Math.sin(4*d)+14*Math.sin(u+u+d+d)-13*Math.sin(3*u-d-d); xl += dl/1296000.+xnut_; lbn[0] = fract(xl)*360.e0; lbn[1] = (18461*Math.sin(f)+1010*Math.sin(u+f)-1000*Math.sin(f-u) -624*Math.sin(f-2*d)-167*Math.sin(u+f-d-d)+199*Math.sin(f-u+d+d) +117*Math.sin(f+d+d)+62*Math.sin(u+u+f)-33*Math.sin(f-u-d-d) -32*Math.sin(f-u-u)-30*Math.sin(v+f-d-d)-16*Math.sin(u+u+f-d-d) +15*Math.sin(u+f+d+d)+12*Math.sin(f-v-d-d)+9*Math.sin(f-u-v+d+d))/3600.; lbn[2] = fmod(an/6.28318531,1.e0)*360.e0; return lbn; } /** Löst das Keplerproblem. Im Array elements[] werden die Bahnelemente sowie ein Korrekturterm für den Radiusvektor übergeben. Als Rückgabewert erhält man einen Array mit den Polarkoordinaten der Lösung des Keplerproblems. @param elements Bahnelemente. Übergeben werden <table> <tr><td>Grosse Halbachse</td><td><code>= elements[0]</code></td></tr> <tr><td>Exzentrizität </td><td><code>= elements[1]</code></td></tr> <tr><td>Bahnneigung </td><td><code>= elements[2]</code></td></tr> <tr><td>Aufst. Knoten </td><td><code>= elements[3]</code></td></tr> <tr><td>Perhihellänge </td><td><code>= elements[4]</code></td></tr> <tr><td>Mittl. Anomalie </td><td><code>= elements[5]</code></td></tr> <tr><td>Tagesbewegung </td><td><code>= elements[6]</code></td></tr> <tr><td>Korrektur für r </td><td><code>= elements[7]</code></td></tr> </table> */ public static double[] kepler ( double[] elements ) { boolean firstTime = true; double lbr[] = { 0., 0., 0. }; double m = elements[5]*toRad; double inc1 = elements[2]*toRad; double omega1 = elements[4]*toRad; double node1 = elements[3]*toRad; double denom,e0,e,u; e0 = m; e = 0; /*1*/ while ( ( Math.abs(e-e0) > 1.e-7 ) || firstTime ) { firstTime = false; e = e0; denom = elements[1]*Math.cos(e)-1.; e0 = e - (m-e+elements[1]*Math.sin(e))/denom; } u = Math.sqrt((1.+elements[1])/(1.-elements[1]))*Math.sin(e/2.); u = Math.atan2(u,Math.cos(e/2.))*2.; u = u + omega1 - node1; u = fmod(u,2*Math.PI); lbr[2] = elements[0]*(1.-elements[1]*Math.cos(e)); lbr[1] = Math.asin(Math.sin(u)*Math.sin(inc1))*toDeg; lbr[0] = Math.atan2(Math.sin(u)*Math.cos(inc1),Math.cos(u)) + node1; lbr[0] = fmod(lbr[0]*toDeg, 360.); return lbr; } /** Berechnet die Nutationskorrektur, die an die geozentrischen Längen zur mittleren Ekliptik des Datums anzubringen ist, um die sogenannten wahren Längen zu bekommen @param jd Julianisches Datum @return Nutationskorrektur in Grad */ public static double nutation( double jd ) { double t,lm,m,an,ls,ms,nut; t = (jd - .2451545e7)/.36525e5; lm = 218.316 + .481267881e6*t; m = 134.963 + .477198867e6*t; an = 125.045 - .1934136e4*t; ls = 280.466 + .36000770e5*t; ms = 357.528 + .35999050e5*t; nut = - .172e2*Math.sin(an*toRad) -.1319e1*Math.sin(2*ls*toRad) - .227e0*Math.sin(2*lm*toRad) +.2060e0*Math.sin(2*an*toRad) + .143e0*Math.sin(ms*toRad) +.071e0*Math.sin(m*toRad); return nut/3600.; } /** Berechnet die Nutationskorrektur, die an die geozentrischen Längen zur mittleren Ekliptik des Datums anzubringen ist, um die sogenannten wahren Längen zu bekommen. <p>Dies ist die Instanzmethode nutation(). Sie berechnet die Korrektur für das Julianische Datum der Instanz. @return Nutationskorrektur in Grad */ public double nutation() { return nutation(xjd); } /** Mittlere Schiefe der Ekliptik berechnen. @param jd Julianisches Datum @return Mittlere Schiefe der Ekliptik in Grad */ public static double tilt( double jd) { return .2343929166e2-.4682e2*(jd-.2451545e7)/.36525e5/.36e4; } /** Instanzmethode zur Berechnung der Schiefe der Ekliptik. Es wird das Datum der Instanz zugrundegelegt. @return Mittlere Schiefe der Ekliptik in Grad */ public double tilt() { return tilt( xjd ); } /** Greenwich Sternzeit (in Grad, also die RAMC) um 0h Weltzeit berechnen. @param jd Julianisches Datum @return RAMC */ public static double gst0(double jd) { double t,y,rc; y = Math.floor(jd-.5)+.5; t = (y-2451545.)/36525.; rc = ((-.0000062*t + .093104)*t +184.812866)*t ; rc = 6.697374558 +24.*(100.*t-Math.floor(100.*t)) + rc/3600.; return( fmod(rc*15.,360.)); } /** RAMC aus: <ul> <li>Greenwich-Sternzeit um 0 Uhr, <li>Weltzeit und <li>östl. Länge </ul> berechnen. @param st0 Greenwich-Sternzeit (RAMC) um 0 Uhr Weltzeit, z.B. mit der Methode {@link #gst0(double) gst0()} berechnet. @param ut Weltzeit in Stunden @param laenge geographische Länge in Grad @return Ortssternzeit in Grad ( = RAMC ) */ public static double lst(double st0, double ut, double laenge) { double x; x=st0 +ut*ST_UT*15.; x+= laenge; return (fmod(x,360d)); } /** Instanzmethode zur Methode {@link LowPrecCalculator#lst(double,double,double) lst(st0,ut,laenge)}. Es werden das Datum (xjd) und die Weltzeit (ut) der Instanz zugrundegelegt. @return Ortssternzeit in Grad ( = RAMC ). */ public double lst() { return lst( gst0(xjd), ut, lon ); } /** Cartesische in Polarkoordinaten umwandeln. */ public static double[] carpo ( double[] car ) { double rho; double[] lbr = new double[3]; lbr[2] = Math.sqrt( car[0]*car[0] + car[1]*car[1] + car[2]*car[2] ); rho = Math.sqrt(car[0]*car[0] + car[1]*car[1]); if (rho == 0.) { lbr[0] = 0.; if (car[2] > 0.) lbr[1] = 90; if (car[2] < 0.) lbr[1] = -90; if (car[2] == 0.) lbr[1] = 0; } else { lbr[1] = Math.atan2(car[2],rho)*toDeg; lbr[0] = 2.*Math.atan2(car[1],fabs(car[0])+rho)*toDeg; if (car[0] < 0.) lbr[0] = 180 - lbr[0]; else if (car[1] < 0) lbr[0] += 360.; } return lbr; } public static double[] pocar (double[] lbr) { double[] car = new double[3]; car[0] = lbr[2]*Calculator.cos(lbr[1])*Calculator.cos(lbr[0]); car[1] = lbr[2]*Calculator.cos(lbr[1])*Calculator.sin(lbr[0]); car[2] = lbr[2]*Calculator.sin(lbr[1]); return car; } /** Ekliptikale in aequatoriale Koordinaten umwandeln */ public static double[] ekq ( double e, double[] lb ) { double[] rd = new double[2]; e *= toRad; // Ekliptikschiefe in Bogenmass umrechnen rd[1] = Math.asin (Math.sin(e)*Math.cos(lb[1]*toRad)*Math.sin(lb[0]*toRad) + Math.cos(e)*Math.sin(lb[1]*toRad))*toDeg; rd[0] = Math.atan2( Math.cos(e)*Math.cos(lb[1]*toRad)*Math.sin(lb[0]*toRad)-Math.sin(e) * Math.sin(lb[1]*toRad), Math.cos(lb[1]*toRad)*Math.cos(lb[0]*toRad) )*toDeg; if (rd[0] < 0) rd[0] += .36e3; return rd; } /** Aequatoriale in ekliptikale Koordinaten umrechnen */ public static double[] qek ( double e, double rd[] ) { double[] lb = new double[2]; e *= toRad; // Ekliptikschiefe in Radiant umrechnen (lokale Giltigkeit) lb[1] = Math.asin (-Math.sin(e)*Math.cos(rd[1]*toRad)*Math.sin(rd[0]*toRad) + Math.cos(e)*Math.sin(rd[1]*toRad))*toDeg; lb[0] = Math.atan2( Math.cos(e)*Math.cos(rd[1]*toRad)*Math.sin(rd[0]*toRad)+Math.sin(e) * Math.sin(rd[1]*toRad), Math.cos(rd[1]*toRad)*Math.cos(rd[0]*toRad) )*toDeg; if (lb[0] < 0) lb[0] += .36e3; return lb; } /** Die Längen der zehn astrologischen Planeten errechnen. Die Genauigkeit der Methode liegt im Bereich von 1 Bogenminute. @param jd Julianisches Datum @return Array mit den zehn geozentrischen Planetenlängen. Die Reihenfolge entspricht der Reihenfolge der Planeten in der globalen Konstante {@link Calculator#pknam Calculator.pknam} */ public static double[] compute ( double jd ) { double planet[] = new double[10]; double[][] lbr = new double[10][3]; compute( jd, lbr ); for ( byte i = 0; i < 10; i++ ) planet[i] = lbr[i][0]; return planet; } /** Die vollständigen geozentrischen Polarkoordinaten der zehn astrologischen Planeten errechnen. Die Genauigkeit der Methode liegt im Bereich von 1 Bogenminute. @param jd Julianisches Datum @param lbr Zweidimensionaler Array mit den Ergebnissen. Der erste Index entspricht der Nummer des Planeten in der globalen Konstante {@link Calculator#pknam Calculator.pknam}. Der zweite Index zählt die drei Polarkoordinaten durch, in der Reihenfolge Länge, Breite, Distanz in AE. */ public static void compute( double jd, double[][] lbr) { byte i; double nut, dist; double lbrHelio[], lbrEarth[] = {0.,0.,0.}, elements[] = new double[8]; /* Sonnenkoordinaten */ lbr[0] = newcomb(jd); /* Nutationskorrektur (und Lichtlaufzeit) für Sonne */ nut = nutation(jd); lbr[0][0] += nut - (geometric ? 0 : 20.81/3600.); lbrEarth[0] = fmod(180. + lbr[0][0],360.); lbrEarth[1] = - lbr[0][1]; lbrEarth[2] = lbr[0][2]; /* Mond (brown macht schon Nutationskorrektur) */ lbr[1] = brown( jd ); for (i=2;i<=9;i++) { /* Grosse Halbachse = elements[0]; Exzentrizität = elements[1]; Bahnneigung = elements[2]; Aufst. Knoten = elements[3]; Perihellänge = elements[4]; Mittlere Anomalie = elements[5]; Tagesbewegung = elements[6]; Korrekturfaktor r = elements[7]; */ /* Bahnelemente errechnen */ Elements.get( jd, i, elements ); /* Lichtlaufzeit-Korrektur für Planeten */ if (!geometric) { // 1) Näherungsweisen Abstand berechnen dist = Math.sqrt(1+elements[0]*(elements[0]-2*Calculator.cos(elements[4]+elements[5]-lbrEarth[2]))); // 2) Mittlere Anomalie vor Eingang ins Keplerproblem um Lichtlaufzeit verringern elements[5] -= elements[6] * dist * cInvers; } /* Keplerproblem lösen */ lbrHelio = kepler ( elements ); /* Für Jupiter ... Pluto: Korrekturfaktor deltaR */ if (i >= 5) lbrHelio[2] *= 1 + elements[7]/10000.; /* Umwandlung in geozentrische Koordinaten */ /* Aberration inbegriffen */ lbr[i] = helge(lbrHelio,lbrEarth); /* Nutation */ lbr[i][0] += nut; } } /** Umrechnung von heliozentrisch auf geozentrisch. Alle Positionen sind in <em>Polarkoordinaten</em> anzugeben. Diese werden in einem Array in der Form { Länge, Breite, Distanz } übergeben. <p>Ist das Flag {@link LowPrecCalculator#geometric geometric} abgeschaltet (Default), so so wird an dieser Stelle auch die Aberration (<em>nicht die Lichtlaufzeit</em>) berücksichtigt, wobei näherungsweise die mittlere Erdgeschwindigkeit (Naibodbogen) verwendet wird. @param lbrHelio Heliozentrische Position des Objekts @param lbrEarth Heliozentrische Position der Erde @return Geozentrische Position des Objekts */ public static double[] helge (double[] lbrHelio, double[] lbrEarth) { double h1,h2,h3,a; double[] lbrGeo = new double[3]; /* Berechne den kartesischen geozentrischen Positionsvektor (h1,h2,h3) */ h1 = lbrHelio[2]*Math.cos(lbrHelio[1]*toRad)*Math.cos(lbrHelio[0]*toRad)-lbrEarth[2]*Math.cos(lbrEarth[1]*toRad)*Math.cos(lbrEarth[0]*toRad); h2 = lbrHelio[2]*Math.cos(lbrHelio[1]*toRad)*Math.sin(lbrHelio[0]*toRad)-lbrEarth[2]*Math.cos(lbrEarth[1]*toRad)*Math.sin(lbrEarth[0]*toRad); h3 = lbrHelio[2]*Math.sin(lbrHelio[1]*toRad) - lbrEarth[2]*Math.sin(lbrEarth[1]*toRad); /* Aberration */ lbrGeo[2] = Math.sqrt(h1*h1+h2*h2+h3*h3) ; a = lbrEarth[2] * lbrGeo[2] * naibod * cInvers * toRad; if (!geometric) { h1 -= Math.sin( lbrEarth[0]*toRad ) * a ; h2 += Math.cos( lbrEarth[0]*toRad ) * a ; } /* Cartesisch in Polar umrechnen */ lbrGeo[0] = Math.atan2(h2,h1); lbrGeo[0] = fmod(lbrGeo[0],2*Math.PI); lbrGeo[1] = Math.atan2(h3,h2/Math.sin(lbrGeo[0])); lbrGeo[0] = lbrGeo[0] * toDeg; lbrGeo[1] = lbrGeo[1] * toDeg; return lbrGeo; } } // class LowPrecCalculator