Sonnenstand aus Kommandozeilenprogramm?

2 Antworten

Vom Fragesteller als hilfreich ausgezeichnet

Zwei schnell ergooglete Fundstücke - keine Ahnung wie gut die sind, aber die tun auf den ersten Blick genau das, was du suchst:

https://github.com/s-bear/sun-position

https://github.com/klausbrunner/solarpos

Das hier kann anscheinend nur Sonnenaufgang/Untergang, ist wohl nicht die Anforderung: https://github.com/risacher/sunwait


juni2000 
Fragesteller
 04.09.2023, 15:19

Sieht echt gut aus, guck ich mir genauer an, danke!!

0

Also Online finden sich auf jeden Fall Excel-Sheets zur Berechnung. Da waren auch sehr exakte dabei.

Schau mal hier:

https://astronomy.stackexchange.com/questions/24598/how-to-calculate-the-maximum-and-minimum-solar-azimuth-at-a-given-location

Als C++-Version (aber ich glaube irgendwo mit Fehler):

void sun::update(std::time_t time, double longitude, double latitude){
    //See also https://astronomy.stackexchange.com/questions/24598/how-to-calculate-the-maximum-and-minimum-solar-azimuth-at-a-given-location

    const double time_hours = double(time) / 3600.0;
    const double time_days = time_hours / 24.0;
    const double hours_past_local_midnight = time_hours - (std::floor(time_days) * 24.0);

    const double julian_day = time_days+2440587.5;
    const double julian_century = (julian_day - 2451545.0)/36525.0;

    const double geom_mean_anom_sun = (357.52911 + julian_century * (35999.05029 - 0.0001537 * julian_century)) * (2.0 * M_PI/360.0);
    const double earth_eccent_orbit = 0.016708634 - julian_century * (0.000042037 + 0.0000001267 * julian_century);
    const double mean_obliq_eliptic = (23.0 + (26.0 + ((21.448 - julian_century * (46.815 + julian_century * (0.00059 - julian_century * 0.001813)))) / 60.0) / 60.0) * (2.0 * M_PI/360.0);
    const double geom_mean_long_sun = std::fmod((280.46646 + julian_century * (36000.76983 + julian_century * 0.0003032)), 360.0) * (2.0 * M_PI/360.0);

    const double sun_equ_of_ctr = (std::sin(geom_mean_anom_sun) * (1.914602 - julian_century * (0.004817 + 0.000014 * julian_century)) + std::sin(2.0 * geom_mean_anom_sun) * (0.019993 - 0.000101 * julian_century) + std::sin(3.0 * geom_mean_anom_sun) * 0.000289) * (2.0 * M_PI/360.0);
    const double obliq_corr = mean_obliq_eliptic + 0.00000355556 * M_PI * std::cos((0.1736667 - 2.686583333 * julian_century) * M_PI);

    const double sun_true_long = geom_mean_long_sun + sun_equ_of_ctr;
    const double vary = std::tan(obliq_corr / 2.0) * std::tan(obliq_corr / 2.0);

    const double app_long = sun_true_long - 0.000007902777778 * M_PI - 0.000006638888889 * M_PI * std::sin((0.1736667 - 2.686583333 * julian_century) * M_PI);
    const double equation_of_time = 60.0 * 4.0 * (vary * std::sin(2.0 * geom_mean_long_sun) - 2.0 * earth_eccent_orbit * std::sin(geom_mean_anom_sun) + 4.0 * earth_eccent_orbit * vary * std::sin(geom_mean_anom_sun) * std::cos(2.0 * geom_mean_long_sun) - 0.5 * vary * vary * std::sin(4.0 * geom_mean_long_sun) - 1.25 * earth_eccent_orbit * earth_eccent_orbit * std::sin(2.0 * geom_mean_anom_sun));

    const double true_solar_time = std::fmod((hours_past_local_midnight/24.0) * 1440.0 + equation_of_time + 4.0 * (longitude * (360.0/(2 * M_PI))), 1440.0);

    const double hour_angle = (true_solar_time / 4.0 < 0.0 ? true_solar_time / 4.0 + 180.0 : true_solar_time / 4.0 - 180.0) * ((2 * M_PI)/360.0);

    const double declination = std::asin(std::sin(obliq_corr) * std::sin(app_long));

    const double zenith_angle = std::acos(std::sin(latitude) * std::sin(declination) + std::cos(latitude) * std::cos(declination) * std::cos(hour_angle));

    const double azimuth_angle = (hour_angle > 0.0 ? std::fmod(std::acos((std::sin(latitude) * std::cos(zenith_angle) - std::sin(declination)) / (std::cos(latitude) * std::sin(zenith_angle))) + M_PI, 2 * M_PI) : std::fmod((3 * M_PI) - std::acos((std::sin(latitude) * std::cos(zenith_angle) - std::sin(declination)) / (std::cos(latitude) * std::sin(zenith_angle))), 2 * M_PI));

    dir = glm::normalize(glm::rotateX(glm::rotateY(glm::vec3(0.0, 0.0, -1.0), float(azimuth_angle)), float(-declination)));
    this->zenith_angle = float(zenith_angle);
}

