Move longitude time correction out of calc_sun
calc_sun reported sun trajectory in seconds since the start of a UTC day, as they would occur for the specified UTC day. The caller would then add the UTC timestamp for the start of a UTC day to these numbers. This lead to complications, as e.g. a sunrise in China would be a negative value, as it occurred in the last UTC day. Futhermore, the start of a UTC day was used to signal the need for new sun calculations. This would lead to recalculations to possibly occur after its results were needed, such as after sunrise when the target longitude deviated significantly from the prime meridian. To fix this, we apply longitude time correction to the start of day calculation. This way recalculation will occur on the start of the longitude local day, close midnight for the observer. We also remove the longitude time correction from calc_sun, so that it simply returning the number of seconds since the start of the local day of the observer. The caller then adds the start of the longitude local day to get the final numbers.master
parent
b43cd9f343
commit
b9f0b8e3c0
14
color_math.c
14
color_math.c
|
@ -43,9 +43,9 @@ static double sun_hour_angle(double latitude, double declination, double target_
|
||||||
tan(latitude) * tan(declination));
|
tan(latitude) * tan(declination));
|
||||||
}
|
}
|
||||||
|
|
||||||
static time_t hour_angle_to_time(double longitude, double eqtime, double hour_angle) {
|
static time_t hour_angle_to_time(double hour_angle, double eqtime) {
|
||||||
// https://www.esrl.noaa.gov/gmd/grad/solcalc/solareqns.PDF
|
// https://www.esrl.noaa.gov/gmd/grad/solcalc/solareqns.PDF
|
||||||
return DEGREES((4.0 * M_PI - 4 * (longitude + hour_angle) - eqtime) * 60);
|
return DEGREES((4.0 * M_PI - 4 * hour_angle - eqtime) * 60);
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum sun_condition condition(double latitude_rad, double sun_declination) {
|
static enum sun_condition condition(double latitude_rad, double sun_declination) {
|
||||||
|
@ -54,7 +54,7 @@ static enum sun_condition condition(double latitude_rad, double sun_declination)
|
||||||
return sign_lat == sign_decl ? MIDNIGHT_SUN : POLAR_NIGHT;
|
return sign_lat == sign_decl ? MIDNIGHT_SUN : POLAR_NIGHT;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum sun_condition calc_sun(struct tm *tm, double longitude, double latitude, struct sun *sun) {
|
enum sun_condition calc_sun(struct tm *tm, double latitude, struct sun *sun) {
|
||||||
double orbit_angle = date_orbit_angle(tm);
|
double orbit_angle = date_orbit_angle(tm);
|
||||||
double decl = sun_declination(orbit_angle);
|
double decl = sun_declination(orbit_angle);
|
||||||
double eqtime = equation_of_time(orbit_angle);
|
double eqtime = equation_of_time(orbit_angle);
|
||||||
|
@ -62,10 +62,10 @@ enum sun_condition calc_sun(struct tm *tm, double longitude, double latitude, st
|
||||||
double ha_twilight = sun_hour_angle(latitude, decl, SOLAR_START_TWILIGHT);
|
double ha_twilight = sun_hour_angle(latitude, decl, SOLAR_START_TWILIGHT);
|
||||||
double ha_daylight = sun_hour_angle(latitude, decl, SOLAR_END_TWILIGHT);
|
double ha_daylight = sun_hour_angle(latitude, decl, SOLAR_END_TWILIGHT);
|
||||||
|
|
||||||
sun->dawn = hour_angle_to_time(longitude, eqtime, fabs(ha_twilight));
|
sun->dawn = hour_angle_to_time(fabs(ha_twilight), eqtime);
|
||||||
sun->dusk = hour_angle_to_time(longitude, eqtime, -fabs(ha_twilight));
|
sun->dusk = hour_angle_to_time(-fabs(ha_twilight), eqtime);
|
||||||
sun->sunrise = hour_angle_to_time(longitude, eqtime, fabs(ha_daylight));
|
sun->sunrise = hour_angle_to_time(fabs(ha_daylight), eqtime);
|
||||||
sun->sunset = hour_angle_to_time(longitude, eqtime, -fabs(ha_daylight));
|
sun->sunset = hour_angle_to_time(-fabs(ha_daylight), eqtime);
|
||||||
|
|
||||||
return isnan(ha_twilight) || isnan(ha_daylight) ? condition(latitude, decl) : NORMAL;
|
return isnan(ha_twilight) || isnan(ha_daylight) ? condition(latitude, decl) : NORMAL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ struct sun {
|
||||||
time_t dusk;
|
time_t dusk;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum sun_condition calc_sun(struct tm *tm, double longitude, double latitude, struct sun *sun);
|
enum sun_condition calc_sun(struct tm *tm, double latitude, struct sun *sun);
|
||||||
void calc_whitepoint(int temp, double *rw, double *gw, double *bw);
|
void calc_whitepoint(int temp, double *rw, double *gw, double *bw);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
25
main.c
25
main.c
|
@ -64,12 +64,16 @@ static inline void adjust_timerspec(struct itimerspec *timerspec) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static time_t round_day(time_t now) {
|
static time_t round_day_offset(time_t now, time_t offset) {
|
||||||
return now - (now % 86400);
|
return now - ((now - offset) % 86400);
|
||||||
}
|
}
|
||||||
|
|
||||||
static time_t tomorrow(time_t now) {
|
static time_t tomorrow(time_t now, time_t offset) {
|
||||||
return round_day(now) + 86400;
|
return round_day_offset(now, offset) + 86400;
|
||||||
|
}
|
||||||
|
|
||||||
|
static time_t longitude_time_offset(double longitude) {
|
||||||
|
return longitude * 43200 / M_PI;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct config {
|
struct config {
|
||||||
|
@ -94,6 +98,8 @@ struct context {
|
||||||
struct config config;
|
struct config config;
|
||||||
struct sun sun;
|
struct sun sun;
|
||||||
|
|
||||||
|
double longitude_time_offset;
|
||||||
|
|
||||||
enum state state;
|
enum state state;
|
||||||
enum sun_condition condition;
|
enum sun_condition condition;
|
||||||
|
|
||||||
|
@ -149,7 +155,7 @@ static void print_trajectory(struct context *ctx) {
|
||||||
static int anim_kelvin_step = 25;
|
static int anim_kelvin_step = 25;
|
||||||
|
|
||||||
static void recalc_stops(struct context *ctx, time_t now) {
|
static void recalc_stops(struct context *ctx, time_t now) {
|
||||||
time_t day = round_day(now);
|
time_t day = round_day_offset(now, -ctx->longitude_time_offset);
|
||||||
time_t last_day = ctx->calc_day;
|
time_t last_day = ctx->calc_day;
|
||||||
if (day == last_day) {
|
if (day == last_day) {
|
||||||
return;
|
return;
|
||||||
|
@ -159,7 +165,7 @@ static void recalc_stops(struct context *ctx, time_t now) {
|
||||||
struct sun sun;
|
struct sun sun;
|
||||||
struct tm tm = { 0 };
|
struct tm tm = { 0 };
|
||||||
gmtime_r(&day, &tm);
|
gmtime_r(&day, &tm);
|
||||||
enum sun_condition cond = calc_sun(&tm, ctx->config.longitude, ctx->config.latitude, &sun);
|
enum sun_condition cond = calc_sun(&tm, ctx->config.latitude, &sun);
|
||||||
|
|
||||||
switch (cond) {
|
switch (cond) {
|
||||||
case NORMAL:
|
case NORMAL:
|
||||||
|
@ -272,7 +278,7 @@ static time_t get_deadline_normal(const struct context *ctx, time_t now) {
|
||||||
} else if (now < ctx->sun.dusk) {
|
} else if (now < ctx->sun.dusk) {
|
||||||
return now + ctx->dusk_step_time;
|
return now + ctx->dusk_step_time;
|
||||||
} else {
|
} else {
|
||||||
return tomorrow(now);
|
return tomorrow(now, -ctx->longitude_time_offset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -284,7 +290,7 @@ static time_t get_deadline_transition(const struct context *ctx, time_t now) {
|
||||||
}
|
}
|
||||||
// fallthrough
|
// fallthrough
|
||||||
case POLAR_NIGHT:
|
case POLAR_NIGHT:
|
||||||
return tomorrow(now);
|
return tomorrow(now, -ctx->longitude_time_offset);
|
||||||
default:
|
default:
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
@ -300,7 +306,7 @@ static void update_timer(const struct context *ctx, timer_t timer, time_t now) {
|
||||||
deadline = get_deadline_transition(ctx, now);
|
deadline = get_deadline_transition(ctx, now);
|
||||||
break;
|
break;
|
||||||
case STATE_STATIC:
|
case STATE_STATIC:
|
||||||
deadline = tomorrow(now);
|
deadline = tomorrow(now, -ctx->longitude_time_offset);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
abort();
|
abort();
|
||||||
|
@ -595,6 +601,7 @@ static int wlrun(struct config cfg) {
|
||||||
struct context ctx = {
|
struct context ctx = {
|
||||||
.sun = { 0 },
|
.sun = { 0 },
|
||||||
.condition = SUN_CONDITION_LAST,
|
.condition = SUN_CONDITION_LAST,
|
||||||
|
.longitude_time_offset = longitude_time_offset(cfg.longitude),
|
||||||
.state = STATE_INITIAL,
|
.state = STATE_INITIAL,
|
||||||
.config = cfg,
|
.config = cfg,
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue