//Conversion functions
    public static COR Equatorial2TopocentricDelta(double Alpha, double Delta, double Distance, double Longitude, double Latitude, double Height, double JD)
    {
        double RhoSinThetaPrime = CAAGlobe.RhoSinThetaPrime(Latitude, Height);
        double RhoCosThetaPrime = CAAGlobe.RhoCosThetaPrime(Latitude, Height);

        //Calculate the Sidereal time
        double theta = CAASidereal.ApparentGreenwichSiderealTime(JD);

        //Convert to radians
        Delta = CT.D2R(Delta);
        double cosDelta = Math.Cos(Delta);

        //Calculate the Parallax
        double pi = Math.Asin(GFX.g_AAParallax_C1 / Distance);

        //Calculate the hour angle
        double H    = CT.H2R(theta - Longitude / 15 - Alpha);
        double cosH = Math.Cos(H);
        double sinH = Math.Sin(H);

        COR DeltaTopocentric = new COR();

        DeltaTopocentric.X = CT.R2H(-pi * RhoCosThetaPrime * sinH / cosDelta);
        DeltaTopocentric.Y = CT.R2D(-pi * (RhoSinThetaPrime * cosDelta - RhoCosThetaPrime * cosH * Math.Sin(Delta)));
        return(DeltaTopocentric);
    }
//Static methods
//Tangible Process Only End


    ////////////////////////////////// Implementation /////////////////////////////

    public static CAABinaryStarDetails Calculate(double t, double P, double T, double e, double a, double i, double omega, double w)
    {
        double n = 360 / P;
        double M = CT.M360(n * (t - T));
        double E = CAAKepler.Calculate(M, e);

        E     = CT.D2R(E);
        i     = CT.D2R(i);
        w     = CT.D2R(w);
        omega = CT.D2R(omega);

        CAABinaryStarDetails details = new CAABinaryStarDetails();

        details.r = a * (1 - e * Math.Cos(E));

        double v = Math.Atan(Math.Sqrt((1 + e) / (1 - e)) * Math.Tan(E / 2)) * 2;

        details.Theta = Math.Atan2(Math.Sin(v + w) * Math.Cos(i), Math.Cos(v + w)) + omega;
        details.Theta = CT.M360(CT.R2D(details.Theta));

        double sinvw = Math.Sin(v + w);
        double cosvw = Math.Cos(v + w);
        double cosi  = Math.Cos(i);

        details.Rho = details.r * Math.Sqrt((sinvw * sinvw * cosi * cosi) + (cosvw * cosvw));

        return(details);
    }
    public static COR Equatorial2Topocentric(double Alpha, double Delta, double Distance, double Longitude, double Latitude, double Height, double JD)
    {
        double RhoSinThetaPrime = CAAGlobe.RhoSinThetaPrime(Latitude, Height);
        double RhoCosThetaPrime = CAAGlobe.RhoCosThetaPrime(Latitude, Height);

        //Calculate the Sidereal time
        double theta = CAASidereal.ApparentGreenwichSiderealTime(JD);

        //Convert to radians
        Delta = CT.D2R(Delta);
        double cosDelta = Math.Cos(Delta);

        //Calculate the Parallax
        double pi    = Math.Asin(GFX.g_AAParallax_C1 / Distance);
        double sinpi = Math.Sin(pi);

        //Calculate the hour angle
        double H    = CT.H2R(theta - Longitude / 15 - Alpha);
        double cosH = Math.Cos(H);
        double sinH = Math.Sin(H);

        //Calculate the adjustment in right ascension
        double DeltaAlpha = Math.Atan2(-RhoCosThetaPrime * sinpi * sinH, cosDelta - RhoCosThetaPrime * sinpi * cosH);

        COR Topocentric = new COR();

        Topocentric.X = CT.M24(Alpha + CT.R2H(DeltaAlpha));
        Topocentric.Y = CT.R2D(Math.Atan2((Math.Sin(Delta) - RhoSinThetaPrime * sinpi) * Math.Cos(DeltaAlpha), cosDelta - RhoCosThetaPrime * sinpi * cosH));

        return(Topocentric);
    }
    public static CAAEclipticalElementDetails FK4B1950ToFK5J2000(double i0, double w0, double omega0)
    {
        //convert to radians
        double L         = CT.D2R(5.19856209);
        double J         = CT.D2R(0.00651966);
        double i0rad     = CT.D2R(i0);
        double omega0rad = CT.D2R(omega0);
        double sini0rad  = Math.Sin(i0rad);
        double cosi0rad  = Math.Cos(i0rad);

        //Calculate some values used later
        double cosJ = Math.Cos(J);
        double sinJ = Math.Sin(J);
        double W    = L + omega0rad;
        double cosW = Math.Cos(W);
        double sinW = Math.Sin(W);
        double A    = sinJ * sinW;
        double B    = sini0rad * cosJ + cosi0rad * sinJ * cosW;

        //Calculate the values
        CAAEclipticalElementDetails details = new CAAEclipticalElementDetails();

        details.i = CT.R2D(Math.Asin(Math.Sqrt(A * A + B * B)));
        double cosi = cosi0rad * cosJ - sini0rad * sinJ * cosW;

        if (cosi < 0)
        {
            details.i = 180 - details.i;
        }

        details.w     = CT.M360(w0 + CT.R2D(Math.Atan2(A, B)));
        details.omega = CT.M360(CT.R2D(Math.Atan2(sini0rad * sinW, cosi0rad * sinJ + sini0rad * cosJ * cosW)) - 4.50001688);

        return(details);
    }