//Mostly from https://graphics.stanford.edu/~henrik/papers/nightsky/nightsky.pdf
void moon::update(std::time_t time, double longitude, double latitude){

    const double time_hours = double(time) / 3600.0;
    const double time_days = time_hours / 24.0;
    const double hours_past_local_midnight = time_hours - (std::floor(time_days) * 24.0);

    const double julian_day = time_days+2440587.5;
    const double julian_century = (julian_day - 2451545.0)/36525.0;

    const double l_tmp = 3.8104 + 8399.7091 * julian_century;
    const double m_tmp = 2.3554 + 8328.6911 * julian_century;
    const double m = 6.2300 + 628.3019 * julian_century;
    const double d = 5.1985 + 7771.3772 * julian_century;
    const double f = 1.6280 + 8433.4663 * julian_century;

    const double eliptic_longitude = l_tmp + 0.1098 * std::sin(m_tmp) + 0.0222 * std::sin(2 * d - m_tmp) + 0.0115 * std::sin(2 * d) + 0.0037 * std::sin(2 * m_tmp) - 0.0032 * std::sin(m) - 0.0020 * std::sin(2 * f) + 0.0010 * std::sin(2 * d - 2 * m_tmp) + 0.0010 * std::sin(2 * d - m - m_tmp) + 0.0009 * std::sin(2 * d + m_tmp) + 0.0008 * std::sin(2 * d - m) + 0.0007 * std::sin(m_tmp - m) - 0.0006 * std::sin(d) - 0.0005 * std::sin(m + m_tmp);
    const double eliptic_latitude = 0.0895 * std::sin(f) + 0.0049 * std::sin(m_tmp + f) + 0.0048 * std::sin(m_tmp - f) + 0.0030 * std::sin(2 * d - f) + 0.0010 * std::sin(2 * d + f - m_tmp) + 0.0008 * std::sin(2 * d - f - m_tmp) + 0.0006 * std::sin(2 * d+ f);
    const double distance = 1.0 / (0.016593 + 0.000904 * std::cos(m_tmp) + 0.000166 * std::cos(2 * d - m_tmp) + 0.000137 * std::cos(2 * d) + 0.000049 * std::cos(2 * m_tmp) + 0.000015 * std::cos(2 * d + m_tmp) + 0.000009 * std::cos(2 * d - m));

    const double mean_obliq_eliptic = (23.0 + (26.0 + ((21.448 - julian_century * (46.815 + julian_century * (0.00059 - julian_century * 0.001813)))) / 60.0) / 60.0) * (2.0 * M_PI/360.0);
    const double obliq_corr = mean_obliq_eliptic + 0.00000355556 * M_PI * std::cos((0.1736667 - 2.686583333 * julian_century) * M_PI);
    const double local_mean_sidereal_time = 4.894961 + 230121.675315 * julian_century + (longitude * (360.0/(2 * M_PI)));

    const double hour_angle = local_mean_sidereal_time - std::atan((std::sin(eliptic_longitude) * std::cos(obliq_corr) + std::tan(eliptic_latitude) * std::sin(obliq_corr)) / std::cos(eliptic_longitude));

    const double declination = std::asin(std::sin(eliptic_latitude) * std::cos(obliq_corr) + std::cos(eliptic_latitude) * std::sin(obliq_corr) * std::sin(eliptic_longitude));

    const double zenith_angle = std::acos(std::sin(latitude) * std::sin(declination) + std::cos(latitude) * std::cos(declination) * std::cos(hour_angle));

    const double azimuth_angle = -std::atan2(std::cos(declination) * std::sin(hour_angle), -std::sin(latitude) * std::cos(declination) * std::cos(hour_angle) + std::cos(latitude) * std::sin(declination));

    dir = glm::normalize(glm::rotateX(glm::rotateY(glm::vec3(0.0, 0.0, -1.0), float(azimuth_angle)), float(-declination)));
    this->distance = float(distance);
}

juni2000 
Fragesteller
 04.09.2023, 14:54

Danke erstmal, aber ein Excel-Sheet möchte ich vermeiden und dieser C++ code...ich kann nicht wirklich C++ aber glaube da wird nur Azimuth gerechnet, also fehlt schon mal die Höhe?

0
juni2000 
Fragesteller
 04.09.2023, 15:00
@juni2000

Am liebsten hätte ich wirklich ein Programm das ich aufrufe wie "sonnenstand.exe länge breite zeit" und das gibt mir einfach die zwei Werte als Text raus. So ist es nämlich derzeit gemacht. Und es soll möglichst weniger als 0.1 Grad abweichen und nicht wieder in ein paar Jahren ungenau werden...

0
Destranix  04.09.2023, 15:01
@juni2000

