Beispiel #1
0
        /// <summary>
        /// Calculates the part of the day, using the given parameters
        /// </summary>
        /// <param name="observationTime">The date and time of observation</param>
        /// <param name="timezone">The observer's time zone</param>
        /// <param name="deltaUT1">The "delta UT1" parameter, retrieved from observation in seconds</param>
        /// <param name="deltaT">The "delta T" parameter, retrieved from observation in seconds</param>
        /// <param name="latitude">The observer's latitude in degrees (negative south of the Equator)</param>
        /// <param name="longitude">The observer's longitude in degrees (negative west of Greenwich)</param>
        /// <param name="elevation">The observer's elevation in meters</param>
        /// <param name="temperature">The annual average local temperature in degrees Celsius</param>
        /// <param name="pressure">The annual average local pressure in millibars</param>
        /// <param name="refraction">The atmospheric refraction at the horizon (at sunrise / sunset) in degrees</param>
        /// <returns>Returns the part of the day. In case of invalid input data, returns Unknown</returns>
        public static PartOfDay GetPartOfDay(
            DateTime observationTime,
            TimeSpan timezone,
            double deltaUT1,
            double?deltaT,
            double latitude,
            double longitude,
            double elevation,
            double temperature,
            double pressure,
            double?refraction)
        {
            var sunData = new SunData(observationTime, timezone.TotalHours, deltaUT1, deltaT, latitude, longitude, elevation, temperature, pressure, refraction);

            try
            {
                SunPositionCalculator.CalculateSunPosition(sunData);
            }
            catch (ArgumentException)
            {
                // Invalid input data - should return an Unknown value
                return(PartOfDay.Unknown);
            }

            var azimuth     = sunData.AstronomicalTopocentricAzimuth;
            var zenithAngle = sunData.TopocentricZenithAngle;

            if (zenithAngle < 90)
            {
                return(PartOfDay.Day);
            }
            else if (zenithAngle >= 90 + TwilightElevation)
            {
                return(PartOfDay.Night);
            }
            else
            {
                if (azimuth > 180)
                {
                    return(PartOfDay.Dawn);
                }
                else
                {
                    return(PartOfDay.Dusk);
                }
            }
        }
Beispiel #2
0
        private static void CalculateSunGeocentricEquatorialCoordinates(SunData data)
        {
            double[] correctionTerms = new double[Constants.TermsXCount];

            data.JulianCentury = CalculateJulianCentury(data.JulianDay);

            data.JulianEphemerisDay        = CalculateJulianEphemerisDay(data.JulianDay, data.DeltaT);
            data.JulianEphemerisCentury    = CalculateJulianEphemerisCentury(data.JulianEphemerisDay);
            data.JulianEphemerisMillennium = CalculateJulianEphemerisMillennium(data.JulianEphemerisCentury);

            data.EarthHeliocentricLongitude = CalculateEarthHeliocentricLongitude(data.JulianEphemerisMillennium);
            data.EarthHeliocentricLatitude  = CalculateEarthHeliocentricLatitude(data.JulianEphemerisMillennium);
            data.EarthRadiusVector          = CalculateEarthRadiusVector(data.JulianEphemerisMillennium);

            data.GeocentricLongitude = CalculateGeocentricLongitude(data.EarthHeliocentricLongitude);
            data.GeocentricLatitude  = CalculateGeocentricLatitude(data.EarthHeliocentricLatitude);

            correctionTerms[Constants.TermX0] = data.MeanElongationOfTheMoonFromTheSun = CalculateTheMeanElongationOfTheMoonFromTheSun(data.JulianEphemerisCentury);
            correctionTerms[Constants.TermX1] = data.MeanSunAnomaly = CalculateTheMeanSunAnomaly(data.JulianEphemerisCentury);
            correctionTerms[Constants.TermX2] = data.MeanMoonAnomaly = CalculateTheMeanMoonAnomaly(data.JulianEphemerisCentury);
            correctionTerms[Constants.TermX3] = data.MoonArgumentOfLatitude = CalculateTheMoonArgumentOfLatitude(data.JulianEphemerisCentury);
            correctionTerms[Constants.TermX4] = data.MoonAscendingNodeLongitude = CalculateTheMoonAscendingNodeLongitude(data.JulianEphemerisCentury);

            double longitudeNutation;
            double obliquityNutation;

            CalculateTheNutationInLongitudeAndObliquity(data.JulianEphemerisCentury, correctionTerms, out longitudeNutation, out obliquityNutation);
            data.LongitudeNutation = longitudeNutation;
            data.ObliquityNutation = obliquityNutation;

            data.MeanEclipticObliquity = CalculateTheMeanEclipticObliquity(data.JulianEphemerisMillennium);
            data.TrueEclipticObliquity = CalculateTheTrueEclipticObliquity(data.ObliquityNutation, data.MeanEclipticObliquity);

            data.AberrationCorrection      = CalculateAberrationCorrection(data.EarthRadiusVector);
            data.ApparentSunLongitude      = CalculateApparentSunLongitude(data.GeocentricLongitude, data.LongitudeNutation, data.AberrationCorrection);
            data.GreenwichMeanSiderealTime = CalculateTheGreenwichMeanSiderealTime(data.JulianDay, data.JulianCentury);
            data.GreenwichSiderealTime     = CalculateTheGreenwichSiderealTime(data.GreenwichMeanSiderealTime, data.LongitudeNutation, data.TrueEclipticObliquity);

            data.SunRightAscension = CalculateTheSunGeocentricRightAscension(data.ApparentSunLongitude, data.TrueEclipticObliquity, data.GeocentricLatitude);
            data.SunDeclination    = CalculateTheSunGeocentricDeclination(data.GeocentricLatitude, data.TrueEclipticObliquity, data.ApparentSunLongitude);
        }
