コード例 #1
0
ファイル: Precession.cs プロジェクト: iamanas20/ADK
        /// <summary>
        /// Performs reduction of equatorial coordinates from one epoch to another
        /// with using of precessional elements.
        /// </summary>
        /// <param name="eq0">Equatorial coordinates for initial epoch.</param>
        /// <param name="p">Precessional elements for reduction from initial epoch to target (final) epoch.</param>
        /// <returns>Equatorial coordinates for target (final) epoch.</returns>
        /// <remarks>
        /// This method is taken from AA(I), formula 20.4.
        /// </remarks>
        public static CrdsEquatorial GetEquatorialCoordinates(CrdsEquatorial eq0, PrecessionalElements p)
        {
            CrdsEquatorial eq = new CrdsEquatorial();

            double sinDelta0     = Math.Sin(Angle.ToRadians(eq0.Delta));
            double cosDelta0     = Math.Cos(Angle.ToRadians(eq0.Delta));
            double sinTheta      = Math.Sin(Angle.ToRadians(p.theta));
            double cosTheta      = Math.Cos(Angle.ToRadians(p.theta));
            double sinAlpha0Zeta = Math.Sin(Angle.ToRadians(eq0.Alpha + p.zeta));
            double cosAlpha0Zeta = Math.Cos(Angle.ToRadians(eq0.Alpha + p.zeta));

            double A = cosDelta0 * sinAlpha0Zeta;
            double B = cosTheta * cosDelta0 * cosAlpha0Zeta - sinTheta * sinDelta0;
            double C = sinTheta * cosDelta0 * cosAlpha0Zeta + cosTheta * sinDelta0;

            eq.Alpha = Angle.ToDegrees(Math.Atan2(A, B)) + p.z;
            eq.Alpha = Angle.To360(eq.Alpha);

            if (Math.Abs(C) == 1)
            {
                eq.Delta = Angle.ToDegrees(Math.Acos(A * A + B * B));
            }
            else
            {
                eq.Delta = Angle.ToDegrees(Math.Asin(C));
            }

            return(eq);
        }
コード例 #2
0
        /// <summary>
        /// Gets geocentric elongation angle of the Moon from Sun
        /// </summary>
        /// <param name="sun">Ecliptical geocentrical coordinates of the Sun</param>
        /// <param name="moon">Ecliptical geocentrical coordinates of the Moon</param>
        /// <returns>Geocentric elongation angle, in degrees, from 0 to 180.</returns>
        /// <remarks>
        /// AA(II), formula 48.2
        /// </remarks>
        public static double Elongation(CrdsEcliptical sun, CrdsEcliptical moon)
        {
            double beta    = Angle.ToRadians(moon.Beta);
            double lambda  = Angle.ToRadians(moon.Lambda);
            double lambda0 = Angle.ToRadians(sun.Lambda);

            return(Angle.ToDegrees(Math.Acos(Math.Cos(beta) * Math.Cos(lambda - lambda0))));
        }
コード例 #3
0
ファイル: Extensions.cs プロジェクト: t9mike/ADK
        /// <summary>
        /// Converts rectangular topocentric coordinates of a planet to topocentrical ecliptical coordinates
        /// </summary>
        /// <param name="rect">Rectangular topocentric coordinates of a planet</param>
        /// <returns>Topocentrical ecliptical coordinates of a planet</returns>
        public static CrdsEcliptical ToEcliptical(this CrdsRectangular rect)
        {
            double lambda   = Angle.To360(Angle.ToDegrees(Math.Atan2(rect.Y, rect.X)));
            double beta     = Angle.ToDegrees(Math.Atan(rect.Z / Math.Sqrt(rect.X * rect.X + rect.Y * rect.Y)));
            double distance = Math.Sqrt(rect.X * rect.X + rect.Y * rect.Y + rect.Z * rect.Z);

            return(new CrdsEcliptical(lambda, beta, distance));
        }
