From 30040aecacb67e72d0cced1a4c3d27e41adbc323 Mon Sep 17 00:00:00 2001 From: Jimmy Bjorklund Date: Thu, 4 Oct 2018 17:47:21 +0200 Subject: [PATCH] Fixed LF --- CMakeLists.txt | 2 +- Date.cpp | 127 ++++++----- Date.h | 36 ++-- Readme.md | 56 ++--- SunCalc.cpp | 498 +++++++++++++++++++++---------------------- SunCalc.h | 102 ++++----- SunLight.cpp | 290 ++++++++++++------------- SunLight.h | 156 +++++++------- Tests/CMakeLists.txt | 21 +- 9 files changed, 645 insertions(+), 643 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9515ca9..370a6db 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ option( INCLUDE_LIBSUNLIGHT "Include libSunLight" ON ) if( NOT ${INCLUDE_LIBSUNLIGHT} ) return() endif() - +option( make_tests "Build g tests" OFF ) project(SunLight) diff --git a/Date.cpp b/Date.cpp index 607ecc8..09e92bf 100644 --- a/Date.cpp +++ b/Date.cpp @@ -1,53 +1,76 @@ -#include -#include "Date.h" - -Date::Date() : year(0), month(0), day(0) -{ -} - -Date::Date(int y, int m, int d) : year(y), month(m), day(d) -{ -} - -Date::Date(const time_t& time) -{ - struct tm t; - gmtime_r(&time, &t); - year = t.tm_year + 1900; - month = t.tm_mon + 1; - day = t.tm_mday; -} - -Date::Date(double juliandate) -{ - double z = floor(juliandate + 0.5); - double f = (juliandate + 0.5) - z; - double A; - if (z < 2299161) - { - A = z; - } - else - { - double alpha = floor((z - 1867216.25) / 36524.25); - A = z + 1 + alpha - floor(alpha / 4); - } - double B = A + 1524; - double C = floor((B - 122.1) / 365.25); - double D = floor(365.25 * C); - double E = floor((B - D) / 30.6001); - day = B - D - floor(30.6001 * E) + f; - month = (E < 14) ? E - 1 : E - 13; - year = ((month > 2) ? C - 4716 : C - 4715); -} - -double Date::toJulianDate() const -{ - double y = year; - double m = month; - double d = day; - double A = floor(y / 100); - double B = 2 - A + floor(A / 4); - double JD = floor(365.25 * (y + 4716)) + floor(30.6001 * (m + 1)) + d + B - 1524.5; - return JD; +#include +#include +#include "Date.h" + +Date::Date() : year(0), month(0), day(0) +{ +} + +Date::Date(int y, int m, int d) : year(y), month(m), day(d) +{ +} + +Date::Date(const time_t& time) +{ + struct tm t; + gmtime_r(&time, &t); + year = t.tm_year + 1900; + month = t.tm_mon + 1; + day = t.tm_mday; +} + +Date::Date(double juliandate) +{ + double z = floor(juliandate + 0.5); + double f = (juliandate + 0.5) - z; + double A; + if (z < 2299161) + { + A = z; + } + else + { + double alpha = floor((z - 1867216.25) / 36524.25); + A = z + 1 + alpha - floor(alpha / 4); + } + double B = A + 1524; + double C = floor((B - 122.1) / 365.25); + double D = floor(365.25 * C); + double E = floor((B - D) / 30.6001); + day = B - D - floor(30.6001 * E) + f; + month = (E < 14) ? E - 1 : E - 13; + year = ((month > 2) ? C - 4716 : C - 4715); +} + +double Date::toJulianDate() const +{ + double y = year; + double m = month; + double d = day; + double A = floor(y / 100); + double B = 2 - A + floor(A / 4); + double JD = floor(365.25 * (y + 4716)) + floor(30.6001 * (m + 1)) + d + B - 1524.5; + return JD; +} + +time_t Date::julianDateToTimeT(double jd) +{ + return (jd - 2440587.5) * 86400.0; +} + +time_t Date::ToTimeT(const Date& d, double time) +{ + struct tm tm; + memset(&tm, 0, sizeof(struct tm)); + tm.tm_year = d.year - 1900; + tm.tm_mon = d.month - 1; + tm.tm_mday = d.day; + time_t date = mktime(&tm); // Make time creates the time assuming the current time, remove gmtoff later! + + int min = floor(time); + double sec = time - floor(time); + date += (min * 60) + (sec * 60.0); + + date += tm.tm_gmtoff - (tm.tm_isdst * 3600); + return date; } \ No newline at end of file diff --git a/Date.h b/Date.h index 687c6f9..65b9a91 100644 --- a/Date.h +++ b/Date.h @@ -1,18 +1,20 @@ -#ifndef __SUN_CALC_DATE_H__ -#define __SUN_CALC_DATE_H__ -#include - -class Date -{ -public: - int year; //!< Year in format YYYY e.g 2000 - int month; //!< Month of the year 1-12. - int day; //!< Day of the month 1-32. - Date(); - Date(int year, int month, int day); - Date(double); //!< Juliandate - Date(const time_t& time); - double toJulianDate() const; -}; - +#ifndef __SUN_CALC_DATE_H__ +#define __SUN_CALC_DATE_H__ +#include + +class Date +{ +public: + int year; //!< Year in format YYYY e.g 2000 + int month; //!< Month of the year 1-12. + int day; //!< Day of the month 1-32. + Date(); + Date(int year, int month, int day); + Date(double); //!< Juliandate + Date(const time_t& time); + double toJulianDate() const; + static time_t julianDateToTimeT(double jd); //!< Converst julian date to time_t + static time_t ToTimeT(const Date& d, double time); //!< Combine julian timestamp and date to create a new time_t +}; + #endif // __SUN_CALC_DATE_H__ \ No newline at end of file diff --git a/Readme.md b/Readme.md index 73a7e79..ee2208f 100644 --- a/Readme.md +++ b/Readme.md @@ -1,29 +1,29 @@ -# SunLight - - This class library gives you varios sunrise and sunset values depening on your date and longiture and latitude. - It bases its implementation on the NOAA Solar Calculator. - - -### Credits: - This is strongly influenced by the javascript library solar-calc - https://github.com/jonhester/solar-calc - -### Reference: - https://www.esrl.noaa.gov/gmd/grad/solcalc/index.html - - -### Sample: - -```cpp - double latitude = 59.370272; - double longitude = 18.000767; - time_t now = time(NULL); - - SunLight sunLight(Date(now), latitude, longitude); - - time_t sunrise = sunLight.sunrise(); - time_t sunset = sunLight.sunset(); - - std::cout << "sunrise: " << asctime( gmtime(&sunrise)) << std::endl; - std::cout << "sunset: " << asctime( gmtime(&sunrise)) << std::endl; +# SunLight + + This class library gives you varios sunrise and sunset values depening on your date and longiture and latitude. + It bases its implementation on the NOAA Solar Calculator. + + +### Credits: + This is strongly influenced by the javascript library solar-calc + https://github.com/jonhester/solar-calc + +### Reference: + https://www.esrl.noaa.gov/gmd/grad/solcalc/index.html + + +### Sample: + +```cpp + double latitude = 59.370272; + double longitude = 18.000767; + time_t now = time(NULL); + + SunLight sunLight(Date(now), latitude, longitude); + + time_t sunrise = sunLight.sunrise(); + time_t sunset = sunLight.sunset(); + + std::cout << "sunrise: " << asctime( gmtime(&sunrise)) << std::endl; + std::cout << "sunset: " << asctime( gmtime(&sunrise)) << std::endl; ``` \ No newline at end of file diff --git a/SunCalc.cpp b/SunCalc.cpp index 66fea3b..6bb1b83 100644 --- a/SunCalc.cpp +++ b/SunCalc.cpp @@ -1,260 +1,238 @@ -#include - -#include -#include -#include -#include - -#include "SunCalc.h" - -SunCalc::SunCalc(const Date &date, double latitude, double longitude) -{ - _date = date; - _latitude = latitude; - _longitude = longitude; - _julianDate = date.toJulianDate(); -} - -time_t SunCalc::ToTimeT(const Date& d, double x) -{ - struct tm tm; - memset(&tm, 0, sizeof(struct tm)); - tm.tm_year = d.year - 1900; - tm.tm_mon = d.month - 1; - tm.tm_mday = d.day; - time_t date = mktime(&tm); // Make time creates the time assuming the current time, remove gmtoff later! - - int min = floor(x); - double sec = x - floor(x); - date += (min * 60) + (sec * 60.0); - - date += tm.tm_gmtoff - (tm.tm_isdst * 3600); - return date; -} - -double SunCalc::timeAtAngle(float angle, bool rising) -{ - return calcSunriseSet(rising, angle, _julianDate, _date, _latitude, _longitude); -} - -time_t SunCalc::JdToDate(double jd) -{ - return (jd - 2440587.5) * 86400.0; -} - -// rise = true for sunrise, false for sunset -time_t SunCalc::calcSunriseSet(bool rise, float angle, double JD, Date date, double latitude, double longitude) -{ - double timeUTC = calcSunriseSetUTC(rise, angle, JD, latitude, longitude); - double newTimeUTC = calcSunriseSetUTC(rise, angle, JD + timeUTC / 1440.0, latitude, longitude); - - if (!isnan(newTimeUTC)) - { - return ToTimeT(_date, newTimeUTC); - } - // no sunrise/set found - double doy = calcDoyFromJD(JD); - double jdy; - if (( (latitude > 66.4) && (doy > 79) && (doy < 267) ) || - ( (latitude < -66.4) && ((doy < 83) || (doy > 263)))) - { - //previous sunrise/next sunset - jdy = calcJDofNextPrevRiseSet(!rise, rise, angle, timeUTC); - } - else - { - //previous sunset/next sunrise - jdy = calcJDofNextPrevRiseSet(rise, rise, angle, timeUTC); - } - timeUTC = calcSunriseSetUTC(rise, angle, jdy, latitude, longitude); - newTimeUTC = calcSunriseSetUTC(rise, angle, jdy + timeUTC / 1440.0, latitude, longitude); - return ToTimeT(Date(jdy), newTimeUTC); - //return JdToDate(jdy); -} - -double SunCalc::calcSunriseSetUTC(bool rise, float angle, double JD, double latitude, double longitude) -{ - double t = calcTimeJulianCent(JD); - double eqTime = calcEquationOfTime(t); - double solarDec = calcSunDeclination(t); - double hourAngle = calcHourAngle(angle, latitude, solarDec); - //alert("HA = " + radToDeg(hourAngle)); - if (!rise) - hourAngle = -hourAngle; - double delta = longitude + radToDeg(hourAngle); - double timeUTC = 720.0 - (4.0 * delta) - eqTime; // in minutes - return timeUTC; -} - -double SunCalc::calcTimeJulianCent(double jd) -{ - double d = (jd - 2451545.0); - double T = d / 36525.0; - return T; -} - -double SunCalc::calcEquationOfTime(double t) -{ - double epsilon = calcObliquityCorrection(t); - double l0 = calcGeomMeanLongSun(t); - double e = calcEccentricityEarthOrbit(t); - double m = calcGeomMeanAnomalySun(t); - double tmp1 = degToRad(epsilon); - double y = tan(tmp1 / 2.0); - y *= y; - - double t_l0 = degToRad(l0); - double t_m = degToRad(m); - - double sin2l0 = sin(2.0 * t_l0); - double cos2l0 = cos(2.0 * t_l0); - - double sinm = sin(t_m); - - double tmp3 = 4.0 * t_l0; - double sin4l0 = sin(tmp3); - double sin2m = sin(2.0 * t_m); - - double Etime = y * sin2l0 - 2.0 * e * sinm + 4.0 * e * y * sinm * cos2l0 - 0.5 * y * y * sin4l0 - 1.25 * e * e * sin2m; - return radToDeg(Etime) * 4.0; // in minutes of time -} - -double SunCalc::calcSunDeclination(double t) -{ - double e = calcObliquityCorrection(t); - double lambda = calcSunApparentLong(t); - - double sint = sin(degToRad(e)) * sin(degToRad(lambda)); - double theta = radToDeg(asin(sint)); - return theta; // in degrees -} - -double SunCalc::calcHourAngle(float angle, double lat, double solarDec) -{ - double latRad = degToRad(lat); - double sdRad = degToRad(solarDec); - double HAarg = (cos(degToRad(90.0 + angle)) / (cos(latRad) * cos(sdRad)) - tan(latRad) * tan(sdRad)); - double HA = acos(HAarg); - return HA; // in radians (for sunset, use -HA) -} - -double SunCalc::calcObliquityCorrection(double t) -{ - double e0 = calcMeanObliquityOfEcliptic(t); - double omega = 125.04 - 1934.136 * t; - double e = e0 + 0.00256 * cos(degToRad(omega)); - return e; // in degrees -} - -double SunCalc::calcGeomMeanLongSun(double t) -{ - double L0 = 280.46646 + t * (36000.76983 + t * (0.0003032)); - while (L0 > 360.0) - { - L0 -= 360.0; - } - while (L0 < 0.0) - { - L0 += 360.0; - } - return L0; // in degrees -} -double SunCalc::calcEccentricityEarthOrbit(double t) -{ - double e = 0.016708634 - t * (0.000042037 + 0.0000001267 * t); - return e; // unitless -} - -double SunCalc::calcGeomMeanAnomalySun(double t) -{ - double M = 357.52911 + t * (35999.05029 - 0.0001537 * t); - return M; // in degrees -} - -double SunCalc::radToDeg(double angleRad) -{ - return (180.0 * angleRad / PI); -} - -double SunCalc::degToRad(double angleDeg) -{ - return (PI * angleDeg / 180.0); -} -double SunCalc::calcSunApparentLong(double t) -{ - double o = calcSunTrueLong(t); - double omega = 125.04 - 1934.136 * t; - double lambda = o - 0.00569 - 0.00478 * sin(degToRad(omega)); - return lambda; // in degrees -} - -double SunCalc::calcMeanObliquityOfEcliptic(double t) -{ - double seconds = 21.448 - t * (46.8150 + t * (0.00059 - t * (0.001813))); - double e0 = 23.0 + (26.0 + (seconds / 60.0)) / 60.0; - return e0; // in degrees -} - -double SunCalc::calcSunTrueLong(double t) -{ - double l0 = calcGeomMeanLongSun(t); - double c = calcSunEqOfCenter(t); - double O = l0 + c; - return O; // in degrees -} - -double SunCalc::calcSunEqOfCenter(double t) -{ - double m = calcGeomMeanAnomalySun(t); - double mrad = degToRad(m); - double sinm = sin(mrad); - double sin2m = sin(mrad + mrad); - double sin3m = sin(mrad + mrad + mrad); - double C = sinm * (1.914602 - t * (0.004817 + 0.000014 * t)) + sin2m * (0.019993 - 0.000101 * t) + sin3m * 0.000289; - return C; // in degrees -} - -double SunCalc::calcDoyFromJD(double jd) -{ - double z = floor(jd + 0.5); - double f = (jd + 0.5) - z; - double A; - if (z < 2299161) - { - A = z; - } - else - { - double alpha = floor((z - 1867216.25) / 36524.25); - A = z + 1 + alpha - floor(alpha / 4.0); - } - double B = A + 1524.0; - int C = floor((B - 122.1) / 365.25); - double D = floor(365.25 * C); - double E = floor((B - D) / 30.6001); - double day = B - D - floor(30.6001 * E) + f; - double month = (E < 14) ? E - 1 : E - 13; - int year = (month > 2) ? C - 4716.0 : C - 4715.0; - - double k = (isLeapYear(year) ? 1.0 : 2.0); - double doy = floor((275 * month) / 9) - k * floor((month + 9) / 12) + day - 30; - return doy; -} - -bool SunCalc::isLeapYear(int yr) -{ - return ((yr % 4 == 0 && yr % 100 != 0) || yr % 400 == 0); -} - -double SunCalc::calcJDofNextPrevRiseSet(bool next, bool rise, float type, double time) -{ - double julianday = _julianDate; - double increment = ((next) ? 1.0 : -1.0); - while (isnan(time)) - { - julianday += increment; - time = calcSunriseSetUTC(rise, type, julianday, _latitude, _longitude); - } - return julianday; -} - +#include + +#include +#include +#include +#include + +#include "SunCalc.h" + +SunCalc::SunCalc(const Date &date, double latitude, double longitude) +{ + _date = date; + _latitude = latitude; + _longitude = longitude; + _julianDate = date.toJulianDate(); +} + +double SunCalc::timeAtAngle(float angle, bool rising) +{ + return calcSunriseSet(rising, angle, _julianDate, _date, _latitude, _longitude); +} + +// rise = true for sunrise, false for sunset +time_t SunCalc::calcSunriseSet(bool rise, float angle, double JD, Date date, double latitude, double longitude) +{ + double timeUTC = calcSunriseSetUTC(rise, angle, JD, latitude, longitude); + double newTimeUTC = calcSunriseSetUTC(rise, angle, JD + timeUTC / 1440.0, latitude, longitude); + + if (!isnan(newTimeUTC)) + { + return Date::ToTimeT(_date, newTimeUTC); + } + // no sunrise/set found + double doy = calcDoyFromJD(JD); + double jdy; + if (( (latitude > 66.4) && (doy > 79) && (doy < 267) ) || + ( (latitude < -66.4) && ((doy < 83) || (doy > 263)))) + { + //previous sunrise/next sunset + jdy = calcJDofNextPrevRiseSet(!rise, rise, angle, timeUTC); + } + else + { + //previous sunset/next sunrise + jdy = calcJDofNextPrevRiseSet(rise, rise, angle, timeUTC); + } + timeUTC = calcSunriseSetUTC(rise, angle, jdy, latitude, longitude); + newTimeUTC = calcSunriseSetUTC(rise, angle, jdy + timeUTC / 1440.0, latitude, longitude); + return Date::ToTimeT(Date(jdy), newTimeUTC); + //return JdToDate(jdy); +} + +double SunCalc::calcSunriseSetUTC(bool rise, float angle, double JD, double latitude, double longitude) +{ + double t = calcTimeJulianCent(JD); + double eqTime = calcEquationOfTime(t); + double solarDec = calcSunDeclination(t); + double hourAngle = calcHourAngle(angle, latitude, solarDec); + //alert("HA = " + radToDeg(hourAngle)); + if (!rise) + hourAngle = -hourAngle; + double delta = longitude + radToDeg(hourAngle); + double timeUTC = 720.0 - (4.0 * delta) - eqTime; // in minutes + return timeUTC; +} + +double SunCalc::calcTimeJulianCent(double jd) +{ + double d = (jd - 2451545.0); + double T = d / 36525.0; + return T; +} + +double SunCalc::calcEquationOfTime(double t) +{ + double epsilon = calcObliquityCorrection(t); + double l0 = calcGeomMeanLongSun(t); + double e = calcEccentricityEarthOrbit(t); + double m = calcGeomMeanAnomalySun(t); + double tmp1 = degToRad(epsilon); + double y = tan(tmp1 / 2.0); + y *= y; + + double t_l0 = degToRad(l0); + double t_m = degToRad(m); + + double sin2l0 = sin(2.0 * t_l0); + double cos2l0 = cos(2.0 * t_l0); + + double sinm = sin(t_m); + + double tmp3 = 4.0 * t_l0; + double sin4l0 = sin(tmp3); + double sin2m = sin(2.0 * t_m); + + double Etime = y * sin2l0 - 2.0 * e * sinm + 4.0 * e * y * sinm * cos2l0 - 0.5 * y * y * sin4l0 - 1.25 * e * e * sin2m; + return radToDeg(Etime) * 4.0; // in minutes of time +} + +double SunCalc::calcSunDeclination(double t) +{ + double e = calcObliquityCorrection(t); + double lambda = calcSunApparentLong(t); + + double sint = sin(degToRad(e)) * sin(degToRad(lambda)); + double theta = radToDeg(asin(sint)); + return theta; // in degrees +} + +double SunCalc::calcHourAngle(float angle, double lat, double solarDec) +{ + double latRad = degToRad(lat); + double sdRad = degToRad(solarDec); + double HAarg = (cos(degToRad(90.0 + angle)) / (cos(latRad) * cos(sdRad)) - tan(latRad) * tan(sdRad)); + double HA = acos(HAarg); + return HA; // in radians (for sunset, use -HA) +} + +double SunCalc::calcObliquityCorrection(double t) +{ + double e0 = calcMeanObliquityOfEcliptic(t); + double omega = 125.04 - 1934.136 * t; + double e = e0 + 0.00256 * cos(degToRad(omega)); + return e; // in degrees +} + +double SunCalc::calcGeomMeanLongSun(double t) +{ + double L0 = 280.46646 + t * (36000.76983 + t * (0.0003032)); + while (L0 > 360.0) + { + L0 -= 360.0; + } + while (L0 < 0.0) + { + L0 += 360.0; + } + return L0; // in degrees +} +double SunCalc::calcEccentricityEarthOrbit(double t) +{ + double e = 0.016708634 - t * (0.000042037 + 0.0000001267 * t); + return e; // unitless +} + +double SunCalc::calcGeomMeanAnomalySun(double t) +{ + double M = 357.52911 + t * (35999.05029 - 0.0001537 * t); + return M; // in degrees +} + +double SunCalc::radToDeg(double angleRad) +{ + return (180.0 * angleRad / PI); +} + +double SunCalc::degToRad(double angleDeg) +{ + return (PI * angleDeg / 180.0); +} +double SunCalc::calcSunApparentLong(double t) +{ + double o = calcSunTrueLong(t); + double omega = 125.04 - 1934.136 * t; + double lambda = o - 0.00569 - 0.00478 * sin(degToRad(omega)); + return lambda; // in degrees +} + +double SunCalc::calcMeanObliquityOfEcliptic(double t) +{ + double seconds = 21.448 - t * (46.8150 + t * (0.00059 - t * (0.001813))); + double e0 = 23.0 + (26.0 + (seconds / 60.0)) / 60.0; + return e0; // in degrees +} + +double SunCalc::calcSunTrueLong(double t) +{ + double l0 = calcGeomMeanLongSun(t); + double c = calcSunEqOfCenter(t); + double O = l0 + c; + return O; // in degrees +} + +double SunCalc::calcSunEqOfCenter(double t) +{ + double m = calcGeomMeanAnomalySun(t); + double mrad = degToRad(m); + double sinm = sin(mrad); + double sin2m = sin(mrad + mrad); + double sin3m = sin(mrad + mrad + mrad); + double C = sinm * (1.914602 - t * (0.004817 + 0.000014 * t)) + sin2m * (0.019993 - 0.000101 * t) + sin3m * 0.000289; + return C; // in degrees +} + +double SunCalc::calcDoyFromJD(double jd) +{ + double z = floor(jd + 0.5); + double f = (jd + 0.5) - z; + double A; + if (z < 2299161) + { + A = z; + } + else + { + double alpha = floor((z - 1867216.25) / 36524.25); + A = z + 1 + alpha - floor(alpha / 4.0); + } + double B = A + 1524.0; + int C = floor((B - 122.1) / 365.25); + double D = floor(365.25 * C); + double E = floor((B - D) / 30.6001); + double day = B - D - floor(30.6001 * E) + f; + double month = (E < 14) ? E - 1 : E - 13; + int year = (month > 2) ? C - 4716.0 : C - 4715.0; + + double k = (isLeapYear(year) ? 1.0 : 2.0); + double doy = floor((275 * month) / 9) - k * floor((month + 9) / 12) + day - 30; + return doy; +} + +bool SunCalc::isLeapYear(int yr) +{ + return ((yr % 4 == 0 && yr % 100 != 0) || yr % 400 == 0); +} + +double SunCalc::calcJDofNextPrevRiseSet(bool next, bool rise, float type, double time) +{ + double julianday = _julianDate; + double increment = ((next) ? 1.0 : -1.0); + while (isnan(time)) + { + julianday += increment; + time = calcSunriseSetUTC(rise, type, julianday, _latitude, _longitude); + } + return julianday; +} + diff --git a/SunCalc.h b/SunCalc.h index 28a086c..8db5b16 100644 --- a/SunCalc.h +++ b/SunCalc.h @@ -1,51 +1,51 @@ -#include "time.h" -#include "Date.h" - -class SunCalc -{ -public: - static const float sunrise = 0.833; - static const float sunriseEnd = 0.3; - static const float twilight = 6.0; - static const float nauticalTwilight = 12.0; - static const float night = 18.0; - static const float goldenHour = -6.0; - -private: - static const double PI=3.141592653589793; - - double _latitude; - double _longitude; - Date _date; - double _julianDate; - -public: - SunCalc(const Date& date, double latitude, double longitude); - inline void ChangeDate(const Date& date) { _date = date; } - time_t ToTimeT(const Date& d, double x); - - double timeAtAngle(float angle, bool rising); - -private: - // rise = true for sunrise, false for sunset - time_t calcSunriseSet(bool rise, float angle, double JD, Date date, double latitude, double longitude); - double calcSunriseSetUTC(bool rise, float angle, double JD, double latitude,double longitude); - double calcTimeJulianCent(double jd); - double calcEquationOfTime(double t); - double calcSunDeclination(double t); - double calcHourAngle(float angle, double lat, double solarDec); - double calcObliquityCorrection(double t); - double calcGeomMeanLongSun(double t); - double calcEccentricityEarthOrbit(double t); - double calcGeomMeanAnomalySun(double t); - double radToDeg(double angleRad); - double degToRad(double angleDeg); - double calcSunApparentLong(double t); - double calcMeanObliquityOfEcliptic(double t); - double calcSunTrueLong(double t); - double calcSunEqOfCenter(double t); - double calcDoyFromJD(double jd); - double calcJDofNextPrevRiseSet(bool next, bool rise, float type, double time); - bool isLeapYear(int yr); - time_t JdToDate(double jd); -}; +#include "time.h" +#include "Date.h" + +class SunCalc +{ +public: + static const float sunrise = 0.833; + static const float sunriseEnd = 0.3; + static const float twilight = 6.0; + static const float nauticalTwilight = 12.0; + static const float night = 18.0; + static const float goldenHour = -6.0; + +private: + static const double PI=3.141592653589793; + + double _latitude; + double _longitude; + Date _date; + double _julianDate; + +public: + SunCalc(const Date& date, double latitude, double longitude); + inline void ChangeDate(const Date& date) { _date = date; } + time_t ToTimeT(const Date& d, double x); + + double timeAtAngle(float angle, bool rising); + +private: + // rise = true for sunrise, false for sunset + time_t calcSunriseSet(bool rise, float angle, double JD, Date date, double latitude, double longitude); + double calcSunriseSetUTC(bool rise, float angle, double JD, double latitude,double longitude); + double calcTimeJulianCent(double jd); + double calcEquationOfTime(double t); + double calcSunDeclination(double t); + double calcHourAngle(float angle, double lat, double solarDec); + double calcObliquityCorrection(double t); + double calcGeomMeanLongSun(double t); + double calcEccentricityEarthOrbit(double t); + double calcGeomMeanAnomalySun(double t); + double radToDeg(double angleRad); + double degToRad(double angleDeg); + double calcSunApparentLong(double t); + double calcMeanObliquityOfEcliptic(double t); + double calcSunTrueLong(double t); + double calcSunEqOfCenter(double t); + double calcDoyFromJD(double jd); + double calcJDofNextPrevRiseSet(bool next, bool rise, float type, double time); + bool isLeapYear(int yr); + time_t JdToDate(double jd); +}; diff --git a/SunLight.cpp b/SunLight.cpp index 0d519cf..f94cc38 100644 --- a/SunLight.cpp +++ b/SunLight.cpp @@ -1,146 +1,146 @@ -#include -#include -#include -#include - -#include "SunLight.h" - -SunLight::SunLight(Date date, double latitude, double longitude) -{ - _date = date; - _latitude = latitude; - _longitude = longitude; - - _sun = new SunCalc(date, latitude, longitude); -} - -/// \brief When the upper edge of the Sun appears over the eastern horizon in the morning (0.833 degrees) -time_t SunLight::sunrise() -{ - return _sun->timeAtAngle(SunCalc::sunrise, true); -} - -/// \brief When the upper edge of the Sun disappears below the horizon -time_t SunLight::sunset() -{ - return _sun->timeAtAngle(SunCalc::sunrise, false); -} - -/// \brief -time_t SunLight::sunriseEnd() -{ - return _sun->timeAtAngle(SunCalc::sunriseEnd, true); -} - -/// \brief -time_t SunLight::sunsetStart() -{ - return _sun->timeAtAngle(SunCalc::sunriseEnd, false); -} - -/// \brief Aka civild Dawn. -time_t SunLight::dawn() -{ - return civilDawn(); -} - -/// \brief Aka civild dusk. -time_t SunLight::dusk() -{ - return civilDusk(); -} - -/// \brief When there is enough light for objects to be distinguishable. This occurs when the sun is 6 degrees below the horizon in the morning -time_t SunLight::civilDawn() -{ - return _sun->timeAtAngle(SunCalc::twilight, true); -} - -/// \brief When the sun is 6 degrees below the horizon in the evening. At this time objects are distinguishable and some stars and planets are -/// visible to the naked eye. -time_t SunLight::civilDusk() -{ - return _sun->timeAtAngle(SunCalc::twilight, false); -} - -/// \brief When there is enough sunlight for the horizon and some objects to be distinguishable. This occurs when the Sun is 12 degrees below -// the horizon in the morning -time_t SunLight::nauticalDawn() -{ - return _sun->timeAtAngle(SunCalc::nauticalTwilight, true); -} - -/// \brief When the sun is 12 degrees below the horizon in the evening. At this time, objects are no longer distinguishable, and the horizon is -/// no longer visible to the naked eye -time_t SunLight::nauticalDusk() -{ - return _sun->timeAtAngle(SunCalc::nauticalTwilight, false); -} - -/// \brief Astronomical dusk is the moment when the geometric center of the Sun is 18 degrees below the horizon in the evening. -time_t SunLight::astronomicalDusk() -{ - return _sun->timeAtAngle(SunCalc::night, false); -} - -/// \brief When the sky is no longer completely dark. This occurs when the Sun is 18 degrees below the horizon in the morning -time_t SunLight::astronomicalDawn() -{ - return _sun->timeAtAngle(SunCalc::night, true); -} - -/// \brief When the Sun is close to the horizon on a sunny day, its light appears warmer and softer. -time_t SunLight::goldenHourStart() -{ - return _sun->timeAtAngle(SunCalc::goldenHour, false); -} - -/// \brief When the Sun is close to the horizon on a sunny day, its light appears warmer and softer. -time_t SunLight::goldenHourEnd() -{ - return _sun->timeAtAngle(SunCalc::goldenHour, true); -} - -/* -int main(int argc, char *argv[]) -{ - tzset(); - Date d; - d.year = 2015; - d.month = 3; - d.day = 8; - SunLight s(d, 35.78L, -78.649999L); - time_t expt = 1425814530; - time_t x = s.sunrise(); - if( x != expt ) - { - std::cout << "Failed" << std::endl; - } - - struct tm *ptm2 = gmtime(&x); - char buf[1024]; - memset(buf, 0, sizeof(buf)); - strftime(buf, sizeof(buf), "%Y %m %d %H:%M:%SZ", ptm2); - std::cout << buf << std::endl; - - expt = 1425856548; - x = s.sunset(); - if( x != expt ) - { - std::cout << "Failed" << std::endl; - } - - // London - SunLight london(d, 51.508530L, -0.076132L); - expt = 1425796261; - x = london.sunrise(); - if( x != expt ) - { - std::cout << "Failed" << std::endl; - } - ptm2 = gmtime(&x); - memset(buf, 0, sizeof(buf)); - strftime(buf, sizeof(buf), "%Y %m %d %H:%M:%SZ", ptm2); - std::cout << buf << std::endl; - return 0; +#include +#include +#include +#include + +#include "SunLight.h" + +SunLight::SunLight(Date date, double latitude, double longitude) +{ + _date = date; + _latitude = latitude; + _longitude = longitude; + + _sun = new SunCalc(date, latitude, longitude); +} + +/// \brief When the upper edge of the Sun appears over the eastern horizon in the morning (0.833 degrees) +time_t SunLight::sunrise() +{ + return _sun->timeAtAngle(SunCalc::sunrise, true); +} + +/// \brief When the upper edge of the Sun disappears below the horizon +time_t SunLight::sunset() +{ + return _sun->timeAtAngle(SunCalc::sunrise, false); +} + +/// \brief +time_t SunLight::sunriseEnd() +{ + return _sun->timeAtAngle(SunCalc::sunriseEnd, true); +} + +/// \brief +time_t SunLight::sunsetStart() +{ + return _sun->timeAtAngle(SunCalc::sunriseEnd, false); +} + +/// \brief Aka civild Dawn. +time_t SunLight::dawn() +{ + return civilDawn(); +} + +/// \brief Aka civild dusk. +time_t SunLight::dusk() +{ + return civilDusk(); +} + +/// \brief When there is enough light for objects to be distinguishable. This occurs when the sun is 6 degrees below the horizon in the morning +time_t SunLight::civilDawn() +{ + return _sun->timeAtAngle(SunCalc::twilight, true); +} + +/// \brief When the sun is 6 degrees below the horizon in the evening. At this time objects are distinguishable and some stars and planets are +/// visible to the naked eye. +time_t SunLight::civilDusk() +{ + return _sun->timeAtAngle(SunCalc::twilight, false); +} + +/// \brief When there is enough sunlight for the horizon and some objects to be distinguishable. This occurs when the Sun is 12 degrees below +// the horizon in the morning +time_t SunLight::nauticalDawn() +{ + return _sun->timeAtAngle(SunCalc::nauticalTwilight, true); +} + +/// \brief When the sun is 12 degrees below the horizon in the evening. At this time, objects are no longer distinguishable, and the horizon is +/// no longer visible to the naked eye +time_t SunLight::nauticalDusk() +{ + return _sun->timeAtAngle(SunCalc::nauticalTwilight, false); +} + +/// \brief Astronomical dusk is the moment when the geometric center of the Sun is 18 degrees below the horizon in the evening. +time_t SunLight::astronomicalDusk() +{ + return _sun->timeAtAngle(SunCalc::night, false); +} + +/// \brief When the sky is no longer completely dark. This occurs when the Sun is 18 degrees below the horizon in the morning +time_t SunLight::astronomicalDawn() +{ + return _sun->timeAtAngle(SunCalc::night, true); +} + +/// \brief When the Sun is close to the horizon on a sunny day, its light appears warmer and softer. +time_t SunLight::goldenHourStart() +{ + return _sun->timeAtAngle(SunCalc::goldenHour, false); +} + +/// \brief When the Sun is close to the horizon on a sunny day, its light appears warmer and softer. +time_t SunLight::goldenHourEnd() +{ + return _sun->timeAtAngle(SunCalc::goldenHour, true); +} + +/* +int main(int argc, char *argv[]) +{ + tzset(); + Date d; + d.year = 2015; + d.month = 3; + d.day = 8; + SunLight s(d, 35.78L, -78.649999L); + time_t expt = 1425814530; + time_t x = s.sunrise(); + if( x != expt ) + { + std::cout << "Failed" << std::endl; + } + + struct tm *ptm2 = gmtime(&x); + char buf[1024]; + memset(buf, 0, sizeof(buf)); + strftime(buf, sizeof(buf), "%Y %m %d %H:%M:%SZ", ptm2); + std::cout << buf << std::endl; + + expt = 1425856548; + x = s.sunset(); + if( x != expt ) + { + std::cout << "Failed" << std::endl; + } + + // London + SunLight london(d, 51.508530L, -0.076132L); + expt = 1425796261; + x = london.sunrise(); + if( x != expt ) + { + std::cout << "Failed" << std::endl; + } + ptm2 = gmtime(&x); + memset(buf, 0, sizeof(buf)); + strftime(buf, sizeof(buf), "%Y %m %d %H:%M:%SZ", ptm2); + std::cout << buf << std::endl; + return 0; }*/ \ No newline at end of file diff --git a/SunLight.h b/SunLight.h index 409ed94..b6890a1 100644 --- a/SunLight.h +++ b/SunLight.h @@ -1,79 +1,79 @@ -#ifndef __SUN_LIGHT_H__ -#define __SUN_LIGHT_H__ - -#include -#include "Date.h" -#include "SunCalc.h" - -/* - This class gives you varios sunrise and sunset values depening on your date and longiture and latitude. - It bases its implementation on the NOAA Solar Calculator. - - Credits: - This is strongly influenced by the javascript library solar-calc - https://github.com/jonhester/solar-calc - - Reference: - https://www.esrl.noaa.gov/gmd/grad/solcalc/index.html -*/ - -class SunLight -{ - private: - SunCalc *_sun; - double _latitude; - double _longitude; - Date _date; - - public: - SunLight(Date date, double latitude, double longitude); - - inline void Changer(Date date) { _date = date; } - - /// \brief When the upper edge of the Sun appears over the eastern horizon in the morning (0.833 degrees) - time_t sunrise(); - - /// \brief When the upper edge of the Sun disappears below the horizon - time_t sunset(); - - /// \brief - time_t sunriseEnd(); - - /// \brief - time_t sunsetStart(); - - /// \brief Aka civil Dawn. - time_t dawn(); - - /// \brief Aka civil Dusk. - time_t dusk(); - - /// \brief When there is enough light for objects to be distinguishable. This occurs when the sun is 6 degrees below the horizon in the morning - time_t civilDawn(); - - /// \brief When the sun is 6 degrees below the horizon in the evening. At this time objects are distinguishable and some stars and planets are - /// visible to the naked eye. - time_t civilDusk(); - - /// \brief When there is enough sunlight for the horizon and some objects to be distinguishable. This occurs when the Sun is 12 degrees below - // the horizon in the morning - time_t nauticalDawn(); - - /// \brief When the sun is 12 degrees below the horizon in the evening. At this time, objects are no longer distinguishable, and the horizon is - /// no longer visible to the naked eye - time_t nauticalDusk(); - - /// \brief Astronomical dusk is the moment when the geometric center of the Sun is 18 degrees below the horizon in the evening. - time_t astronomicalDusk(); - - /// \brief When the sky is no longer completely dark. This occurs when the Sun is 18 degrees below the horizon in the morning - time_t astronomicalDawn(); - - /// \brief When the Sun is close to the horizon on a sunny day, its light appears warmer and softer. - time_t goldenHourStart(); - - /// \brief When the Sun is close to the horizon on a sunny day, its light appears warmer and softer. - time_t goldenHourEnd(); -}; - +#ifndef __SUN_LIGHT_H__ +#define __SUN_LIGHT_H__ + +#include +#include "Date.h" +#include "SunCalc.h" + +/* + This class gives you varios sunrise and sunset values depening on your date and longiture and latitude. + It bases its implementation on the NOAA Solar Calculator. + + Credits: + This is strongly influenced by the javascript library solar-calc + https://github.com/jonhester/solar-calc + + Reference: + https://www.esrl.noaa.gov/gmd/grad/solcalc/index.html +*/ + +class SunLight +{ + private: + SunCalc *_sun; + double _latitude; + double _longitude; + Date _date; + + public: + SunLight(Date date, double latitude, double longitude); + + inline void Changer(Date date) { _date = date; } + + /// \brief When the upper edge of the Sun appears over the eastern horizon in the morning (0.833 degrees) + time_t sunrise(); + + /// \brief When the upper edge of the Sun disappears below the horizon + time_t sunset(); + + /// \brief + time_t sunriseEnd(); + + /// \brief + time_t sunsetStart(); + + /// \brief Aka civil Dawn. + time_t dawn(); + + /// \brief Aka civil Dusk. + time_t dusk(); + + /// \brief When there is enough light for objects to be distinguishable. This occurs when the sun is 6 degrees below the horizon in the morning + time_t civilDawn(); + + /// \brief When the sun is 6 degrees below the horizon in the evening. At this time objects are distinguishable and some stars and planets are + /// visible to the naked eye. + time_t civilDusk(); + + /// \brief When there is enough sunlight for the horizon and some objects to be distinguishable. This occurs when the Sun is 12 degrees below + // the horizon in the morning + time_t nauticalDawn(); + + /// \brief When the sun is 12 degrees below the horizon in the evening. At this time, objects are no longer distinguishable, and the horizon is + /// no longer visible to the naked eye + time_t nauticalDusk(); + + /// \brief Astronomical dusk is the moment when the geometric center of the Sun is 18 degrees below the horizon in the evening. + time_t astronomicalDusk(); + + /// \brief When the sky is no longer completely dark. This occurs when the Sun is 18 degrees below the horizon in the morning + time_t astronomicalDawn(); + + /// \brief When the Sun is close to the horizon on a sunny day, its light appears warmer and softer. + time_t goldenHourStart(); + + /// \brief When the Sun is close to the horizon on a sunny day, its light appears warmer and softer. + time_t goldenHourEnd(); +}; + #endif // __SUN_LIGHT_H__ \ No newline at end of file diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index a8112ef..69743ed 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -1,12 +1,11 @@ -# Locate GTest -find_package(GTest REQUIRED) -include_directories(${GTEST_INCLUDE_DIRS} ../ ./) - -file(GLOB SOURCE "*.cpp" "../*.cpp") -#LIST(REMOVE_ITEM SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/../metad.cpp) - -add_executable(SunLight_tests ${SOURCE} ) - -target_link_libraries(SunLight_tests SunLight ${GTEST_LIBRARIES} pthread) - +# Locate GTest +find_package(GTest REQUIRED) +include_directories(${GTEST_INCLUDE_DIRS} ../ ./) + +file(GLOB SOURCE "*.cpp" "../*.cpp") + +add_executable(SunLight_tests ${SOURCE} ) + +target_link_libraries(SunLight_tests SunLight ${GTEST_LIBRARIES} pthread) + add_test (NAME SunLight COMMAND SunLight_tests) \ No newline at end of file