Beispiel #5
0
//Static methods

    /////////////////////////////// Implementation ////////////////////////////////

    public static double EclipticLongitude(double JD)
    {
        double rho        = (JD - 2451545) / 365250;
        double rhosquared = rho * rho;
        double rhocubed   = rhosquared * rho;
        double rho4       = rhocubed * rho;

        //Calculate L0
        int    nL0Coefficients = GFX.g_L0UranusCoefficients.Length;
        double L0 = 0;
        int    i;

        for (i = 0; i < nL0Coefficients; i++)
        {
            L0 += GFX.g_L0UranusCoefficients[i].A * Math.Cos(GFX.g_L0UranusCoefficients[i].B + GFX.g_L0UranusCoefficients[i].C * rho);
        }

        //Calculate L1
        int    nL1Coefficients = GFX.g_L1UranusCoefficients.Length;
        double L1 = 0;

        for (i = 0; i < nL1Coefficients; i++)
        {
            L1 += GFX.g_L1UranusCoefficients[i].A * Math.Cos(GFX.g_L1UranusCoefficients[i].B + GFX.g_L1UranusCoefficients[i].C * rho);
        }

        //Calculate L2
        int    nL2Coefficients = GFX.g_L2UranusCoefficients.Length;
        double L2 = 0;

        for (i = 0; i < nL2Coefficients; i++)
        {
            L2 += GFX.g_L2UranusCoefficients[i].A * Math.Cos(GFX.g_L2UranusCoefficients[i].B + GFX.g_L2UranusCoefficients[i].C * rho);
        }

        //Calculate L3
        int    nL3Coefficients = GFX.g_L3UranusCoefficients.Length;
        double L3 = 0;

        for (i = 0; i < nL3Coefficients; i++)
        {
            L3 += GFX.g_L3UranusCoefficients[i].A * Math.Cos(GFX.g_L3UranusCoefficients[i].B + GFX.g_L3UranusCoefficients[i].C * rho);
        }

        //Calculate L4
        int    nL4Coefficients = GFX.g_L4UranusCoefficients.Length;
        double L4 = 0;

        for (i = 0; i < nL4Coefficients; i++)
        {
            L4 += GFX.g_L4UranusCoefficients[i].A * Math.Cos(GFX.g_L4UranusCoefficients[i].B + GFX.g_L4UranusCoefficients[i].C * rho);
        }


        double @value = (L0 + L1 * rho + L2 * rhosquared + L3 * rhocubed + L4 * rho4) / 100000000;

        //convert results back to degrees
        @value = CT.M360(CT.R2D(@value));
        return(@value);
    }
    public static double EclipticLatitude(double JD)
    {
        double rho        = (JD - 2451545) / 365250;
        double rhosquared = rho * rho;
        double rhocubed   = rhosquared * rho;
        double rho4       = rhocubed * rho;

        //Calculate B0
        int    nB0Coefficients = GFX.g_B0VenusCoefficients.Length;
        double B0 = 0;
        int    i;

        for (i = 0; i < nB0Coefficients; i++)
        {
            B0 += GFX.g_B0VenusCoefficients[i].A * Math.Cos(GFX.g_B0VenusCoefficients[i].B + GFX.g_B0VenusCoefficients[i].C * rho);
        }

        //Calculate B1
        int    nB1Coefficients = GFX.g_B1VenusCoefficients.Length;
        double B1 = 0;

        for (i = 0; i < nB1Coefficients; i++)
        {
            B1 += GFX.g_B1VenusCoefficients[i].A * Math.Cos(GFX.g_B1VenusCoefficients[i].B + GFX.g_B1VenusCoefficients[i].C * rho);
        }

        //Calculate B2
        int    nB2Coefficients = GFX.g_B2VenusCoefficients.Length;
        double B2 = 0;

        for (i = 0; i < nB2Coefficients; i++)
        {
            B2 += GFX.g_B2VenusCoefficients[i].A * Math.Cos(GFX.g_B2VenusCoefficients[i].B + GFX.g_B2VenusCoefficients[i].C * rho);
        }

        //Calculate B3
        int    nB3Coefficients = GFX.g_B3VenusCoefficients.Length;
        double B3 = 0;

        for (i = 0; i < nB3Coefficients; i++)
        {
            B3 += GFX.g_B3VenusCoefficients[i].A * Math.Cos(GFX.g_B3VenusCoefficients[i].B + GFX.g_B3VenusCoefficients[i].C * rho);
        }

        //Calculate B4
        int    nB4Coefficients = GFX.g_B4VenusCoefficients.Length;
        double B4 = 0;

        for (i = 0; i < nB4Coefficients; i++)
        {
            B4 += GFX.g_B4VenusCoefficients[i].A * Math.Cos(GFX.g_B4VenusCoefficients[i].B + GFX.g_B4VenusCoefficients[i].C * rho);
        }

        double @value = (B0 + B1 * rho + B2 * rhosquared + B3 * rhocubed + B4 * rho4) / 100000000;

        //convert results back to degrees
        @value = CT.R2D(@value);
        return(@value);
    }
Beispiel #7
0
    public static double PhaseAngle(double GeocentricElongation, double EarthObjectDistance, double EarthSunDistance)
    {
        //Convert from degrees to radians
        GeocentricElongation = CT.D2R(GeocentricElongation);

        //Return the result
        return(CT.M360(CT.R2D(Math.Atan2(EarthSunDistance * Math.Sin(GeocentricElongation), EarthObjectDistance - EarthSunDistance * Math.Cos(GeocentricElongation)))));
    }
Beispiel #8
0
//Static methods

    ////////////////////// Implementation /////////////////////////////////////////

    public static double ParallacticAngle(double HourAngle, double Latitude, double delta)
    {
        HourAngle = CT.H2R(HourAngle);
        Latitude  = CT.D2R(Latitude);
        delta     = CT.D2R(delta);

        return(CT.R2D(Math.Atan2(Math.Sin(HourAngle), Math.Tan(Latitude) * Math.Cos(delta) - Math.Sin(delta) * Math.Cos(HourAngle))));
    }