コード例 #4
0
        /// <summary>
        /// Calculates phase angle of the Moon
        /// </summary>
        /// <param name="psi">Geocentric elongation of the Moon.</param>
        /// <param name="R">Distance Earth-Sun, in kilometers</param>
        /// <param name="Delta">Distance Earth-Moon, in kilometers</param>
        /// <returns>Phase angle, in degrees, from 0 to 180</returns>
        /// <remarks>
        /// AA(II), formula 48.3.
        /// </remarks>
        public static double PhaseAngle(double psi, double R, double Delta)
        {
            psi = Angle.ToRadians(Math.Abs(psi));
            double phaseAngle = Angle.ToDegrees(Math.Atan(R * Math.Sin(psi) / (Delta - R * Math.Cos(psi))));

            if (phaseAngle < 0)
            {
                phaseAngle += 180;
            }
            return(phaseAngle);
        }
コード例 #5
0
        /// <summary>
        /// Calculates appearance of Saturn rings
        /// </summary>
        /// <param name="jd">Julian date to calculate for</param>
        /// <param name="saturn">Heliocentric coordinates of Saturn.</param>
        /// <param name="earth">Heliocentric coordinates of Earth.</param>
        /// <param name="epsilon">True obliquity of ecliptic.</param>
        /// <returns>
        /// Appearance data for Saturn rings.
        /// </returns>
        /// <remarks>
        /// Method is taken from AA(II), chapter 45.
        /// </remarks>
        public static RingsAppearance SaturnRings(double jd, CrdsHeliocentrical saturn, CrdsHeliocentrical earth, double epsilon)
        {
            RingsAppearance rings = new RingsAppearance();
            double          T     = (jd - 2451545.0) / 36525.0;
            double          T2    = T * T;

            double i     = 28.075216 - 0.012998 * T + 0.000004 * T2;
            double Omega = 169.508470 + 1.394681 * T + 0.000412 * T2;

            double lambda0 = Omega - 90;
            double beta0   = 90 - i;

            i     = Angle.ToRadians(i);
            Omega = Angle.ToRadians(Omega);

            CrdsEcliptical ecl = saturn.ToRectangular(earth).ToEcliptical();

            double beta   = Angle.ToRadians(ecl.Beta);
            double lambda = Angle.ToRadians(ecl.Lambda);

            rings.B = Angle.ToDegrees(Math.Asin(Math.Sin(i) * Math.Cos(beta) * Math.Sin(lambda - Omega) - Math.Cos(i) * Math.Sin(beta)));
            rings.a = 375.35 / ecl.Distance;
            rings.b = rings.a * Math.Sin(Math.Abs(Angle.ToRadians(rings.B)));

            double N  = 113.6655 + 0.8771 * T;
            double l_ = Angle.ToRadians(saturn.L - 0.01759 / saturn.R);
            double b_ = Angle.ToRadians(saturn.B - 0.000764 * Math.Cos(Angle.ToRadians(saturn.L - N)) / saturn.R);

            double U1 = Angle.ToDegrees(Math.Atan((Math.Sin(i) * Math.Sin(b_) + Math.Cos(i) * Math.Cos(b_) * Math.Sin(l_ - Omega)) / (Math.Cos(b_) * Math.Cos(l_ - Omega))));
            double U2 = Angle.ToDegrees(Math.Atan((Math.Sin(i) * Math.Sin(beta) + Math.Cos(i) * Math.Cos(beta) * Math.Sin(lambda - Omega)) / (Math.Cos(beta) * Math.Cos(lambda - Omega))));

            rings.DeltaU = Math.Abs(U1 - U2);

            CrdsEcliptical eclPole = new CrdsEcliptical();

            eclPole.Set(lambda0, beta0);

            CrdsEquatorial eq     = ecl.ToEquatorial(epsilon);
            CrdsEquatorial eqPole = eclPole.ToEquatorial(epsilon);

            double alpha  = Angle.ToRadians(eq.Alpha);
            double delta  = Angle.ToRadians(eq.Delta);
            double alpha0 = Angle.ToRadians(eqPole.Alpha);
            double delta0 = Angle.ToRadians(eqPole.Delta);

            double y = Math.Cos(delta0) * Math.Sin(alpha0 - alpha);
            double x = Math.Sin(delta0) * Math.Cos(delta) - Math.Cos(delta0) * Math.Sin(delta) * Math.Cos(alpha0 - alpha);

            rings.P = Angle.ToDegrees(Math.Atan2(y, x));

            return(rings);
        }
