//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);
    }
    //Static methods
    //////////////////////////////// Implementation ///////////////////////////////
    public static CAASaturnRingDetails Calculate(double JD)
    {
        //What will be the return value
        var details = new CAASaturnRingDetails();

        var T = (JD - 2451545) / 36525;
        var 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
        var i = 28.075216 - 0.012998 *T + 0.000004 *T2;
        var irad = CAACoordinateTransformation.DegreesToRadians(i);
        var omega = 169.508470 + 1.394681 *T + 0.000412 *T2;
        var omegarad = CAACoordinateTransformation.DegreesToRadians(omega);

        //Step 2. Calculate the heliocentric longitude, latitude and radius vector of the Earth in the FK5 system
        var l0 = CAAEarth.EclipticLongitude(JD);
        var b0 = CAAEarth.EclipticLatitude(JD);
        l0 += CAAFK5.CorrectionInLongitude(l0, b0, JD);
        var l0rad = CAACoordinateTransformation.DegreesToRadians(l0);
        b0 += CAAFK5.CorrectionInLatitude(l0, JD);
        var b0rad = CAACoordinateTransformation.DegreesToRadians(b0);
        var 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;
        var EarthLightTravelTime = CAAElliptical.DistanceToLightTime(DELTA);
        var JD1 = JD - EarthLightTravelTime;
        var 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);

          var lrad = CAACoordinateTransformation.DegreesToRadians(l);
          var brad = CAACoordinateTransformation.DegreesToRadians(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 = CAAElliptical.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
        var lambda = Math.Atan2(y, x);
        var 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 = CAACoordinateTransformation.RadiansToDegrees(details.B);

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

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

        //Step 9. Calculate DeltaU
        var 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));
        var 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 = CAACoordinateTransformation.RadiansToDegrees(Math.Abs(U1 - U2));

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

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

        //Step 12. Correct lambda and beta for the aberration of Saturn
        lambda += CAACoordinateTransformation.DegreesToRadians(0.005693 *Math.Cos(l0rad - lambda)/Math.Cos(beta));
        beta += CAACoordinateTransformation.DegreesToRadians(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 = CAACoordinateTransformation.RadiansToDegrees(lambda);
        lambda += NutationInLongitude/3600;
        lambda = CAACoordinateTransformation.MapTo0To360Range(lambda);
        lambda0 += NutationInLongitude/3600;
        lambda0 = CAACoordinateTransformation.MapTo0To360Range(lambda0);

        //Step 14. Convert to equatorial coordinates
        beta = CAACoordinateTransformation.RadiansToDegrees(beta);
        var GeocentricEclipticSaturn = CAACoordinateTransformation.Ecliptic2Equatorial(lambda, beta, Obliquity);
        var alpha = CAACoordinateTransformation.HoursToRadians(GeocentricEclipticSaturn.X);
        var delta = CAACoordinateTransformation.DegreesToRadians(GeocentricEclipticSaturn.Y);
        var GeocentricEclipticNorthPole = CAACoordinateTransformation.Ecliptic2Equatorial(lambda0, beta0, Obliquity);
        var alpha0 = CAACoordinateTransformation.HoursToRadians(GeocentricEclipticNorthPole.X);
        var delta0 = CAACoordinateTransformation.DegreesToRadians(GeocentricEclipticNorthPole.Y);

        //Step 15. Calculate the Position angle
        details.P = CAACoordinateTransformation.RadiansToDegrees(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;
    }