package AstroOL; import AstroOL.Calculator; import java.util.*; import java.io.*; import swisseph.*; /** Die Klasse Horoskop verwaltet die mit einem Horoskop verbundenen Informationen und bietet Methoden zum Berechnen, Laden und Speichern von Horoskopen und aus diesen abgeleiteten Informationen (z.B. einer Aspekttafel). */ public class Horoscope { /** Festwert für Zeitbestimmung aus der Länge des Medium Coeli */ public static final char timeSpecMediumCoeli = 'm'; /** Festwert für Zeitbestimmung aus der Länge des Aszendenten */ public static final char timeSpecAscendent = 'a'; /** Festwert für Zeitbestimmung: Sternzeit */ public static final char timeSpecSiderealTime = 's'; /** Festwert für Zeitbestimmung: RAMC */ public static final char timeSpecRAMC = 'r'; /** Festwert für Zeitbestimmung: Weltzeit (U.T. oder GMT) */ public static final char timeSpecUniversalTime = 'u'; /** Festwert für Zeitbestimmung: Ephemeridenzeit (E.T.) */ public static final char timeSpecEphemerisTime = 'e'; /** Festwert für Zeitbestimmung: Mittlere Ortszeit */ public static final char timeSpecLocalMeanTime = 'l'; /** Festwert für Zeitbestimmung: Wahre Ortszeit */ public static final char timeSpecTrueLocalTime = 'w'; /** Festwert für Zeitbestimmung: Temporalstunden. Die klassische Zeitrechnung basierte auf ungleich langen Stunden am Tage und in der Nacht, entsprechend dem Tag- und Nachtbogen der Sonne. Die Zeitbestimmung gemäß Temporalstunden ist so geeicht, daß die Uhrzeit 12 Uhr immer dem Sonnenauf- und 0 Uhr dem Sonnenuntergang entspricht. */ public static final char timeSpecTemporalHours = 'h'; /** Festwert für Zeitbestimmung aus der Länge der Sonne (Solarhoroskop). Es wird ab dem angegebenen Datum nach der Zeit gesucht, zu der die Sonne den angegebenen Längenwert erreicht. */ public static final char timeSpecSolarRevolution = 'S'; /** Festwert für Zeitbestimmung aus der Länge des Mondes (Lunarhoroskop). Es wird ab dem angegebenen Datum nach der Zeit gesucht, zu der der Mond den angegebenen Längenwert erreicht. */ public static final char timeSpecLunarRevolution = 'L'; /** Festwert für Zeitbestimmung aus dem letzten Erreichen der angegebenen Mondphase */ public static final char timeSpecLunarReturn = 'P'; /** Festwert für sensitive Punkte: Starke Aspekte. */ public static long sensPtAspStrong = 1l; /** Festwert für sensitive Punkte: Mittlere Aspekte. */ public static long sensPtAspMedium = 2l; /** Festwert für sensitive Punkte: Schwache Aspekte. */ public static long sensPtAspWeak = 4l; /** Festwert für sensitive Punkte: Alle Aspekte. Dieser Festwert ist nichts anderes als das Bit-Oder der Festwerte für starke, schwache und mittlere Aspekte. */ public static long sensPtAsp = 7l; /** Festwert für sensitive Punkte: Halbdistanzpunkte. */ public static long sensPtHdp = 8l; /** Festwert für sensitive Punkte: Antiszien. */ public static long sensPtAzm = 16l; /** Festwert für sensitive Punkte: Alles. Es werden alle Arten von sensitiven Punkten berücksichtigt. */ public static long sensPtAll = 31l; public static final int houseRange = 1000; /** Array der dreibuchstabiger Kurztexte für die Häuserspitzen */ public static final String[] houseTextShort = { "ASC", "II", "III", "IC", "V", "VI", "DSC", "VIII", "IX", "MC", "XI", "XII" } ; /** Array der zweibuchstabiger Kurztexte für die Planeten in der Reihenfolge SO, MO, ME, ... PL */ public static final String[] planetTextShort = { "SO", "MO", "ME", "VE", "MA", "JU", "SA", "UR", "NE", "PL" }; /** Planetennamen */ public static final String[] planet = { "Sonne","Mond","Merkur", "Venus", "Mars","Jupiter", "Saturn","Uranus","Neptun", "Pluto" }, /** Namen der Tierkreiszeichen */ sign = {"Widder","Stier","Zwillinge", "Krebs","Loewe","Jungfrau", "Waage","Skorpion","Schuetze", "Steinbock","Wassermann","Fische"}; public static final double[] aspect = { 0d, 30d, 45d, 60d, 90d, 120d, 135d, 150d, 180d }; /** Boolescher Array der schwachen Aspekte (Halbsextil und Quincunx) */ public static final boolean[] isWeak = {false, true, false, false, false, false, false, true, false }; /** Boolescher Array der mittleren Aspekte ( Halbquadrat, Sextil, Trigon, Anderhalbquadrat ) */ public static final boolean[] isMedium = { false,false,true,true, false,true,true,false,false}; /** Boolescher Array der starken Aspekte ( Konjunktion, Quadrat, Opposition ) */ public static final boolean[] isStrong = { true, false, false, false, true, false, false, false, true }; /** Array der dreibuchstabiger Kurztexte für die Aspekte */ public static final String[] aspectTextShort = { "CON","SSX","SSQ","SXT","SQU","TRI","SQQ","QCX","OPP" }; /** Aspekte: Index der Konjunktion */ public static final int con = 0; /** Aspekte: Index des Halbsextils */ public static final int ssx = 1; /** Aspekte: Index des Halbquadrats */ public static final int ssq = 2; /** Aspekte: Index des Sextils */ public static final int sxt = 3; /** Aspekte: Index des Quadrats */ public static final int squ = 4; /** Aspekte: Index des Trigons */ public static final int tri = 5; /** Aspekte: Index des Anderthalbquadrats */ public static final int sqq = 6; /** Aspekte: Index des Quincunx */ public static final int qcx = 7; /** Aspekte: Index der Opposition */ public static final int opp = 8; /** Schlüssel für Halbdistanzpunkte */ public static final int hdp = 100; /** Schlüssel für Antiszien */ public static final int azm = 200; /** Schlüssel für Gegenpunkt von Antiszien */ public static final int aaz = 201; // Gegenpunkt /** Schlüssel für freie Aspektstelle */ public static final int fra = 1000; /** Schlüssel für freie Ekliptikstelle */ public static final int frp = 1001; /** Gesamtzahl der verwendeten Faktoren (Planeten) */ public static final int maxPlanets = 10; /** Sternzeit in Grad (= RAMC) */ public double st; /** Geographische Koordinaten */ public double lon, lat; /** Julianisches Datum in UT */ public double jd; /** Zeitmass */ public double time; /** Zeitart (Wahre Zeit, Sommerzeit, etc. ) */ public char timeSpec; /** Wahre Ekliptikschiefe des Datums */ public double ee; /** Differenz ET-UT in Tagen */ public double deltaT; /** Name des Geburtsortes (optional) */ public String location; /** Name des Horoskops (optional) */ public String name; /** Kurzname des Horoskops (zum Sichern etc.) */ public String nameShort; /** Kommentar */ public String comment; /** Längen, Breiten, tägliche Bewegungen der Planeten */ public double[] pl,pb,dm; /** Häuserspitzen, besondere trig. Punkte */ public double[] houses = new double[13], ascmc = new double[10]; /** Symbolisches Horoskop */ public boolean symbolic = false; /** Aspekttafel - wird auf Anforderung aufgebaut */ ArrayList aspectarium; /** Filterwert zum aktuellen Aspektarium - welche Aspekte sind in die Liste aufzunehmen? */ long aspectariumFilter = 0; /** Indextabelle für Planeten: Um die Planeten Nr. 3, 17 und 22 in einem Array der Länge 3 abzulegen. Wird zur Zeit nicht benötigt, da die Nummern 0 bis 9 der Swiss Ephemeris (SO, MO, ME, ... PL) genau die benötigten Horoskopsymbole sind. */ private int[] tabix; /** Häusersystem */ private int hsys = Mundan.PLACIDUS; /** Funktionen der Swiss Library */ private static SwissLib sl; public static SwissLib sl() { if (sl == null) sl = new SwissLib(); return sl; } private static SwissEph se; public static SwissEph se() { if (se == null) se = new SwissEph("C:\\Sweph\\ephe"); return se; } private static SweDate sd; public static SweDate sd() { if (sd == null) sd = new SweDate(); return sd; } /** Testmethode */ public static void main(String[] args) { double[] tt = new double[3]; tt[0] = SweDate.getJulDay(1954,2,19,22.5,SweDate.SE_GREG_CAL);; Horoscope h = new Horoscope( tt[0], 7.2833, 52.3333); System.out.println(h); System.out.println(aufgang(tt,SweConst.SE_SUN, 7.2833, 52.3333)); h = new Horoscope( tt[0]-sd().getDeltaT(tt[0]), 7.2833, 52.3333); System.out.println( h ); } public Horoscope() {}; /** Konstruktor für symbolische Horoskope */ public Horoscope(double[] planets, double[] houses) { this.pl = planets; this.houses = houses; this.symbolic = true; } /** Horoskop aus seinen Minimal-Angaben konstruieren */ public Horoscope(double jd_ut, double lon, double lat, int hsys) { setAttributes( jd_ut, lon, lat, hsys); } /** Horoskop aus Ort und Zeit konstruieren, verschiedene Arten der Zeitangabe sind möglich. */ public Horoscope(double jd0, double lon, double lat, double time, char timeSpec, int hsys) { double[] tt = new double[3]; tt[0] = jd0; zeitbest(tt, lon, lat, time, timeSpec); setAttributes(tt[0]-sd().getDeltaT(tt[0]), lon, lat, hsys); } /** Horoskop aus seinen Minimal-Angaben konstruieren. Es wird das Default-Häusersystem (Placidus) verwendet */ public Horoscope(double jd_ut, double lon, double lat) { this(jd_ut,lon,lat,(int) Mundan.PLACIDUS ); } /** In allen Konstruktoren (ausser dem symbolischen) durchlaufenes Coding */ private void setAttributes(double jd_ut, double lon, double lat, int hsys) { double[] xx = new double[6]; StringBuffer serr = new StringBuffer(); this.jd = jd_ut; this.lon = lon; this.lat = lat; time = (jd-.5d-Math.floor(jd-.5d))*24; timeSpec = timeSpecUniversalTime; tabix = new int[10] ; pl = new double[10] ; pb = new double[10] ; dm = new double[10] ; deltaT = SweDate.getDeltaT(jd); for (int i=0; i<10;i++) { se().swe_calc(jd+deltaT,i,SweConst.SEFLG_SPEED,xx,serr); pl[i] = xx[0]; pb[i] = xx[1]; dm[i] = xx[3]; tabix[i] = i; } se().swe_calc(jd+deltaT,SweConst.SE_ECL_NUT,0,xx,serr); ee = xx[0]; se().swe_houses(jd,0,lat,lon,hsys,houses,ascmc); st = 15 * sl().swe_sidtime( jd ) + lon; } /** Planet oder Haus mit der Nummer i zurückgeben */ public double pl( int i ) { if (i < houseRange) return pl[i]; else return houses[ i - houseRange ]; } public double pb( int i ) { if (i < houseRange) return pb[i]; else return 0d; } public double dm( int i ) { if (i<houseRange)return dm[i]; else return 0d; } public double h( int i ) { return houses[i]; } public static String planetTextShort( int i ) { if (i <= houseRange) return planetTextShort[i]; else return houseTextShort[i-houseRange-1]; } public byte hsys() { return (byte) hsys; } public ArrayList aspectarium() { return aspectarium( sensPtAll ); } public ArrayList aspectarium(long filter) { if (aspectarium == null) aspectarium = new ArrayList(); // Passt der aktuelle Filter? Dann kann Aspekttafel zurückgegeben werden if (filter == aspectariumFilter) return aspectarium; // Es müssen die neu hinzukommenden Aspekte eingefügt werden if ((filter & ~aspectariumFilter) != 0) { addAspects( filter & ~aspectariumFilter ); } // Die nicht mehr gewünschten Komponenten müssen entfernt werden if ((~filter & aspectariumFilter) != 0) { subtractAspects( ~filter & aspectariumFilter ); } aspectariumFilter = filter; return aspectarium; } /** Hinzufügen der durch Filter gegebenen Objekte zur Liste */ private void addAspects(long filter) { int i,j,k,s; AspectPoint a; // 1.) Aspekte der Planeten if ((filter & sensPtAsp) != 0) for (i = 0; i < maxPlanets; i++) for (j = 0; j < aspect.length; j++) { if (( (filter & sensPtAspWeak) == 0) && isWeak[j] ) continue; if (( (filter & sensPtAspMedium) == 0) && isMedium[j] ) continue; if (( (filter & sensPtAspStrong) == 0) && isStrong[j] ) continue; for (s = -1; s <= 1 ; s+=2) { // Konjunktion und Opposition werden nur positiv gerechnet if ( (s==-1) && ((j == 0) || (j == aspect.length-1))) continue; a = new AspectPoint(); a.aspect = j; a.aspectSign = (s > 0) ? '+' : '-'; a.planet1 = i; a.planet2 = -1; a.lon = Calculator.fmod360(pl(i)+s*aspect[j]); k = Collections.binarySearch(aspectarium, a); if (k < 0) aspectarium.add(-k-1,a); } } // 1a) Häuserspitzen sowie Aspekte zu den Achsen for (i = 1; i<=12; i++) { if (((i==1)||(i==10))&&((filter & sensPtAsp)!=0)) { for (j = 0; j < aspect.length; j++) { if (( (filter & sensPtAspWeak) == 0) && isWeak[j] ) continue; if (( (filter & sensPtAspMedium) == 0) && isMedium[j] ) continue; if (( (filter & sensPtAspStrong) == 0) && isStrong[j] ) continue; for (s = -1; s <=1; s+=2) { if ( (s==1) && ((j == 0) || (j == aspect.length-1))) continue; a = new AspectPoint(); a.aspect = j; a.planet1 = houseRange + i; a.planet2 = -1; a.lon = Calculator.fmod360(h(i)+s*aspect[j]); k = Collections.binarySearch(aspectarium, a); if (k < 0) aspectarium.add(-k-1,a); } } } // Wenn nur starke Aspekte gewünscht sind: Keine Zwischenhäuser else if ((filter & sensPtAsp) != sensPtAspStrong) { a = new AspectPoint(); a.aspect = 0; a.planet1 = houseRange + i; a.planet2 = -1; a.lon = Calculator.fmod360(h(i)); k = Collections.binarySearch(aspectarium, a); if (k < 0) aspectarium.add(-k-1,a); } } // 2.) Alle Halbsummen if ((filter & sensPtHdp) != 0) for (i = 0; i < maxPlanets; i++) for (j = 0; j < maxPlanets; j++) for (s = 0; s <=180; s+=180) { a = new AspectPoint(); a.aspect = hdp; a.planet1 = i; a.planet2 = j; a.lon = Calculator.fmod360((pl(i)+pl(j))/2+s); k = Collections.binarySearch(aspectarium, a); if (k < 0) aspectarium.add(-k-1,a); } // 3.) Alle Antiszien if ((filter & sensPtAzm) != 0) for (i = 0; i < maxPlanets; i++) for (s = 0; s <=180; s+=180) { a = new AspectPoint(); if (s==0) a.aspect = azm; else a.aspect = aaz; a.planet1 = i; a.planet2 = -1; a.lon = Calculator.fmod360(180d-pl(i)+s); k = Collections.binarySearch(aspectarium, a); if (k < 0) aspectarium.add(-k-1,a); } } /** Entfernen der durch filter gegebenen Objekte aus der Liste */ private void subtractAspects( long filter ) { ListIterator aIt = aspectarium.listIterator(); while (aIt.hasNext()) { AspectPoint a = (AspectPoint) aIt.next(); if ((a.aspect == hdp) && ( (filter & sensPtHdp) != 0) ){ aIt.remove(); continue; } if ((a.aspect == azm) && ( (filter & sensPtAzm) != 0)) { aIt.remove(); continue; } if ((a.aspect >= 0) && (a.aspect < aspect.length) && ( (filter & sensPtAsp) != 0) ){ if (isWeak[a.aspect] & ( (filter & sensPtAspWeak) != 0) ) { aIt.remove(); continue; } if (isMedium[a.aspect] & ( (filter & sensPtAspMedium) != 0) ) { aIt.remove(); continue; } if (isStrong[a.aspect] & ( (filter & sensPtAspStrong) != 0) ) { aIt.remove(); continue; } } } } /** Liefert eine Liste aller Kontakte mit sensitiven Ekliptikpunkten, die auf dem Intervall [l1,l2] auftreten */ public ArrayList getTransits(double l1, double l2) { return getTransits(l1,l2,sensPtAll); } /** Liefert eine Liste aller Kontakte mit sensitiven Ekliptikpunkten, die auf dem Intervall [l1,l2] auftreten */ public ArrayList getTransits(double l1, double l2, long filter) { ArrayList list; l1 = Calculator.fmod360(l1); if (l2 != 360d) l2 = Calculator.fmod360(l2); if (l1 > l2) { list = getTransits(0d,l2,filter); list.addAll(getTransits(l1,360d,filter)); return list; } list = new ArrayList(); ArrayList a = aspectarium(filter); AspectPoint ap1 = new AspectPoint(l1), ap2 = new AspectPoint(l2); int i1 = Collections.binarySearch(a,ap1); if (i1 < 0) i1 = -i1 - 1; int i2 = Collections.binarySearch(a,ap2); if (i2 < 0) i2 = -i2 - 1; for (int i = i1; i < i2; i++) list.add(a.get(i)); return list; } public static void printAspectarium(ArrayList al, PrintStream p) { Iterator iter = al.iterator(); while (iter.hasNext()) { AspectPoint a = (AspectPoint) iter.next(); p.print(Calculator.dms(a.lon,Calculator.ECL+Calculator.SEC)+"\t"); if (a.planet2 >= 0) p.print(planetTextShort(a.planet1)+"/"+planetTextShort(a.planet2)); else if (a.aspect < 100) p.print(aspectTextShort[a.aspect]+" "+planetTextShort(a.planet1)); else p.print("AZM "+planetTextShort(a.planet1)); p.println(); } } public void setName(String name) { this.name = name; } public void setNameShort(String nameShort) { this.nameShort = nameShort; } public void setComment(String comment) { this.comment = comment; } /** Kurzname zurückgeben oder aus Langname ableiten */ public String shortName() { if (nameShort.length() > 0) return nameShort; else { char c; StringBuffer x = new StringBuffer(); for (int i=0; (i < name.length()) && (i < 15); i++) if (Character.isJavaIdentifierPart(c = name.charAt(i))) x.append(Character.toLowerCase(c)); if (x.length() > 0) return x.toString(); } return null; } /** Output des Horoskops als ini Datei auf die Datenbank */ public void save() throws java.io.IOException { if (shortName() != null) save( nameShort + ".dat" ); else save( "horoscope.dat" ); } public void save(String fileName) throws java.io.IOException { Properties horoOut = new Properties(); horoOut.put("jd",Double.toString(jd)); horoOut.put("time",Double.toString(time)); horoOut.put("st",Double.toString(st)); horoOut.put("timeSpec",""+timeSpec); horoOut.put("ee",Double.toString(ee)); horoOut.put("lon",Double.toString(lon)); horoOut.put("lat",Double.toString(lat)); horoOut.put("deltaT",Double.toString(deltaT)); horoOut.put("pl",Calculator.doubleList(pl)); horoOut.put("pb",Calculator.doubleList(pb)); horoOut.put("dm",Calculator.doubleList(dm)); horoOut.put("houses",Calculator.doubleList(houses)); horoOut.put("hsys",""+(char)hsys); horoOut.put("symbolic",Boolean.toString(symbolic)); if (comment != null) horoOut.put("comment",comment); if (name != null) horoOut.put("name",name); if (nameShort == null) nameShort = shortName(); if (nameShort != null) horoOut.put("nameShort", nameShort); if (location != null) horoOut.put("location",location); horoOut.store(new FileOutputStream(fileName), name); } /** Horoskop einlesen */ public static Horoscope load(String fileName) throws java.io.IOException { int i; Properties horoIn = new Properties(); if ((i = fileName.indexOf('.')) <= 0) fileName += ".dat"; horoIn.load( new FileInputStream(fileName) ); Horoscope h = new Horoscope(); h.jd = Double.parseDouble(horoIn.getProperty("jd")); h.time = Double.parseDouble(horoIn.getProperty("time")); h.timeSpec = horoIn.getProperty("timeSpec").charAt(0); h.st = Double.parseDouble(horoIn.getProperty("st")); h.ee = Double.parseDouble(horoIn.getProperty("ee")); h.lon = Double.parseDouble(horoIn.getProperty("lon")); h.lat = Double.parseDouble(horoIn.getProperty("lat")); h.deltaT = Double.parseDouble(horoIn.getProperty("deltaT")); h.houses = new double[13]; Calculator.parseDoubleList(horoIn.getProperty("houses"),h.houses); h.hsys = horoIn.getProperty("hsys").charAt(0); h.pl = new double[10]; Calculator.parseDoubleList(horoIn.getProperty("pl"),h.pl); h.pb = new double[10]; Calculator.parseDoubleList(horoIn.getProperty("pb"),h.pb); h.dm = new double[10]; Calculator.parseDoubleList(horoIn.getProperty("dm"),h.dm); h.symbolic = Boolean.valueOf(horoIn.getProperty("symbolic")).booleanValue(); h.comment = horoIn.getProperty("comment"); h.name = horoIn.getProperty("name"); h.nameShort = horoIn.getProperty("nameShort"); h.location = horoIn.getProperty("location"); return h; } /** Zeitberechnung für verschiedene Zeitangaben. @param time Ein double[3] mit den Werten time[0] = Julianisches Datum in ET (dieser Wert ist zu übergeben) time[1] = Weltzeit (Ergebnis der Rechnung) time[2] = Sternzeit (Ergebnis der Rechnung) @param specifier Ein Charakter, der die Zeitangabe bestimmt: <pre> 'e' Ephemeris Time (Default) 'w' True Local Time 'l' Local Mean Time 't' Temporal Hour 'u' Universal Time 's' Sidereal Time in Hours 'r' Sidereal Time in Degrees (=RAMC) 'a' Ascendent Longitude 'm' Medium Coeli Longitude 'S' Solar Revolution 'L' Lunar Revolution </pre> */ public static boolean zeitbest( double[] time, double lon, double lat, double x, char specifier) { double jd,jd0,jd1,jd2,ut,st; double b,et,dt,y,z,l,r,v,jd12; double ecl; int flag = 0, i,count; double[] xx = new double[6], tt = new double[3]; StringBuffer serr = new StringBuffer(); jd = time[0]; jd12=Math.floor(jd-.5)+.5; /* Jul. Datum um 0 Uhr UT */ et=(jd-jd12)*24.; dt = sd().getDeltaT(jd); st=15*sl().swe_sidtime(jd12)+lon; se().swe_calc(jd,SweConst.SE_ECL_NUT, 0, xx, serr); ecl = xx[0]; // Ein Objekt für sphärische Berechnungen Mundan m = new Mundan(0., lat, ecl, Mundan.PLACIDUS); switch (specifier) { case timeSpecMediumCoeli: x = m.ramc(x)/15.; /* LST aus MC-Laenge */ case timeSpecSiderealTime: x = 15.*x; /* Sternzeit in Stunden */ case timeSpecRAMC: /* Sternzeit in Grad = RAMC: hier einsteigen */ ut = Calculator.fmod((x-st)/15d,24.)/Direct.ST_UT; /* ut */ et = ut + dt*24; break; case timeSpecAscendent: y = Calculator.fmod(m.oaasc(x)/15d-6d,24.); /* RAMC */ ut = Calculator.fmod(y-st/15,24.)/Direct.ST_UT; /* ut */ et = ut + dt*24; break; case timeSpecUniversalTime: /* Greenwich Mean Time (= Universal Time) */ ut = x; et = ut + dt*24; break; case timeSpecLocalMeanTime: /* Mittlere Ortszeit */ ut = x - lon/15.; et = ut + dt*24; break; case timeSpecTrueLocalTime: /* Wahre Ortszeit */ for (i=0;i<=5;i++) { se().swe_calc(jd,SweConst.SE_SUN,flag,xx,serr); y = m.ramc(xx[0]); z = Calculator.fmod360(y + x*15. - 180.); st=15.*sl().swe_sidtime(jd-dt)+lon; if (i==0) b = Calculator.fmod360(z-st)/360./Direct.ST_UT; else b = Calculator.arcdiff(z,st)/360./Direct.ST_UT; jd += b; et=(jd-.5-Math.floor(jd-.5))*24.; } ut = et - dt*24; break; case timeSpecSolarRevolution: /* Solar Revolution */ /* Das zum angegebenen Datum gültige Solar */ se().swe_calc(jd12,SweConst.SE_SUN,flag,xx,serr); /* 1. Ungefähres Erreichen der Sonnenlänge */ y = jd - Calculator.fmod360(xx[0]-x)/Direct.naibod; for(i=0; (Calculator.arcdiffAbs(xx[0],x) > Mundan.SPREC) && (i<Mundan.MAXIT); i++) { se().swe_calc(y,SweConst.SE_SUN,SweConst.SEFLG_SPEED,xx,serr); y -= Calculator.arcdiff(xx[0],x)/xx[3]; } if (i==Mundan.MAXIT) { // System.out.println("Genauigkeitsfehler bei Solarberechnung!\n"); // System.out.println("Letzter Längenwert: %s\n",Calculator.dms(l)); return false; } jd12=Math.floor(y-.5)+.5; /* Jul. Datum um 0 Uhr UT */ et=(y-jd12)*24.; ut = et - dt*24; break; case timeSpecTemporalHours: /* Temporal */ /* 0 Uhr = Sonnenuntergang, 12 Uhr = Sonnenaufgang */ /* Berechne den naechsten Sonnenuntergang */ tt = new double[2]; tt[0] = jd; tt[1] = et; if (!aufgang(tt,SweConst.SE_SUN,Calculator.arcdiff(lon+180.,0d),-lat)) return false; jd0 = tt[0]; // ET /* Berechne den darauffolgenden Sonnenaufgang */ if (!aufgang(tt,SweConst.SE_SUN,lon,lat)) return false; jd1 = tt[0]; // ET /* Berechne den darauffolgenden Sonnenuntergang */ if (!aufgang(tt,SweConst.SE_SUN,Calculator.arcdiff(lon+180.,0d),-lat)) return false; jd2 = tt[0]; // ET /* Tag- oder Nachtzeit */ if (x<12) jd = x/12.*(jd1-jd0)+jd0; else jd = (x-12.)/12.*(jd2-jd1)+jd1; jd12=Math.floor(jd-.5)+.5; /* Jul. Datum um 0 Uhr UT */ et=(jd-jd12)*24.; ut = et - 24*dt; st=15.*sl().swe_sidtime(jd-dt)+lon; break; case timeSpecLunarRevolution: /* Letztes Erreichen der angegebenen Mondlon */ /* 1. Ungefaehres Erreichen */ count = 0; y = jd-Direct.tropicalLunation; se().swe_calc(y,SweConst.SE_MOON,0,xx,serr); y += Calculator.fmod360(x-xx[0])/360.*Direct.tropicalLunation; se().swe_calc(y,SweConst.SE_MOON,SweConst.SEFLG_SPEED,xx,serr); /* 2. Genaues Erreichen */ for(i=0; (Calculator.arcdiffAbs(xx[0],x) > Mundan.SPREC) && (i<Mundan.MAXIT); i++) { y += Calculator.arcdiff(x,xx[0])/xx[3]; se().swe_calc(y,SweConst.SE_MOON,SweConst.SEFLG_SPEED,xx,serr); } if (i==Mundan.MAXIT) { return false; } jd12=Math.floor(y-.5)+.5; /* Jul. Datum um 0 Uhr UT */ et=(y-jd12)*24.; ut = et - dt*24; break; case timeSpecLunarReturn: /* Letztes Erreichen der angegebenen Mondphase */ i = 0; y = jd; do { if (++i == Mundan.MAXIT ) return false; se().swe_calc(y,SweConst.SE_MOON,SweConst.SEFLG_SPEED,xx,serr); l = xx[0]; v = xx[3]; se().swe_calc(y,SweConst.SE_SUN,SweConst.SEFLG_SPEED,xx,serr); if (i==1) l = Calculator.fmod360(l-xx[0]-x); else l = Calculator.arcdiff(l,xx[0]-x); v = v-xx[3]; y -= l/v; } while (Calculator.fabs(l) > Mundan.SPREC); jd12=Math.floor(y-.5)+.5; /* Jul. Datum um 0 Uhr UT */ et=(y-jd12)*24.; ut = et - dt*24; break; default: et = x; /* Default ist ET */ ut = et - dt*24; /* Weltzeit */ } /* Ende von SWITCH */ /* Für späteren Gebrauch */ jd = jd12 + et/24.; st=15.*sl().swe_sidtime(jd-dt)+lon; time[0] = jd; time[1] = et; time[2] = st; return true; } // Hilfskonstante für die formatierte Ausgabe der Planetennamen in Methode toString() private static final String sep = ": "; /* Horoskop im Plain-Text Format ausgeben */ public String toString() { double jd12=Math.floor(jd-.5)+.5; /* Jul. Datum um 0 Uhr UT */ double ut=(jd-jd12)*24.; StringBuffer s = new StringBuffer(); if (!symbolic) { s.append("Julianisches Datum: " + Double.toString(jd) + "\n"); s.append("Kalenderdatum: " + Calculator.date(jd) + "\n"); s.append("Weltzeit: " + Calculator.dms(ut,Calculator.TIME+Calculator.SEC) + "\n"); s.append("Sternzeit (RAMC) " + Calculator.dms(st,Calculator.GEO+Calculator.SEC) + "\n"); s.append("Geographische Länge: " + Calculator.dms(lon,Calculator.LONG+Calculator.SEC) + "\n"); s.append("Geographische Breite: " + Calculator.dms(lat,Calculator.LAT+Calculator.SEC) + "\n"); } s.append("Aszendent: " + Calculator.dms(h(1),Calculator.ECL+Calculator.SEC) + "\n"); s.append("Medium Coeli: " + Calculator.dms(h(10),Calculator.ECL+Calculator.SEC) + "\n"); s.append("Haus 2: " + Calculator.dms(h(2),Calculator.ECL) + "\n"); s.append("Haus 3: " + Calculator.dms(h(3),Calculator.ECL) + "\n"); s.append("Haus 11: " + Calculator.dms(h(11),Calculator.ECL) + "\n"); s.append("Haus 12: " + Calculator.dms(h(12),Calculator.ECL) + "\n"); for ( int i = 0; i < 10; i++ ) s.append(planet[i] + sep.substring(0,12-planet[i].length()) + Calculator.dms(pl[i],Calculator.ECL+Calculator.SEC) + "\n"); return s.toString(); } /* Berechne ET des naechsten Aufgangs des Planeten planet */ public static boolean aufgang(double[] tt,int planet, double lon, double lat) { double xjd, xjd12, st, lst0,et0,et1,dt,l,b,r,alngspeed,a,d,y, ecl; double[] coor = new double[3]; double[] xx = new double[6]; int flag = 0, zahl = 0; StringBuffer serr = new StringBuffer(); xjd = tt[0]; dt = sd().getDeltaT(xjd)*24.; /* Delta T in Stunden */ xjd12 = Math.floor(xjd-0.5)+0.5; /* Jul. Datum um 0 Uhr ET */ tt[1] = et0 = (xjd-xjd12)*24.; /* Angegebene Zeit */ lst0 = 15*sl().swe_sidtime(tt[0]-dt/24)+lon; /* Ortssternzeit (RAMC) zum ang. Datum */ se().swe_calc( xjd, SweConst.SE_ECL_NUT, 0, xx, serr); ecl = xx[0]; // Wahre Ekliptikschiefe (= inklusive Nutation) do { et1 = tt[1]; /* Letzte ET merken */ se().swe_calc(xjd12+tt[1]/24,planet,flag,xx,serr); /* Umwandlung der ekliptikalen in aequatoriale Koordinaten */ sl().swe_cotrans( xx,0,coor,0,-ecl); /* Wenn man in den zirkumpolaren Bereich gelangt: Aufhören */ if (Calculator.fabs(coor[1])+Calculator.fabs(lat)>90.) return false; /* Schräge Aufsteigung aus RA, Deklination und geogr. Breite */ y = Calculator.fmod360(Mundan.oa(coor[0],coor[1],lat)-90.); /* OA-90 -> RAMC */ tt[1] = Calculator.fmod360(y-lst0)/Direct.ST_UT/15. + et0; /* in den 24 Std. nach ET0 */ zahl ++; } while (((Calculator.arcdiffAbs(tt[1]*15,et1*15)/15d)>Mundan.SPREC) && (zahl<Mundan.MAXIT)); if (zahl == Mundan.MAXIT) return false; tt[0] = xjd12 + tt[1]/24.; /* JD in ET zurückgeben */ tt[1] = Calculator.fmod(tt[1],24d); return true; } /** Letzte Syzygie (Voll- oder Neumond) vor dem angegebenen julianischen Datum berechnen @param jd Julianisches Datum (ET). Es wird der letzte Neu- oder Vollmond vor diesem Datum berechnet. @return Julianisches Datum (ET) der Syzygie */ public static double lastSyzygy( double jd ) { double x; double[] xx = new double[6], tt = new double[3]; StringBuffer serr = new StringBuffer(); se().swe_calc(jd,SweConst.SE_MOON,SweConst.SEFLG_SPEED,xx,serr); x = xx[0]; se().swe_calc(jd,SweConst.SE_SUN,SweConst.SEFLG_SPEED,xx,serr); x -= xx[0]; tt[0] = jd; if (Calculator.fmod360(x)>180) zeitbest(tt,0d,0d,180d,timeSpecLunarReturn); else zeitbest(tt,0d,0d,0d,timeSpecLunarReturn); return tt[0]; } /** Ermittle den Index eines Planeten im Array -1 wenn Planet (noch?) nicht im Array abgelegt */ private int ix( int i ) { int index; if (i >= tabix.length) return -1; else return tabix[i]; } }