コード例 #6
0
        /// <summary>
        /// Calculates visible appearance of planet for given date.
        /// </summary>
        /// <param name="jd">Julian day</param>
        /// <param name="planet">Planet number to calculate appearance, 1 = Mercury, 2 = Venus and etc.</param>
        /// <param name="eq">Equatorial coordinates of the planet</param>
        /// <param name="distance">Distance from the planet to the Earth</param>
        /// <returns>Appearance parameters of the planet</returns>
        /// <remarks>
        /// This method is based on book "Practical Ephemeris Calculations", Montenbruck.
        /// See topic 6.4, pp. 88-92.
        /// </remarks>
        public static PlanetAppearance PlanetAppearance(double jd, int planet, CrdsEquatorial eq, double distance)
        {
            PlanetAppearance a = new PlanetAppearance();

            double d = jd - 2451545.0;
            double T = d / 36525.0;

            // coordinates of the point to which the north pole of the planet is pointing.
            CrdsEquatorial eq0 = new CrdsEquatorial();

            eq0.Alpha = Angle.To360(cAlpha0[planet - 1][0] + cAlpha0[planet - 1][1] * T + cAlpha0[planet - 1][2] * T);
            eq0.Delta = cDelta0[planet - 1][0] + cDelta0[planet - 1][1] * T + cDelta0[planet - 1][2] * T;

            // take light time effect into account
            d -= PlanetPositions.LightTimeEffect(distance);
            T  = d / 36525.0;

            // position of null meridian
            double W = Angle.To360(cW[planet - 1][0] + cW[planet - 1][1] * d + cW[planet - 1][2] * T);

            double delta = Angle.ToRadians(eq.Delta);
            double alpha = Angle.ToRadians(eq.Alpha);

            double delta0  = Angle.ToRadians(eq0.Delta);
            double dAlpha0 = Angle.ToRadians(eq0.Alpha - eq.Alpha);

            double sinD = -Math.Sin(delta0) * Math.Sin(delta) - Math.Cos(delta0) * Math.Cos(delta) * Math.Cos(dAlpha0);

            // planetographic latitude of the Earth
            a.D = Angle.ToDegrees(Math.Asin(sinD));

            double cosD = Math.Cos(Angle.ToRadians(a.D));

            double sinP = Math.Cos(delta0) * Math.Sin(dAlpha0) / cosD;
            double cosP = (Math.Sin(delta0) * Math.Cos(delta) - Math.Cos(delta0) * Math.Sin(delta) * Math.Cos(dAlpha0)) / cosD;

            // position angle of the axis
            a.P = Angle.To360(Angle.ToDegrees(Math.Atan2(sinP, cosP)));

            double sinK = (-Math.Cos(delta0) * Math.Sin(delta) + Math.Sin(delta0) * Math.Cos(delta) * Math.Cos(dAlpha0)) / cosD;

            double cosK = Math.Cos(delta) * Math.Sin(dAlpha0) / cosD;

            double K = Angle.ToDegrees(Math.Atan2(sinK, cosK));

            // planetographic longitude of the central meridian
            a.CM = planet == 5 ?
                   JupiterCM2(jd) :
                   Angle.To360(Math.Sign(W) * (W - K));

            return(a);
        }
