예제 #1
0
        private static (double longitude, double obliquity) swi_nutation(JulianDayNumber tjd, SweData swed)
        {
            // from interpolation, with three data points in 1-day steps;
            // maximum error is about 3 mas
            if (swed.InterpolateNutation)
            {
                // precalculated data points available
                if (swed.InterpolatedNutation != null && tjd < swed.InterpolatedNutation.Time2 && tjd > swed.InterpolatedNutation.Time0)
                {
                    var dx        = (tjd - swed.InterpolatedNutation.Time0).Raw - 1.0;
                    var longitude = quadratic_intp(swed.InterpolatedNutation.DPsi0, swed.InterpolatedNutation.DPsi1, swed.InterpolatedNutation.DPsi2, dx);
                    var obliquity = quadratic_intp(swed.InterpolatedNutation.DEps0, swed.InterpolatedNutation.DEps1, swed.InterpolatedNutation.DEps2, dx);
                    return(longitude, obliquity);
                }
                else
                {
                    var interpol = new InterpolatedNutation
                    {
                        Time0 = tjd.AddDays(-1.0),                       // one day earlier
                        Time2 = tjd.AddDays(1.0)                         // one day later
                    };

                    (interpol.DPsi0, interpol.DEps0) = calc_nutation(interpol.Time0, swed);
                    (interpol.DPsi2, interpol.DEps2) = calc_nutation(interpol.Time2, swed);
                    (interpol.DPsi1, interpol.DEps1) = calc_nutation(tjd, swed);

                    swed.InterpolatedNutation = interpol;
                    return(interpol.DPsi1, interpol.DEps1);
                }
            }
            return(calc_nutation(tjd, swed));
        }
예제 #2
0
        private (PlanetPosition position, PlanetPosition speed) CalcBySegment(JulianDayNumber tjd, SEFileSegment segment, bool calcSpeed = true)
        {
            var t = (tjd - segment.Start).Raw / segment.Size.Raw;

            t = t * 2 - 1;

            var position = new PlanetPosition(
                longitude: echeb(t, segment.LongitudeCoefficients),
                latitude: echeb(t, segment.LatitudeCoefficients),
                distance: echeb(t, segment.DistanceCoefficients)
                );

            PlanetPosition speed = default;

            if (calcSpeed)
            {
                speed = new PlanetPosition(
                    longitude: edcheb(t, segment.LongitudeCoefficients),
                    latitude: edcheb(t, segment.LatitudeCoefficients),
                    distance: edcheb(t, segment.DistanceCoefficients)
                    );
            }

            return(position, speed);
        }
예제 #3
0
        /// <summary>
        /// <see cref="swi_check_nutation"/>
        /// </summary>
        internal static Nutation Calculate(JulianDayNumber tjd, SweData swed)
        {
            var(longitude, obliquity) = swi_nutation(tjd, swed);
            var matrix = nut_matrix(longitude, obliquity, swed.oec);

            return(new Nutation(tjd, longitude, obliquity, matrix));
        }
