Exemplo n.º 1
0
        /// <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);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Finds constellation name by point with specified equatorial coordinates for any epoch.
        /// </summary>
        /// <param name="eq">Equatorial coordinates of the point for any epoch.</param>
        /// <param name="epoch">Epoch value, in Julian Days.</param>
        /// <returns>International 3-letter code of a constellation.</returns>
        /// <remarks>
        /// Implementation is based on <see href="ftp://cdsarc.u-strasbg.fr/pub/cats/VI/42/"/>.
        /// </remarks>
        public static string FindConstellation(CrdsEquatorial eq, double epoch)
        {
            var pe     = Precession.ElementsFK5(epoch, Date.EPOCH_B1875);
            var eq1875 = Precession.GetEquatorialCoordinates(eq, pe);

            return(FindConstellation(eq1875));
        }
Exemplo n.º 3
0
        /// <summary>
        /// Adds corrections to equatorial coordinates
        /// </summary>
        public static CrdsEquatorial operator +(CrdsEquatorial lhs, CrdsEquatorial rhs)
        {
            CrdsEquatorial eq = new CrdsEquatorial();

            eq.Alpha = Angle.To360(lhs.Alpha + rhs.Alpha);
            eq.Delta = lhs.Delta + rhs.Delta;
            return(eq);
        }
Exemplo n.º 4
0
        /// <summary>
        /// Finds constellation name by point with specified equatorial coordinates for epoch B1875.
        /// </summary>
        /// <param name="eq1875">Equatorial coordinates of the point for epoch B1875.</param>
        /// <returns>International 3-letter code of a constellation.</returns>
        /// <remarks>
        /// Implementation is based on <see href="ftp://cdsarc.u-strasbg.fr/pub/cats/VI/42/"/>.
        /// </remarks>
        public static string FindConstellation(CrdsEquatorial eq1875)
        {
            // Load borders data if needed
            if (Borders == null)
            {
                using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream($"ADK.Data.Constells.dat"))
                    using (var reader = new StreamReader(stream))
                    {
                        Borders = new List <Border>();

                        string line;
                        while ((line = reader.ReadLine()) != null)
                        {
                            float  ra1       = float.Parse(line.Substring(0, 8), CultureInfo.InvariantCulture);
                            float  ra2       = float.Parse(line.Substring(9, 7), CultureInfo.InvariantCulture);
                            float  dec       = float.Parse(line.Substring(17, 8), CultureInfo.InvariantCulture);
                            string constName = line.Substring(26, 3);

                            Borders.Add(new Border(ra1, ra2, dec, constName));
                        }
                    }
            }

            double alpha = eq1875.Alpha / 15.0;
            double delta = eq1875.Delta;

            for (int i = 0; i < Borders.Count; i++)
            {
                if (Borders[i].Dec > delta)
                {
                    continue;
                }

                if (Borders[i].RA1 <= alpha)
                {
                    continue;
                }

                if (Borders[i].RA2 > alpha)
                {
                    continue;
                }

                if (alpha >= Borders[i].RA2 &&
                    alpha < Borders[i].RA1 &&
                    Borders[i].Dec <= delta)
                {
                    return(Borders[i].ConstName);
                }
                else if (Borders[i].RA1 < alpha)
                {
                    continue;
                }
            }

            return("");
        }
Exemplo n.º 5
0
        // TODO: description
        private static CrdsEquatorial InterpolateEq(double[] alpha, double[] delta, double n)
        {
            double[]       x  = new double[] { 0, 0.5, 1 };
            CrdsEquatorial eq = new CrdsEquatorial();

            eq.Alpha = Interpolation.Lagrange(x, alpha, n);
            eq.Delta = Interpolation.Lagrange(x, delta, n);
            return(eq);
        }