コード例 #7
0
        /// <summary>
        /// Converts ecliptical coordinates to equatorial.
        /// </summary>
        /// <param name="ecl">Pair of ecliptical cooordinates.</param>
        /// <param name="epsilon">Obliquity of the ecliptic, in degrees.</param>
        /// <returns>Pair of equatorial coordinates.</returns>
        public static CrdsEquatorial ToEquatorial(this CrdsEcliptical ecl, double epsilon)
        {
            CrdsEquatorial eq = new CrdsEquatorial();

            epsilon = Angle.ToRadians(epsilon);
            double lambda = Angle.ToRadians(ecl.Lambda);
            double beta   = Angle.ToRadians(ecl.Beta);

            double Y = Math.Sin(lambda) * Math.Cos(epsilon) - Math.Tan(beta) * Math.Sin(epsilon);
            double X = Math.Cos(lambda);

            eq.Alpha = Angle.To360(Angle.ToDegrees(Math.Atan2(Y, X)));
            eq.Delta = Angle.ToDegrees(Math.Asin(Math.Sin(beta) * Math.Cos(epsilon) + Math.Cos(beta) * Math.Sin(epsilon) * Math.Sin(lambda)));

            return(eq);
        }
コード例 #8
0
        /// <summary>
        /// Converts galactical coodinates to equatorial, for equinox B1950.0.
        /// </summary>
        /// <param name="gal">Galactical coodinates.</param>
        /// <returns>Equatorial coodinates, for equinox B1950.0.</returns>
        public static CrdsEquatorial ToEquatorial(this CrdsGalactical gal)
        {
            CrdsEquatorial eq = new CrdsEquatorial();

            double l_l0   = Angle.ToRadians(gal.l - 123.0);
            double delta0 = Angle.ToRadians(27.4);
            double b      = Angle.ToRadians(gal.b);

            double Y        = Math.Sin(l_l0);
            double X        = Math.Cos(l_l0) * Math.Sin(delta0) - Math.Tan(b) * Math.Cos(delta0);
            double sinDelta = Math.Sin(b) * Math.Sin(delta0) + Math.Cos(b) * Math.Cos(delta0) * Math.Cos(l_l0);

            eq.Alpha = Angle.To360(Angle.ToDegrees(Math.Atan2(Y, X)) + 12.25);
            eq.Delta = Angle.ToDegrees(Math.Asin(sinDelta));
            return(eq);
        }
コード例 #9
0
        /// <summary>
        /// Converts equatorial coordinates (for equinox B1950.0) to galactical coordinates.
        /// </summary>
        /// <param name="eq">Equatorial coordinates for equinox B1950.0</param>
        /// <returns>Galactical coordinates.</returns>
        public static CrdsGalactical ToGalactical(this CrdsEquatorial eq)
        {
            CrdsGalactical gal = new CrdsGalactical();

            double alpha0_alpha = Angle.ToRadians(192.25 - eq.Alpha);
            double delta        = Angle.ToRadians(eq.Delta);
            double delta0       = Angle.ToRadians(27.4);

            double Y    = Math.Sin(alpha0_alpha);
            double X    = Math.Cos(alpha0_alpha) * Math.Sin(delta0) - Math.Tan(delta) * Math.Cos(delta0);
            double sinb = Math.Sin(delta) * Math.Sin(delta0) + Math.Cos(delta) * Math.Cos(delta0) * Math.Cos(alpha0_alpha);

            gal.l = Angle.To360(303 - Angle.ToDegrees(Math.Atan2(Y, X)));
            gal.b = Angle.ToDegrees(Math.Asin(sinb));
            return(gal);
        }