//Static methods

    /////////////////////////// Implementation ////////////////////////////////////

    public static CAAEclipticalElementDetails Calculate(double i0, double w0, double omega0, double JD0, double JD)
    {
        double T        = (JD0 - 2451545.0) / 36525;
        double Tsquared = T * T;
        double t        = (JD - JD0) / 36525;
        double tsquared = t * t;
        double tcubed   = tsquared * t;

        //Now convert to radians
        double i0rad     = CT.D2R(i0);
        double omega0rad = CT.D2R(omega0);

        double eta = (47.0029 - 0.06603 * T + 0.000598 * Tsquared) * t + (-0.03302 + 0.000598 * T) * tsquared + 0.00006 * tcubed;

        eta = CT.D2R(CT.DMS2D(0, 0, eta));

        double pi = 174.876384 * 3600 + 3289.4789 * T + 0.60622 * Tsquared - (869.8089 + 0.50491 * T) * t + 0.03536 * tsquared;

        pi = CT.D2R(CT.DMS2D(0, 0, pi));

        double p = (5029.0966 + 2.22226 * T - 0.000042 * Tsquared) * t + (1.11113 - 0.000042 * T) * tsquared - 0.000006 * tcubed;

        p = CT.D2R(CT.DMS2D(0, 0, p));

        double sini0rad        = Math.Sin(i0rad);
        double cosi0rad        = Math.Cos(i0rad);
        double sinomega0rad_pi = Math.Sin(omega0rad - pi);
        double cosomega0rad_pi = Math.Cos(omega0rad - pi);
        double sineta          = Math.Sin(eta);
        double coseta          = Math.Cos(eta);
        double A    = sini0rad * sinomega0rad_pi;
        double B    = -sineta * cosi0rad + coseta * sini0rad * cosomega0rad_pi;
        double irad = Math.Asin(Math.Sqrt(A * A + B * B));

        CAAEclipticalElementDetails details = new CAAEclipticalElementDetails();

        details.i = CT.R2D(irad);
        double cosi = cosi0rad * coseta + sini0rad * sineta * cosomega0rad_pi;

        if (cosi < 0)
        {
            details.i = 180 - details.i;
        }

        double phi = pi + p;

        details.omega = CT.M360(CT.R2D(Math.Atan2(A, B) + phi));

        A = -sineta * sinomega0rad_pi;
        B = sini0rad * coseta - cosi0rad * sineta * cosomega0rad_pi;
        double deltaw = CT.R2D(Math.Atan2(A, B));

        details.w = CT.M360(w0 + deltaw);

        return(details);
    }
Beispiel #10
0
    public static double AngleBetweenEclipticAndHorizon(double LocalSiderealTime, double ObliquityOfEcliptic, double Latitude)
    {
        LocalSiderealTime   = CT.H2R(LocalSiderealTime);
        Latitude            = CT.D2R(Latitude);
        ObliquityOfEcliptic = CT.D2R(ObliquityOfEcliptic);

        double @value = CT.R2D(Math.Acos(Math.Cos(ObliquityOfEcliptic) * Math.Sin(Latitude) - Math.Sin(ObliquityOfEcliptic) * Math.Cos(Latitude) * Math.Sin(LocalSiderealTime)));

        return(CT.M360(@value));
    }
Beispiel #11
0
    public static double EclipticLongitudeOnHorizon(double LocalSiderealTime, double ObliquityOfEcliptic, double Latitude)
    {
        LocalSiderealTime   = CT.H2R(LocalSiderealTime);
        Latitude            = CT.D2R(Latitude);
        ObliquityOfEcliptic = CT.D2R(ObliquityOfEcliptic);

        double @value = CT.R2D(Math.Atan2(-Math.Cos(LocalSiderealTime), Math.Sin(ObliquityOfEcliptic) * Math.Tan(Latitude) + Math.Cos(ObliquityOfEcliptic) * Math.Sin(LocalSiderealTime)));

        return(CT.M360(@value));
    }
    public static double PhaseAngle2(double R, double R0, double B, double L, double L0, double Delta)
    {
        //Convert from degrees to radians
        B  = CT.D2R(B);
        L  = CT.D2R(L);
        L0 = CT.D2R(L0);

        //Return the result
        return(CT.M360(CT.R2D(Math.Acos((R - R0 * Math.Cos(B) * Math.Cos(L - L0)) / Delta))));
    }
    public static double PhaseAngleRectangular(double x, double y, double z, double B, double L, double Delta)
    {
        //Convert from degrees to radians
        B = CT.D2R(B);
        L = CT.D2R(L);
        double cosB = Math.Cos(B);

        //Return the result
        return(CT.M360(CT.R2D(Math.Acos((x * cosB * Math.Cos(L) + y * cosB * Math.Sin(L) + z * Math.Sin(B)) / Delta))));
    }
Beispiel #14
0
    public static double PositionAngle(double Alpha0, double Delta0, double Alpha, double Delta)
    {
        //Convert to radians
        Alpha0 = CT.H2R(Alpha0);
        Alpha  = CT.H2R(Alpha);
        Delta0 = CT.D2R(Delta0);
        Delta  = CT.D2R(Delta);

        return(CT.M360(CT.R2D(Math.Atan2(Math.Cos(Delta0) * Math.Sin(Alpha0 - Alpha), Math.Sin(Delta0) * Math.Cos(Delta) - Math.Cos(Delta0) * Math.Sin(Delta) * Math.Cos(Alpha0 - Alpha)))));
    }
Beispiel #15
0
    public static double AngleBetweenNorthCelestialPoleAndNorthPoleOfEcliptic(double Lambda, double Beta, double ObliquityOfEcliptic)
    {
        Lambda = CT.D2R(Lambda);
        Beta   = CT.D2R(Beta);
        ObliquityOfEcliptic = CT.D2R(ObliquityOfEcliptic);

        double @value = CT.R2D(Math.Atan2(Math.Cos(Lambda) * Math.Tan(ObliquityOfEcliptic), Math.Sin(Beta) * Math.Sin(Lambda) * Math.Tan(ObliquityOfEcliptic) - Math.Cos(Beta)));

        return(CT.M360(@value));
    }
Beispiel #16
0
//Static methods

    //////////////////// Implementation ///////////////////////////////////////////

    public static double GeocentricElongation(double ObjectAlpha, double ObjectDelta, double SunAlpha, double SunDelta)
    {
        //Convert the RA's to radians
        ObjectAlpha = CT.D2R(ObjectAlpha * 15);
        SunAlpha    = CT.D2R(SunAlpha * 15);

        //Convert the declinations to radians
        ObjectDelta = CT.D2R(ObjectDelta);
        SunDelta    = CT.D2R(SunDelta);

        //Return the result
        return(CT.R2D(Math.Acos(Math.Sin(SunDelta) * Math.Sin(ObjectDelta) + Math.Cos(SunDelta) * Math.Cos(ObjectDelta) * Math.Cos(SunAlpha - ObjectAlpha))));
    }