Exemplo n.º 6
0
        /// <summary>
        /// Returns nutation corrections for equatorial coordiantes.
        /// </summary>
        /// <param name="eq">Initial (not corrected) equatorial coordiantes.</param>
        /// <param name="ne">Nutation elements for given instant.</param>
        /// <param name="epsilon">True obliquity of the ecliptic (ε), in degrees.</param>
        /// <returns>Nutation corrections for equatorial coordiantes.</returns>
        /// <remarks>AA(II), formula 23.1</remarks>
        public static CrdsEquatorial NutationEffect(CrdsEquatorial eq, NutationElements ne, double epsilon)
        {
            CrdsEquatorial correction = new CrdsEquatorial();

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

            correction.Alpha = (Math.Cos(epsilon) + Math.Sin(epsilon) * Math.Sin(alpha) * Math.Tan(delta)) * ne.deltaPsi - (Math.Cos(alpha) * Math.Tan(delta)) * ne.deltaEpsilon;
            correction.Delta = Math.Sin(epsilon) * Math.Cos(alpha) * ne.deltaPsi + Math.Sin(alpha) * ne.deltaEpsilon;
            return(correction);
        }
Exemplo n.º 7
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);
        }
Exemplo n.º 8
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);
        }
Exemplo n.º 9
0
        /// <summary>
        /// Calculates angular separation between two points with equatorial coordinates
        /// </summary>
        /// <param name="p1">Equatorial coordinates of the first point</param>
        /// <param name="p2">Equatorial coordinates of the second point</param>
        /// <returns>Angular separation in degrees</returns>
        public static double Separation(CrdsEquatorial p1, CrdsEquatorial p2)
        {
            double a1 = ToRadians(p1.Delta);
            double a2 = ToRadians(p2.Delta);
            double A1 = p1.Alpha;
            double A2 = p2.Alpha;

            double a = Math.Acos(
                Math.Sin(a1) * Math.Sin(a2) +
                Math.Cos(a1) * Math.Cos(a2) * Math.Cos(ToRadians(A1 - A2)));

            return(double.IsNaN(a) ? 0 : ToDegrees(a));
        }
Exemplo n.º 10
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);
        }
Exemplo n.º 11
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);
        }
Exemplo n.º 12
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);
        }
Exemplo n.º 13
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);
        }
Exemplo n.º 14
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);
        }
Exemplo n.º 15
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);
        }
Exemplo n.º 16
0
        /// <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_));
        }
Exemplo n.º 17
0
        /// <summary>
        /// Calculates the aberration effect for a celestial body (star or planet) for given instant.
        /// </summary>
        /// <param name="eq">Equatorial coordinates of the body (not corrected).</param>
        /// <param name="ae">Aberration elements needed for calculation of aberration correction.</param>
        /// <returns>Returns aberration correction values for equatorial coordinates.</returns>
        /// <remarks>AA(II), formula 23.3</remarks>
        public static CrdsEquatorial AberrationEffect(CrdsEquatorial eq, AberrationElements ae, double epsilon)
        {
            double a     = Angle.ToRadians(eq.Alpha);
            double d     = Angle.ToRadians(eq.Delta);
            double theta = Angle.ToRadians(ae.lambda);
            double pi    = Angle.ToRadians(ae.pi);

            epsilon = Angle.ToRadians(epsilon);

            double da = -k * (Math.Cos(a) * Math.Cos(theta) * Math.Cos(epsilon) + Math.Sin(a) * Math.Sin(theta)) / Math.Cos(d)
                        + epsilon * k * (Math.Cos(a) * Math.Cos(pi) * Math.Cos(epsilon) + Math.Sin(a) * Math.Sin(pi)) / Math.Cos(d);

            double m = Math.Tan(epsilon) * Math.Cos(d) - Math.Sin(a) * Math.Sin(d);

            double dd = -k * (Math.Cos(theta) * Math.Cos(epsilon) * m
                              + Math.Cos(a) * Math.Sin(d) * Math.Sin(theta))
                        + epsilon * k * (Math.Cos(pi) * Math.Cos(epsilon) * m + Math.Cos(a) * Math.Sin(d) * Math.Sin(pi));

            return(new CrdsEquatorial(da / 3600, dd / 3600));
        }