コード例 #10
0
        /// <summary>
        /// Converts equatorial coordinates to ecliptical coordinates.
        /// </summary>
        /// <param name="eq">Pair of equatorial coordinates.</param>
        /// <param name="epsilon">Obliquity of the ecliptic, in degrees.</param>
        /// <returns></returns>
        public static CrdsEcliptical ToEcliptical(this CrdsEquatorial eq, double epsilon)
        {
            CrdsEcliptical ecl = new CrdsEcliptical();

            epsilon = Angle.ToRadians(epsilon);
            double alpha = Angle.ToRadians(eq.Alpha);
            double delta = Angle.ToRadians(eq.Delta);

            double Y = Math.Sin(alpha) * Math.Cos(epsilon) + Math.Tan(delta) * Math.Sin(epsilon);
            double X = Math.Cos(alpha);

            ecl.Lambda = Angle.ToDegrees(Math.Atan2(Y, X));
            ecl.Beta   = Angle.ToDegrees(Math.Asin(Math.Sin(delta) * Math.Cos(epsilon) - Math.Cos(delta) * Math.Sin(epsilon) * Math.Sin(alpha)));

            return(ecl);
        }
コード例 #11
0
        /// <summary>
        /// Converts local horizontal coordinates to equatorial coordinates.
        /// </summary>
        /// <param name="hor">Pair of local horizontal coordinates.</param>
        /// <param name="geo">Geographical of the observer</param>
        /// <param name="theta0">Local sidereal time.</param>
        /// <returns>Pair of equatorial coordinates</returns>
        public static CrdsEquatorial ToEquatorial(this CrdsHorizontal hor, CrdsGeographical geo, double theta0)
        {
            CrdsEquatorial eq  = new CrdsEquatorial();
            double         A   = Angle.ToRadians(hor.Azimuth);
            double         h   = Angle.ToRadians(hor.Altitude);
            double         phi = Angle.ToRadians(geo.Latitude);

            double Y = Math.Sin(A);
            double X = Math.Cos(A) * Math.Sin(phi) + Math.Tan(h) * Math.Cos(phi);

            double H = Angle.ToDegrees(Math.Atan2(Y, X));

            eq.Alpha = Angle.To360(theta0 - geo.Longitude - H);
            eq.Delta = Angle.ToDegrees(Math.Asin(Math.Sin(phi) * Math.Sin(h) - Math.Cos(phi) * Math.Cos(h) * Math.Cos(A)));

            return(eq);
        }
コード例 #12
0
        /// <summary>
        /// Converts equatorial coodinates to local horizontal
        /// </summary>
        /// <param name="eq">Pair of equatorial coodinates</param>
        /// <param name="geo">Geographical coordinates of the observer</param>
        /// <param name="theta0">Local sidereal time</param>
        /// <remarks>
        /// Implementation is taken from AA(I), formulae 12.5, 12.6.
        /// </remarks>
        public static CrdsHorizontal ToHorizontal(this CrdsEquatorial eq, CrdsGeographical geo, double theta0)
        {
            double H     = Angle.ToRadians(HourAngle(theta0, geo.Longitude, eq.Alpha));
            double phi   = Angle.ToRadians(geo.Latitude);
            double delta = Angle.ToRadians(eq.Delta);

            CrdsHorizontal hor = new CrdsHorizontal();

            double Y = Math.Sin(H);
            double X = Math.Cos(H) * Math.Sin(phi) - Math.Tan(delta) * Math.Cos(phi);

            hor.Altitude = Angle.ToDegrees(Math.Asin(Math.Sin(phi) * Math.Sin(delta) + Math.Cos(phi) * Math.Cos(delta) * Math.Cos(H)));

            hor.Azimuth = Angle.ToDegrees(Math.Atan2(Y, X));
            hor.Azimuth = Angle.To360(hor.Azimuth);

            return(hor);
        }
