/*****************************************************************************\
 * RiseSet
\*****************************************************************************/

package com.mhuss.AstroLib;

//import android.util.Log;

/**
 * Calculates rise & set times of the sun or moon, and
 * also calculates twilight times (civil/nautical/astronomical).
 * 

* Based on code by Bill Gray (www.projectpluto.com) *

* [Bill Gray's Comments:]
* This class computes the times at which the sun or moon will rise * and set during a given day starting on the given Julian day. It * does this by computing the altitude of the object during each of * the 24 hours of that day (and 1 hour of the next). What we really * want to know is the object's altitude relative to the "rise/set * altitude." This is the altitude at which the top of the object * becomes visible, after correcting for refraction and (in the case * of the Moon) topocentric parallax. *

* For the sun, this altitude is -.8333 degrees (its apparent radius * is about .25 degrees, and refraction 'lifts it up' by .58333 * degrees.) For the moon, this altitude is +.125 degrees. *

* If we find that the object was below this altitude at one hour, * and above it on the next hour, then it must have risen in that * interval; Conversely, if we find that the object was above this * altitude at one hour, and below it on the next hour, then it must * have set in that interval. *

* We then do an iterative search to find the instant during that * hour that it rose or set. This starts with a guessed rise/set * time in the middle of the particular hour in question. At each * step, we look at the altitude of that object at that time, and * use it to adjust the rise/set time based on the assumption that * the motion was linear during the hour (this isn't a perfect * assumption, but we still usually converge in a few iterations.) *

* As a side benefit, this function will also calculate twilight * times by using the sun and just changing the event altitude. The * modified altitudes are -6 degrees (civil twilight), -12 degrees * (nautical twilight) and -18 degrees (astronomical twilight). *

* TimePair.a stores the rise (or twilight start) times.
* TimePair.b stores the set (or twilight end) times. */ public class RiseSet { /** * Calulation type (pseudo-enum) */ public static final int SUN = 0, MOON = 1, CIVIL_TWI = 2, NAUTICAL_TWI = 3, ASTRONOMICAL_TWI = 4; /** * Solar altitude adjustment */ public static final double SUN_ALT = Math.toRadians(-.83333); /** * Solar an lunar topocentric altitude adjustment */ public static final double SUN_TOPO_ALT = Math.toRadians(-.83555); /** * Lunar altitude adjustment */ public static final double MOON_ALT = Math.toRadians(.125); // Valid for _geocentric_ lunar coordinates, not topocentric! /** * Stellar altitude adjustment */ public static final double PLANET_ALT = Math.toRadians(-0.57); // Valid for _geocentric_ lunar coordinates, not topocentric! /** * Civil twilight altitude (when sun is 6 degrees below horizon). */ public static final double C_TWI_ALT = Math.toRadians(-6.); /** * Nautical twilight altitude (when sun is 12 degrees below horizon). */ public static final double N_TWI_ALT = Math.toRadians(-12.); /** * Astronomical twilight altitude (when sun is 18 degrees below horizon). */ public static final double A_TWI_ALT = Math.toRadians(-18.); /** * State enum */ public static final int UNKNOWN = 0, RISING=1, SETTING=2, CULMINATING=3; /** * Calculate the rise/set (or start/end) times. * * @param rsType Rise/Set type (SUN, MOON, CIVIL_TWI, NAUTICAL_TWI, or ASTRONOMICAL_TWI). * @param jd The Julian day for which to calculate the desired information (set to 0h local time * @param oi The observer's location * @param pd A PlanetData instance to use for our calculations. * * @return the TimePair result, local time */ public static TimePair getTimes( int rsType, double jd, ObsInfo oi, PlanetData pd) { //default to SUN double risesetAlt = SUN_ALT; // r/s altitude int planet = Planets.EARTH; switch ( rsType ) { case MOON: risesetAlt = MOON_ALT; planet = Planets.LUNA; // moon break; case CIVIL_TWI: risesetAlt = C_TWI_ALT; break; case NAUTICAL_TWI: risesetAlt = N_TWI_ALT; break; case ASTRONOMICAL_TWI: risesetAlt = A_TWI_ALT; break; default: break; }; /* * Mark both the rise and set times as INVALID, to indicate that * they've not been found. Note that it may turn out that one or * both do not occur during the given 24 hours. */ TimePair riseSet = new TimePair( Astro.INVALID, Astro.INVALID ); double altitude[] = new double[Astro.IHOURS_PER_DAY+1]; // 24 hrs + 1 // Compute the altitude for each hour: // for( int i=0; i<=Astro.IHOURS_PER_DAY; i++ ) { pd.calc( planet, jd + AstroOps.toDays(i), oi ); try { // altitude[i] = Math.asin( pd.getAltAzRadius() ) - risesetAlt; // Strickling correction after correction of PlanetData return methods altitude[i] = pd.getAltAzLat() - risesetAlt; } catch ( NoInitException ni ) {} } // Scan the hours, looking for rise/sets: // for( int i=0; i 0.) { // object is rising rs = RISING; } else if( altitude[i] > 0. && altitude[i+1] <= 0. ) { // object is setting rs= SETTING; } if ( UNKNOWN != rs ) { // we found a rise or set to refine double fraction = AstroOps.toDays(i); double alt0 = altitude[i]; double altDiff = altitude[i+1] - alt0; double delta = 1.; int iterations = 10; while( delta > .0001 && iterations > 0 ) { iterations--; delta = ( -alt0 / altDiff ) / Astro.HOURS_PER_DAY; fraction += delta; pd.calc( planet, jd + fraction, oi ); try { // alt0 = Math.asin( pd.getAltAzRadius() ) - risesetAlt; // Strickling correction after correction of PlanetData return methods alt0 = pd.getAltAzLat() - risesetAlt; } catch ( NoInitException ni ) {} } if ( RISING == rs ) riseSet.a = fraction; else if ( SETTING == rs ) riseSet.b = fraction; } } return riseSet; } /** * Calculate the rise/set (or start/end) times. * * @param rsType Rise/Set type (SUN, MOON, CIVIL_TWI, NAUTICAL_TWI, or ASTRONOMICAL_TWI). * @param jd The Julian day for which to calculate the desired information * @param oi The observer's location */ public static TimePair getTimes( int rsType, double jd, ObsInfo oi) { return getTimes( rsType, jd, oi, new PlanetData() ); } }

Ads help maintain this website.