Beispiel #17
0
//C++ TO C# CONVERTER NOTE: C# does not allow default values for parameters. Overloaded methods are inserted above.
//ORIGINAL LINE: static double Calculate(double M, double e, int nIterations = 53)
    public static double CalculateIter(double M, double e, int nIterations)
    {
        //Convert from degrees to radians
        M = CT.D2R(M);
        double PI = CT.PI();

        double F = 1;

        if (M < 0)
        {
            F = -1;
        }
        M = Math.Abs(M) / (2 * PI);
        M = (M - (int)(M)) * 2 * PI * F;
        if (M < 0)
        {
            M += 2 * PI;
        }
        F = 1;
        if (M > PI)
        {
            F = -1;
        }
        if (M > PI)
        {
            M = 2 * PI - M;
        }

        double E     = PI / 2;
        double scale = PI / 4;

        for (int i = 0; i < nIterations; i++)
        {
            double R = E - e * Math.Sin(E);
            if (M > R)
            {
                E += scale;
            }
            else
            {
                E -= scale;
            }
            scale /= 2;
        }

        //Convert the result back to degrees
        return(CT.R2D(E) * F);
    }
    public static double TopocentricMoonSemidiameter(double DistanceDelta, double Delta, double H, double Latitude, double Height)
    {
        //Convert to radians
        H     = CT.H2R(H);
        Delta = CT.D2R(Delta);

        double pi = Math.Asin(6378.14 / DistanceDelta);
        double A  = Math.Cos(Delta) * Math.Sin(H);
        double B  = Math.Cos(Delta) * Math.Cos(H) - CAAGlobe.RhoCosThetaPrime(Latitude, Height) * Math.Sin(pi);
        double C  = Math.Sin(Delta) - CAAGlobe.RhoSinThetaPrime(Latitude, Height) * Math.Sin(pi);
        double q  = Math.Sqrt(A * A + B * B + C * C);

        double s = CT.D2R(GeocentricMoonSemidiameter(DistanceDelta) / 3600);

        return(CT.R2D(Math.Asin(Math.Sin(s) / q)) * 3600);
    }
    public static CAATopocentricEclipticDetails Ecliptic2Topocentric(double Lambda, double Beta, double Semidiameter, double Distance, double Epsilon, double Longitude, double Latitude, double Height, double JD)
    {
        double S = CAAGlobe.RhoSinThetaPrime(Latitude, Height);
        double C = CAAGlobe.RhoCosThetaPrime(Latitude, Height);

        //Convert to radians
        Lambda       = CT.D2R(Lambda);
        Beta         = CT.D2R(Beta);
        Epsilon      = CT.D2R(Epsilon);
        Longitude    = CT.D2R(Longitude);
        Latitude     = CT.D2R(Latitude);
        Semidiameter = CT.D2R(Semidiameter);
        double sine    = Math.Sin(Epsilon);
        double cose    = Math.Cos(Epsilon);
        double cosBeta = Math.Cos(Beta);
        double sinBeta = Math.Sin(Beta);

        //Calculate the Sidereal time
        double theta = CAASidereal.ApparentGreenwichSiderealTime(JD);

        theta = CT.H2R(theta);
        double sintheta = Math.Sin(theta);

        //Calculate the Parallax
        double pi    = Math.Asin(GFX.g_AAParallax_C1 / Distance);
        double sinpi = Math.Sin(pi);

        double N = Math.Cos(Lambda) * cosBeta - C * sinpi * Math.Cos(theta);

        CAATopocentricEclipticDetails Topocentric = new CAATopocentricEclipticDetails();

        Topocentric.Lambda = Math.Atan2(Math.Sin(Lambda) * cosBeta - sinpi * (S * sine + C * cose * sintheta), N);
        double cosTopocentricLambda = Math.Cos(Topocentric.Lambda);

        Topocentric.Beta         = Math.Atan(cosTopocentricLambda * (sinBeta - sinpi * (S * cose - C * sine * sintheta)) / N);
        Topocentric.Semidiameter = Math.Asin(cosTopocentricLambda * Math.Cos(Topocentric.Beta) * Math.Sin(Semidiameter) / N);

        //Convert back to degrees
        Topocentric.Semidiameter = CT.R2D(Topocentric.Semidiameter);
        Topocentric.Lambda       = CT.M360(CT.R2D(Topocentric.Lambda));
        Topocentric.Beta         = CT.R2D(Topocentric.Beta);

        return(Topocentric);
    }