コード例 #13
0
ファイル: Extensions.cs プロジェクト: t9mike/ADK
        /// <summary>
        /// Calculates topocentric equatorial coordinates of celestial body
        /// with taking into account correction for parallax.
        /// </summary>
        /// <param name="eq">Geocentric equatorial coordinates of the body</param>
        /// <param name="geo">Geographical coordinates of the body</param>
        /// <param name="theta0">Apparent sidereal time at Greenwich</param>
        /// <param name="pi">Parallax of a body</param>
        /// <returns>Topocentric equatorial coordinates of the celestial body</returns>
        /// <remarks>
        /// Method is taken from AA(II), formulae 40.6-40.7.
        /// </remarks>
        public static CrdsEquatorial ToTopocentric(this CrdsEquatorial eq, CrdsGeographical geo, double theta0, double pi)
        {
            double H     = Angle.ToRadians(HourAngle(theta0, geo.Longitude, eq.Alpha));
            double delta = Angle.ToRadians(eq.Delta);
            double sinPi = Math.Sin(Angle.ToRadians(pi));

            double A = Math.Cos(delta) * Math.Sin(H);
            double B = Math.Cos(delta) * Math.Cos(H) - geo.RhoCosPhi * sinPi;
            double C = Math.Sin(delta) - geo.RhoSinPhi * sinPi;

            double q = Math.Sqrt(A * A + B * B + C * C);

            double H_ = Angle.ToDegrees(Math.Atan2(A, B));

            double alpha_ = Angle.To360(theta0 - geo.Longitude - H_);
            double delta_ = Angle.ToDegrees(Math.Asin(C / q));

            return(new CrdsEquatorial(alpha_, delta_));
        }
コード例 #14
0
ファイル: Extensions.cs プロジェクト: t9mike/ADK
        public static CrdsEquatorial ToEquatorial(this CrdsRectangular m, CrdsEquatorial planet, double P, double semidiameter)
        {
            // convert to polar coordinates

            // radius-vector of moon, in planet's equatorial radii
            double r = Math.Sqrt(m.X * m.X + m.Y * m.Y);

            // rotation angle
            double theta = Angle.ToDegrees(Math.Atan2(m.Y, m.X));

            // rotate with position angle of the planet
            theta += P;

            // convert back to rectangular coordinates, but rotated with P angle:
            double x = r * Math.Cos(Angle.ToRadians(theta));
            double y = r * Math.Sin(Angle.ToRadians(theta));

            double dAlpha = (1 / Math.Cos(Angle.ToRadians(planet.Delta))) * x * semidiameter / 3600;
            double dDelta = y * semidiameter / 3600;

            return(new CrdsEquatorial(planet.Alpha - dAlpha, planet.Delta + dDelta));
        }
コード例 #15
0
ファイル: BasicEphem.cs プロジェクト: t9mike/ADK
        /// <summary>
        /// Gets geocentric elongation angle of the celestial body
        /// </summary>
        /// <param name="sun">Ecliptical geocentrical coordinates of the Sun</param>
        /// <param name="body">Ecliptical geocentrical coordinates of the body</param>
        /// <returns>Geocentric elongation angle, in degrees, from -180 to 180.
        /// Negative sign means western elongation, positive eastern.
        /// </returns>
        /// <remarks>
        /// AA(II), formula 48.2
        /// </remarks>
        // TODO: tests
        public static double Elongation(CrdsEcliptical sun, CrdsEcliptical body)
        {
            double beta    = Angle.ToRadians(body.Beta);
            double lambda  = Angle.ToRadians(body.Lambda);
            double lambda0 = Angle.ToRadians(sun.Lambda);

            double s = sun.Lambda;
            double b = body.Lambda;

            if (Math.Abs(s - b) > 180)
            {
                if (s < b)
                {
                    s += 360;
                }
                else
                {
                    b += 360;
                }
            }

            return(Math.Sign(b - s) * Angle.ToDegrees(Math.Acos(Math.Cos(beta) * Math.Cos(lambda - lambda0))));
        }