Exemplo n.º 18
0
        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));
        }
Exemplo n.º 19
0
 /// <summary>
 /// Copying construtor
 /// </summary>
 /// <param name="eq">Equatorial coordinates to be copied</param>
 public CrdsEquatorial(CrdsEquatorial eq)
 {
     Alpha = eq.Alpha;
     Delta = eq.Delta;
 }
Exemplo n.º 20
0
        /// <summary>
        /// Calculates instants of rising, transit and setting for stationary celestial body for the desired date.
        /// Stationary in this particular case means that body has unchanged (or slightly changing) celestial coordinates during the day.
        /// </summary>
        /// <param name="eq">Equatorial coordinates of the celestial body.</param>
        /// <param name="location">Geographical location of the observation point.</param>
        /// <param name="theta0">Apparent sidereal time at Greenwich for local midnight of the desired date.</param>
        /// <param name="minAltitude">Minimal altitude of the body above the horizon, in degrees, to detect rise/set. Used only for calculating visibility conditions.</param>
        /// <returns>Instants of rising, transit and setting for the celestial body for the desired date.</returns>
        public static RTS RiseTransitSet(CrdsEquatorial eq, CrdsGeographical location, double theta0, double minAltitude = 0)
        {
            List <CrdsHorizontal> hor = new List <CrdsHorizontal>();

            for (int i = 0; i <= 24; i++)
            {
                double n       = i / 24.0;
                var    sidTime = InterpolateSiderialTime(theta0, n);
                hor.Add(eq.ToHorizontal(location, sidTime));
            }

            var result = new RTS();

            for (int i = 0; i < 24; i++)
            {
                double n = (i + 0.5) / 24.0;

                var sidTime = InterpolateSiderialTime(theta0, n);
                var hor0    = eq.ToHorizontal(location, sidTime);

                if (double.IsNaN(result.Transit) && hor0.Altitude > 0)
                {
                    double r = SolveParabola(Math.Sin(Angle.ToRadians(hor[i].Azimuth)), Math.Sin(Angle.ToRadians(hor0.Azimuth)), Math.Sin(Angle.ToRadians(hor[i + 1].Azimuth)));
                    if (!double.IsNaN(r))
                    {
                        double t = (i + r) / 24.0;
                        sidTime = InterpolateSiderialTime(theta0, t);

                        result.Transit         = t;
                        result.TransitAltitude = eq.ToHorizontal(location, sidTime).Altitude;
                    }
                }

                if (double.IsNaN(result.Rise) || double.IsNaN(result.Set))
                {
                    double r = SolveParabola(hor[i].Altitude - minAltitude, hor0.Altitude - minAltitude, hor[i + 1].Altitude - minAltitude);

                    if (!double.IsNaN(r))
                    {
                        double t = (i + r) / 24.0;
                        sidTime = InterpolateSiderialTime(theta0, t);

                        if (double.IsNaN(result.Rise) && hor[i].Altitude - minAltitude < 0 && hor[i + 1].Altitude - minAltitude > 0)
                        {
                            result.Rise        = t;
                            result.RiseAzimuth = eq.ToHorizontal(location, sidTime).Azimuth;
                        }

                        if (double.IsNaN(result.Set) && hor[i].Altitude - minAltitude > 0 && hor[i + 1].Altitude - minAltitude < 0)
                        {
                            result.Set        = t;
                            result.SetAzimuth = eq.ToHorizontal(location, sidTime).Azimuth;
                        }

                        if (!double.IsNaN(result.Transit) && !double.IsNaN(result.Rise) && !double.IsNaN(result.Set))
                        {
                            break;
                        }
                    }
                }
            }

            return(result);
        }