Beispiel #20
0
    public static COR EquatorialAberration(double Alpha, double Delta, double JD)
    {
        //Convert to radians
        Alpha = CT.D2R(Alpha * 15);
        Delta = CT.D2R(Delta);

        double cosAlpha = Math.Cos(Alpha);
        double sinAlpha = Math.Sin(Alpha);
        double cosDelta = Math.Cos(Delta);
        double sinDelta = Math.Sin(Delta);

        C3D velocity = EarthVelocity(JD);

        //What is the return value
        COR aberration = new COR();

        aberration.X = CT.R2H((velocity.Y * cosAlpha - velocity.X * sinAlpha) / (17314463350.0 * cosDelta));
        aberration.Y = CT.R2D(-(((velocity.X * cosAlpha + velocity.Y * sinAlpha) * sinDelta - velocity.Z * cosDelta) / 17314463350.0));

        return(aberration);
    }
    public static COR AdjustPositionUsingMotionInSpace(double r, double DeltaR, double t, double Alpha, double Delta, double PMAlpha, double PMDelta)
    {
        //Convert DeltaR from km/s to Parsecs / Year
        DeltaR /= 977792;

        //Convert from seconds of time to Radians / Year
        PMAlpha /= 13751;

        //Convert from seconds of arc to Radians / Year
        PMDelta /= 206265;

        //Now convert to radians
        Alpha = CT.H2R(Alpha);
        Delta = CT.D2R(Delta);

        double x = r * Math.Cos(Delta) * Math.Cos(Alpha);
        double y = r * Math.Cos(Delta) * Math.Sin(Alpha);
        double z = r * Math.Sin(Delta);

        double DeltaX = x / r * DeltaR - z * PMDelta * Math.Cos(Alpha) - y * PMAlpha;
        double DeltaY = y / r * DeltaR - z * PMDelta * Math.Sin(Alpha) + x * PMAlpha;
        double DeltaZ = z / r * DeltaR + r * PMDelta * Math.Cos(Delta);

        x += t * DeltaX;
        y += t * DeltaY;
        z += t * DeltaZ;

        COR @value = new COR();

        @value.X = CT.R2H(Math.Atan2(y, x));
        if (@value.X < 0)
        {
            @value.X += 24;
        }

        @value.Y = CT.R2D(Math.Atan2(z, Math.Sqrt(x * x + y * y)));

        return(@value);
    }
    public static COR PrecessEcliptic(double Lambda, double Beta, double JD0, double JD)
    {
        double T        = (JD0 - 2451545.0) / 36525;
        double Tsquared = T * T;
        double t        = (JD - JD0) / 36525;
        double tsquared = t * t;
        double tcubed   = tsquared * t;

        //Now convert to radians
        Lambda = CT.D2R(Lambda);
        Beta   = CT.D2R(Beta);

        double eta = (47.0029 - 0.06603 * T + 0.000598 * Tsquared) * t + (-0.03302 + 0.000598 * T) * tsquared + 0.00006 * tcubed;

        eta = CT.D2R(CT.DMS2D(0, 0, eta));

        double pi = 174.876384 * 3600 + 3289.4789 * T + 0.60622 * Tsquared - (869.8089 + 0.50491 * T) * t + 0.03536 * tsquared;

        pi = CT.D2R(CT.DMS2D(0, 0, pi));

        double p = (5029.0966 + 2.22226 * T - 0.000042 * Tsquared) * t + (1.11113 - 0.000042 * T) * tsquared - 0.000006 * tcubed;

        p = CT.D2R(CT.DMS2D(0, 0, p));

        double A = Math.Cos(eta) * Math.Cos(Beta) * Math.Sin(pi - Lambda) - Math.Sin(eta) * Math.Sin(Beta);
        double B = Math.Cos(Beta) * Math.Cos(pi - Lambda);
        double C = Math.Cos(eta) * Math.Sin(Beta) + Math.Sin(eta) * Math.Cos(Beta) * Math.Sin(pi - Lambda);

        COR @value = new COR();

        @value.X = CT.R2D(p + pi - Math.Atan2(A, B));
        if (@value.X < 0)
        {
            @value.X += 360;
        }
        @value.Y = CT.R2D(Math.Asin(C));

        return(@value);
    }
//Static methods
    public static COR PrecessEquatorial(double Alpha, double Delta, double JD0, double JD)
    {
        double T        = (JD0 - 2451545.0) / 36525;
        double Tsquared = T * T;
        double t        = (JD - JD0) / 36525;
        double tsquared = t * t;
        double tcubed   = tsquared * t;

        //Now convert to radians
        Alpha = CT.H2R(Alpha);
        Delta = CT.D2R(Delta);

        double sigma = (2306.2181 + 1.39656 * T - 0.000139 * Tsquared) * t + (0.30188 - 0.0000344 * T) * tsquared + 0.017988 * tcubed;

        sigma = CT.D2R(CT.DMS2D(0, 0, sigma));

        double zeta = (2306.2181 + 1.39656 * T - 0.000138 * Tsquared) * t + (1.09468 + 0.000066 * T) * tsquared + 0.018203 * tcubed;

        zeta = CT.D2R(CT.DMS2D(0, 0, zeta));

        double phi = (2004.3109 - 0.8533 * T - 0.000217 * Tsquared) * t - (0.42665 + 0.000217 * T) * tsquared - 0.041833 * tcubed;

        phi = CT.D2R(CT.DMS2D(0, 0, phi));

        double A = Math.Cos(Delta) * Math.Sin(Alpha + sigma);
        double B = Math.Cos(phi) * Math.Cos(Delta) * Math.Cos(Alpha + sigma) - Math.Sin(phi) * Math.Sin(Delta);
        double C = Math.Sin(phi) * Math.Cos(Delta) * Math.Cos(Alpha + sigma) + Math.Cos(phi) * Math.Sin(Delta);

        COR @value = new COR();

        @value.X = CT.R2H(Math.Atan2(A, B) + zeta);
        if (@value.X < 0)
        {
            @value.X += 24;
        }
        @value.Y = CT.R2D(Math.Asin(C));

        return(@value);
    }
    public static COR PrecessEquatorialFK4(double Alpha, double Delta, double JD0, double JD)
    {
        double T        = (JD0 - 2415020.3135) / 36524.2199;
        double t        = (JD - JD0) / 36524.2199;
        double tsquared = t * t;
        double tcubed   = tsquared * t;

        //Now convert to radians
        Alpha = CT.H2R(Alpha);
        Delta = CT.D2R(Delta);

        double sigma = (2304.250 + 1.396 * T) * t + 0.302 * tsquared + 0.018 * tcubed;

        sigma = CT.D2R(CT.DMS2D(0, 0, sigma));

        double zeta = 0.791 * tsquared + 0.001 * tcubed;

        zeta  = CT.D2R(CT.DMS2D(0, 0, zeta));
        zeta += sigma;

        double phi = (2004.682 - 0.853 * T) * t - 0.426 * tsquared - 0.042 * tcubed;

        phi = CT.D2R(CT.DMS2D(0, 0, phi));

        double A = Math.Cos(Delta) * Math.Sin(Alpha + sigma);
        double B = Math.Cos(phi) * Math.Cos(Delta) * Math.Cos(Alpha + sigma) - Math.Sin(phi) * Math.Sin(Delta);
        double C = Math.Sin(phi) * Math.Cos(Delta) * Math.Cos(Alpha + sigma) + Math.Cos(phi) * Math.Sin(Delta);

        COR @value = new COR();

        @value.X = CT.R2H(Math.Atan2(A, B) + zeta);
        if (@value.X < 0)
        {
            @value.X += 24;
        }
        @value.Y = CT.R2D(Math.Asin(C));

        return(@value);
    }
    //Static methods

    //////////////////////////// Implementation ///////////////////////////////////

    public static double Separation(double Alpha1, double Delta1, double Alpha2, double Delta2)
    {
        Delta1 = CT.D2R(Delta1);
        Delta2 = CT.D2R(Delta2);

        Alpha1 = CT.H2R(Alpha1);
        Alpha2 = CT.H2R(Alpha2);

        double x = Math.Cos(Delta1) * Math.Sin(Delta2) - Math.Sin(Delta1) * Math.Cos(Delta2) * Math.Cos(Alpha2 - Alpha1);
        double y = Math.Cos(Delta2) * Math.Sin(Alpha2 - Alpha1);
        double z = Math.Sin(Delta1) * Math.Sin(Delta2) + Math.Cos(Delta1) * Math.Cos(Delta2) * Math.Cos(Alpha2 - Alpha1);

        double @value = Math.Atan2(Math.Sqrt(x * x + y * y), z);

        @value = CT.R2D(@value);
        if (@value < 0)
        {
            @value += 180;
        }

        return(@value);
    }
    public static double PositionAngle(double alpha1, double delta1, double alpha2, double delta2)
    {
        double Alpha1;
        double Delta1;
        double Alpha2;
        double Delta2;

        Delta1 = CT.D2R(delta1);
        Delta2 = CT.D2R(delta2);

        Alpha1 = CT.H2R(alpha1);
        Alpha2 = CT.H2R(alpha2);

        double DeltaAlpha  = Alpha1 - Alpha2;
        double demoninator = Math.Cos(Delta2) * Math.Tan(Delta1) - Math.Sin(Delta2) * Math.Cos(DeltaAlpha);
        double numerator   = Math.Sin(DeltaAlpha);
        double @value      = Math.Atan2(numerator, demoninator);

        @value = CT.R2D(@value);

        return(@value);
    }
    public static double DistanceFromGreatArc(double Alpha1, double Delta1, double Alpha2, double Delta2, double Alpha3, double Delta3)
    {
        Delta1 = CT.D2R(Delta1);
        Delta2 = CT.D2R(Delta2);
        Delta3 = CT.D2R(Delta3);

        Alpha1 = CT.H2R(Alpha1);
        Alpha2 = CT.H2R(Alpha2);
        Alpha3 = CT.H2R(Alpha3);

        double X1 = Math.Cos(Delta1) * Math.Cos(Alpha1);
        double X2 = Math.Cos(Delta2) * Math.Cos(Alpha2);

        double Y1 = Math.Cos(Delta1) * Math.Sin(Alpha1);
        double Y2 = Math.Cos(Delta2) * Math.Sin(Alpha2);

        double Z1 = Math.Sin(Delta1);
        double Z2 = Math.Sin(Delta2);

        double A = Y1 * Z2 - Z1 * Y2;
        double B = Z1 * X2 - X1 * Z2;
        double C = X1 * Y2 - Y1 * X2;

        double m = Math.Tan(Alpha3);
        double n = Math.Tan(Delta3) / Math.Cos(Alpha3);

        double @value = Math.Asin((A + B * m + C * n) / (Math.Sqrt(A * A + B * B + C * C) * Math.Sqrt(1 + m * m + n * n)));

        @value = CT.R2D(@value);
        if (@value < 0)
        {
            @value = Math.Abs(@value);
        }

        return(@value);
    }