コード例 #16
0
        /// <summary>
        /// Calculates heliocentrical coordinates of the planet using VSOP87 motion theory.
        /// </summary>
        /// <param name="planet">Planet serial number - from 1 (Mercury) to 8 (Neptune) to calculate heliocentrical coordinates.</param>
        /// <param name="jde">Julian Ephemeris Day</param>
        /// <returns>Returns heliocentric coordinates of the planet for given date.</returns>
        public static CrdsHeliocentrical GetPlanetCoordinates(int planet, double jde, bool highPrecision = true, bool epochOfDate = true)
        {
            Initialize();

            const int L = 0;
            const int B = 1;
            const int R = 2;

            int p = planet - 1;
            int e = epochOfDate ? 1 : 0;

            double t = (jde - 2451545.0) / 365250.0;

            double t2 = t * t;
            double t3 = t * t2;
            double t4 = t * t3;
            double t5 = t * t4;

            double[] l = new double[6];
            double[] b = new double[6];
            double[] r = new double[6];

            for (int j = 0; j < 6; j++)
            {
                l[j] = 0;
                for (int i = 0; i < Terms[e, p, L, j]?.Count; i++)
                {
                    if (!highPrecision && i > LPTermsCount[e, p, L, j])
                    {
                        break;
                    }

                    l[j] += Terms[e, p, L, j][i].A * Math.Cos(Terms[e, p, L, j][i].B + Terms[e, p, L, j][i].C * t);
                }
                b[j] = 0;
                for (int i = 0; i < Terms[e, p, B, j]?.Count; i++)
                {
                    if (!highPrecision && i > LPTermsCount[e, p, B, j])
                    {
                        break;
                    }

                    b[j] += Terms[e, p, B, j][i].A * Math.Cos(Terms[e, p, B, j][i].B + Terms[e, p, B, j][i].C * t);
                }
                r[j] = 0;
                for (int i = 0; i < Terms[e, p, R, j]?.Count; i++)
                {
                    if (!highPrecision && i > LPTermsCount[e, p, R, j])
                    {
                        break;
                    }

                    r[j] += Terms[e, p, R, j][i].A * Math.Cos(Terms[e, p, R, j][i].B + Terms[e, p, R, j][i].C * t);
                }
            }

            CrdsHeliocentrical result = new CrdsHeliocentrical();

            result.L = l[0] + l[1] * t + l[2] * t2 + l[3] * t3 + l[4] * t4 + l[5] * t5;
            result.L = Angle.ToDegrees(result.L);
            result.L = Angle.To360(result.L);

            result.B = b[0] + b[1] * t + b[2] * t2 + b[3] * t3 + b[4] * t4 + b[5] * t5;
            result.B = Angle.ToDegrees(result.B);

            result.R = r[0] + r[1] * t + r[2] * t2 + r[3] * t3 + r[4] * t4 + r[5] * t5;

            return(result);
        }
コード例 #17
0
        /// <summary>
        /// Loads VSOP terms from file if not loaded yet
        /// </summary>
        private static void Initialize()
        {
            // high precision
            if (Terms == null)
            {
                Terms        = new List <Term> [EPOCHS_COUNT, PLANETS_COUNT, SERIES_COUNT, POWERS_COUNT];
                LPTermsCount = new int[EPOCHS_COUNT, PLANETS_COUNT, SERIES_COUNT, POWERS_COUNT];
            }
            // already initialized
            else
            {
                return;
            }

            for (int e = 0; e < 2; e++)
            {
                using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream($"ADK.Data.VSOP87{(e == 0 ? "B" : "D")}.bin"))
                    using (var reader = new BinaryReader(stream))
                    {
                        while (reader.BaseStream.Position != reader.BaseStream.Length)
                        {
                            int p     = reader.ReadInt32();
                            int t     = reader.ReadInt32();
                            int power = reader.ReadInt32();
                            int count = reader.ReadInt32();

                            double A, B, C;

                            Terms[e, p, t, power] = new List <Term>();

                            for (int i = 0; i < count; i++)
                            {
                                A = reader.ReadDouble();
                                B = reader.ReadDouble();
                                C = reader.ReadDouble();
                                Terms[e, p, t, power].Add(new Term(A, B, C));
                            }

                            // sort terms by A coefficient descending
                            Terms[e, p, t, power].Sort((x, y) => Math.Sign(y.A - x.A));
                            LPTermsCount[e, p, t, power] = count;

                            for (int i = 0; i < count; i++)
                            {
                                // L, B
                                if (t < 2)
                                {
                                    // maximal error in seconds of arc
                                    // calculated by rule descibed in AA(II), p. 220 (Accuracy of the results)
                                    double err = Angle.ToDegrees(2 * Math.Sqrt(i + 1) * Terms[e, p, t, power][i].A) * 3600;
                                    if (err < 1)
                                    {
                                        LPTermsCount[e, p, t, power] = i;
                                        break;
                                    }
                                }
                                // R
                                else
                                {
                                    // maximal error in AU
                                    // calculated by rule descibed in AA(II), p. 220 (Accuracy of the results)
                                    double err = 2 * Math.Sqrt(i + 1) * Terms[e, p, t, power][i].A;
                                    if (err < 1e-8)
                                    {
                                        LPTermsCount[e, p, t, power] = i;
                                        break;
                                    }
                                }
                            }
                        }
                    }
            }
        }