Exemplo n.º 21
0
        /// <summary>
        /// Calculates visibity details for the celestial body,
        /// </summary>
        /// <param name="eqBody">Mean equatorial coordinates of the body for the desired day.</param>
        /// <param name="eqSun">Mean equatorial coordinates of the Sun for the desired day.</param>
        /// <param name="minAltitude">Minimal altitude of the body, in degrees, to be considered as approproate for observations. By default it's 5 degrees for planet.</param>
        /// <returns><see cref="VisibilityDetails"/> instance describing details of visibility.</returns>
        // TODO: tests
        public static VisibilityDetails Details(CrdsEquatorial eqBody, CrdsEquatorial eqSun, CrdsGeographical location, double theta0, double minAltitude = 5)
        {
            var details = new VisibilityDetails();

            // period when the planet is above the horizon and its altitude is larger than "minAltitude"
            RTS body = RiseTransitSet(eqBody, location, theta0, minAltitude);

            // period when the Sun is above the horizon
            RTS sun = RiseTransitSet(eqSun, location, theta0);

            // body reaches minimal altitude but Sun does not rise at all (polar night)
            if (body.TransitAltitude > minAltitude && sun.TransitAltitude <= 0)
            {
                details.Period   = VisibilityPeriod.WholeNight;
                details.Duration = body.Duration * 24;
            }
            // body does not reach the minimal altitude during the day
            else if (body.TransitAltitude <= minAltitude)
            {
                details.Period   = VisibilityPeriod.Invisible;
                details.Duration = 0;
            }
            // there is a day/night change during the day and body reaches minimal altitude
            else if (body.TransitAltitude > minAltitude)
            {
                // "Sun is below horizon" time range, expressed in degrees (0 is midnight, 180 is noon)
                var r1 = new AngleRange(sun.Set * 360, (1 - sun.Duration) * 360);

                // "body is above horizon" time range, expressed in degrees (0 is midnight, 180 is noon)
                var r2 = new AngleRange(body.Rise * 360, body.Duration * 360);

                // find the intersections of two ranges
                var ranges = r1.Overlaps(r2);

                // no intersections of time ranges
                if (!ranges.Any())
                {
                    details.Period   = VisibilityPeriod.Invisible;
                    details.Duration = 0;
                    details.Begin    = double.NaN;
                    details.End      = double.NaN;
                }
                // the body is observable during the day
                else
                {
                    // duration of visibility
                    details.Duration = ranges.Sum(i => i.Range / 360 * 24);

                    // beginning of visibility
                    details.Begin = ranges.First().Start / 360;

                    // end of visibility
                    details.End = (details.Begin + details.Duration / 24) % 1;

                    // Evening time range, expressed in degrees
                    // Start is a sunset time, range is a timespan from sunset to midnight.
                    var rE = new AngleRange(sun.Set * 360, (1 - sun.Set) * 360);

                    // Night time range, expressed in degrees
                    // Start is a midnight time, range is a half of timespan from midnight to sunrise
                    var rN = new AngleRange(0, sun.Rise / 2 * 360);

                    // Morning time range, expressed in degrees
                    // Start is a half of time from midnight to sunrise, range is a time to sunrise
                    var rM = new AngleRange(sun.Rise / 2 * 360, sun.Rise / 2 * 360);

                    foreach (var r in ranges)
                    {
                        var isEvening = r.Overlaps(rE);
                        if (isEvening.Any())
                        {
                            details.Period |= VisibilityPeriod.Evening;
                        }

                        var isNight = r.Overlaps(rN);
                        if (isNight.Any())
                        {
                            details.Period |= VisibilityPeriod.Night;
                        }

                        var isMorning = r.Overlaps(rM);
                        if (isMorning.Any())
                        {
                            details.Period |= VisibilityPeriod.Morning;
                        }
                    }
                }
            }

            return(details);
        }