//Static methods

    //////////////////////////////// Implementation ///////////////////////////////

    public static CAAPhysicalSunDetails Calculate(double JD)
    {
        double theta = CT.M360((JD - 2398220) * 360 / 25.38);
        double I     = 7.25;
        double K     = 73.6667 + 1.3958333 * (JD - 2396758) / 36525;

        //Calculate the apparent longitude of the sun (excluding the effect of nutation)
        double L           = CAAEarth.EclipticLongitude(JD);
        double R           = CAAEarth.RadiusVector(JD);
        double SunLong     = L + 180 - CT.DMS2D(0, 0, 20.4898 / R);
        double SunLongDash = SunLong + CT.DMS2D(0, 0, CAANutation.NutationInLongitude(JD));

        double epsilon = CAANutation.TrueObliquityOfEcliptic(JD);

        //Convert to radians
        epsilon     = CT.D2R(epsilon);
        SunLong     = CT.D2R(SunLong);
        SunLongDash = CT.D2R(SunLongDash);
        K           = CT.D2R(K);
        I           = CT.D2R(I);
        theta       = CT.D2R(theta);

        double x = Math.Atan(-Math.Cos(SunLong) * Math.Tan(epsilon));
        double y = Math.Atan(-Math.Cos(SunLong - K) * Math.Tan(I));

        CAAPhysicalSunDetails details = new CAAPhysicalSunDetails();

        details.P  = CT.R2D(x + y);
        details.B0 = CT.R2D(Math.Asin(Math.Sin(SunLong - K) * Math.Sin(I)));

        double eta = Math.Atan(Math.Tan(SunLong - K) * Math.Cos(I));

        details.L0 = CT.M360(CT.R2D(eta - theta));

        return(details);
    }
