You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

#### 136 lines 3.5 KiB Raw Blame History

 `#define _USE_MATH_DEFINES` `#include ` `#include ` `using namespace Rcpp;` ``` ``` `#define rad2deg(rad) ((rad * 180.0) / M_PI)` `#define deg2rad(deg) ((deg * M_PI) / 180.0)` `#define get_julian(time) (((double)time / 86400.0) + 2440587.5)` `#define get_gmst(j_day) (fmod((18.697374558 + 24.06570982441908 * (j_day - 2451545.0)), 24.0))` `inline std::vector < double > sun_ecliptic_position(double j_day) {` ``` ``` ` // compute the position of the Sun in ecliptic coordinates days since start of J2000.0` ` double n = j_day - 2451545.0;` ``` ``` ` // mean longitude of the Sun` ` double L = fmod((280.460 + 0.9856474 * n), 360.0);` ``` ``` ` // mean anomaly of the Sun` ` double g = fmod((357.528 + 0.9856003 * n), 360.0);` ``` ``` ` // ecliptic longitude of Sun` ` double lambda = L + 1.915 * sin(deg2rad(g)) + 0.02 * sin(2 * deg2rad(g));` ``` ``` ` // distance from Sun in AU` ` double R = 1.00014 - 0.01671 * cos(deg2rad(g)) - 0.0014 * cos(2 * deg2rad(g));` ``` ``` ` std::vector< double > ret(2);` ` ret[0] = lambda;` ` ret[1] = R;` ``` ``` ` return(ret);` ``` ``` `}` ``` ``` `inline double ecliptic_obliquity(double j_day) {` ``` ``` ` double n = j_day - 2451545.0;` ``` ``` ` // Julian centuries since J2000.0` ` double T = n / 36525.0;` ``` ``` ` // compute epsilon` ` return(23.43929111 -` ` T * (46.836769 / 3600.0` ` - T * (0.0001831 / 3600.0` ` + T * (0.00200340 / 3600.0` ` - T * (0.576e-6 / 3600.0` ` - T * 4.34e-8 / 3600.0)))));` ``` ``` `}` ``` ``` `std::vector< double > sun_equatorial_position(double lng, double obliq) {` ``` ``` ` double alpha = rad2deg(atan(cos(deg2rad(obliq)) * tan(deg2rad(lng))));` ` double delta = rad2deg(asin(sin(deg2rad(obliq)) * sin(deg2rad(lng))));` ``` ``` ` double lQuadrant = floor(lng / 90.0) * 90.0;` ` double raQuadrant = floor(alpha / 90.0) * 90.0;` ``` ``` ` alpha = alpha + (lQuadrant - raQuadrant);` ``` ``` ` std::vector< double > ret(2);` ``` ``` ` ret[0] = alpha;` ` ret[1] = delta;` ``` ``` ` return(ret);` ``` ``` `}` ``` ``` `inline double hour_angle(double lng, std::vector< double >sun_pos, double gst) {` ` return((gst + lng / 15.0) * 15.0 - sun_pos[0]);` `}` ``` ``` `inline double longitude(double ha, std::vector< double >sun_pos) {` ` return(rad2deg(atan(-cos(deg2rad(ha)) / tan(deg2rad(sun_pos[1])))));` `}` ``` ``` `//' Compute a single termiantor band` `//'` `//' Returns a dataframe of latitude and longitude for the line that separates illuminated` `//' day and dark night for any given time` `//'` `//' @md` `//' @param time time (numeric from `POSIXct`) for the computation (bands are time-dependent)` `//' @param from,to,by latitude sequence setup` `//' @return data frame` `//' @references ,` `//' ` `//' @export` `// [[Rcpp::export]]` `DataFrame terminator(int time, double from = -180, double to = 180, double by = 0.1) {` ``` ``` ` // calculate latitude and longitude of terminator within specified range using time (in POSIXct format, e.g. `Sys.time()`)` ` double j_day = get_julian(time);` ``` ``` ` double gst = get_gmst(j_day);` ``` ``` ` std::vector< double > sunEclPos = sun_ecliptic_position(j_day);` ``` ``` ` double eclObliq = ecliptic_obliquity(j_day);` ``` ``` ` std::vector< double > sunEqPos = sun_equatorial_position(sunEclPos[0], eclObliq);` ``` ``` ` std::vector< double > out_lat, out_lon;` ``` ``` ` out_lat.reserve(4000);` ` out_lon.reserve(4000);` ``` ``` ` int n=0;` ``` ``` ` for (double i=from; i<=to; i+=by) {` ` n += 1;` ` out_lat.push_back(i);` ` out_lon.push_back(` ` longitude(` ` hour_angle(i, sunEqPos, gst),` ` sunEqPos` ` )` ` );` ` }` ``` ``` ` out_lat.resize(n);` ` out_lon.resize(n);` ``` ``` ` return(` ` DataFrame::create(` ` Named("lat") = out_lat,` ` Named("lon") = out_lon` ` )` ` );` ``` ``` `}`