Ejemplo n.º 1
0
        /// <summary>
        /// Calculates the solar direction vector.
        /// Used for locating the sun graphic and as the location of the main scenery light source.
        /// </summary>
        /// <param name="latitude">latitude</param>
        /// <param name="longitude">longitude</param>
        /// <param name="clockTime">wall clock time since start of activity, days</param>
        /// <param name="date">structure made up of day, month, year and ordinal date</param>
        public static Vector3 SolarAngle(double latitude, double longitude, float clockTime, SkyViewer.Date date)
        {
            Vector3 sunDirection;

            // For these calculations, west longitude is in positive degrees,
            float NOAAlongitude = -MathHelper.ToDegrees((float)longitude);
            // Fractional year, radians
            double fYear = (MathHelper.TwoPi / 365) * (date.ordinalDate - 1 + (clockTime - 0.5));
            // Equation of time, minutes
            double eqTime = 229.18 * (0.000075
                                      + 0.001868 * Math.Cos(fYear)
                                      - 0.032077 * Math.Sin(fYear)
                                      - 0.014615 * Math.Cos(2 * fYear)
                                      - 0.040849 * Math.Sin(2 * fYear));
            // Solar declination, radians
            double solarDeclination = 0.006918
                                      - 0.399912 * Math.Cos(fYear)
                                      + 0.070257 * Math.Sin(fYear)
                                      - 0.006758 * Math.Cos(2 * fYear)
                                      + 0.000907 * Math.Sin(2 * fYear)
                                      - 0.002697 * Math.Cos(3 * fYear)
                                      + 0.001480 * Math.Sin(3 * fYear);
            // Time offset at present longitude, minutes
            double timeOffset = eqTime - 4 * NOAAlongitude + 60 * Math.Round(NOAAlongitude / 15);
            // True solar time, minutes (since midnight)
            double trueSolar = clockTime * 24 * 60 + timeOffset;
            // Solar hour angle, radians
            double solarHourAngle = MathHelper.ToRadians((float)(trueSolar / 4) - 180);

            // Solar zenith cosine. This is the Y COORDINATE of the solar Vector.
            double solarZenithCosine = Math.Sin(latitude)
                                       * Math.Sin(solarDeclination)
                                       + Math.Cos(latitude)
                                       * Math.Cos(solarDeclination)
                                       * Math.Cos(solarHourAngle);

            // Solar elevation angle, radians. Currently not used.
            //          double solarElevationAngle = MathHelper.PiOver2 - Math.Acos(solarZenithCosine);

            // Solar azimuth cosine. This is the Z COORDINATE of the solar Vector.
            double solarAzimuthCosine = -(Math.Sin(latitude)
                                          * solarZenithCosine
                                          - Math.Sin(solarDeclination)) / (
                +Math.Cos(latitude)
                * Math.Sin(Math.Acos(solarZenithCosine)));

            // Solar azimuth angle, radians. Currently not used.
            //          double solarAzimuthAngle = Math.Acos(solarAzimuthCosine);
            //          if (clockTime > 0.5)
            //              solarAzimuthAngle = MathHelper.TwoPi - solarAzimuthAngle;

            // Solar azimuth sine. This is the X COORDINATE of the solar Vector.
            double solarAzimuthSine = Math.Sin(Math.Acos(solarAzimuthCosine)) * (clockTime > 0.5 ? 1 : -1);

            sunDirection.X = -(float)solarAzimuthSine;
            sunDirection.Y = (float)solarZenithCosine;
            sunDirection.Z = -(float)solarAzimuthCosine;
            sunDirection.Normalize();
            return(sunDirection);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Calculates the lunar direction vector.
        /// </summary>
        /// <param name="latitude">latitude</param>
        /// <param name="longitude">longitude</param>
        /// <param name="clockTime">wall clock time since start of activity</param>
        /// <param name="date">structure made up of day, month, year and ordinal date</param>
        public static Vector3 LunarAngle(double latitude, double longitude, float clockTime, SkyViewer.Date date)
        {
            Vector3 moonDirection;

            // Julian day.
            double JEday = (float)367 * date.year - 7 * (date.year + (date.month + 9) / 12) / 4 + 275 * date.month / 9 + date.day - 730531.5 + clockTime;
            // Fractional time within current 100-year epoch, days
            double Ftime = JEday / 36525;
            // Ecliptic longitude, radians
            double GeoLong = Normalize(Normalize(3.8104 + 8399.71 * Ftime, MathHelper.TwoPi)
                                       + 0.10978 * Math.Sin(Normalize(2.3544 + 8328.69 * Ftime, MathHelper.TwoPi))
                                       - 0.02216 * Math.Sin(Normalize(4.5239 - 7214.12 * Ftime, MathHelper.TwoPi))
                                       + 0.0115 * Math.Sin(Normalize(4.11374 + 15542.75 * Ftime, MathHelper.TwoPi))
                                       + 0.003665 * Math.Sin(Normalize(4.7106 + 16657.38 * Ftime, MathHelper.TwoPi))
                                       - 0.003316 * Math.Sin(Normalize(6.2396 + 628.3 * Ftime, MathHelper.TwoPi))
                                       - 0.00192 * Math.Sin(Normalize(3.2568 + 16866.93 * Ftime, MathHelper.TwoPi)), MathHelper.TwoPi);
            // Ecliptic latitude, radians
            double GeoLat = 0.08954 * Math.Sin(Normalize(1.6284 + 8433.47 * Ftime, MathHelper.TwoPi))
                            + 0.004887 * Math.Sin(Normalize(3.9828 + 16762.16 * Ftime, MathHelper.TwoPi))
                            - 0.004887 * Math.Sin(Normalize(5.5554 + 104.76 * Ftime, MathHelper.TwoPi))
                            - 0.002967 * Math.Sin(Normalize(3.7978 - 7109.29 * Ftime, MathHelper.TwoPi));
            // Parallax, radians
            double Parallax = 0.0165946
                              + 0.0009041 * Math.Cos(Normalize(2.3544 + 832869 * Ftime, MathHelper.TwoPi))
                              + 0.000166 * Math.Cos(Normalize(4.5238 - 7214.06 * Ftime, MathHelper.TwoPi))
                              + 0.000136 * Math.Cos(Normalize(4.1137 + 15542.75 * Ftime, MathHelper.TwoPi))
                              + 0.000489 * Math.Cos(Normalize(4.7106 + 16657.38 * Ftime, MathHelper.TwoPi));
            // Geocentric distance, dimensionless
            double GeoDist = 1 / Math.Sin(Parallax);
            // Geocentric vector coordinates, dimensionless
            double geoX = GeoDist * Math.Cos(GeoLong) * Math.Cos(GeoLat);
            double geoY = GeoDist * Math.Sin(GeoLong) * Math.Cos(GeoLat);
            double geoZ = GeoDist * Math.Sin(GeoLat);
            // Mean obliquity of ecliptic, radians
            double Ecliptic = (0.4091 - 0.00000000623 * JEday);
            // Equator of ordinalDate vector coordinates, dimensionless
            double eclX = geoX;
            double eclY = geoY * Math.Cos(Ecliptic) - geoZ * Math.Sin(Ecliptic);
            double eclZ = geoY * Math.Sin(Ecliptic) + geoZ * Math.Cos(Ecliptic);
            // Right ascension and declination, radians
            double RightAsc = Math.Atan(eclY / eclX);

            if (eclX < 0)
            {
                RightAsc += MathHelper.Pi;
            }
            if ((eclY < 0) && (eclX > 0))
            {
                RightAsc += MathHelper.TwoPi;
            }
            double Declination = Math.Atan(eclZ / (Math.Pow((Math.Pow(eclX, 2) + Math.Pow(eclY, 2)), 0.5)));
            // Convert right ascension and declination to altitude and azimuth.
            // Equations by Stephen R. Schmitt.
            // Greenwich Mean Sidereal Time, degrees
            double GMST = 280.46061837 + 360.98564736629 * JEday;

            GMST = Normalize(GMST, 360);
            // Local Mean Sidereal Time, degrees
            double LMST = GMST + MathHelper.ToDegrees((float)longitude) / 15;
            // Hour angle, degrees
            double HA = LMST - MathHelper.ToDegrees((float)RightAsc) / 15;
            // Hour angle, radians
            double lunarHourAngle = MathHelper.ToRadians((float)HA);
            // Lunar Altitude, radians from its Sine
            double lunarAltSin   = Math.Sin(latitude) * Math.Sin(Declination) + Math.Cos(latitude) * Math.Cos(lunarHourAngle);
            double lunarAltitude = Math.Asin(lunarAltSin);
            // Lunar Azimuth, radians from its Cosine
            double lunarAltCos  = Math.Cos(lunarAltitude);
            double hourAngleSin = Math.Sin(lunarHourAngle);
            double lunarAzCos   = (Math.Sin(Declination) - lunarAltSin * Math.Sin(latitude)) / (lunarAltCos * Math.Cos(latitude));

            lunarAzCos = lunarAzCos < -1 ? -1 : lunarAzCos;
            lunarAzCos = lunarAzCos > 1 ? 1 : lunarAzCos;
            double lunarAzimuth;

            if (hourAngleSin < 0)
            {
                lunarAzimuth = Math.Acos(lunarAzCos);
            }
            else
            {
                lunarAzimuth = MathHelper.TwoPi - Math.Acos(lunarAzCos);
            }

            moonDirection.X = (float)Math.Sin(lunarAzimuth);
            moonDirection.Y = (float)lunarAltSin;
            moonDirection.Z = (float)Math.Cos(lunarAzimuth);
            moonDirection.Normalize();
            return(moonDirection);
        }