//Static methods

    //////////////////////////////// Implementation ///////////////////////////////

    public static CAAPhysicalJupiterDetails Calculate(double JD)
    {
        //What will be the return value
        CAAPhysicalJupiterDetails details = new CAAPhysicalJupiterDetails();

        //Step 1
        double d         = JD - 2433282.5;
        double T1        = d / 36525;
        double alpha0    = 268.00 + 0.1061 * T1;
        double alpha0rad = CT.D2R(alpha0);
        double delta0    = 64.50 - 0.0164 * T1;
        double delta0rad = CT.D2R(delta0);

        //Step 2
        double W1 = CT.M360(17.710 + 877.90003539 * d);
        double W2 = CT.M360(16.838 + 870.27003539 * d);

        //Step 3
        double l0    = CAAEarth.EclipticLongitude(JD);
        double l0rad = CT.D2R(l0);
        double b0    = CAAEarth.EclipticLatitude(JD);
        double b0rad = CT.D2R(b0);
        double R     = CAAEarth.RadiusVector(JD);

        //Step 4
        double l    = CAAJupiter.EclipticLongitude(JD);
        double lrad = CT.D2R(l);
        double b    = CAAJupiter.EclipticLatitude(JD);
        double brad = CT.D2R(b);
        double r    = CAAJupiter.RadiusVector(JD);

        //Step 5
        double x     = r * Math.Cos(brad) * Math.Cos(lrad) - R * Math.Cos(l0rad);
        double y     = r * Math.Cos(brad) * Math.Sin(lrad) - R * Math.Sin(l0rad);
        double z     = r * Math.Sin(brad) - R * Math.Sin(b0rad);
        double DELTA = Math.Sqrt(x * x + y * y + z * z);

        //Step 6
        l   -= 0.012990 * DELTA / (r * r);
        lrad = CT.D2R(l);

        //Step 7
        x     = r * Math.Cos(brad) * Math.Cos(lrad) - R * Math.Cos(l0rad);
        y     = r * Math.Cos(brad) * Math.Sin(lrad) - R * Math.Sin(l0rad);
        z     = r * Math.Sin(brad) - R * Math.Sin(b0rad);
        DELTA = Math.Sqrt(x * x + y * y + z * z);

        //Step 8
        double e0    = CAANutation.MeanObliquityOfEcliptic(JD);
        double e0rad = CT.D2R(e0);

        //Step 9
        double alphas = Math.Atan2(Math.Cos(e0rad) * Math.Sin(lrad) - Math.Sin(e0rad) * Math.Tan(brad), Math.Cos(lrad));
        double deltas = Math.Asin(Math.Cos(e0rad) * Math.Sin(brad) + Math.Sin(e0rad) * Math.Cos(brad) * Math.Sin(lrad));

        //Step 10
        details.DS = CT.R2D(Math.Asin(-Math.Sin(delta0rad) * Math.Sin(deltas) - Math.Cos(delta0rad) * Math.Cos(deltas) * Math.Cos(alpha0rad - alphas)));

        //Step 11
        double u        = y * Math.Cos(e0rad) - z * Math.Sin(e0rad);
        double v        = y * Math.Sin(e0rad) + z * Math.Cos(e0rad);
        double alpharad = Math.Atan2(u, x);
        double alpha    = CT.R2D(alpharad);
        double deltarad = Math.Atan2(v, Math.Sqrt(x * x + u * u));
        double delta    = CT.R2D(deltarad);
        double xi       = Math.Atan2(Math.Sin(delta0rad) * Math.Cos(deltarad) * Math.Cos(alpha0rad - alpharad) - Math.Sin(deltarad) * Math.Cos(delta0rad), Math.Cos(deltarad) * Math.Sin(alpha0rad - alpharad));

        //Step 12
        details.DE = CT.R2D(Math.Asin(-Math.Sin(delta0rad) * Math.Sin(deltarad) - Math.Cos(delta0rad) * Math.Cos(deltarad) * Math.Cos(alpha0rad - alpharad)));

        //Step 13
        details.Geometricw1 = CT.M360(W1 - CT.R2D(xi) - 5.07033 * DELTA);
        details.Geometricw2 = CT.M360(W2 - CT.R2D(xi) - 5.02626 * DELTA);

        //Step 14
        double C = 57.2958 * (2 * r * DELTA + R * R - r * r - DELTA * DELTA) / (4 * r * DELTA);

        if (Math.Sin(lrad - l0rad) > 0)
        {
            details.Apparentw1 = CT.M360(details.Geometricw1 + C);
            details.Apparentw2 = CT.M360(details.Geometricw2 + C);
        }
        else
        {
            details.Apparentw1 = CT.M360(details.Geometricw1 - C);
            details.Apparentw2 = CT.M360(details.Geometricw2 - C);
        }

        //Step 15
        double NutationInLongitude = CAANutation.NutationInLongitude(JD);
        double NutationInObliquity = CAANutation.NutationInObliquity(JD);

        e0   += NutationInObliquity / 3600;
        e0rad = CT.D2R(e0);

        //Step 16
        alpha   += 0.005693 * (Math.Cos(alpharad) * Math.Cos(l0rad) * Math.Cos(e0rad) + Math.Sin(alpharad) * Math.Sin(l0rad)) / Math.Cos(deltarad);
        alpha    = CT.M360(alpha);
        alpharad = CT.D2R(alpha);
        delta   += 0.005693 * (Math.Cos(l0rad) * Math.Cos(e0rad) * (Math.Tan(e0rad) * Math.Cos(deltarad) - Math.Sin(alpharad) * Math.Sin(deltarad)) + Math.Cos(alpharad) * Math.Sin(deltarad) * Math.Sin(l0rad));
        deltarad = CT.D2R(delta);

        //Step 17
        double NutationRA   = CAANutation.NutationInRightAscension(alpha / 15, delta, e0, NutationInLongitude, NutationInObliquity);
        double alphadash    = alpha + NutationRA / 3600;
        double alphadashrad = CT.D2R(alphadash);
        double NutationDec  = CAANutation.NutationInDeclination(alpha / 15, delta, e0, NutationInLongitude, NutationInObliquity);
        double deltadash    = delta + NutationDec / 3600;
        double deltadashrad = CT.D2R(deltadash);

        NutationRA = CAANutation.NutationInRightAscension(alpha0 / 15, delta0, e0, NutationInLongitude, NutationInObliquity);
        double alpha0dash    = alpha0 + NutationRA / 3600;
        double alpha0dashrad = CT.D2R(alpha0dash);

        NutationDec = CAANutation.NutationInDeclination(alpha0 / 15, delta0, e0, NutationInLongitude, NutationInObliquity);
        double delta0dash    = delta0 + NutationDec / 3600;
        double delta0dashrad = CT.D2R(delta0dash);

        //Step 18
        details.P = CT.M360(CT.R2D(Math.Atan2(Math.Cos(delta0dashrad) * Math.Sin(alpha0dashrad - alphadashrad), Math.Sin(delta0dashrad) * Math.Cos(deltadashrad) - Math.Cos(delta0dashrad) * Math.Sin(deltadashrad) * Math.Cos(alpha0dashrad - alphadashrad))));

        return(details);
    }