예제 #4
0
        private static (double longitude, double obliquity) calc_nutation(JulianDayNumber J, SweData swed)
        {
            int    n;
            double dpsi, deps;
            double longitude = 0.0, obliquity = 0.0;
            var    jplhora_model = swed.JplHorizonsMode;
            var    nut_model     = swed.NutationModel;
            bool   is_jplhor     = false;

            if (swed.Iflag.HasFlag(SEFLG.JPLHOR))
            {
                is_jplhor = true;
            }
            if (swed.Iflag.HasFlag(SEFLG.JPLHOR_APPROX) &&
                jplhora_model == JplHorizonsMode.Three &&
                J <= HORIZONS_TJD0_DPSI_DEPS_IAU1980)
            {
                is_jplhor = true;
            }

            if (is_jplhor)
            {
                (longitude, obliquity) = calc_nutation_iau1980(J, nut_model);
                if (swed.Iflag.HasFlag(SEFLG.JPLHOR))
                {
                    n = (int)(swed.Eop.EndDate.Raw - swed.Eop.BeginDate.Raw + 0.000001);
                    var J2 = J;
                    if (J < DPSI_DEPS_IAU1980_TJD0_HORIZONS)
                    {
                        J2 = DPSI_DEPS_IAU1980_TJD0_HORIZONS;
                    }
                    var t = (J2 - swed.Eop.BeginDate).Raw;
                    dpsi       = bessel(swed.Eop.dPsi, n + 1, t);
                    deps       = bessel(swed.Eop.dEps, n + 1, t);
                    longitude += dpsi / 3600.0 * DEGTORAD;
                    obliquity += deps / 3600.0 * DEGTORAD;
                }
                else
                {
                    longitude += DPSI_IAU1980_TJD0 / 3600.0 * DEGTORAD;
                    obliquity += DEPS_IAU1980_TJD0 / 3600.0 * DEGTORAD;
                }
            }
            else if (nut_model == NutationModel.IAU_1980 || nut_model == NutationModel.IAU_CORR_1987)
            {
                (longitude, obliquity) = calc_nutation_iau1980(J, nut_model);
            }
            else if (nut_model == NutationModel.IAU_2000A || nut_model == NutationModel.IAU_2000B)
            {
                (longitude, obliquity) = calc_nutation_iau2000ab(J, nut_model);
                if (swed.Iflag.HasFlag(SEFLG.JPLHOR_APPROX) && jplhora_model == JplHorizonsMode.Two)
                {
                    longitude += -41.7750 / 3600.0 / 1000.0 * DEGTORAD;
                    obliquity += -6.8192 / 3600.0 / 1000.0 * DEGTORAD;
                }
            }
            return(longitude, obliquity);
        }
예제 #5
0
 private EarthOrientationParameters(
     JulianDayNumber beginDate, JulianDayNumber endDate,
     IReadOnlyList <double> dPsi, IReadOnlyList <double> dEps)
 {
     BeginDate         = beginDate;
     EndDate           = endDate;
     BeginDateHorizons = JulianDayNumber.FromRaw(2437684.5);
     this.dPsi         = dPsi;
     this.dEps         = dEps;
 }
예제 #6
0
 internal SEFileData GetFile(int bodyNumber, JulianDayNumber jd)
 {
     if (_files.TryGetValue(bodyNumber, out var bag))
     {
         foreach (var item in bag)
         {
             if (item.StartDate <= jd && jd <= item.EndDate)
             {
                 return(item);
             }
         }
     }
     throw new FileNotFoundException();
 }
예제 #7
0
 public Nutation(
     JulianDayNumber date,
     double longitude,
     double obliquity,
     double[,] matrix
     )
 {
     Date      = date;
     Longitude = longitude;
     Obliquity = obliquity;
     Matrix    = matrix;
     Sin       = Math.Sin(obliquity);
     Cos       = Math.Cos(obliquity);
 }
예제 #8
0
 public SweData(SEFLG iflag, DateTime dateTimeInUTC, EarthOrientationParameters eop, bool interpolateNutation = false)
 {
     Iflag                      = iflag;
     CalculationDate            = dateTimeInUTC;
     Eop                        = eop;
     InterpolateNutation        = interpolateNutation;
     CalculationJulianDayNumber = JulianDayNumber.FromDate(dateTimeInUTC);
     TidalAcc                   = TidalAcceleration.Get(TidalAccelerationMode.Default);
     IsManualTidalAcc           = false;
     LongtermPrecessionMode     = PrecessionModel.Default;
     ShorttermPrecessionMode    = PrecessionModel.Default;
     JplHorizonsMode            = JplHorizonsMode.Default;
     NutationModel              = NutationModel.Default;
     oec                        = Epsilon.Calc(CalculationJulianDayNumber, iflag, this);
     oec2000                    = Epsilon.Calc(JulianDayNumber.J2000, iflag, this);
 }