コード例 #18
0
ファイル: PlanetPositions.cs プロジェクト: iamanas20/ADK
        /// <summary>
        /// Calculates heliocentrical coordinates of the planet using VSOP87 motion theory.
        /// </summary>
        /// <param name="planet"><see cref="Planet"/> to calculate heliocentrical coordinates.</param>
        /// <param name="jde">Julian Ephemeris Day</param>
        /// <returns>Returns heliocentric coordinates of the planet for given date.</returns>
        public static CrdsHeliocentrical GetPlanetCoordinates(Planet planet, double jde, bool highPrecision = true)
        {
            Initialize(highPrecision);

            const int L = 0;
            const int B = 1;
            const int R = 2;

            int p = (int)planet - 1;

            double t = (jde - 2451545.0) / 365250.0;

            double t2 = t * t;
            double t3 = t * t2;
            double t4 = t * t3;
            double t5 = t * t4;

            double[] l = new double[6];
            double[] b = new double[6];
            double[] r = new double[6];

            List <Term>[,,] terms = highPrecision ? TermsHP : TermsLP;

            for (int j = 0; j < 6; j++)
            {
                l[j] = 0;
                for (int i = 0; i < terms[p, L, j]?.Count; i++)
                {
                    l[j] += terms[p, L, j][i].A * Math.Cos(terms[p, L, j][i].B + terms[p, L, j][i].C * t);
                }
                b[j] = 0;
                for (int i = 0; i < terms[p, B, j]?.Count; i++)
                {
                    b[j] += terms[p, B, j][i].A * Math.Cos(terms[p, B, j][i].B + terms[p, B, j][i].C * t);
                }
                r[j] = 0;
                for (int i = 0; i < terms[p, R, j]?.Count; i++)
                {
                    r[j] += terms[p, R, j][i].A * Math.Cos(terms[p, R, j][i].B + terms[p, R, j][i].C * t);
                }
            }

            // Dimension coefficient.
            // Should be applied for the shortened VSOP87 formulae listed in AA book
            // because "A" coefficient expressed in 1e-8 radian for longitude and latitude and in 1e-8 AU for radius vector
            // Original (high-precision) version of VSOP has "A" expressed in radians and AU respectively.
            double d = highPrecision ? 1 : 1e-8;

            CrdsHeliocentrical result = new CrdsHeliocentrical();

            result.L = (l[0] + l[1] * t + l[2] * t2 + l[3] * t3 + l[4] * t4 + l[5] * t5) * d;
            result.L = Angle.ToDegrees(result.L);
            result.L = Angle.To360(result.L);

            result.B = (b[0] + b[1] * t + b[2] * t2 + b[3] * t3 + b[4] * t4 + b[5] * t5) * d;
            result.B = Angle.ToDegrees(result.B);

            result.R = (r[0] + r[1] * t + r[2] * t2 + r[3] * t3 + r[4] * t4 + r[5] * t5) * d;

            return(result);
        }