//Static methods

    //////////////////////////////// Implementation ///////////////////////////////

    public static CAASaturnRingDetails Calculate(double JD)
    {
        //What will be the return value
        CAASaturnRingDetails details = new CAASaturnRingDetails();

        double T  = (JD - 2451545) / 36525;
        double T2 = T * T;

        //Step 1. Calculate the inclination of the plane of the ring and the longitude of the ascending node referred to the ecliptic and mean equinox of the date
        double i        = 28.075216 - 0.012998 * T + 0.000004 * T2;
        double irad     = CT.D2R(i);
        double omega    = 169.508470 + 1.394681 * T + 0.000412 * T2;
        double omegarad = CT.D2R(omega);

        //Step 2. Calculate the heliocentric longitude, latitude and radius vector of the Earth in the FK5 system
        double l0 = CAAEarth.EclipticLongitude(JD);
        double b0 = CAAEarth.EclipticLatitude(JD);

        l0 += CAAFK5.CorrectionInLongitude(l0, b0, JD);
        double l0rad = CT.D2R(l0);

        b0 += CAAFK5.CorrectionInLatitude(l0, JD);
        double b0rad = CT.D2R(b0);
        double R     = CAAEarth.RadiusVector(JD);

        //Step 3. Calculate the corresponding coordinates l,b,r for Saturn but for the instance t-lightraveltime
        double DELTA = 9;
        double PreviousEarthLightTravelTime = 0;
        double EarthLightTravelTime         = ELL.DistanceToLightTime(DELTA);
        double JD1      = JD - EarthLightTravelTime;
        bool   bIterate = true;
        double x        = 0;
        double y        = 0;
        double z        = 0;
        double l        = 0;
        double b        = 0;
        double r        = 0;

        while (bIterate)
        {
            //Calculate the position of Saturn
            l  = CAASaturn.EclipticLongitude(JD1);
            b  = CAASaturn.EclipticLatitude(JD1);
            l += CAAFK5.CorrectionInLongitude(l, b, JD1);
            b += CAAFK5.CorrectionInLatitude(l, JD1);

            double lrad = CT.D2R(l);
            double brad = CT.D2R(b);
            r = CAASaturn.RadiusVector(JD1);

            //Step 4
            x     = r * Math.Cos(brad) * Math.Cos(lrad) - R * Math.Cos(l0rad);
            y     = r * Math.Cos(brad) * Math.Sin(lrad) - R * Math.Sin(l0rad);
            z     = r * Math.Sin(brad) - R * Math.Sin(b0rad);
            DELTA = Math.Sqrt(x * x + y * y + z * z);
            EarthLightTravelTime = ELL.DistanceToLightTime(DELTA);

            //Prepare for the next loop around
            bIterate = (Math.Abs(EarthLightTravelTime - PreviousEarthLightTravelTime) > 2E-6); //2E-6 corresponds to 0.17 of a second
            if (bIterate)
            {
                JD1 = JD - EarthLightTravelTime;
                PreviousEarthLightTravelTime = EarthLightTravelTime;
            }
        }

        //Step 5. Calculate Saturn's geocentric Longitude and Latitude
        double lambda = Math.Atan2(y, x);
        double beta   = Math.Atan2(z, Math.Sqrt(x * x + y * y));

        //Step 6. Calculate B, a and b
        details.B = Math.Asin(Math.Sin(irad) * Math.Cos(beta) * Math.Sin(lambda - omegarad) - Math.Cos(irad) * Math.Sin(beta));
        details.a = 375.35 / DELTA;
        details.b = details.a * Math.Sin(Math.Abs(details.B));
        details.B = CT.R2D(details.B);

        //Step 7. Calculate the longitude of the ascending node of Saturn's orbit
        double N        = 113.6655 + 0.8771 * T;
        double Nrad     = CT.D2R(N);
        double ldash    = l - 0.01759 / r;
        double ldashrad = CT.D2R(ldash);
        double bdash    = b - 0.000764 * Math.Cos(ldashrad - Nrad) / r;
        double bdashrad = CT.D2R(bdash);

        //Step 8. Calculate Bdash
        details.Bdash = CT.R2D(Math.Asin(Math.Sin(irad) * Math.Cos(bdashrad) * Math.Sin(ldashrad - omegarad) - Math.Cos(irad) * Math.Sin(bdashrad)));

        //Step 9. Calculate DeltaU
        double U1 = Math.Atan2(Math.Sin(irad) * Math.Sin(bdashrad) + Math.Cos(irad) * Math.Cos(bdashrad) * Math.Sin(ldashrad - omegarad), Math.Cos(bdashrad) * Math.Cos(ldashrad - omegarad));
        double U2 = Math.Atan2(Math.Sin(irad) * Math.Sin(beta) + Math.Cos(irad) * Math.Cos(beta) * Math.Sin(lambda - omegarad), Math.Cos(beta) * Math.Cos(lambda - omegarad));

        details.DeltaU = CT.R2D(Math.Abs(U1 - U2));

        //Step 10. Calculate the Nutations
        double Obliquity           = CAANutation.TrueObliquityOfEcliptic(JD);
        double NutationInLongitude = CAANutation.NutationInLongitude(JD);

        //Step 11. Calculate the Ecliptical longitude and latitude of the northern pole of the ring plane
        double lambda0 = omega - 90;
        double beta0   = 90 - i;

        //Step 12. Correct lambda and beta for the aberration of Saturn
        lambda += CT.D2R(0.005693 * Math.Cos(l0rad - lambda) / Math.Cos(beta));
        beta   += CT.D2R(0.005693 * Math.Sin(l0rad - lambda) * Math.Sin(beta));

        //Step 13. Add nutation in longitude to lambda0 and lambda
        //double NLrad = CAACoordinateTransformation::DegreesToRadians(NutationInLongitude/3600);
        lambda   = CT.R2D(lambda);
        lambda  += NutationInLongitude / 3600;
        lambda   = CT.M360(lambda);
        lambda0 += NutationInLongitude / 3600;
        lambda0  = CT.M360(lambda0);

        //Step 14. Convert to equatorial coordinates
        beta = CT.R2D(beta);
        COR    GeocentricEclipticSaturn = CT.Ec2Eq(lambda, beta, Obliquity);
        double alpha = CT.H2R(GeocentricEclipticSaturn.X);
        double delta = CT.D2R(GeocentricEclipticSaturn.Y);
        COR    GeocentricEclipticNorthPole = CT.Ec2Eq(lambda0, beta0, Obliquity);
        double alpha0 = CT.H2R(GeocentricEclipticNorthPole.X);
        double delta0 = CT.D2R(GeocentricEclipticNorthPole.Y);

        //Step 15. Calculate the Position angle
        details.P = CT.R2D(Math.Atan2(Math.Cos(delta0) * Math.Sin(alpha0 - alpha), Math.Sin(delta0) * Math.Cos(delta) - Math.Cos(delta0) * Math.Sin(delta) * Math.Cos(alpha0 - alpha)));

        return(details);
    }