diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Julian.cpp | 89 | ||||
-rw-r--r-- | src/calendar.cpp | 120 | ||||
-rw-r--r-- | src/calendar.h | 71 | ||||
-rw-r--r-- | src/parameters.cpp | 210 |
4 files changed, 490 insertions, 0 deletions
diff --git a/src/Julian.cpp b/src/Julian.cpp new file mode 100644 index 0000000..1d3c4b7 --- /dev/null +++ b/src/Julian.cpp | |||
@@ -0,0 +1,89 @@ | |||
1 | #include "calendar.h" | ||
2 | |||
3 | double Julian::d[23][5]={ | ||
4 | {-4000, 108371.700000, -13036.800000, 392.000000, 0.000000}, | ||
5 | { -500, 17201.000000, -627.820000, 16.170000, -0.341300}, | ||
6 | { -150, 12200.600000, -346.410000, 5.403000, -0.159300}, | ||
7 | { 150, 9113.800000, -328.130000, -1.647000, 0.037700}, | ||
8 | { 500, 5707.500000, -391.410000, 0.915000, 0.314500}, | ||
9 | { 900, 2203.400000, -283.450000, 13.034000, -0.177800}, | ||
10 | { 1300, 490.100000, -57.350000, 2.085000, -0.007200}, | ||
11 | { 1600, 120.000000, -9.810000, -1.532000, 0.140300}, | ||
12 | { 1700, 10.200000, -0.910000, 0.510000, -0.037000}, | ||
13 | { 1800, 13.400000, -0.720000, 0.202000, -0.019300}, | ||
14 | { 1830, 7.800000, -1.810000, 0.416000, -0.024700}, | ||
15 | { 1860, 8.300000, -0.130000, -0.406000, 0.029200}, | ||
16 | { 1880, -5.400000, 0.320000, -0.183000, 0.017300}, | ||
17 | { 1900, -2.300000, 2.060000, 0.169000, -0.013500}, | ||
18 | { 1920, 21.200000, 1.690000, -0.304000, 0.016700}, | ||
19 | { 1940, 24.200000, 1.220000, -0.064000, 0.003100}, | ||
20 | { 1960, 33.200000, 0.510000, 0.231000, -0.010900}, | ||
21 | { 1980, 51.000000, 1.290000, -0.026000, 0.003200}, | ||
22 | { 2000, 63.870000, 0.100000, 0.000000, 0.000000}, | ||
23 | { 2005, 64.700000, 0.210000, 0.000000, 0.000000}, | ||
24 | { 2012, 66.800000, 0.220000, 0.000000, 0.000000}, | ||
25 | { 2018, 69.000000, 0.360000, 0.000000, 0.000000}, | ||
26 | { 2028, 72.600000, 0.000000, 0.000000, 0.000000} | ||
27 | }; | ||
28 | |||
29 | double Julian::dt_ext(int y,double jsd) | ||
30 | { | ||
31 | double dy=(double)(y-1820)/100.0; | ||
32 | return -20+jsd*dy*dy; | ||
33 | } | ||
34 | |||
35 | //计算力学时与世界时之差,传入年份 | ||
36 | double Julian::delta_t(int y) | ||
37 | { | ||
38 | int y0=d[22][0];//表中最后一行的年份 | ||
39 | double t0=d[22][1];//表中最后一行的delta_t | ||
40 | double jsd; | ||
41 | |||
42 | if(y>y0) | ||
43 | { | ||
44 | jsd=31; | ||
45 | if(y-y0>100) | ||
46 | { | ||
47 | return dt_ext(y,jsd); | ||
48 | } | ||
49 | |||
50 | double v=dt_ext(y,jsd); | ||
51 | double dv=dt_ext(y0,jsd)-t0; | ||
52 | return v-dv*(y0+100-y)/100; | ||
53 | } | ||
54 | |||
55 | double res; | ||
56 | for(int i=0;i<22;i++) | ||
57 | { | ||
58 | if(y<d[i+1][0]) | ||
59 | { | ||
60 | break; | ||
61 | } | ||
62 | double t1=(y-d[i][0])/(d[i+1][0]-d[i][0])*10; | ||
63 | double t2=t1*t1; | ||
64 | double t3=t2*t1; | ||
65 | res=d[i][1]+d[i][2]*t1+d[i][3]*t2+d[i][4]*t3; | ||
66 | } | ||
67 | return res; | ||
68 | } | ||
69 | // 计算儒略日 | ||
70 | double Julian::getJulianDay(time_t time) | ||
71 | { | ||
72 | double t=(double)time; | ||
73 | return (double)t/86400.0+2440587.5; | ||
74 | } | ||
75 | |||
76 | // 计算儒略千年数 | ||
77 | double Julian::getJulianKiloYear(time_t time) | ||
78 | { | ||
79 | double jd = getJulianDay(time); | ||
80 | return (double)(jd-2451545.0)/365250.0; | ||
81 | } | ||
82 | |||
83 | //儒略千年数转时间戳 | ||
84 | time_t Julian::kiloYearToTime(double t,int year) | ||
85 | { | ||
86 | double jd=t*365250.0+2451545.0; | ||
87 | time_t time=(time_t)((jd-2440587.5)*86400.0-delta_t(year)); | ||
88 | return time; | ||
89 | } | ||
diff --git a/src/calendar.cpp b/src/calendar.cpp new file mode 100644 index 0000000..c81316a --- /dev/null +++ b/src/calendar.cpp | |||
@@ -0,0 +1,120 @@ | |||
1 | // Encoding: UTF-8 | ||
2 | #include "calendar.h" | ||
3 | |||
4 | double pi=3.14159265358979323846; | ||
5 | double delta=5e-9; | ||
6 | |||
7 | void Plus(Date &date) | ||
8 | { | ||
9 | if(date.tm_mday<10) | ||
10 | { | ||
11 | date.tm_mday=20; | ||
12 | } | ||
13 | else | ||
14 | { | ||
15 | date.tm_mday=6; | ||
16 | date.tm_mon++; | ||
17 | } | ||
18 | return; | ||
19 | } | ||
20 | |||
21 | double fuck(double a,double b) | ||
22 | { | ||
23 | while(b<0) | ||
24 | b+=360; | ||
25 | while(b>=360) | ||
26 | b-=360; | ||
27 | if(b==0) | ||
28 | { | ||
29 | return min(fabs(b),fabs(360-b)); | ||
30 | } | ||
31 | else | ||
32 | { | ||
33 | return fabs(a-b); | ||
34 | } | ||
35 | } | ||
36 | |||
37 | int main() | ||
38 | { | ||
39 | Date* date=new Date; | ||
40 | cout<<"Please input the year: "<<endl; | ||
41 | |||
42 | //时间确认 | ||
43 | cin>>date->tm_year; | ||
44 | date->tm_year-=1900;//年份减去1900 | ||
45 | //当年元旦零时 | ||
46 | date->tm_mon=0; | ||
47 | date->tm_mday=1; | ||
48 | date->tm_hour=0; | ||
49 | date->tm_min=0; | ||
50 | date->tm_sec=0; | ||
51 | |||
52 | //输出年份 | ||
53 | cout<<"Year: "<<date->tm_year+1900<<endl; | ||
54 | |||
55 | //计算当年二十四节气准确时刻 | ||
56 | parameter p; | ||
57 | Julian julian; | ||
58 | time_t time; | ||
59 | //double dL;//dL为L对t导数 | ||
60 | double t,t_end,t_middle; | ||
61 | double target; | ||
62 | char JieQi[24][10]={"小寒","大寒","立春","雨水","惊蛰","春分","清明","谷雨","立夏","小满","芒种","夏至","小暑","大暑","立秋","处暑","白露","秋分","寒露","霜降","立冬","小雪","大雪","冬至"}; | ||
63 | //date->tm_mday=6; | ||
64 | for(int i=0;date->tm_mon<12;Plus(*date),i++) | ||
65 | { | ||
66 | //转换为时间戳 | ||
67 | time=mktime(date); | ||
68 | //暂时放弃牛顿迭代法 | ||
69 | //t=julian.getJulianKiloYear(time); | ||
70 | //while(fuck(p.longitude(t),(double)i*15-75)>=1e-8) | ||
71 | //{ | ||
72 | // dL=(p.longitude(t+delta)-p.longitude(t-delta))/(2*delta); | ||
73 | // t=t-p.longitude(t)/dL; | ||
74 | //} | ||
75 | |||
76 | |||
77 | //计算儒略千年数 | ||
78 | t=julian.getJulianKiloYear(time); | ||
79 | t_end=julian.getJulianKiloYear(time+86400); | ||
80 | target=i*15-75; | ||
81 | if(target<0) | ||
82 | { | ||
83 | target+=360; | ||
84 | } | ||
85 | |||
86 | //二分法 | ||
87 | while(p.sun_longitude(t)>target) | ||
88 | { | ||
89 | time-=86400; | ||
90 | t_end=t; | ||
91 | t=julian.getJulianKiloYear(time); | ||
92 | } | ||
93 | while(p.sun_longitude(t_end)<=target) | ||
94 | { | ||
95 | time+=86400; | ||
96 | t=t_end; | ||
97 | t_end=julian.getJulianKiloYear(time); | ||
98 | } | ||
99 | while(t_end-t>=1e-10) | ||
100 | { | ||
101 | t_middle=(t+t_end)/2; | ||
102 | if(p.sun_longitude(t_middle)>target) | ||
103 | { | ||
104 | t_end=t_middle; | ||
105 | } | ||
106 | else | ||
107 | { | ||
108 | t=t_middle; | ||
109 | } | ||
110 | } | ||
111 | //double t转为时间戳 | ||
112 | time=julian.kiloYearToTime(t,date->tm_year+1900); | ||
113 | |||
114 | //date换新 | ||
115 | date=localtime(&time); | ||
116 | printf("%d-%02d-%02d %02d:%02d:%02d %s\n",date->tm_year+1900,date->tm_mon+1,date->tm_mday,date->tm_hour,date->tm_min,date->tm_sec,JieQi[i]); | ||
117 | } | ||
118 | printf("\n\n"); | ||
119 | return 0; | ||
120 | } | ||
diff --git a/src/calendar.h b/src/calendar.h new file mode 100644 index 0000000..c87531d --- /dev/null +++ b/src/calendar.h | |||
@@ -0,0 +1,71 @@ | |||
1 | #ifndef _CALENDAR_H_ | ||
2 | #define _CALENDAR_H_ | ||
3 | |||
4 | |||
5 | #include <iostream> | ||
6 | #include <string> | ||
7 | #include <ctime> | ||
8 | #include <vector> | ||
9 | #include <fstream> | ||
10 | #include <math.h> | ||
11 | using namespace std; | ||
12 | |||
13 | typedef struct tm Date; | ||
14 | |||
15 | extern double pi; | ||
16 | extern double delta; | ||
17 | |||
18 | class Julian | ||
19 | { | ||
20 | private: | ||
21 | static double d[23][5]; | ||
22 | |||
23 | double dt_ext(int y,double jsd); | ||
24 | |||
25 | //计算力学时与世界时之差,传入年份 | ||
26 | double delta_t(int y); | ||
27 | public: | ||
28 | // 计算儒略日 | ||
29 | double getJulianDay(time_t time); | ||
30 | |||
31 | // 计算儒略千年数 | ||
32 | double getJulianKiloYear(time_t time); | ||
33 | |||
34 | //儒略千年数转时间戳 | ||
35 | time_t kiloYearToTime(double t,int year); | ||
36 | }; | ||
37 | |||
38 | |||
39 | class parameter{ | ||
40 | private: | ||
41 | |||
42 | // 计算地球日心黄经 | ||
43 | double get_longitude(vector<double> l,double t); | ||
44 | |||
45 | // 计算地球日心黄纬 | ||
46 | double get_latitude(vector<double> b,double t); | ||
47 | |||
48 | double get_R(vector<double> r,double t); | ||
49 | |||
50 | // 转换FK5误差,返回弧度制 | ||
51 | double delta_FK5(double L,double B,double T); | ||
52 | |||
53 | //获取章动有关角 | ||
54 | vector<double> get_angle(double T); | ||
55 | |||
56 | |||
57 | //章动修正 | ||
58 | double nution(double T); | ||
59 | |||
60 | //光行差修正,返回弧度制 | ||
61 | double aberration(double R); | ||
62 | |||
63 | // 获取地日运行参数,L为地球日心黄经,B为地球日心黄纬,R为地日距离 | ||
64 | vector<vector<double>> get_parameters(double t); | ||
65 | |||
66 | public: | ||
67 | |||
68 | double sun_longitude(double t); | ||
69 | }; | ||
70 | |||
71 | #endif | ||
diff --git a/src/parameters.cpp b/src/parameters.cpp new file mode 100644 index 0000000..704f083 --- /dev/null +++ b/src/parameters.cpp | |||
@@ -0,0 +1,210 @@ | |||
1 | #include "calendar.h" | ||
2 | using namespace std; | ||
3 | |||
4 | // 计算地球日心黄经 | ||
5 | double parameter::get_longitude(vector<double> l,double t) | ||
6 | { | ||
7 | double L=l[0]; | ||
8 | for(int i=1;i<l.size();i++) | ||
9 | { | ||
10 | L+=l[i]*pow(t,i); | ||
11 | } | ||
12 | //返回弧度制 | ||
13 | return L+pi; | ||
14 | } | ||
15 | |||
16 | // 计算地球日心黄纬 | ||
17 | double parameter::get_latitude(vector<double> b,double t) | ||
18 | { | ||
19 | double B=b[0]; | ||
20 | for(int i=1;i<b.size();i++) | ||
21 | { | ||
22 | B+=b[i]*pow(t,i); | ||
23 | } | ||
24 | //返回弧度制 | ||
25 | //地心黄纬=-太阳黄纬 | ||
26 | return -B; | ||
27 | } | ||
28 | |||
29 | double parameter::get_R(vector<double> r,double t) | ||
30 | { | ||
31 | double R=r[0]; | ||
32 | for(int i=1;i<r.size();i++) | ||
33 | { | ||
34 | R+=r[i]*pow(t,i); | ||
35 | } | ||
36 | return R; | ||
37 | } | ||
38 | |||
39 | // 转换FK5误差,返回弧度制 | ||
40 | double parameter::delta_FK5(double L,double B,double T) | ||
41 | { | ||
42 | //L转角度制 | ||
43 | L*=180/pi; | ||
44 | //计算L',角度制 | ||
45 | double L_p=L-1.397*T-0.00031*T*T; | ||
46 | //计算L',弧度制 | ||
47 | L_p*=pi/180; | ||
48 | while(L_p<0) | ||
49 | L_p+=2*pi; | ||
50 | while(L_p>2*pi) | ||
51 | L_p-=2*pi; | ||
52 | //计算delta_L,单位为角秒 | ||
53 | double delta_L=-0.09033+0.03916*(cos(L_p)+sin(L_p))*tan(B); | ||
54 | //转换为弧度制 | ||
55 | delta_L*=pi/(180*3600); | ||
56 | return delta_L; | ||
57 | } | ||
58 | |||
59 | //获取章动有关角 | ||
60 | vector<double> parameter::get_angle(double T) | ||
61 | { | ||
62 | vector<double> ang; | ||
63 | //计算平距角 | ||
64 | ang.push_back(297.85036+445267.111480*T-0.0019142*T*T+T*T*T/189474); | ||
65 | //计算日地平近点角 | ||
66 | ang.push_back(357.52772+35999.050340*T-0.0001603*T*T-T*T*T/300000); | ||
67 | //计算月球平近点角 | ||
68 | ang.push_back(134.96298+477198.867398*T+0.0086972*T*T+T*T*T/56250); | ||
69 | //计算月球纬度参数 | ||
70 | ang.push_back(93.27191+483202.017538*T-0.0036825*T*T+T*T*T/327270); | ||
71 | //计算黄道与月球平轨道交点黄经 | ||
72 | ang.push_back(125.04452-1934.136261*T+0.0020708*T*T+T*T*T/450000); | ||
73 | return ang; | ||
74 | } | ||
75 | |||
76 | |||
77 | //章动修正 | ||
78 | double parameter::nution(double T) | ||
79 | { | ||
80 | vector<double> ang=get_angle(T); | ||
81 | fstream fr; | ||
82 | fr.open("data/nutation.txt",ios::in); | ||
83 | string str; | ||
84 | double sita; | ||
85 | double s,s1,s2; | ||
86 | double c,c1,c2; | ||
87 | double m,n,o,p,q; | ||
88 | |||
89 | s=c=0; | ||
90 | while(getline(fr,str)) | ||
91 | { | ||
92 | sscanf(str.c_str(),"%lf%lf%lf%lf%lf%lf%lf%lf%lf",&m,&n,&o,&p,&q,&s1,&s2,&c1,&c2); | ||
93 | sita=m*ang[0]+n*ang[1]+o*ang[2]+p*ang[3]+q*ang[4]; | ||
94 | |||
95 | //sita为角度制,转换为弧度制 | ||
96 | sita*=pi/180; | ||
97 | //计算黄经章动,单位为0.0001角秒 | ||
98 | s+=(s1+s2*T)*sin(sita); | ||
99 | //计算交角章动,单位为0.0001角秒 | ||
100 | //c+=(c1+c2*T)*cos(sita); | ||
101 | } | ||
102 | //关闭文件 | ||
103 | fr.close(); | ||
104 | // 计算得到的s和c单位0.0001秒,转换为弧度制 | ||
105 | s*=0.0001; | ||
106 | s*=pi/(180*3600); | ||
107 | return s; | ||
108 | } | ||
109 | |||
110 | //光行差修正,返回弧度制 | ||
111 | double parameter::aberration(double R) | ||
112 | { | ||
113 | //return -20.4898/R/3600.0*pi/180.0; | ||
114 | //公式,单位0.0001角秒 | ||
115 | double delta=-20.4898/R; | ||
116 | //转换为弧度制 | ||
117 | delta*=pi/(180*3600); | ||
118 | return delta; | ||
119 | } | ||
120 | |||
121 | // 获取地日运行参数,L为地球日心黄经,B为地球日心黄纬,R为地日距离 | ||
122 | vector<vector<double>> parameter::get_parameters(double t) | ||
123 | { | ||
124 | fstream fr; | ||
125 | fr.open("data/earth.txt",ios::in); | ||
126 | string s; | ||
127 | double l=0; | ||
128 | double a,b,c,num_tmp=0; | ||
129 | vector<vector<double>> parameters; | ||
130 | vector<double> tmp; | ||
131 | while(getline(fr,s)) | ||
132 | { | ||
133 | //当分割符为/时,表明一组参数结束,将参数存入parameters中,并清空tmp | ||
134 | if(s[0]=='/') | ||
135 | { | ||
136 | parameters.push_back(tmp); | ||
137 | tmp.resize(0); | ||
138 | num_tmp=0; | ||
139 | } | ||
140 | //当分割符为=时,表明一组参数中的一类结束,将参数存入tmp中,并清空num_tmp | ||
141 | else if(s[0]=='=') | ||
142 | { | ||
143 | tmp.push_back(num_tmp); | ||
144 | num_tmp=0; | ||
145 | } | ||
146 | else | ||
147 | { | ||
148 | sscanf(s.c_str(),"%lf%lf%lf",&a,&b,&c); | ||
149 | num_tmp+=a*cos(b+c*t); | ||
150 | } | ||
151 | } | ||
152 | //关闭文件 | ||
153 | fr.close(); | ||
154 | /* 最终传参情况: | ||
155 | * parameters[0]为L系列,用来计算地球日心黄经 | ||
156 | * parameters[1]为B系列,用来计算地球日心黄纬 | ||
157 | * parameters[2]为R系列,用来计算地日距离 | ||
158 | */ | ||
159 | return parameters; | ||
160 | } | ||
161 | |||
162 | |||
163 | double parameter::sun_longitude(double t) | ||
164 | { | ||
165 | //从文件中计算地日运行参数 | ||
166 | vector<vector<double>> p=get_parameters(t); | ||
167 | |||
168 | //取出各类参数 | ||
169 | vector<double> l=p[0],b=p[1],r=p[2]; | ||
170 | |||
171 | //计算地球日心黄经纬,返回弧度制/天文单位 | ||
172 | double L=get_longitude(l,t); | ||
173 | double B=get_latitude(b,t); | ||
174 | double R=get_R(r,t); | ||
175 | |||
176 | |||
177 | //以下修正需要的都是儒略世纪数而非千年数 | ||
178 | //转FK5误差,返回弧度制 | ||
179 | L+=delta_FK5(L,B,10*t); | ||
180 | //章动修正,返回弧度制 | ||
181 | L+=nution(10*t); | ||
182 | //光行差修正,返回弧度制 | ||
183 | L+=aberration(R); | ||
184 | |||
185 | |||
186 | //L转角度制 | ||
187 | L*=180/pi; | ||
188 | while(L<0) | ||
189 | L+=360; | ||
190 | while(L>=360) | ||
191 | L-=360; | ||
192 | if(360-L<=5) | ||
193 | { | ||
194 | L-=360; | ||
195 | } | ||
196 | return L; | ||
197 | } | ||
198 | |||
199 | //double moon_longitude(double t) | ||
200 | //{ | ||
201 | // //文件中获取地月运行参数 | ||
202 | // vector<vector<double>> p=get_moon_parameters(t); | ||
203 | // vector<double> l=p[0],b=p[1],r=p[2]; | ||
204 | |||
205 | // //计算地月日心黄经纬,返回弧度制/天文单位 | ||
206 | // double L=get_moon_longitude(l,t); | ||
207 | // double B=get_moon_latitude(b,t); | ||
208 | // double R=get_moon_R(r,t); | ||
209 | |||
210 | //} | ||