/*********************************************************************/ /* */ /* m1 - previous moon position */ /* m2 - next moon position */ /* s1 - previous sun position */ /* s2 - next sun position */ /* */ /* Test for conjunction of the sun and moon */ /* m1,s1 is in one time moment */ /* m2,s2 is in second time moment */ /* */ /* this function tests whether conjunction occurs between */ /* these two moments */ /* */ /*********************************************************************/ public static bool IsConjunction(double m1, double s1, double s2, double m2) { if (m2 < m1) { m2 += 360.0; } if (s2 < s1) { s2 += 360.0; } if ((m1 <= s1) && (s1 < s2) && (s2 <= m2)) { return(true); } m1 = GCMath.putIn180(m1); m2 = GCMath.putIn180(m2); s1 = GCMath.putIn180(s1); s2 = GCMath.putIn180(s2); if ((m1 <= s1) && (s1 < s2) && (s2 <= m2)) { return(true); } return(false); }
/////////////////////////////////////////////////////////////////////// // GET PREVIOUS CONJUNCTION OF THE SUN AND MOON // // THIS IS HELP FUNCTION FOR GetPrevConjunction(VCTIME test_date, // VCTIME &found, bool this_day, EARTHDATA earth) // // looking for previous sun-moon conjunction // it starts from input day from 12:00 AM (noon) UTC // so output can be the same day // if output is the same day, then conjunction occurs between 00:00 AM and noon of this day // // date - input / output // earth - input // return value - sun longitude in degs // // error is when return value is greater than 999.0 deg public static double GetPrevConjunction(ref GregorianDateTime date, GCEarthData earth) { int bCont = 32; double prevSun = 0.0, prevMoon = 0.0, prevDiff = 0.0; double nowSun = 0.0, nowMoon = 0.0, nowDiff = 0.0; // SUNDATA sun; double jd, longitudeMoon; GregorianDateTime d = new GregorianDateTime(); d.Set(date); d.shour = 0.5; d.TimezoneHours = 0.0; jd = d.GetJulian();//GetJulianDay(d.year, d.month, d.day); // set initial data for input day // NOTE: for grenwich //SunPosition(d, earth, sun); longitudeMoon = GCCoreAstronomy.GetMoonLongitude(d, earth); prevSun = GCSunData.GetSunLongitude(d); prevMoon = longitudeMoon; prevDiff = GCMath.putIn180(prevSun - prevMoon); do { // shift to day before d.PreviousDay(); jd -= 1.0; // calculation //SunPosition(d, earth, sun); longitudeMoon = GCCoreAstronomy.GetMoonLongitude(d, earth); nowSun = GCSunData.GetSunLongitude(d); nowMoon = longitudeMoon; nowDiff = GCMath.putIn180(nowSun - nowMoon); // if difference of previous has another sign than now calculated // then it is the case that moon was faster than sun and he //printf(" prevsun=%f\nprevmoon=%f\nnowsun=%f\nnowmoon=%f\n", prevSun, prevMoon, nowSun, nowMoon); if (IsConjunction(nowMoon, nowSun, prevSun, prevMoon)) { // now it calculates actual time and zodiac of conjunction double x; if (prevDiff == nowDiff) { return(0); } x = Math.Abs(nowDiff) / Math.Abs(prevDiff - nowDiff); if (x < 0.5) { d.shour = x + 0.5; } else { d.NextDay(); d.shour = x - 0.5; } date.Set(d); double other = GCSunData.GetSunLongitude(d); // double other2 = nowSun + (prevSun - nowSun)*x; GCMath.putIn360(prevSun); GCMath.putIn360(nowSun); if (Math.Abs(prevSun - nowSun) > 10.0) { return(GCMath.putIn180(nowSun) + (GCMath.putIn180(prevSun) - GCMath.putIn180(nowSun)) * x); } else { return(nowSun + (prevSun - nowSun) * x); } // return other2; } prevSun = nowSun; prevMoon = nowMoon; prevDiff = nowDiff; bCont--; }while (bCont >= 0); return(1000.0); }
/*********************************************************************/ /* */ /* */ /* */ /* */ /* */ /*********************************************************************/ public static double GetNextConjunction(GregorianDateTime test_date, out GregorianDateTime found, bool this_conj, GCEarthData earth) { double phi = 12.0; double l1, l2, longitudeSun, longitudeMoon; if (this_conj) { test_date.shour += 0.2; test_date.NormalizeValues(); } double jday = test_date.GetJulianComplete(); double xj; GregorianDateTime d = new GregorianDateTime(); d.Set(test_date); GregorianDateTime xd = new GregorianDateTime(); double scan_step = 1.0; int prev_tit = 0; int new_tit = -1; longitudeMoon = GCCoreAstronomy.GetMoonLongitude(d, earth); longitudeSun = GCSunData.GetSunLongitude(d); l1 = GCMath.putIn180(longitudeMoon - longitudeSun); prev_tit = GCMath.IntFloor(l1 / phi); int counter = 0; while (counter < 20) { xj = jday; xd.Set(d); jday += scan_step; d.shour += scan_step; if (d.shour > 1.0) { d.shour -= 1.0; d.NextDay(); } longitudeMoon = GCCoreAstronomy.GetMoonLongitude(d, earth); longitudeSun = GCSunData.GetSunLongitude(d); l2 = GCMath.putIn180(longitudeMoon - longitudeSun); new_tit = GCMath.IntFloor(l2 / phi); if (prev_tit < 0 && new_tit >= 0) { jday = xj; d.Set(xd); scan_step *= 0.5; counter++; continue; } else { l1 = l2; } prev_tit = new_tit; } found = new GregorianDateTime(); found.Set(d); return(longitudeSun); }
// this is not used effectovely // it is just try to have some alternative function for calculation sun position // but it needs to be fixed, because // it calculates correct ecliptical coordinates, but when transforming // into horizontal coordinates (azimut, elevation) it will do something wrong public static GCHorizontalCoords sunPosition(int year, int month, int day, int hour, int min, int sec, double lat, double longi) { double twopi = GCMath.PI2; double deg2rad = GCMath.PI2 / 180; int[] month_days = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30 }; for (int y2 = 0; y2 < month; y2++) { day += month_days[y2]; } if ((year % 4 == 0) && ((year % 400 == 0) || (year % 100 != 0)) && (day >= 60) && !(month == 2 & day == 60)) { day++; } //# Get Julian date - 2400000 double hourd = hour + min / 60.0 + sec / 3600.0; // hour plus fraction double delta = year - 1949; double leap = Math.Floor(delta / 4); // former leapyears double jd = 32916.5 + delta * 365 + leap + day + hourd / 24.0; // The input to the Atronomer's almanach is the difference between // the Julian date and JD 2451545.0 (noon, 1 January 2000) double time = jd - 51545.0; // Ecliptic coordinates // Mean longitude double mnlong = GCMath.putIn360(280.460 + .9856474 * time); // Mean anomaly double mnanom = GCMath.putIn360(357.528 + .9856003 * time); //mnanom <- mnanom * deg2rad // Ecliptic longitude and obliquity of ecliptic double eclong = mnlong + 1.915 * GCMath.sinDeg(mnanom) + 0.020 * GCMath.sinDeg(2 * mnanom); eclong = GCMath.putIn360(eclong); double oblqec = 23.439 - 0.0000004 * time; //-- eclong <- eclong * deg2rad //-- oblqec <- oblqec * deg2rad // Celestial coordinates // Right ascension and declination double num = GCMath.cosDeg(oblqec) * GCMath.sinDeg(eclong); double den = GCMath.cosDeg(eclong); double ra = GCMath.arcTan2Deg(num, den); while (ra < 0) { ra += 180; } //-- ra[den < 0] <- ra[den < 0] + pi if (den >= 0 && num < 0) { ra += 360; } double dec = GCMath.arcSinDeg(GCMath.sinDeg(oblqec) * GCMath.sinDeg(eclong)); // Local coordinates // Greenwich mean sidereal time double gmst = 6.697375 + .0657098242 * time + hourd; gmst = GCMath.putIn24(gmst); // Local mean sidereal time double lmst = gmst + longi / 15.0; lmst = GCMath.putIn24(lmst); lmst = lmst * 15.0; // Hour angle double ha = lmst - ra; ha = GCMath.putIn180(ha); // Azimuth and elevation double el = GCMath.arcSinDeg(GCMath.sinDeg(dec) * GCMath.sinDeg(lat) + GCMath.cosDeg(dec) * GCMath.cosDeg(lat) * GCMath.cosDeg(ha)); double az = GCMath.arcSinDeg(-GCMath.cosDeg(dec) * GCMath.sinDeg(ha) / GCMath.cosDeg(el)); //# ----------------------------------------------- //# New code //# Solar zenith angle double zenithAngle = GCMath.arccosDeg(GCMath.sinDeg(lat) * GCMath.sinDeg(dec) + GCMath.cosDeg(lat) * GCMath.cosDeg(dec) * GCMath.cosDeg(ha)); //# Solar azimuth az = GCMath.arccosDeg(((GCMath.sinDeg(lat) * GCMath.cosDeg(zenithAngle)) - GCMath.sinDeg(dec)) / (GCMath.cosDeg(lat) * GCMath.sinDeg(zenithAngle))); //# ----------------------------------------------- //# Azimuth and elevation el = GCMath.arcSinDeg(GCMath.sinDeg(dec) * GCMath.sinDeg(lat) + GCMath.cosDeg(dec) * GCMath.cosDeg(lat) * GCMath.cosDeg(ha)); //# ----------------------------------------------- //# New code if (ha > 0) { az += 180; } else { az = 540 - az; } az = GCMath.putIn360(az); // For logic and names, see Spencer, J.W. 1989. Solar Energy. 42(4):353 //cosAzPos <- (0 <= sin(dec) - sin(el) * sin(lat)) //sinAzNeg <- (sin(az) < 0) //az[cosAzPos & sinAzNeg] <- az[cosAzPos & sinAzNeg] + twopi //az[!cosAzPos] <- pi - az[!cosAzPos] /* * if (0 < GCMath.sinDeg(dec) - GCMath.sinDeg(el) * GCMath.sinDeg(lat)) * { * if(GCMath.sinDeg(az) < 0) * { * az = az + 360; * } * } * else * { * az = 180 - az; * } */ //el <- el / deg2rad //az <- az / deg2rad //lat <- lat / deg2rad GCHorizontalCoords coords; coords.azimut = az; coords.elevation = el; return(coords); }