Beispiel #3
0
        /// <summary>
        /// Calculates the position of the Sun (zenith angle and azimuth) for a given SunData object
        /// </summary>
        /// <param name="data">An object holding information about the place and time of observation</param>
        public static void CalculateSunPosition(SunData data)
        {
            SunDataValidator.ValidateSunData(data);

            data.JulianDay = CalculateJulianDay(data.ObservationTime, data.Timezone, data.DeltaUT1);

            CalculateSunGeocentricEquatorialCoordinates(data);

            data.ObserverHourAngle = CalculateObserverHourAngle(data.GreenwichSiderealTime, data.Longitude, data.SunRightAscension);
            data.SunEquatorialHorizontalParallax = CalculateTheSunEquatorialHorizontalParallax(data.EarthRadiusVector);

            double rightAscensionParallax;
            double topocentricSunDeclination;

            CalculateRightAscensionParallaxAndTopocentricDeclination(
                data.Latitude,
                data.Elevation,
                data.SunEquatorialHorizontalParallax,
                data.ObserverHourAngle,
                data.SunDeclination,
                out rightAscensionParallax,
                out topocentricSunDeclination);
            data.RightAscensionParallax    = rightAscensionParallax;
            data.TopocentricSunDeclination = topocentricSunDeclination;

            data.TopocentricSunRightAscension = CalculateTopocentricRightAscension(data.SunRightAscension, data.RightAscensionParallax);
            data.TopocentricLocalHourAngle    = CalculateTopocentricHourAngle(data.ObserverHourAngle, data.RightAscensionParallax);

            data.TopocentricElevation          = CalculateTopocentricElevationAngle(data.Latitude, data.TopocentricSunDeclination, data.TopocentricLocalHourAngle);
            data.RefractionCorrection          = CalculateAtmosphericRefraction(data.Pressure, data.Temperature, data.Refraction.Value, data.TopocentricElevation);
            data.TopocentricElevationCorrected = CalculateTopocentricElevationAngleWithRefractionCorrection(data.TopocentricElevation, data.RefractionCorrection);

            data.TopocentricZenithAngle         = CalculateTopocentricZenithAngle(data.TopocentricElevationCorrected);
            data.AstronomicalTopocentricAzimuth = CalculateAstronomicalTopocentricAzimuth(data.TopocentricLocalHourAngle, data.Latitude, data.TopocentricSunDeclination);
            data.TopocentricAzimuth             = CalculateTopocentricAzimuth(data.AstronomicalTopocentricAzimuth);
        }
Beispiel #4
0
        public static void ValidateSunData(SunData data)
        {
            if (Math.Abs(data.Timezone) > MaxAbsTimeZone)
            {
                throw new ArgumentException(string.Format(
                                                "The timezone is invalid. It should be between -{0} and {0}.",
                                                MaxAbsTimeZone));
            }

            if (data.DeltaUT1 <= MinDeltaUT1 || data.DeltaUT1 >= MaxDeltaUT1)
            {
                throw new ArgumentException(string.Format(
                                                "The delta UT1 parameter is invalid. It should be between {0} and {1} seconds.",
                                                MinDeltaUT1,
                                                MaxDeltaUT1));
            }

            if (data.DeltaT.HasValue && Math.Abs(data.DeltaT.Value) > MaxAbsDeltaT)
            {
                throw new ArgumentException(string.Format(
                                                "The delta T parameter is invalid. It should be between -{0} and {0} seconds.",
                                                MaxAbsDeltaT));
            }

            if (Math.Abs(data.Latitude) > MaxAbsLatitude)
            {
                throw new ArgumentException(string.Format(
                                                "The latitude is invalid. It should be between -{0} and {0} degrees.",
                                                MaxAbsLatitude));
            }

            if (Math.Abs(data.Longitude) > MaxAbsLongitude)
            {
                throw new ArgumentException(string.Format(
                                                "The longitude is invalid. It should be between -{0} and {0} degrees.",
                                                MaxAbsLongitude));
            }

            if (data.Elevation < MinElevation)
            {
                throw new ArgumentException(string.Format(
                                                "The elevation is invalid. It should be at least {0} meters.",
                                                MinElevation));
            }

            if (data.Temperature <= MinTemperature || data.Temperature >= MaxTemperature)
            {
                throw new ArgumentException(string.Format(
                                                "The temperature is invalid. It should be between {0} and {1} degrees Celsius.",
                                                MinTemperature,
                                                MaxTemperature));
            }

            if (data.Pressure < MinAtmosphericPressure || data.Pressure > MaxAtmosphericPressure)
            {
                throw new ArgumentException(string.Format(
                                                "The atmospheric pressure is invalid. It should be between {0} and {1} millibars.",
                                                MinAtmosphericPressure,
                                                MaxAtmosphericPressure));
            }

            if (data.Refraction.HasValue && data.Refraction > MaxRefraction)
            {
                throw new ArgumentException(string.Format(
                                                "The refraction at the horizon is invalid. It should be at most {0} degrees.",
                                                MaxRefraction));
            }
        }