Пример #1
0
        protected override double AdjustAltitude(Body body)
        {
            /* Readjust moon altitude based on earth radius and refraction */
            var horizon  = 90.0;
            var location = new NOVAS.OnSurface()
            {
                Latitude  = Latitude,
                Longitude = Longitude
            };
            var refraction = NOVAS.Refract(ref location, NOVAS.RefractionOption.StandardRefraction, horizon);;
            var altitude   = body.Altitude - Astrometry.ToDegree(Earth.Radius) / body.Distance + Astrometry.ToDegree(body.Radius) / body.Distance + refraction;

            return(altitude);
        }
Пример #2
0
        public Task Calculate()
        {
            return(Task.Run(() => {
                var jd = Astrometry.GetJulianDate(Date);
                var deltaT = Astrometry.DeltaT(Date);

                var location = new NOVAS.OnSurface()
                {
                    Latitude = Latitude,
                    Longitude = Longitude
                };

                var observer = new NOVAS.Observer()
                {
                    OnSurf = location,
                    Where = (short)NOVAS.ObserverLocation.EarthGeoCenter
                };

                var obj = new NOVAS.CelestialObject()
                {
                    Name = Name,
                    Number = (short)BodyNumber,
                    Star = new NOVAS.CatalogueEntry(),
                    Type = (short)NOVAS.ObjectType.MajorPlanetSunOrMoon
                };

                var objPosition = new NOVAS.SkyPosition();

                NOVAS.Place(jd + Astrometry.SecondsToDays(deltaT), obj, observer, deltaT, NOVAS.CoordinateSystem.EquinoxOfDate, NOVAS.Accuracy.Full, ref objPosition);
                this.Distance = Astrometry.AUToKilometer(objPosition.Dis);

                var siderealTime = Astrometry.GetLocalSiderealTime(Date, Longitude);
                var hourAngle = Astrometry.HoursToDegrees(Astrometry.GetHourAngle(siderealTime, objPosition.RA));
                this.Altitude = Astrometry.GetAltitude(hourAngle, Latitude, objPosition.Dec);
            }));
        }
Пример #3
0
        /// <summary>
        /// Calculates rise and set time
        /// Caveat: does not consider more than one rise and one set event
        /// </summary>
        /// <returns></returns>
        public Task <bool> Calculate()
        {
            return(Task.Run(async() => {
                // Check rise and set events in two hour periods
                var offset = 0;

                do
                {
                    // Shift date by offset
                    var offsetDate = Date.AddHours(offset);

                    // Get three body locations for date, date + 1 hour and date + 2 hours
                    var bodyAt0 = GetBody(offsetDate);
                    var bodyAt1 = GetBody(offsetDate.AddHours(1));
                    var bodyAt2 = GetBody(offsetDate.AddHours(2));

                    await Task.WhenAll(bodyAt0.Calculate(), bodyAt1.Calculate(), bodyAt2.Calculate());

                    var location = new NOVAS.OnSurface()
                    {
                        Latitude = Latitude,
                        Longitude = Longitude
                    };

                    // Adjust altitude for the three body parameters
                    var altitude0 = AdjustAltitude(bodyAt0);
                    var altitude1 = AdjustAltitude(bodyAt1);
                    var altitude2 = AdjustAltitude(bodyAt2);

                    // fit the three reference positions into a quadratic equation

                    //P1 (offsetDate | altitude0) => (0 | altitude0)
                    //P2 (offsetDate + 1 | altitude1) => (1 | altitude1)
                    //P3 (offsetDate + 2 | altitude2) => (2 | altitude2)

                    // ax² + bx + c

                    // Solve for c
                    // => altitude0 = 0 * x² + 0 * x + c => altitude0 = c

                    // Solve for b using c
                    // altitude1 = a * 1² + b * 1 + altitude0
                    //    => altitude1 = a + b + altitude0
                    //    => b = altitude1 - a - altitude0

                    // Solve for a using b and c
                    // altitude2 = a * 2² + b * 2 + altitude0
                    //   => altitude2 = 4a + 2(altitude1 - a - altitude0) + altitude0
                    //   => altitude2 = 4a + 2*altitude1 - 2a - 2*altitude0 + altitude0
                    //   => altitude2 = 2a + 2*altitude1 - altitude0
                    //   => 2a = altitude2 - 2*altitude1 + altitude0
                    //   => a = 0.5 * altitude2  - altitude1 + 0.5 * altitude0
                    //   => a = 0.5 * (altitude2 + altitude0) - altitude1

                    // Solve for b using a and c
                    //   => b = altitude1 - (0.5 * (altitude2 + altitude0) - altitude1) - altitude0
                    //   => b = altitude1 - 0.5 * altitude2 - 0.5 * altitude0 + altitude1 - altitude0
                    //   => b = 2 * altitude1 - 0.5 * altitude2 - 1.5 * altitude0

                    var a = 0.5 * (altitude2 + altitude0) - altitude1;
                    var b = 2 * altitude1 - 0.5 * altitude2 - 1.5 * altitude0;
                    var c = altitude0;

                    // a-b-c formula
                    // x = -b +- Sqrt(b² - 4ac) / 2a

                    // Discriminant definition: b² - 4ac
                    var discriminant = (Math.Pow(b, 2)) - (4.0 * a * c);

                    var zeroPoint1 = double.NaN;
                    var zeroPoint2 = double.NaN;
                    var events = 0;

                    if (discriminant == 1)
                    {
                        zeroPoint1 = (-b + Math.Sqrt(discriminant)) / (2 * a);
                        if (zeroPoint1 >= 0 && zeroPoint1 <= 2)
                        {
                            events++;
                        }
                    }
                    else if (discriminant > 1)
                    {
                        zeroPoint1 = (-b + Math.Sqrt(discriminant)) / (2 * a);
                        zeroPoint2 = (-b - Math.Sqrt(discriminant)) / (2 * a);

                        // Check if zero point is inside the span of 0 to 2 (to be inside the checked timeframe)
                        if (zeroPoint1 >= 0 && zeroPoint1 <= 2)
                        {
                            events++;
                        }
                        if (zeroPoint2 >= 0 && zeroPoint2 <= 2)
                        {
                            events++;
                        }
                        if (zeroPoint1 < 0 || zeroPoint1 > 2)
                        {
                            zeroPoint1 = zeroPoint2;
                        }
                    }

                    //find the gradient at zeroPoint1. positive => rise event, negative => set event
                    var gradient = 2 * a * zeroPoint1 + b;

                    if (events == 1)
                    {
                        if (gradient > 0)
                        {
                            // rise
                            this.Rise = offsetDate.AddHours(zeroPoint1);
                        }
                        else
                        {
                            // set
                            this.Set = offsetDate.AddHours(zeroPoint1);
                        }
                    }
                    else if (events == 2)
                    {
                        if (gradient > 0)
                        {
                            // rise and set
                            this.Rise = offsetDate.AddHours(zeroPoint1);
                            this.Set = offsetDate.AddHours(zeroPoint2);
                        }
                        else
                        {
                            // set and rise
                            this.Rise = offsetDate.AddHours(zeroPoint2);
                            this.Set = offsetDate.AddHours(zeroPoint1);
                        }
                    }
                    offset += 2;
                    //Repeat until rise and set events are found, or after a whole day
                } while (!((this.Rise != null && this.Set != null) || offset > 24));

                return true;
            }));
        }