summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Julian.cpp89
-rw-r--r--src/calendar.cpp120
-rw-r--r--src/calendar.h71
-rw-r--r--src/parameters.cpp210
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
3double 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
29double 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//计算力学时与世界时之差,传入年份
36double 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// 计算儒略日
70double Julian::getJulianDay(time_t time)
71{
72 double t=(double)time;
73 return (double)t/86400.0+2440587.5;
74}
75
76// 计算儒略千年数
77double Julian::getJulianKiloYear(time_t time)
78{
79 double jd = getJulianDay(time);
80 return (double)(jd-2451545.0)/365250.0;
81}
82
83//儒略千年数转时间戳
84time_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
4double pi=3.14159265358979323846;
5double delta=5e-9;
6
7void 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
21double 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
37int 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>
11using namespace std;
12
13typedef struct tm Date;
14
15extern double pi;
16extern double delta;
17
18class 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
39class 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"
2using namespace std;
3
4// 计算地球日心黄经
5double 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// 计算地球日心黄纬
17double 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
29double 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误差,返回弧度制
40double 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//获取章动有关角
60vector<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//章动修正
78double 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//光行差修正,返回弧度制
111double 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为地日距离
122vector<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
163double 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//}