Naja, Höhe gibt es nicht, nur Winkel. Höhe der Sonne wäre auch etwas komisch, ist ja ein paar Lichtminuten hoch.

Und wenn du das als Skript möchtest kannst du es dir umschreiben. Evtl. aber auch prüfen, dass kein Fehler drinnen ist.

Ansonsten: Das C++ hier ist tatsächlich sehr trivial, evtl. bekommst du es sogar hin das verwendbar zu machen.

So musst du nur noch das Parsing machen und dann compilieren (und evtl. Fegler finden falls vorhanden):

#include <iostream>

void print_sun_position(std::time_t time, double longitude, double latitude){
    //See also https://astronomy.stackexchange.com/questions/24598/how-to-calculate-the-maximum-and-minimum-solar-azimuth-at-a-given-location

    const double time_hours = double(time) / 3600.0;
    const double time_days = time_hours / 24.0;
    const double hours_past_local_midnight = time_hours - (std::floor(time_days) * 24.0);

    const double julian_day = time_days+2440587.5;
    const double julian_century = (julian_day - 2451545.0)/36525.0;

    const double geom_mean_anom_sun = (357.52911 + julian_century * (35999.05029 - 0.0001537 * julian_century)) * (2.0 * M_PI/360.0);
    const double earth_eccent_orbit = 0.016708634 - julian_century * (0.000042037 + 0.0000001267 * julian_century);
    const double mean_obliq_eliptic = (23.0 + (26.0 + ((21.448 - julian_century * (46.815 + julian_century * (0.00059 - julian_century * 0.001813)))) / 60.0) / 60.0) * (2.0 * M_PI/360.0);
    const double geom_mean_long_sun = std::fmod((280.46646 + julian_century * (36000.76983 + julian_century * 0.0003032)), 360.0) * (2.0 * M_PI/360.0);

    const double sun_equ_of_ctr = (std::sin(geom_mean_anom_sun) * (1.914602 - julian_century * (0.004817 + 0.000014 * julian_century)) + std::sin(2.0 * geom_mean_anom_sun) * (0.019993 - 0.000101 * julian_century) + std::sin(3.0 * geom_mean_anom_sun) * 0.000289) * (2.0 * M_PI/360.0);
    const double obliq_corr = mean_obliq_eliptic + 0.00000355556 * M_PI * std::cos((0.1736667 - 2.686583333 * julian_century) * M_PI);

    const double sun_true_long = geom_mean_long_sun + sun_equ_of_ctr;
    const double vary = std::tan(obliq_corr / 2.0) * std::tan(obliq_corr / 2.0);

    const double app_long = sun_true_long - 0.000007902777778 * M_PI - 0.000006638888889 * M_PI * std::sin((0.1736667 - 2.686583333 * julian_century) * M_PI);
    const double equation_of_time = 60.0 * 4.0 * (vary * std::sin(2.0 * geom_mean_long_sun) - 2.0 * earth_eccent_orbit * std::sin(geom_mean_anom_sun) + 4.0 * earth_eccent_orbit * vary * std::sin(geom_mean_anom_sun) * std::cos(2.0 * geom_mean_long_sun) - 0.5 * vary * vary * std::sin(4.0 * geom_mean_long_sun) - 1.25 * earth_eccent_orbit * earth_eccent_orbit * std::sin(2.0 * geom_mean_anom_sun));

    const double true_solar_time = std::fmod((hours_past_local_midnight/24.0) * 1440.0 + equation_of_time + 4.0 * (longitude * (360.0/(2 * M_PI))), 1440.0);

    const double hour_angle = (true_solar_time / 4.0 < 0.0 ? true_solar_time / 4.0 + 180.0 : true_solar_time / 4.0 - 180.0) * ((2 * M_PI)/360.0);

    const double declination = std::asin(std::sin(obliq_corr) * std::sin(app_long));

    const double zenith_angle = std::acos(std::sin(latitude) * std::sin(declination) + std::cos(latitude) * std::cos(declination) * std::cos(hour_angle));

    const double azimuth_angle = (hour_angle > 0.0 ? std::fmod(std::acos((std::sin(latitude) * std::cos(zenith_angle) - std::sin(declination)) / (std::cos(latitude) * std::sin(zenith_angle))) + M_PI, 2 * M_PI) : std::fmod((3 * M_PI) - std::acos((std::sin(latitude) * std::cos(zenith_angle) - std::sin(declination)) / (std::cos(latitude) * std::sin(zenith_angle))), 2 * M_PI));

    std:.cout << "Azimuth: " << azimuth_angle << " Declination: " << declination << " Zenith: " << zenith_angle << std::endl;
}
int main(int argc, char argv[]){
    //TODO: Parse arguments
    print_sun_position(time, longitude, latitude);
    return 0;
}
1
Destranix  04.09.2023, 15:04
@Destranix

Kleine Korrektur:

int main(int argc, char* argv
[]){
    //TODO: Parse arguments
    print_sun_position(time, longitude, latitude);
    return 0;
}
0