예제 #9
0
        /// <see cref="sweph"/>
        private (PlanetPosition position, PlanetPosition speed) CalcBodyPositionAndSpeedInternal(int bodyNumber, DateTime dateTimeInUTC, bool calcSpeed)
        {
            var tjd    = JulianDayNumber.FromDate(dateTimeInUTC);
            var file   = _storage.GetFile(bodyNumber, tjd);
            var planet = bodyNumber > SEConsts.AseroidOffset
                                ? InternalPlanets.AnyBody
                                : (InternalPlanets)bodyNumber;
            var planetData = file.PlanetsData[planet];
            var segment    = file.ReadSegment(planetData, tjd, _sweData.oec2000);

            var(position, speed) = CalcBySegment(tjd, segment, calcSpeed);

            /* if planet wanted is barycentric sun:
             * current sepl* files have do not have barycentric sun,
             * but have heliocentric earth and barycentric earth.
             * So barycentric sun and must be computed
             * from heliocentric earth and barycentric earth: the
             * computation above gives heliocentric earth, therefore we
             * have to compute barycentric earth and subtract heliocentric
             * earth from it. this may be necessary with calls from
             * sweplan() and from app_pos_etc_sun() (light-time). */
            if (bodyNumber == (int)InternalPlanets.BarycentricSun && planetData.Flags.HasFlag(PlanetFlags.EmbHeliocentric))
            {
                // sweph() calls sweph() !!! for EMB.
                // because we always call new calculation, warning about EARTH and EMB equality was omitted
                var(embPos, embSpeed) = CalcBodyPositionAndSpeedInternal((int)InternalPlanets.EMB, dateTimeInUTC, calcSpeed);
                position = new PlanetPosition(
                    embPos.Longitude - position.Longitude,
                    embPos.Latitude - position.Latitude,
                    embPos.Distance - position.Distance);
                if (calcSpeed)
                {
                    speed = new PlanetPosition(
                        embSpeed.Longitude - speed.Longitude,
                        embSpeed.Latitude - speed.Latitude,
                        embSpeed.Distance - speed.Distance);
                }
            }
            // asteroids are heliocentric.
            // if JPL or SWISSEPH, convert to barycentric - currently always
            if (planet >= InternalPlanets.AnyBody)
            {
                (position, speed) = ConvertToBarycentric(position, speed, dateTimeInUTC, calcSpeed);
            }
            return(position, speed);
        }
예제 #10
0
        /// <see cref="swi_get_tid_acc"/>
        public static double Calculate(EphemerisMode ephemerisMode, JulianDayNumber julianDay, JPLDENumber denum)
        {
            if (denum == JPLDENumber.Auto)
            {
                switch (ephemerisMode)
                {
                case EphemerisMode.Moshier:
                    denum = JPLDENumber.DE404;
                    break;

                case EphemerisMode.JPL:
                    throw new NotImplementedException();

                case EphemerisMode.SWISSEPH:
                    /*
                     * tjd_et = tjd_ut; // + swe_deltat_ex(tjd_ut, 0, NULL); we do not add delta t, because it would result in a recursive call of swi_set_tid_acc()
                     * if (swed.fidat[SEI_FILE_MOON].fptr == NULL ||
                     *      tjd_et < swed.fidat[SEI_FILE_MOON].tfstart + 1 ||
                     *        tjd_et > swed.fidat[SEI_FILE_MOON].tfend - 1)
                     * {
                     *      iflag = SEFLG_SWIEPH | SEFLG_J2000 | SEFLG_TRUEPOS | SEFLG_ICRS;
                     *      iflag = swe_calc(tjd_et, SE_MOON, iflag, xx, serr);
                     * }
                     * if (swed.fidat[SEI_FILE_MOON].fptr != NULL)
                     * {
                     *      denum = swed.fidat[SEI_FILE_MOON].sweph_denum;
                     * }
                     * // Moon ephemeris file is not available, default to Moshier ephemeris
                     * else
                     */
                    denum = JPLDENumber.DE404;                                     // DE number of Moshier ephemeris
                    break;
                }
            }

            return(Get(denum));
        }
