/// <summary> /// Mean orbital element of Saturn with perturbation /// </summary> /// <param name="jd"></param> void PerturbationSaturn(double jd) { int year = (int)((jd - 1721423.5) / 365.244 + 1.0); double T = year / 1000.0; double AT = 0.88 - 0.0633 * T + 0.03 * T * T - 0.0006 * T * T * T; double L7 = -0.50 + AT * UdMath.udsin((T - 0.145) * 360.0 / 0.95); double PS7 = -0.50 + (0.10 - 0.005 * T) * UdMath.udsin((T - 0.54) * 360.0 / 0.95); double PH7 = -0.50 + (0.10 - 0.005 * T) * UdMath.udsin((T - 0.32) * 360.0 / 0.95); double AX7 = -0.050 + (0.004 - 0.0005 * T) * UdMath.udsin((T - 0.35) * 360.0 / 0.95); double ETA = UdMath.degmal(86.1 + 0.033459 * (jd - 1721057.0)); double ZETA = UdMath.degmal(89.1 + 0.049630 * (jd - 1721057.0)); double L8 = PerturbationElement(ETA, ZETA, perturbSat1) / 100.0; double PS8 = PerturbationElement(ETA, ZETA, perturbSat2) / 100.0; double PH8 = PerturbationElement(ETA, ZETA, perturbSat3) / 100.0; double AX8 = PerturbationElement(ETA, ZETA, perturbSat4) / 1000.0; double PH = 3.56 - 0.175 * T - 0.005 * T * T; /* if year > 7000 then PH < 2.0 */ if (PH < 2.0) { PH = 2.0; } L += (L7 + L8); w += (PS7 + PS8) / UdMath.udsin(PH); e = UdMath.udsin(PH + PH7 + PH8); a += AX7 + AX8; }
/// <summary> /// Get Position of the Earth /// </summary> /// <param name="T"></param> /// <returns></returns> private static Xyz GetPosExp0(double T) { double lambda = 279.0358 + 360.00769 * T + (1.9159 - 0.00005 * T) * UdMath.udsin((356.531) + (359.991) * T); for (int i = 0; i < SunLambda.GetLength(0); i++) { lambda += SunLambda[i].a * UdMath.udsin(SunLambda[i].b + SunLambda[i].c * T); } lambda += 0.0057; lambda = UdMath.deg2rad(UdMath.degmal(lambda)); double beta = 0.0; double q = (-0.007261 + 0.0000002 * T) * UdMath.udcos((356.53) + (359.991) * T) + 0.000030; for (int i = 0; i < SunQ.GetLength(0); i++) { q += SunQ[i].a * UdMath.udcos(SunQ[i].b + SunQ[i].b * T); } double radius = Math.Pow(10.0, q); return(new Xyz(-radius * Math.Cos(beta) * Math.Cos(lambda), -radius * Math.Cos(beta) * Math.Sin(lambda), -radius * Math.Sin(beta))); }
/// <summary> /// Orbital element to Xyz /// </summary> /// <returns></returns> public Xyz GetPos() { double re = this.e * 180.0 / Math.PI; double E, M, oldE; E = M = this.L - (this.w + this.N); do { oldE = E; E = M + re * UdMath.udsin(oldE); } while (Math.Abs(E - oldE) > 1.0e-5 * 180.0 / Math.PI); double px = this.a * (UdMath.udcos(E) - this.e); double py = this.a * Math.Sqrt(1.0 - this.e * this.e) * UdMath.udsin(E); double sinperi = UdMath.udsin(this.w); double cosperi = UdMath.udcos(this.w); double sinnode = UdMath.udsin(this.N); double cosnode = UdMath.udcos(this.N); double sinincl = UdMath.udsin(this.i); double cosincl = UdMath.udcos(this.i); double xc = px * (cosnode * cosperi - sinnode * cosincl * sinperi) - py * (cosnode * sinperi + sinnode * cosincl * cosperi); double yc = px * (sinnode * cosperi + cosnode * cosincl * sinperi) - py * (sinnode * sinperi - cosnode * cosincl * cosperi); double zc = px * (sinincl * sinperi) + py * (sinincl * cosperi); return(new Xyz(xc, yc, zc)); }
/// <summary> /// Mean orbital element of Jupiter with perturbation /// </summary> /// <param name="jd"></param> private void PerturbationJupiter(double jd) { int year = (int)((jd - 1721423.5) / 365.244 + 1.0); double T = year / 1000.0; double L7 = (0.42 - 0.075 * T + 0.015 * T * T - 0.003 * T * T * T) * UdMath.udsin((T - 0.62) * 360.0 / 0.925); double PS7 = 0.02 * UdMath.udsin((T + 0.1) * 360.0 / 0.925); double PH7 = 0.03 * UdMath.udsin((T + 0.36) * 360.0 / 0.925); double ETA = UdMath.degmal(86.1 + 0.033459 * (jd - 1721057.0)); double ZETA = UdMath.degmal(89.1 + 0.049630 * (jd - 1721057.0)); double L8 = PerturbationElement(ETA, ZETA, perturbJup1) / 1000.0; double PS8 = PerturbationElement(ETA, ZETA, perturbJup2) / 1000.0; double PH8 = PerturbationElement(ETA, ZETA, perturbJup3) / 1000.0; double PH = 2.58 + 0.1 * T; if (PH > 3.5) { PH = 3.5; } if (PH < 1.5) { PH = 1.5; } L += (L7 + L8); w += (PS7 + PS8) / UdMath.udsin(PH); e = UdMath.udsin(PH + PH7 + PH8); }
/// <summary> /// Get mean orbital elements (Mercury, Venus, Mars, Jupiter, Saturn) /// </summary> /// <param name="planetNo"></param> /// <param name="jd"></param> private void GetPlanetElm1(int planetNo, double jd) { double C1 = (jd - Astro.JD1900) / 36525.0; double C2 = C1 * C1; PlanetElmP1 elmCf; switch (planetNo) { case Planet.MERCURY: elmCf = MercuryE; break; case Planet.VENUS: elmCf = VenusE; break; case Planet.MARS: elmCf = MarsE; break; case Planet.JUPITER: elmCf = JupiterE; break; case Planet.SATURN: elmCf = SaturnE; break; default: throw new ArithmeticException(); } this.L = UdMath.degmal(elmCf.L + elmCf.L1 * C1 + elmCf.L2 * C2 + elmCf.L3 * C1 * C2); this.N = UdMath.degmal(elmCf.N + elmCf.N1 * C1 + elmCf.N2 * C2 + elmCf.N3 * C1 * C2); this.w = UdMath.degmal(elmCf.w + elmCf.w1 * C1 + elmCf.w2 * C2 + elmCf.w3 * C1 * C2 - N); this.a = elmCf.a; this.e = UdMath.degmal(elmCf.e + elmCf.e1 * C1 + elmCf.e2 * C2 + elmCf.e3 * C1 * C2); this.i = UdMath.degmal(elmCf.i + elmCf.i1 * C1 + elmCf.i2 * C2 + elmCf.i3 * C1 * C2); switch (planetNo) { case Planet.JUPITER: PerturbationJupiter(jd); break; case Planet.SATURN: PerturbationSaturn(jd); break; } }
/// <summary> /// Get Position of Venus and Mars /// </summary> /// <param name="planetNo"></param> /// <param name="T"></param> /// <returns></returns> private static Xyz GetPosExp1(int planetNo, double T) { PlanetExpP0[] ParamL0, ParamL1, ParamQ; PlanetExpP1 ParamP; switch (planetNo) { case Planet.VENUS: ParamL0 = VenusL0; ParamL1 = VenusL1; ParamQ = VenusQ; ParamP = VenusP; break; case Planet.MARS: ParamL0 = MarsL0; ParamL1 = MarsL1; ParamQ = MarsQ; ParamP = MarsP; break; default: throw new ArithmeticException(); } double L1 = (ParamP.L6 + ParamP.L7 * T) * UdMath.udsin(ParamP.L8 + ParamP.L9 * T); for (int i = 0; i < ParamL1.GetLength(0); i++) { L1 += ParamL1[i].a * UdMath.udsin(ParamL1[i].b + ParamL1[i].c * T); } double L0 = ParamP.L1 + ParamP.L2 * T + ParamP.L3 * UdMath.udsin(ParamP.L4 + ParamP.L5 * T + 2.0 * L1); for (int i = 0; i < ParamL0.GetLength(0); i++) { L0 += ParamL0[i].a * UdMath.udsin(ParamL0[i].b + ParamL0[i].c * T); } double lambda = UdMath.deg2rad(UdMath.degmal(L0 + L1)); double beta = Math.Asin(ParamP.B1 * UdMath.udsin(ParamP.B2 + ParamP.B3 * T + L1)); double q = (ParamP.q1 + ParamP.q2 * T) * UdMath.udcos(ParamP.q3 + ParamP.q4 * T) + ParamP.q5; for (int i = 0; i < ParamQ.GetLength(0); i++) { q += ParamQ[i].a * UdMath.udcos(ParamQ[i].b + ParamQ[i].c * T); } double radius = Math.Pow(10.0, q); return(new Xyz(radius * Math.Cos(beta) * Math.Cos(lambda), radius * Math.Cos(beta) * Math.Sin(lambda), radius * Math.Sin(beta))); }
/// <summary> /// Get mean orbital elements (Earth) /// </summary> /// <param name="jd"></param> private void GetPlanetElmEarth(double jd) { double c = (jd - Astro.JD1900) / 36525.0; double c2 = c * c; this.L = 180.0 + UdMath.degmal(280.6824 + 36000.769325 * c + 7.22222e-4 * c2); this.w = 180.0 + UdMath.degmal(281.2206 + 1.717697 * c + 4.83333e-4 * c2 + 2.77777e-6 * c * c2); this.N = 0.0; /* no ascending node for the Earth */ this.i = 0.0; /* no inclination for the Earth */ this.e = 0.0167498 - 4.258e-5 * c - 1.37e-7 * c2; this.a = 1.00000129; }
/// <summary> /// Hyperbolic Orbit /// </summary> /// <param name="comet"></param> private void GetOrbitHyper(Comet comet) { int idx1, idx2; idx1 = idx2 = this.Division / 2; double t = Math.Sqrt(comet.e * comet.e - 1.0); double axis = comet.q / (comet.e - 1.0); double dF = UdMath.arccosh((MAXORBIT + axis) / (axis * comet.e)) / (this.Division / 2); double F = 0.0; for (int i = 0; i <= (this.Division / 2); i++, F += dF) { double RCosV = axis * (comet.e - UdMath.cosh(F)); double RSinV = axis * t * UdMath.sinh(F); Orbit[idx1++] = new Xyz(RCosV, RSinV, 0.0); Orbit[idx2--] = new Xyz(RCosV, -RSinV, 0.0); } }
private void DoGetPlanetOrbit(PlanetElm planetElm) { double ae2 = -2.0 * planetElm.a * planetElm.e; double t = Math.Sqrt(1.0 - planetElm.e * planetElm.e); int xp1 = 0; int xp2 = (this.Division / 2); int xp3 = (this.Division / 2); int xp4 = this.Division; double E = 0.0; for (int i = 0; i <= (this.Division / 4); i++, E += (360.0 / this.Division)) { double rcosv = planetElm.a * (UdMath.udcos(E) - planetElm.e); double rsinv = planetElm.a * t * UdMath.udsin(E); this.Orbit[xp1++] = new Xyz(rcosv, rsinv, 0.0); this.Orbit[xp2--] = new Xyz(ae2 - rcosv, rsinv, 0.0); this.Orbit[xp3++] = new Xyz(ae2 - rcosv, -rsinv, 0.0); this.Orbit[xp4--] = new Xyz(rcosv, -rsinv, 0.0); } }
/// <summary> /// Get mean orbital elements (Uranus, Neptune, Pluto) /// </summary> /// <param name="planetNo"></param> /// <param name="jd"></param> private void GetPlanetElm2(int planetNo, double jd) { double T1 = (jd - Astro.JD2000) / 36525.0; double T2 = T1 * T1; double d = T1 * 36525.0; PlanetElmP2 elmCf = null; switch (planetNo) { case Planet.URANUS: elmCf = UranusE; break; case Planet.NEPTUNE: elmCf = NeptuneE; break; case Planet.PLUTO: elmCf = PlutoE; break; default: throw new ArithmeticException(); } this.L = UdMath.degmal(elmCf.L + elmCf.L1 * d + elmCf.L2 * T2); this.N = UdMath.degmal(elmCf.N + elmCf.N1 * T1 + elmCf.N2 * T2); this.w = UdMath.degmal(elmCf.w + elmCf.w1 * T1 + elmCf.w2 * T2 - N); this.a = UdMath.degmal(elmCf.a + elmCf.a1 * T1 + elmCf.a2 * T2); this.e = UdMath.degmal(elmCf.e + elmCf.e1 * T1 + elmCf.e2 * T2); this.i = UdMath.degmal(elmCf.i + elmCf.i1 * T1 + elmCf.i2 * T2); }
public void ChangeDate(ATimeSpan span, int direction) { // // First, calculate new Hour,Minute,Second // double hms1 = this.Hour * 60.0 * 60.0 + this.Minute * 60.0 + this.Second; double hms2 = span.Hour * 60.0 * 60.0 + span.Minute * 60.0 + span.Second; hms1 += hms2 * direction; int day; if (0.0 <= hms1 && hms1 < 24.0 * 60.0 * 60.0) { day = 0; } else if (hms1 >= 24.0 * 60.0 * 60.0) { day = (int)Math.Floor(hms1 / 24.0 / 60.0 / 60.0); hms1 = UdMath.fmod(hms1, 24.0 * 60.0 * 60.0); } else { day = (int)Math.Ceiling(hms1 / 24.0 / 60.0 / 60.0) - 1; hms1 = UdMath.fmod(hms1, 24.0 * 60.0 * 60.0) + 24.0 * 60.0 * 60.0; } int newHour = (int)Math.Floor(hms1 / 60.0 / 60.0); int newMin = (int)Math.Floor(hms1 / 60.0) - newHour * 60; double newSec = hms1 - ((double)newHour * 60.0 * 60.0 + (double)newMin * 60.0); // // Next, calculate new Year, Month, Day // ATime newDate = new ATime(this.Year, this.Month, this.Day, 12, 0, 0.0, 0.0); double jd = newDate.JD; jd += day + span.Day * direction; newDate = new ATime(jd, 0.0); int newYear = newDate.Year; int newMonth = newDate.Month; int newDay = newDate.Day; newMonth += span.Month * direction; if (1 > newMonth) { newYear -= newMonth / 12 + 1; newMonth = 12 + newMonth % 12; } else if (newMonth > 12) { newYear += newMonth / 12; newMonth = 1 + (newMonth - 1) % 12; } newYear += span.Year * direction; // check bound between julian and gregorian if (newYear == 1582 && newMonth == 10) { if (5 <= newDay && newDay < 10) { newDay = 4; } else if (10 <= newDay && newDay < 15) { newDay = 15; } } newDate = LimitATime(new ATime(newYear, newMonth, newDay, 12, 0, 0, 0.0)); newYear = newDate.Year; newMonth = newDate.Month; newDay = newDate.Day; this.Year = newYear; this.Month = newMonth; this.Day = newDay; this.Hour = newHour; this.Minute = newMin; this.Second = newSec; this.JD = GetJD() - this.Timezone / 24.0; this.T = GetT(); this.T2 = GetT2(); }
/// <summary> /// Get Position of Mercury, Uranus, Neptune, Pluto /// </summary> /// <param name="planetNo"></param> /// <param name="T"></param> /// <returns></returns> private static Xyz GetPosExp3(int planetNo, double T) { PlanetExpP0[] ParamL, ParamB, ParamR; double lambda, beta, radius; switch (planetNo) { case Planet.MERCURY: ParamL = MercuryLambda; ParamB = MercuryBeta; ParamR = MercuryR; lambda = 252.2502 + 149474.0714 * T; lambda += (23.4405 + 0.0023 * T) * UdMath.udcos(149472.5153 * T + 84.7947); lambda += (2.9818 + 0.0006 * T) * UdMath.udcos(298945.031 * T + 259.589); beta = (6.7057 + 0.0017 * T) * UdMath.udcos(149472.886 * T + 113.919); beta += (1.4396 + 0.0005 * T) * UdMath.udcos(0.37 * T + 119.12); beta += (1.3643 + 0.0005 * T) * UdMath.udcos(298945.40 * T + 288.71); radius = 0.395283 + 0.000002 * T; radius += (0.078341 + 0.000008 * T) * UdMath.udcos(149472.515 * T + 354.795); radius += (0.007955 + 0.000002 * T) * UdMath.udcos(298945.03 * T + 169.59); break; case Planet.URANUS: ParamL = UranusLambda; ParamB = UranusBeta; ParamR = UranusR; lambda = 313.33676 + 428.72880 * T; lambda += 3.20671 * T * UdMath.udcos(705.15539 * T + 114.02740); lambda += 2.69325 * T * UdMath.udcos(597.77389 * T + 317.76510); lambda += 0.00015 * T * UdMath.udcos(3798.6 * T + 313.4); beta = -0.02997; beta += 1.78488 * T * UdMath.udcos(507.52281 * T + 188.32394); beta += 0.56518 * T * UdMath.udcos(892.2869 * T + 354.9571); beta += 0.00036 * T * UdMath.udcos(1526.5 * T + 263.0); radius = 19.203034 + 0.042617 * T; radius += 0.361949 * T * UdMath.udcos(440.702 * T + 19.879); radius += 0.166685 * T * UdMath.udcos(702.024 * T + 307.419); break; case Planet.NEPTUNE: ParamL = NeptuneLambda; ParamB = NeptuneBeta; ParamR = NeptuneR; lambda = -55.13323 + 219.93503 * T; lambda += 0.04403 * T * UdMath.udcos(684.128 * T + 332.797); lambda += 0.02928 * T * UdMath.udcos(904.371 * T + 342.114); beta = 0.01725; radius = 30.073033; radius += 0.009784 * T * UdMath.udcos(515.2 * T + 195.7); break; case Planet.PLUTO: ParamL = PlutoLambda; ParamB = PlutoBeta; ParamR = PlutoR; lambda = 241.82574 + 179.09519 * T; beta = -2.30285; radius = 38.662489; radius += 0.007619 * T * UdMath.udcos(1425.9 * T + 31.0); radius += 0.002543 * T * UdMath.udcos(2196.1 * T + 199.5); break; default: throw new ArithmeticException(); } for (int i = 0; i < ParamL.GetLength(0); i++) { lambda += ParamL[i].a * UdMath.udcos(ParamL[i].b * T + ParamL[i].c); } lambda = UdMath.deg2rad(UdMath.degmal(lambda)); for (int i = 0; i < ParamB.GetLength(0); i++) { beta += ParamB[i].a * UdMath.udcos(ParamB[i].b * T + ParamB[i].c); } beta = UdMath.deg2rad(beta); for (int i = 0; i < ParamR.GetLength(0); i++) { radius += ParamR[i].a * UdMath.udcos(ParamR[i].b * T + ParamR[i].c); } return(new Xyz(radius * Math.Cos(beta) * Math.Cos(lambda), radius * Math.Cos(beta) * Math.Sin(lambda), radius * Math.Sin(beta))); }
/// <summary> /// Get Position of Jupiter and Saturn /// </summary> /// <param name="planetNo"></param> /// <param name="T"></param> /// <returns></returns> private static Xyz GetPosExp2(int planetNo, double T) { PlanetExpP0[] ParamN, ParamB, ParamQ; PlanetExpP2 ParamP; double q, N; switch (planetNo) { case Planet.JUPITER: ParamN = JupiterN; ParamB = JupiterB; ParamQ = JupiterQ; ParamP = JupiterP; N = 341.5208 + 30.34907 * T; N += (0.0350 + 0.00028 * T) * UdMath.udsin(245.94 - 30.349 * T) + 0.0004; N -= (0.0019 + 0.00002 * T) * UdMath.udsin(162.78 + 0.38 * T); q = (0.000132 + 0.0000011 * T) * UdMath.udcos(245.93 - 30.349 * T); break; case Planet.SATURN: ParamN = SaturnN; ParamB = SaturnB; ParamQ = SaturnQ; ParamP = SaturnP; N = 12.3042 + 12.22117 * T; N += (0.0934 + 0.00075 * T) * UdMath.udsin(250.29 + 12.221 * T) + 0.0008; N += (0.0057 + 0.00005 * T) * UdMath.udsin(265.8 - 11.81 * T); N += (0.0049 + 0.00004 * T) * UdMath.udsin(162.7 + 0.38 * T); N += (0.0019 + 0.00002 * T) * UdMath.udsin(262.0 + 24.44 * T); q = (0.000354 + 0.0000028 * T) * UdMath.udcos(70.28 + 12.22 * T) + 0.000183; q += (0.000021 + 0.0000002 * T) * UdMath.udcos(265.80 - 11.81 * T); break; default: throw new ArithmeticException(); } // Lambda for (int i = 0; i < ParamN.GetLength(0); i++) { N += ParamN[i].a * UdMath.udsin(ParamN[i].b + ParamN[i].c * T); } double f = N + ParamP.f1 * UdMath.udsin(N) + ParamP.f2 * UdMath.udsin(2.0 * N) + ParamP.f3 * UdMath.udsin(3.0 * N) + ParamP.f4 * UdMath.udsin(4.0 * N); double V = ParamP.V1 * UdMath.udsin(2.0 * f + ParamP.V2); double lambda = UdMath.deg2rad(UdMath.degmal(f + V + ParamP.L1 + ParamP.L2 * T)); // Beta double beta = Math.Asin(ParamP.B1 * UdMath.udsin(f + ParamP.B2)) + UdMath.deg2rad((ParamP.B3 + ParamP.B4 * T) * UdMath.udsin(f + ParamP.B5)); for (int i = 0; i < ParamB.GetLength(0); i++) { beta += ParamB[i].a * UdMath.udsin(ParamB[i].b + ParamB[i].c * T); } // Radius for (int i = 0; i < ParamQ.GetLength(0); i++) { q += ParamQ[i].a * UdMath.udcos(ParamQ[i].b + ParamQ[i].c * T); } double r = Math.Pow(10.0, q); double radius = r * ParamP.r1 / (1.0 + ParamP.r2 * UdMath.udcos(f)); return(new Xyz(radius * Math.Cos(beta) * Math.Cos(lambda), radius * Math.Cos(beta) * Math.Sin(lambda), radius * Math.Sin(beta))); }