Split state from config, cleanup

master
Kenny Levinsen 2020-10-14 17:57:34 +02:00
parent 67896358cf
commit 7bd167e9d3
3 changed files with 84 additions and 70 deletions

View File

@ -24,11 +24,9 @@ static double degrees(double radians) {
return radians * 180.0 / M_PI;
}
static void sun_angle(struct tm *tm, double longitude, double latitude, time_t *sunrise, time_t *sunset, double angle) {
void calc_sun(struct tm *tm, double longitude, double latitude, struct sun *sun) {
// https://www.esrl.noaa.gov/gmd/grad/solcalc/solareqns.PDF
double year_rad = 2 * M_PI /
days_in_year(tm->tm_year) *
(tm->tm_yday - 1 + (tm->tm_hour - 12)/24);
double year_rad = 2 * M_PI / days_in_year(tm->tm_year) * (tm->tm_yday - 1);
double eqtime = 229.18 * (0.000075 +
0.001868 * cos(year_rad) -
0.032077 * sin(year_rad) -
@ -41,16 +39,16 @@ static void sun_angle(struct tm *tm, double longitude, double latitude, time_t *
0.000907 * sin(2*year_rad) -
0.002697 * cos(3*year_rad) +
0.00148 * sin(3*year_rad);
double ha = degrees(acos(
cos(radians(angle)) / (cos(radians(latitude)) * cos(decl)) -
double ha1 = degrees(acos(
cos(radians(SOLAR_HORIZON + SOLAR_START_TWILIGHT)) / (cos(radians(latitude)) * cos(decl)) -
tan(radians(latitude)) * tan(decl)));
*sunrise = (720 - 4 * (longitude + fabs(ha)) - eqtime) * 60;
*sunset = (720 - 4 * (longitude - fabs(ha)) - eqtime) * 60;
}
void sun(struct tm *tm, double longitude, double latitude, time_t *dawn, time_t *sunrise, time_t *sunset, time_t *dusk) {
sun_angle(tm, longitude, latitude, dawn, dusk, SOLAR_HORIZON + SOLAR_START_TWILIGHT);
sun_angle(tm, longitude, latitude, sunrise, sunset, SOLAR_HORIZON + SOLAR_END_TWILIGHT);
double ha2 = degrees(acos(
cos(radians(SOLAR_HORIZON + SOLAR_END_TWILIGHT)) / (cos(radians(latitude)) * cos(decl)) -
tan(radians(latitude)) * tan(decl)));
sun->dawn = (720 - 4 * (longitude + fabs(ha1)) - eqtime) * 60;
sun->sunrise = (720 - 4 * (longitude + fabs(ha2)) - eqtime) * 60;
sun->sunset = (720 - 4 * (longitude - fabs(ha2)) - eqtime) * 60;
sun->dusk = (720 - 4 * (longitude - fabs(ha1)) - eqtime) * 60;
}
static int illuminant_d(int temp, double *x, double *y) {

View File

@ -1,7 +1,16 @@
#ifndef _COLOR_MATH_H
#define _COLOR_MATH_H
void sun(struct tm *tm, double longitude, double latitude, time_t *dawn, time_t *sunrise, time_t *sunset, time_t *dusk);
#include "time.h"
struct sun {
time_t dawn;
time_t sunrise;
time_t sunset;
time_t dusk;
};
void calc_sun(struct tm *tm, double longitude, double latitude, struct sun *sun);
double clamp(double value);
void calc_whitepoint(int temp, double *rw, double *gw, double *bw);

113
main.c
View File

@ -63,17 +63,17 @@ static int set_timer(timer_t timer, time_t deadline) {
}
#endif
struct context {
struct config {
int high_temp;
int low_temp;
int duration;
double longitude;
double latitude;
};
time_t dawn;
time_t sunrise;
time_t sunset;
time_t dusk;
struct context {
struct config config;
struct sun sun;
time_t dawn_step_time;
time_t dusk_step_time;
@ -270,38 +270,41 @@ static void set_temperature(struct wl_list *outputs, int temp, int gamma) {
static int anim_kelvin_step = 25;
static void recalc_stops(struct context *ctx, time_t now) {
time_t day = now - (now % 86400);
if (ctx->dusk == 0) {
// First calculation
} else if (now >= ctx->dusk) {
day += 86400;
} else if (day < ctx->dusk) {
if (now < ctx->sun.dusk) {
return;
}
struct tm tm = { 0 };
gmtime_r(&now, &tm);
sun(&tm, ctx->longitude, ctx->latitude, &ctx->dawn, &ctx->sunrise, &ctx->sunset, &ctx->dusk);
if (ctx->duration != -1) {
ctx->dawn = ctx->sunrise - ctx->duration;
ctx->dusk = ctx->sunset + ctx->duration;
time_t day = now - (now % 86400);
if (day < ctx->sun.dusk) {
day += 86400;
}
ctx->dawn += day;
ctx->sunrise += day;
ctx->sunset += day;
ctx->dusk += day;
int temp_diff = ctx->high_temp - ctx->low_temp;
ctx->dawn_step_time = (ctx->sunrise - ctx->dawn) * anim_kelvin_step / temp_diff;
ctx->dusk_step_time = (ctx->dusk - ctx->sunset) * anim_kelvin_step / temp_diff;
struct tm tm = { 0 };
gmtime_r(&day, &tm);
calc_sun(&tm, ctx->config.longitude, ctx->config.latitude, &ctx->sun);
if (ctx->config.duration != -1) {
ctx->sun.dawn = ctx->sun.sunrise - ctx->config.duration;
ctx->sun.dusk = ctx->sun.sunset + ctx->config.duration;
}
// TODO: Cap on eternal days?
ctx->sun.dawn += day;
ctx->sun.sunrise += day;
ctx->sun.sunset += day;
ctx->sun.dusk += day;
assert(ctx->sun.dusk > now);
int temp_diff = ctx->config.high_temp - ctx->config.low_temp;
ctx->dawn_step_time = (ctx->sun.sunrise - ctx->sun.dawn) * anim_kelvin_step / temp_diff;
ctx->dusk_step_time = (ctx->sun.dusk - ctx->sun.sunset) * anim_kelvin_step / temp_diff;
struct tm dawn, sunrise, sunset, dusk;
localtime_r(&ctx->dawn, &dawn);
localtime_r(&ctx->sunrise, &sunrise);
localtime_r(&ctx->sunset, &sunset);
localtime_r(&ctx->dusk, &dusk);
localtime_r(&ctx->sun.dawn, &dawn);
localtime_r(&ctx->sun.sunrise, &sunrise);
localtime_r(&ctx->sun.sunset, &sunset);
localtime_r(&ctx->sun.dusk, &dusk);
fprintf(stderr, "calculated new sun trajectory: dawn %02d:%02d, sunrise %02d:%02d, sunset %02d:%02d, dusk %02d:%02d\n",
dawn.tm_hour, dusk.tm_min,
dawn.tm_hour, dawn.tm_min,
sunrise.tm_hour, sunrise.tm_min,
sunset.tm_hour, sunset.tm_min,
dusk.tm_hour, dusk.tm_min);
@ -314,31 +317,30 @@ static int interpolate_temperature(time_t now, time_t start, time_t stop, int te
}
static int get_temperature(const struct context *ctx, time_t now) {
if (now < ctx->dawn) {
return ctx->low_temp;
} else if (now < ctx->sunrise) {
return interpolate_temperature(now, ctx->dawn, ctx->sunrise, ctx->low_temp, ctx->high_temp);
} else if (now < ctx->sunset) {
return ctx->high_temp;
} else if (now < ctx->dusk) {
return interpolate_temperature(now, ctx->sunset, ctx->dusk, ctx->high_temp, ctx->low_temp);
if (now < ctx->sun.dawn) {
return ctx->config.low_temp;
} else if (now < ctx->sun.sunrise) {
return interpolate_temperature(now, ctx->sun.dawn, ctx->sun.sunrise, ctx->config.low_temp, ctx->config.high_temp);
} else if (now < ctx->sun.sunset) {
return ctx->config.high_temp;
} else if (now < ctx->sun.dusk) {
return interpolate_temperature(now, ctx->sun.sunset, ctx->sun.dusk, ctx->config.high_temp, ctx->config.low_temp);
} else {
return ctx->low_temp;
return ctx->config.low_temp;
}
}
static void update_timer(struct context *ctx, timer_t timer, time_t now) {
assert(now < ctx->dusk);
assert(now < ctx->sun.dusk);
time_t deadline;
if (now < ctx->dawn) {
deadline = ctx->dawn;
} else if (now < ctx->sunrise) {
if (now < ctx->sun.dawn) {
deadline = ctx->sun.dawn;
} else if (now < ctx->sun.sunrise) {
deadline = now + ctx->dawn_step_time;
} else if (now < ctx->sunset) {
deadline = ctx->sunset;
} else if (now < ctx->dusk) {
} else if (now < ctx->sun.sunset) {
deadline = ctx->sun.sunset;
} else if (now < ctx->sun.dusk) {
deadline = now + ctx->dusk_step_time;
}
@ -413,9 +415,14 @@ int main(int argc, char *argv[]) {
// Initialize defaults
struct context ctx = {
.sun = { 0 },
.config = {
.high_temp = 6500,
.low_temp = 4000,
.duration = -1,
.latitude = 0,
.longitude = 0,
}
};
double gamma = 1.0;
wl_list_init(&ctx.outputs);
@ -442,20 +449,20 @@ int main(int argc, char *argv[]) {
while ((opt = getopt(argc, argv, "hT:t:g:d:l:L:")) != -1) {
switch (opt) {
case 'T':
ctx.high_temp = strtol(optarg, NULL, 10);
ctx.config.high_temp = strtol(optarg, NULL, 10);
break;
case 't':
ctx.low_temp = strtol(optarg, NULL, 10);
ctx.config.low_temp = strtol(optarg, NULL, 10);
break;
case 'l':
ctx.latitude = strtod(optarg, NULL);
ctx.config.latitude = strtod(optarg, NULL);
break;
case 'L':
ctx.longitude = strtod(optarg, NULL);
ctx.config.longitude = strtod(optarg, NULL);
break;
case 'd':
fprintf(stderr, "using animation duration override\n");
ctx.duration = strtod(optarg, NULL) * 60;
ctx.config.duration = strtod(optarg, NULL) * 60;
break;
case 'g':
gamma = strtod(optarg, NULL);
@ -467,9 +474,9 @@ int main(int argc, char *argv[]) {
}
}
if (ctx.high_temp == ctx.low_temp) {
if (ctx.config.high_temp == ctx.config.low_temp) {
fprintf(stderr, "high (%d) and low (%d) temperature must not be identical\n",
ctx.high_temp, ctx.low_temp);
ctx.config.high_temp, ctx.config.low_temp);
return -1;
}