예제 #11
0
        private static (double longitude, double obliquity) calc_nutation_iau2000ab(JulianDayNumber J, NutationModel nut_model)
        {
            int    i, j, k, inls;
            double M, SM, F, D, OM;
            double AL, ALSU, AF, AD, AOM, APA;
            double ALME, ALVE, ALEA, ALMA, ALJU, ALSA, ALUR, ALNE;
            double darg, sinarg, cosarg;
            double dpsi = 0, deps = 0;
            double T = (J - JulianDayNumber.J2000).Raw / 36525.0;

            /* luni-solar nutation */
            /* Fundamental arguments, Simon & al. (1994) */
            /* Mean anomaly of the Moon. */
            M = swe_degnorm((485868.249036 +
                             T * (1717915923.2178 +
                                  T * (31.8792 +
                                       T * (0.051635 +
                                            T * (-0.00024470))))) / 3600.0) * DEGTORAD;
            /* Mean anomaly of the Sun */
            SM = swe_degnorm((1287104.79305 +
                              T * (129596581.0481 +
                                   T * (-0.5532 +
                                        T * (0.000136 +
                                             T * (-0.00001149))))) / 3600.0) * DEGTORAD;
            /* Mean argument of the latitude of the Moon. */
            F = swe_degnorm((335779.526232 +
                             T * (1739527262.8478 +
                                  T * (-12.7512 +
                                       T * (-0.001037 +
                                            T * (0.00000417))))) / 3600.0) * DEGTORAD;
            /* Mean elongation of the Moon from the Sun. */
            D = swe_degnorm((1072260.70369 +
                             T * (1602961601.2090 +
                                  T * (-6.3706 +
                                       T * (0.006593 +
                                            T * (-0.00003169))))) / 3600.0) * DEGTORAD;
            /* Mean longitude of the ascending node of the Moon. */
            OM = swe_degnorm((450160.398036 +
                              T * (-6962890.5431 +
                                   T * (7.4722 +
                                        T * (0.007702 +
                                             T * (-0.00005939))))) / 3600.0) * DEGTORAD;
            /* luni-solar nutation series, in reverse order, starting with small terms */
            if (nut_model == NutationModel.IAU_2000B)
            {
                inls = NLS_2000B;
            }
            else
            {
                inls = NLS;
            }
            for (i = inls - 1; i >= 0; i--)
            {
                j    = i * 5;
                darg = swe_radnorm(
                    nls[j + 0] * M +
                    nls[j + 1] * SM +
                    nls[j + 2] * F +
                    nls[j + 3] * D +
                    nls[j + 4] * OM);
                sinarg = Math.Sin(darg);
                cosarg = Math.Cos(darg);
                k      = i * 6;
                dpsi  += (cls[k + 0] + cls[k + 1] * T) * sinarg + cls[k + 2] * cosarg;
                deps  += (cls[k + 3] + cls[k + 4] * T) * cosarg + cls[k + 5] * sinarg;
            }
            var longitude = dpsi * O1MAS2DEG;
            var obliquity = deps * O1MAS2DEG;

            if (nut_model == NutationModel.IAU_2000A)
            {
                /* planetary nutation
                 * note: The MHB2000 code computes the luni-solar and planetary nutation
                 * in different routines, using slightly different Delaunay
                 * arguments in the two cases.  This behaviour is faithfully
                 * reproduced here.  Use of the Simon et al. expressions for both
                 * cases leads to negligible changes, well below 0.1 microarcsecond.*/
                /* Mean anomaly of the Moon.*/
                AL = swe_radnorm(2.35555598 + 8328.6914269554 * T);
                /* Mean anomaly of the Sun.*/
                ALSU = swe_radnorm(6.24006013 + 628.301955 * T);
                /* Mean argument of the latitude of the Moon. */
                AF = swe_radnorm(1.627905234 + 8433.466158131 * T);
                /* Mean elongation of the Moon from the Sun. */
                AD = swe_radnorm(5.198466741 + 7771.3771468121 * T);
                /* Mean longitude of the ascending node of the Moon. */
                AOM = swe_radnorm(2.18243920 - 33.757045 * T);
                /* Planetary longitudes, Mercury through Neptune (Souchay et al. 1999). */
                ALME = swe_radnorm(4.402608842 + 2608.7903141574 * T);
                ALVE = swe_radnorm(3.176146697 + 1021.3285546211 * T);
                ALEA = swe_radnorm(1.753470314 + 628.3075849991 * T);
                ALMA = swe_radnorm(6.203480913 + 334.0612426700 * T);
                ALJU = swe_radnorm(0.599546497 + 52.9690962641 * T);
                ALSA = swe_radnorm(0.874016757 + 21.3299104960 * T);
                ALUR = swe_radnorm(5.481293871 + 7.4781598567 * T);
                ALNE = swe_radnorm(5.321159000 + 3.8127774000 * T);
                /* General accumulated precession in longitude. */
                APA = (0.02438175 + 0.00000538691 * T) * T;
                /* planetary nutation series (in reverse order).*/
                dpsi = 0;
                deps = 0;
                for (i = NPL - 1; i >= 0; i--)
                {
                    j    = i * 14;
                    darg = swe_radnorm(
                        npl[j + 0] * AL +
                        npl[j + 1] * ALSU +
                        npl[j + 2] * AF +
                        npl[j + 3] * AD +
                        npl[j + 4] * AOM +
                        npl[j + 5] * ALME +
                        npl[j + 6] * ALVE +
                        npl[j + 7] * ALEA +
                        npl[j + 8] * ALMA +
                        npl[j + 9] * ALJU +
                        npl[j + 10] * ALSA +
                        npl[j + 11] * ALUR +
                        npl[j + 12] * ALNE +
                        npl[j + 13] * APA);
                    k      = i * 4;
                    sinarg = Math.Sin(darg);
                    cosarg = Math.Cos(darg);
                    dpsi  += icpl[k + 0] * sinarg + icpl[k + 1] * cosarg;
                    deps  += icpl[k + 2] * sinarg + icpl[k + 3] * cosarg;
                }
                longitude += dpsi * O1MAS2DEG;
                obliquity += deps * O1MAS2DEG;

                /* changes required by adoption of P03 precession
                 * according to Capitaine et al. A & A 412, 366 (2005) = IAU 2006 */
                dpsi       = -8.1 * Math.Sin(OM) - 0.6 * Math.Sin(2 * F - 2 * D + 2 * OM);
                dpsi      += T * (47.8 * Math.Sin(OM) + 3.7 * Math.Sin(2 * F - 2 * D + 2 * OM) + 0.6 * Math.Sin(2 * F + 2 * OM) - 0.6 * Math.Sin(2 * OM));
                deps       = T * (-25.6 * Math.Cos(OM) - 1.6 * Math.Cos(2 * F - 2 * D + 2 * OM));
                longitude += dpsi / (3600.0 * 1000000.0);
                obliquity += deps / (3600.0 * 1000000.0);
            }
            longitude *= DEGTORAD;
            obliquity *= DEGTORAD;
            return(longitude, obliquity);
        }
예제 #12
0
 internal static Nutation CalculateForSpeed(JulianDayNumber tjd, SweData swed) =>
 Calculate(tjd.AddDays(-NUT_SPEED_INTV), swed);
예제 #13
0
        private static (double longitude, double obliquity) calc_nutation_iau1980(JulianDayNumber J, NutationModel nut_model)
        {
            /* arrays to hold sines and cosines of multiple angles */
            double[,] ss = new double[5, 8];
            double[,] cc = new double[5, 8];
            double arg;

            double[] args = new double[5];
            double   f, g, T, T2;
            double   MM, MS, FF, DD, OM;
            double   cu, su, cv, sv, sw, s;
            double   C, D;
            int      i, j, k, k1, m, n;

            int[] ns = new int[5];

            /* Julian centuries from 2000 January 1.5,
             * barycentric dynamical time
             */
            T  = (J - JulianDayNumber.J2000).Raw / 36525.0;
            T2 = T * T;

            /* Fundamental arguments in the FK5 reference system.
             * The coefficients, originally given to 0.001",
             * are converted here to degrees.
             */
            /* longitude of the mean ascending node of the lunar orbit
             * on the ecliptic, measured from the mean equinox of date
             */
            OM = -6962890.539 * T + 450160.280 + (0.008 * T + 7.455) * T2;
            OM = swe_degnorm(OM / 3600) * DEGTORAD;

            /* mean longitude of the Sun minus the
             * mean longitude of the Sun's perigee
             */
            MS = 129596581.224 * T + 1287099.804 - (0.012 * T + 0.577) * T2;
            MS = swe_degnorm(MS / 3600) * DEGTORAD;

            /* mean longitude of the Moon minus the
             * mean longitude of the Moon's perigee
             */
            MM = 1717915922.633 * T + 485866.733 + (0.064 * T + 31.310) * T2;
            MM = swe_degnorm(MM / 3600) * DEGTORAD;

            /* mean longitude of the Moon minus the
             * mean longitude of the Moon's node
             */
            FF = 1739527263.137 * T + 335778.877 + (0.011 * T - 13.257) * T2;
            FF = swe_degnorm(FF / 3600) * DEGTORAD;

            /* mean elongation of the Moon from the Sun.
             */
            DD      = 1602961601.328 * T + 1072261.307 + (0.019 * T - 6.891) * T2;
            DD      = swe_degnorm(DD / 3600) * DEGTORAD;
            args[0] = MM;
            ns[0]   = 3;
            args[1] = MS;
            ns[1]   = 2;
            args[2] = FF;
            ns[2]   = 4;
            args[3] = DD;
            ns[3]   = 4;
            args[4] = OM;
            ns[4]   = 2;

            /* Calculate Math.Sin( i*MM ), etc. for needed multiple angles
             */
            for (k = 0; k <= 4; k++)
            {
                arg      = args[k];
                n        = ns[k];
                su       = Math.Sin(arg);
                cu       = Math.Cos(arg);
                ss[k, 0] = su;                          /* Math.Sin(L) */
                cc[k, 0] = cu;                          /* Math.Cos(L) */
                sv       = 2.0 * su * cu;
                cv       = cu * cu - su * su;
                ss[k, 1] = sv;                          /* Math.Sin(2L) */
                cc[k, 1] = cv;
                for (i = 2; i < n; i++)
                {
                    s        = su * cv + cu * sv;
                    cv       = cu * cv - su * sv;
                    sv       = s;
                    ss[k, i] = sv;                          /* Math.Sin( i+1 L ) */
                    cc[k, i] = cv;
                }
            }
            /* first terms, not in table: */
            C = (-0.01742 * T - 17.1996) * ss[4, 0];            /* Math.Sin(OM) */
            D = (0.00089 * T + 9.2025) * cc[4, 0];              /* Math.Cos(OM) */
            foreach (short[] p in nt)
            {
                if (nut_model != NutationModel.IAU_CORR_1987 && (p[0] == 101 || p[0] == 102))
                {
                    continue;
                }
                /* argument of sine and cosine */
                k1 = 0;
                cv = 0.0;
                sv = 0.0;
                for (m = 0; m < 5; m++)
                {
                    j = p[m];
                    if (j > 100)
                    {
                        j = 0;                         /* p[0] is a flag */
                    }
                    if (j > 0)
                    {
                        k = j;
                        if (j < 0)
                        {
                            k = -k;
                        }
                        su = ss[m, k - 1];                         /* Math.Sin(k*angle) */
                        if (j < 0)
                        {
                            su = -su;
                        }
                        cu = cc[m, k - 1];
                        if (k1 == 0)
                        {                         /* set first angle */
                            sv = su;
                            cv = cu;
                            k1 = 1;
                        }
                        else
                        {                               /* combine angles */
                            sw = su * cv + cu * sv;
                            cv = cu * cv - su * sv;
                            sv = sw;
                        }
                    }
                }
                /* longitude coefficient, in 0.0001" */
                f = p[5] * 0.0001;
                if (p[6] != 0)
                {
                    f += 0.00001 * T * p[6];
                }
                /* obliquity coefficient, in 0.0001" */
                g = p[7] * 0.0001;
                if (p[8] != 0)
                {
                    g += 0.00001 * T * p[8];
                }
                if (p[0] >= 100)
                {                   /* coefficients in 0.00001" */
                    f *= 0.1;
                    g *= 0.1;
                }
                /* accumulate the terms */
                if (p[0] != 102)
                {
                    C += f * sv;
                    D += g * cv;
                }
                else
                {                       /* Math.Cos for nutl and Math.Sin for nuto */
                    C += f * cv;
                    D += g * sv;
                }
            }
            /* Save answers, expressed in radians */
            var longitude = DEGTORAD * C / 3600.0;
            var obliquity = DEGTORAD * D / 3600.0;

            return(longitude, obliquity);
        }
