/** Returns true, if the sun is up all day (no rise and set). */ private boolean isSunUpAllDay(Calendar calendar, double latitude, double longitude) { Calendar cal = DateTimeUtils.truncateToMidnight(calendar); Sun sun = new Sun(); for (int minutes = 0; minutes <= MINUTES_PER_DAY; minutes += CURVE_TIME_INTERVAL) { setSunPosition(calendar, latitude, longitude, sun); if (sun.getPosition().getElevation() < SUN_ANGLE) { return false; } cal.add(Calendar.MINUTE, CURVE_TIME_INTERVAL); } return true; }
/** Calculates the sun position (azimuth and elevation). */ public void setSunPosition(Calendar calendar, double latitude, double longitude, Sun sun) { double lw = -longitude * DEG2RAD; double phi = latitude * DEG2RAD; double j = DateTimeUtils.dateToJulianDate(calendar); double m = getSolarMeanAnomaly(j); double c = getEquationOfCenter(m); double lsun = getEclipticLongitude(m, c); double d = getSunDeclination(lsun); double a = getRightAscension(lsun); double th = getSiderealTime(j, lw); double azimuth = getAzimuth(th, a, phi, d) / DEG2RAD; double elevation = getElevation(th, a, phi, d) / DEG2RAD; Position position = sun.getPosition(); position.setAzimuth(azimuth + 180); position.setElevation(elevation); }
private Sun getSunInfo(Calendar calendar, double latitude, double longitude, boolean onlyAstro) { double lw = -longitude * DEG2RAD; double phi = latitude * DEG2RAD; double j = DateTimeUtils.midnightDateToJulianDate(calendar) + 0.5; double n = getJulianCycle(j, lw); double js = getApproxSolarTransit(0, lw, n); double m = getSolarMeanAnomaly(js); double c = getEquationOfCenter(m); double lsun = getEclipticLongitude(m, c); double d = getSunDeclination(lsun); double jtransit = getSolarTransit(js, m, lsun); double w0 = getHourAngle(H0, phi, d); double w1 = getHourAngle(H0 + SUN_DIAMETER, phi, d); double jset = getSunsetJulianDate(w0, m, lsun, lw, n); double jsetstart = getSunsetJulianDate(w1, m, lsun, lw, n); double jrise = getSunriseJulianDate(jtransit, jset); double jriseend = getSunriseJulianDate(jtransit, jsetstart); double w2 = getHourAngle(H1, phi, d); double jnau = getSunsetJulianDate(w2, m, lsun, lw, n); double Jciv2 = getSunriseJulianDate(jtransit, jnau); double w3 = getHourAngle(H2, phi, d); double w4 = getHourAngle(H3, phi, d); double jastro = getSunsetJulianDate(w3, m, lsun, lw, n); double jdark = getSunsetJulianDate(w4, m, lsun, lw, n); double jnau2 = getSunriseJulianDate(jtransit, jastro); double jastro2 = getSunriseJulianDate(jtransit, jdark); Sun sun = new Sun(); sun.setAstroDawn(new Range(DateTimeUtils.toCalendar(jastro2), DateTimeUtils.toCalendar(jnau2))); sun.setAstroDusk(new Range(DateTimeUtils.toCalendar(jastro), DateTimeUtils.toCalendar(jdark))); if (onlyAstro) { return sun; } sun.setNoon( new Range( DateTimeUtils.toCalendar(jtransit), DateTimeUtils.toCalendar(jtransit + JD_ONE_MINUTE_FRACTION))); sun.setRise(new Range(DateTimeUtils.toCalendar(jrise), DateTimeUtils.toCalendar(jriseend))); sun.setSet(new Range(DateTimeUtils.toCalendar(jsetstart), DateTimeUtils.toCalendar(jset))); sun.setCivilDawn(new Range(DateTimeUtils.toCalendar(Jciv2), DateTimeUtils.toCalendar(jrise))); sun.setCivilDusk(new Range(DateTimeUtils.toCalendar(jset), DateTimeUtils.toCalendar(jnau))); sun.setNauticDawn(new Range(DateTimeUtils.toCalendar(jnau2), DateTimeUtils.toCalendar(Jciv2))); sun.setNauticDusk(new Range(DateTimeUtils.toCalendar(jnau), DateTimeUtils.toCalendar(jastro))); boolean isSunUpAllDay = isSunUpAllDay(calendar, latitude, longitude); // daylight Range daylightRange = new Range(); if (sun.getRise().getStart() == null && sun.getRise().getEnd() == null) { if (isSunUpAllDay) { daylightRange = new Range( DateTimeUtils.truncateToMidnight(calendar), DateTimeUtils.truncateToMidnight(addDays(calendar, 1))); } } else { daylightRange = new Range(sun.getRise().getEnd(), sun.getSet().getStart()); } sun.setDaylight(daylightRange); // morning night Sun sunYesterday = getSunInfo(addDays(calendar, -1), latitude, longitude, true); Range morningNightRange = null; if (sunYesterday.getAstroDusk().getEnd() != null && DateUtils.isSameDay(sunYesterday.getAstroDusk().getEnd(), calendar)) { morningNightRange = new Range(sunYesterday.getAstroDusk().getEnd(), sun.getAstroDawn().getStart()); } else if (isSunUpAllDay) { morningNightRange = new Range(); } else { morningNightRange = new Range(DateTimeUtils.truncateToMidnight(calendar), sun.getAstroDawn().getStart()); } sun.setMorningNight(morningNightRange); // evening night Range eveningNightRange = null; if (sun.getAstroDusk().getEnd() != null && DateUtils.isSameDay(sun.getAstroDusk().getEnd(), calendar)) { eveningNightRange = new Range( sun.getAstroDusk().getEnd(), DateTimeUtils.truncateToMidnight(addDays(calendar, 1))); } else { eveningNightRange = new Range(); } sun.setEveningNight(eveningNightRange); // night if (isSunUpAllDay) { sun.setNight(new Range()); } else { Sun sunTomorrow = getSunInfo(addDays(calendar, 1), latitude, longitude, true); sun.setNight(new Range(sun.getAstroDusk().getEnd(), sunTomorrow.getAstroDawn().getStart())); } // eclipse SunEclipse eclipse = sun.getEclipse(); MoonCalc mc = new MoonCalc(); double partial = mc.getEclipse(calendar, MoonCalc.ECLIPSE_TYPE_SUN, j, MoonCalc.ECLIPSE_MODE_PARTIAL); eclipse.setPartial(DateTimeUtils.toCalendar(partial)); double ring = mc.getEclipse(calendar, MoonCalc.ECLIPSE_TYPE_SUN, j, MoonCalc.ECLIPSE_MODE_RING); eclipse.setRing(DateTimeUtils.toCalendar(ring)); double total = mc.getEclipse(calendar, MoonCalc.ECLIPSE_TYPE_SUN, j, MoonCalc.ECLIPSE_MODE_TOTAL); eclipse.setTotal(DateTimeUtils.toCalendar(total)); return sun; }