diff options
author | 2024-03-08 22:53:11 +0800 | |
---|---|---|
committer | 2024-03-09 09:39:48 +0800 | |
commit | b1be91bc7562571bcb156d20ec3f9c8b69340722 (patch) | |
tree | ab72588350a890d06e33a79b730ddd0223bbb828 | |
parent | 6fd843db21af18be0634bac770c6b74ad4e78bb7 (diff) | |
download | calendar-dev.tar.gz calendar-dev.zip |
Calculate sunrise and sunset, showing time and azimuthdev
Add sun trace table, and put all data into file
-rw-r--r-- | src/CMakeLists.txt | 6 | ||||
-rw-r--r-- | src/Julian.cpp | 3 | ||||
-rw-r--r-- | src/calendar.cpp | 120 | ||||
-rw-r--r-- | src/calendar.h | 42 | ||||
-rw-r--r-- | src/parameters.cpp | 56 |
5 files changed, 107 insertions, 120 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 53ddadc..14401b8 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt | |||
@@ -5,10 +5,6 @@ add_definitions(-w) | |||
5 | message("Project root: ${PROJECT_SOURCE_DIR}") | 5 | message("Project root: ${PROJECT_SOURCE_DIR}") |
6 | 6 | ||
7 | set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin) | 7 | set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin) |
8 | set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib) | ||
9 | 8 | ||
10 | # 将Julian.cpp与parameters.cpp编译为一个动态库 | ||
11 | add_library(parameters SHARED Julian.cpp parameters.cpp) | ||
12 | # 将calendar.cpp与List.cpp编译为可执行文件,链接动态库 | 9 | # 将calendar.cpp与List.cpp编译为可执行文件,链接动态库 |
13 | add_executable(calendar calendar.cpp) | 10 | add_executable(calendar calendar.cpp Julian.cpp parameters.cpp) \ No newline at end of file |
14 | target_link_libraries(calendar PRIVATE parameters) | ||
diff --git a/src/Julian.cpp b/src/Julian.cpp index 5a0522b..ecfe391 100644 --- a/src/Julian.cpp +++ b/src/Julian.cpp | |||
@@ -86,6 +86,5 @@ double Julian::getJulianKiloYear(time_t time) { | |||
86 | //儒略千年数转时间戳 | 86 | //儒略千年数转时间戳 |
87 | time_t Julian::kiloYearToTime(double t, int year) { | 87 | time_t Julian::kiloYearToTime(double t, int year) { |
88 | double jd = t * 365250.0 + 2451545.0; | 88 | double jd = t * 365250.0 + 2451545.0; |
89 | time_t time = (time_t)((jd - 2440587.5) * 86400.0 - delta_t(year)); | 89 | return (time_t)((jd - 2440587.5) * 86400.0 - delta_t(year)); |
90 | return time; | ||
91 | } | 90 | } |
diff --git a/src/calendar.cpp b/src/calendar.cpp index 6731692..7e04857 100644 --- a/src/calendar.cpp +++ b/src/calendar.cpp | |||
@@ -1,64 +1,124 @@ | |||
1 | // Encoding: UTF-8 | 1 | // Encoding: UTF-8 |
2 | #include "calendar.h" | 2 | #include "calendar.h" |
3 | #include <cstdio> | 3 | #include <cstdio> |
4 | #include <cstdlib> | ||
4 | #include <ctime> | 5 | #include <ctime> |
5 | #include <iomanip> | 6 | #include <iomanip> |
6 | 7 | ||
7 | /*以下为"calendar.h规定之量*/ | 8 | // 常量 |
8 | double day = 86400; | 9 | #define day_secs 86400 |
9 | double delta = 1e-11; | 10 | #define delta_time 1e-11 |
11 | |||
12 | /* calendar.h规定之量 */ | ||
10 | Julian julian; | 13 | Julian julian; |
11 | parameter p; | 14 | parameter p; |
15 | double epsilon; | ||
12 | 16 | ||
13 | pair<double, double> getSunPos(time_t time) { | 17 | FILE *fp; |
14 | double t = julian.getJulianKiloYear(time); | ||
15 | 18 | ||
19 | pair<double, double> getSunPos(double t, double flag = false) { | ||
16 | pair<double, double> sun = p.sun_longitude(t); | 20 | pair<double, double> sun = p.sun_longitude(t); |
17 | radToDMS("Sun longitude:\t\t", 0, 360, sun.first); | ||
18 | radToDMS("Sun latitude:\t\t", -90, 90, sun.second); | ||
19 | 21 | ||
20 | double alpha, delta; // 太阳赤经赤纬 | 22 | double alpha, delta; // 太阳赤经赤纬 |
21 | double lambda = sun.first, beta = sun.second; // 太阳黄经黄纬 | 23 | double lambda = sun.first, beta = sun.second; // 太阳黄经黄纬 |
22 | // 黄赤交角epsilon | 24 | // 黄赤交角epsilon |
23 | double epsilon = p.get_epsilon(t); | 25 | epsilon = p.get_epsilon(t); |
24 | radToDMS("Ecliptic Obliquity:\t\t", 0, 90, epsilon); | ||
25 | 26 | ||
26 | delta = | 27 | delta = |
27 | asin(sin(epsilon) * sin(lambda) * cos(beta) + cos(epsilon) * sin(beta)); | 28 | asin(sin(epsilon) * sin(lambda) * cos(beta) + cos(epsilon) * sin(beta)); |
28 | alpha = atan2( | 29 | alpha = atan2( |
29 | (cos(epsilon) * sin(lambda) * cos(beta) - sin(epsilon) * sin(beta)), | 30 | (cos(epsilon) * sin(lambda) * cos(beta) - sin(epsilon) * sin(beta)), |
30 | (cos(lambda) * cos(beta))); | 31 | (cos(lambda) * cos(beta))); |
31 | radToDMS("Sun right ascension:\t\t", 0, 360, alpha); | ||
32 | radToDMS("Sun declination:\t\t", -90, 90, delta); | ||
33 | // 时角 | 32 | // 时角 |
34 | double H = p.getHourAngle(t, LONGITUDE, LATITUDE, alpha); | 33 | double H = p.getHourAngle(t, LONGITUDE, LATITUDE, alpha); |
35 | double A, h; //方位角和高度角 | 34 | double A, h; //方位角和高度角 |
36 | h = asin(sin(LATITUDE) * sin(delta) + cos(LATITUDE) * cos(delta) * cos(H)); | 35 | h = asin(sin(LATITUDE) * sin(delta) + cos(LATITUDE) * cos(delta) * cos(H)); |
37 | A = atan2(-cos(delta) * sin(H), | 36 | A = atan2(-cos(delta) * sin(H), |
38 | cos(LATITUDE) * sin(delta) - sin(LATITUDE) * cos(delta) * cos(H)); | 37 | cos(LATITUDE) * sin(delta) - sin(LATITUDE) * cos(delta) * cos(H)); |
39 | A += M_PI; | 38 | if (flag) { |
40 | // 转换为角度制输出 | 39 | fprintf( |
41 | radToDMS("Hour angle:\t\t", 0, 360, H); | 40 | fp, "%s\t%s\t%s\t%s\t%s\t%s\n", radToDMS(0, 360, lambda).c_str(), |
42 | radToDMS("Azimuth:\t\t", 0, 360, A); | 41 | radToDMS(-90, 90, beta).c_str(), radToDMS(0, 360, alpha).c_str(), |
43 | radToDMS("Elevation:\t\t", -90, 90, h); | 42 | radToDMS(-90, 90, delta).c_str(), radToDMS(0, 360, A).c_str(), |
43 | radToDMS(-90, 90, h).c_str()); | ||
44 | } | ||
45 | return make_pair(A, h + M_PI / 216); | ||
44 | } | 46 | } |
45 | 47 | ||
46 | int main(int argc, char *argv[]) { | 48 | void binarySearch(string message, time_t begin, Date date) { |
47 | Date date; | 49 | double t = julian.getJulianKiloYear(begin); |
48 | if (argc != 2) { | 50 | double t_end = julian.getJulianKiloYear(begin + day_secs / 2); |
49 | printf("Input the time you want to calculate in <YYYY-MM-DD,HH:MM:SS> " | 51 | double middle; |
50 | "format:\t\t"); | 52 | time_t res; |
51 | scanf("%d-%d-%d,%d:%d:%d", &date.tm_year, &date.tm_mon, &date.tm_mday, | 53 | pair<double, double> sunPos; |
52 | &date.tm_hour, &date.tm_min, &date.tm_sec); | 54 | while (t_end - t >= delta_time) { |
53 | } else { | 55 | middle = (t + t_end) / 2; |
54 | sscanf(argv[1], "%d-%d-%d,%d:%d:%d", &date.tm_year, &date.tm_mon, | 56 | sunPos = getSunPos(middle, false); |
55 | &date.tm_mday, &date.tm_hour, &date.tm_min, &date.tm_sec); | 57 | if (sunPos.second * getSunPos(t).second > 0) { |
58 | t = middle; | ||
59 | } else { | ||
60 | t_end = middle; | ||
61 | } | ||
62 | } | ||
63 | res = julian.kiloYearToTime(middle, date.tm_year + 1900); | ||
64 | Date *tm = localtime(&res); | ||
65 | printf("%s\t%4d-%02d-%02d %02d:%02d:%02d\tAzimuth\t%s\n", message.c_str(), | ||
66 | tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, | ||
67 | tm->tm_min, tm->tm_sec, radToDMS(0, 360, sunPos.first).c_str()); | ||
68 | fprintf(fp, "%s\t%4d-%02d-%02d %02d:%02d:%02d\tAzimuth\t%s\n", | ||
69 | message.c_str(), tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, | ||
70 | tm->tm_hour, tm->tm_min, tm->tm_sec, | ||
71 | radToDMS(0, 360, sunPos.first).c_str()); | ||
72 | } | ||
73 | |||
74 | void getSunTime(Date date) { | ||
75 | time_t time = mktime(&date); | ||
76 | binarySearch("Sunrize", time, date); | ||
77 | binarySearch("Sunset", time + day_secs / 2, date); | ||
78 | } | ||
79 | |||
80 | void showSunPos(Date date) { | ||
81 | time_t time = mktime(&date); | ||
82 | double t; | ||
83 | fprintf(fp, "\n\nSun Trace Table\n\n"); | ||
84 | fprintf(fp, "--------------------------------------------------------------" | ||
85 | "--------------------------------------------------------------" | ||
86 | "----------\n"); | ||
87 | fprintf(fp, "Time |\tlongitude\t\tlatitude\t\tright " | ||
88 | "ascension\tdeclination\tAzimuth\t\tAltitude\n"); | ||
89 | fprintf(fp, "--------------------------------------------------------------" | ||
90 | "--------------------------------------------------------------" | ||
91 | "----------\n"); | ||
92 | for (int i = 0; i < 24; i++, time += 3600, date.tm_hour++) { | ||
93 | t = julian.getJulianKiloYear(time); | ||
94 | fprintf(fp, "%02d:%02d:%02d |\t", date.tm_hour, date.tm_min, | ||
95 | date.tm_sec); | ||
96 | getSunPos(t, true); | ||
56 | } | 97 | } |
98 | fprintf(fp, "--------------------------------------------------------------" | ||
99 | "--------------------------------------------------------------" | ||
100 | "----------\n"); | ||
101 | } | ||
102 | |||
103 | int main() { | ||
104 | Date date; | ||
105 | cout << "Input a day you want(in YYYY-MM-DD): "; | ||
106 | scanf("%d-%d-%d", &date.tm_year, &date.tm_mon, &date.tm_mday); | ||
57 | date.tm_year -= 1900; | 107 | date.tm_year -= 1900; |
58 | date.tm_mon -= 1; | 108 | date.tm_mon -= 1; |
59 | date.tm_isdst = -1; | 109 | date.tm_hour = date.tm_min = date.tm_sec = 0; |
110 | |||
111 | fp = fopen("sunPos.txt", "w"); | ||
112 | if (fp == NULL) { | ||
113 | printf("File open failed\n"); | ||
114 | exit(1); | ||
115 | } | ||
116 | fprintf(fp, "Sun trace File (Date: %4d-%02d-%02d)\n\n\n", | ||
117 | date.tm_year + 1900, date.tm_mon + 1, date.tm_mday); | ||
118 | getSunTime(date); | ||
119 | |||
120 | showSunPos(date); | ||
121 | fclose(fp); | ||
60 | 122 | ||
61 | time_t time = mktime(&date); | ||
62 | getSunPos(time); | ||
63 | return 0; | 123 | return 0; |
64 | } | 124 | } \ No newline at end of file |
diff --git a/src/calendar.h b/src/calendar.h index 248026f..87ca413 100644 --- a/src/calendar.h +++ b/src/calendar.h | |||
@@ -10,43 +10,13 @@ | |||
10 | using namespace std; | 10 | using namespace std; |
11 | 11 | ||
12 | // 哈尔滨南岗地方经纬度 | 12 | // 哈尔滨南岗地方经纬度 |
13 | #define LONGITUDE 126.533 * M_PI / 180 | 13 | #define M_PI 3.14159265358979323846 |
14 | #define LATITUDE 45.800 * M_PI / 180 | 14 | #define LONGITUDE 126.66854 * M_PI / 180 |
15 | 15 | #define LATITUDE 45.75996 * M_PI / 180 | |
16 | extern double delta; | ||
17 | extern char jieqi[25][10]; | ||
18 | 16 | ||
19 | typedef struct tm Date; | 17 | typedef struct tm Date; |
20 | struct point { | ||
21 | int year, mon, day, hour, min, sec; | ||
22 | bool isShuo, isJieqi, isZhongqi; | ||
23 | int JieqiIndex, MonthIndex; | ||
24 | bool RunYue; | ||
25 | double time; | ||
26 | point *next; | ||
27 | |||
28 | point(int year, int mon, int day, int hour, int min, int sec, bool isShuo, | ||
29 | bool isJieqi, bool isZhongqi, int JieqiIndex, int MonthIndex, | ||
30 | bool RunYue, double time) { | ||
31 | this->year = year; | ||
32 | this->mon = mon; | ||
33 | this->day = day; | ||
34 | this->hour = hour; | ||
35 | this->min = min; | ||
36 | this->sec = sec; | ||
37 | this->isShuo = isShuo; | ||
38 | this->isJieqi = isJieqi; | ||
39 | this->isZhongqi = isZhongqi; | ||
40 | this->JieqiIndex = JieqiIndex; | ||
41 | this->MonthIndex = MonthIndex; | ||
42 | this->RunYue = RunYue; | ||
43 | this->time = time; | ||
44 | this->next = NULL; | ||
45 | } | ||
46 | }; | ||
47 | 18 | ||
48 | void radToDMS(const char *message, int lowerBound, int upperBound, | 19 | string radToDMS(int lowerBound, int upperBound, double radians); |
49 | double radians); | ||
50 | 20 | ||
51 | class Julian { | 21 | class Julian { |
52 | private: | 22 | private: |
@@ -96,8 +66,6 @@ class parameter { | |||
96 | public: | 66 | public: |
97 | pair<double, double> sun_longitude(double t); | 67 | pair<double, double> sun_longitude(double t); |
98 | 68 | ||
99 | double moon_longitude(double t); | ||
100 | |||
101 | double get_epsilon(double T); | 69 | double get_epsilon(double T); |
102 | 70 | ||
103 | // 计算时角,返回弧度制 | 71 | // 计算时角,返回弧度制 |
@@ -107,4 +75,6 @@ class parameter { | |||
107 | 75 | ||
108 | extern Julian julian; | 76 | extern Julian julian; |
109 | extern parameter p; | 77 | extern parameter p; |
78 | extern double epsilon; | ||
79 | |||
110 | #endif \ No newline at end of file | 80 | #endif \ No newline at end of file |
diff --git a/src/parameters.cpp b/src/parameters.cpp index fdcefd1..ff57305 100644 --- a/src/parameters.cpp +++ b/src/parameters.cpp | |||
@@ -5,8 +5,7 @@ | |||
5 | #include <utility> | 5 | #include <utility> |
6 | using namespace std; | 6 | using namespace std; |
7 | 7 | ||
8 | void radToDMS(const char *message, int lowerBound, int upperBound, | 8 | string radToDMS(int lowerBound, int upperBound, double radians) { |
9 | double radians) { | ||
10 | // Convert radians to degrees | 9 | // Convert radians to degrees |
11 | double degrees = radians * 180.0 / M_PI; | 10 | double degrees = radians * 180.0 / M_PI; |
12 | 11 | ||
@@ -15,17 +14,19 @@ void radToDMS(const char *message, int lowerBound, int upperBound, | |||
15 | while (degrees >= upperBound) | 14 | while (degrees >= upperBound) |
16 | degrees -= (upperBound - lowerBound); | 15 | degrees -= (upperBound - lowerBound); |
17 | 16 | ||
18 | bool flag = degrees < 0; | ||
19 | if (flag) | ||
20 | degrees = -degrees; | ||
21 | // Calculate degrees, minutes, and seconds | 17 | // Calculate degrees, minutes, and seconds |
22 | int deg = static_cast<int>(degrees); | 18 | int deg = static_cast<int>(degrees); |
23 | double min_sec = (degrees - deg) * 60.0; | 19 | double min_sec = (degrees - deg) * 60.0; |
24 | int min = static_cast<int>(min_sec); | 20 | int min = static_cast<int>(min_sec); |
25 | double sec = (min_sec - min) * 60.0; | 21 | double sec = (min_sec - min) * 60.0; |
22 | if (degrees < 0) { | ||
23 | min = -min; | ||
24 | sec = -sec; | ||
25 | } | ||
26 | 26 | ||
27 | // Output the result | 27 | char buf[100]; |
28 | printf("%s: %c%d°%d'%06.3f''\n", message, flag ? '-' : ' ', deg, min, sec); | 28 | sprintf(buf, "%4d°%2d'%06.3f''", deg, min, sec); |
29 | return string(buf); | ||
29 | } | 30 | } |
30 | 31 | ||
31 | // 计算地球日心黄经 | 32 | // 计算地球日心黄经 |
@@ -205,51 +206,12 @@ pair<double, double> parameter::sun_longitude(double t) { | |||
205 | return make_pair(L, -B); | 206 | return make_pair(L, -B); |
206 | } | 207 | } |
207 | 208 | ||
208 | // 计算月球地心黄经,外部调用,返回角度制 | ||
209 | double parameter::moon_longitude(double t) { | ||
210 | double T = 10 * t; | ||
211 | vector<double> angles = get_angle(T); | ||
212 | double a, b, c, d, moon_longitude_a; | ||
213 | |||
214 | double L = 218.3164591 + 481267.88134236 * T - 0.0013268 * T * T + | ||
215 | T * T * T / 538841 - T * T * T * T / 65194000; //月球平黄经 | ||
216 | double EI = 0, sita = 0; | ||
217 | double E = 1 - 0.002516 * T - 0.0000074 * T * T; //地球离心率 | ||
218 | |||
219 | for (int i = 0; i < moon_size; i++) { | ||
220 | sita = moon_longitude_parameters[i][0] * angles[0] + | ||
221 | moon_longitude_parameters[i][1] * angles[1] + | ||
222 | moon_longitude_parameters[i][2] * angles[2] + | ||
223 | moon_longitude_parameters[i][3] * angles[3]; | ||
224 | sita *= M_PI / 180; | ||
225 | EI += moon_longitude_parameters[i][4] * sin(sita) * | ||
226 | pow(E, fabs(moon_longitude_parameters[i][1])); | ||
227 | } | ||
228 | |||
229 | //地外行星影响月球地心黄经修正项 | ||
230 | double a1, a2; | ||
231 | a1 = 119.75 + 131.849 * T; | ||
232 | a2 = 53.09 + 479264.290 * T; | ||
233 | |||
234 | EI += 3958.0 * sin(a1 * M_PI / 180); | ||
235 | EI += 1962.0 * sin((L - angles[3]) * M_PI / 180); | ||
236 | EI += 318.0 * sin(a2 * M_PI / 180); | ||
237 | |||
238 | L += EI / 1000000; | ||
239 | L += 180 / M_PI * nutation(T); //地球章动修正 | ||
240 | |||
241 | while (L < 0) | ||
242 | L += 360; | ||
243 | while (L >= 360) | ||
244 | L -= 360; | ||
245 | return L; | ||
246 | } | ||
247 | |||
248 | double parameter::getHourAngle(double julianKiloYear, double longitude, | 209 | double parameter::getHourAngle(double julianKiloYear, double longitude, |
249 | double latitude, double alpha) { | 210 | double latitude, double alpha) { |
250 | double T = julianKiloYear * 10; | 211 | double T = julianKiloYear * 10; |
251 | double GST = 280.46061837 + 360.98564736629 * 36525 * T + | 212 | double GST = 280.46061837 + 360.98564736629 * 36525 * T + |
252 | 0.000387933 * T * T - T * T * T / 38710000; | 213 | 0.000387933 * T * T - T * T * T / 38710000; |
214 | GST += nutation(T) * cos(epsilon); | ||
253 | GST *= M_PI / 180; | 215 | GST *= M_PI / 180; |
254 | return GST + longitude - alpha; // 返回弧度制 | 216 | return GST + longitude - alpha; // 返回弧度制 |
255 | } | 217 | } |