예제 #14
0
        /// <summary>
        /// Load from EOP files
        /// <parameter name="eopC04File">File from https://datacenter.iers.org/data/latestVersion/EOP_14_C04_IAU1980_one_file_1962-now.txt</parameter>
        /// <parameter name="eopFinalsFile">File from https://datacenter.iers.org/data/latestVersion/finals.all.iau1980.txt</parameter>
        /// </summary>
        public static EarthOrientationParameters LoadFrom(
            Stream eopC04File,
            Stream?eopFinalsFile)
        {
            const double    TJDOFS = 2400000.5;
            string          s;
            JulianDayNumber beginDate = default;
            var             dpsi      = new List <double>();
            var             deps      = new List <double>();
            int             mjdsv     = 0;

            using (var reader = new StreamReader(eopC04File))
            {
                while ((s = reader.ReadLine()) != null)
                {
                    if (!s.StartsWith("1962"))
                    {
                        continue;
                    }
                    var values = s.Split(' ', StringSplitOptions.RemoveEmptyEntries);
                    var mjd    = int.Parse(values[3]);
                    // is file in one-day steps?
                    if (mjdsv > 0 && mjd - mjdsv != 1)
                    {
                        throw new FormatException("File must be in one-day steps");
                    }
                    if (mjdsv == 0)
                    {
                        beginDate = JulianDayNumber.FromRaw(mjd + TJDOFS);
                    }
                    dpsi.Add(double.Parse(values[8], CultureInfo.InvariantCulture));
                    deps.Add(double.Parse(values[9], CultureInfo.InvariantCulture));
                    mjdsv = mjd;
                }
            }
            var endDate = JulianDayNumber.FromRaw(mjdsv + TJDOFS);

            // file finals.all may have some more data, and especially estimations for the near future
            if (eopFinalsFile != null)
            {
                mjdsv            = 0;
                using var reader = new StreamReader(eopFinalsFile);
                while ((s = reader.ReadLine()) != null)
                {
                    var mjd = int.Parse(GetDigits(s, 7));
                    var jd  = JulianDayNumber.FromRaw(mjd + TJDOFS);
                    if (jd <= endDate)
                    {
                        continue;
                    }
                    // are data in one-day steps?
                    if (mjdsv > 0 && mjd - mjdsv != 1)
                    {
                        throw new FormatException("File must be in one-day steps");
                    }

                    // dpsi, deps Bulletin B
                    var dPsi = GetDoubleFromStr(s, 168);
                    var dEps = GetDoubleFromStr(s, 178);
                    if (dPsi == 0.0)
                    {
                        // try dpsi, deps Bulletin A
                        dPsi = GetDoubleFromStr(s, 99);
                        dEps = GetDoubleFromStr(s, 118);
                    }
                    if (dPsi == 0.0)
                    {
                        break;
                    }
                    dpsi.Add(dPsi / 1000.0);
                    deps.Add(dEps / 1000.0);
                    mjdsv = mjd;
                }
            }

            return(new EarthOrientationParameters(beginDate, endDate, dpsi, deps));
        }
예제 #15
0
 public bool IsPlanetHeliocentric(int bodyNumber, DateTime dateTimeInUTC) =>
 _storage
 .GetFile(bodyNumber, JulianDayNumber.FromDate(dateTimeInUTC))
 .PlanetsData[(InternalPlanets)bodyNumber]
 .Flags
 .HasFlag(PlanetFlags.Heliocentric);