Exemplo n.º 22
0
        /// <summary>
        /// Calculates instants of rising, transit and setting for non-stationary celestial body for the desired date.
        /// Non-stationary in this particular case means that body has fastly changing celestial coordinates during the day.
        /// </summary>
        /// <param name="eq">Array of three equatorial coordinates of the celestial body correspoding to local midnight, local noon, and local midnight of the following day after the desired date respectively.</param>
        /// <param name="location">Geographical location of the observation point.</param>
        /// <param name="theta0">Apparent sidereal time at Greenwich for local midnight of the desired date.</param>
        /// <param name="pi">Horizontal equatorial parallax of the body.</param>
        /// <param name="sd">Visible semidiameter of the body, expressed in degrees.</param>
        /// <returns>Instants of rising, transit and setting for the celestial body for the desired date.</returns>
        public static RTS RiseTransitSet(CrdsEquatorial[] eq, CrdsGeographical location, double theta0, double pi = 0, double sd = 0)
        {
            if (eq.Length != 3)
            {
                throw new ArgumentException("Number of equatorial coordinates in the array should be equal to 3.");
            }

            double[] alpha = new double[3];
            double[] delta = new double[3];
            for (int i = 0; i < 3; i++)
            {
                alpha[i] = eq[i].Alpha;
                delta[i] = eq[i].Delta;
            }

            Angle.Align(alpha);
            Angle.Align(delta);

            List <CrdsHorizontal> hor = new List <CrdsHorizontal>();

            for (int i = 0; i <= 24; i++)
            {
                double         n       = i / 24.0;
                CrdsEquatorial eq0     = InterpolateEq(alpha, delta, n);
                var            sidTime = InterpolateSiderialTime(theta0, n);
                hor.Add(eq0.ToTopocentric(location, sidTime, pi).ToHorizontal(location, sidTime));
            }

            var result = new RTS();

            for (int i = 0; i < 24; i++)
            {
                double n = (i + 0.5) / 24.0;

                CrdsEquatorial eq0 = InterpolateEq(alpha, delta, n);

                var sidTime = InterpolateSiderialTime(theta0, n);
                var hor0    = eq0.ToTopocentric(location, sidTime, pi).ToHorizontal(location, sidTime);

                if (double.IsNaN(result.Transit) && hor0.Altitude > 0)
                {
                    double r = SolveParabola(Math.Sin(Angle.ToRadians(hor[i].Azimuth)), Math.Sin(Angle.ToRadians(hor0.Azimuth)), Math.Sin(Angle.ToRadians(hor[i + 1].Azimuth)));
                    if (!double.IsNaN(r))
                    {
                        double t = (i + r) / 24.0;

                        eq0     = InterpolateEq(alpha, delta, t);
                        sidTime = InterpolateSiderialTime(theta0, t);

                        result.Transit         = t;
                        result.TransitAltitude = eq0.ToTopocentric(location, sidTime, pi).ToHorizontal(location, sidTime).Altitude;
                    }
                }

                if (double.IsNaN(result.Rise) || double.IsNaN(result.Set))
                {
                    double r = SolveParabola(hor[i].Altitude + sd, hor0.Altitude + sd, hor[i + 1].Altitude + sd);

                    if (!double.IsNaN(r))
                    {
                        double t = (i + r) / 24.0;
                        eq0     = InterpolateEq(alpha, delta, t);
                        sidTime = InterpolateSiderialTime(theta0, t);

                        if (double.IsNaN(result.Rise) && hor[i].Altitude + sd < 0 && hor[i + 1].Altitude + sd > 0)
                        {
                            result.Rise        = t;
                            result.RiseAzimuth = eq0.ToTopocentric(location, sidTime, pi).ToHorizontal(location, sidTime).Azimuth;
                        }

                        if (double.IsNaN(result.Set) && hor[i].Altitude + sd > 0 && hor[i + 1].Altitude + sd < 0)
                        {
                            result.Set        = t;
                            result.SetAzimuth = eq0.ToTopocentric(location, sidTime, pi).ToHorizontal(location, sidTime).Azimuth;
                        }

                        if (!double.IsNaN(result.Transit) && !double.IsNaN(result.Rise) && !double.IsNaN(result.Set))
                        {
                            break;
                        }
                    }
                }
            }

            return(result);
        }