/// <summary> /// 时差计算(高精度) /// </summary> /// <param name="t"></param> /// <returns></returns> public static double shiCha(double t) { double t2 = t * t, t3 = t2 * t, t4 = t3 * t, t5 = t4 * t; double L = (1753469512 + 628331965331.8 * t + 5296.74 * t2 + 0.432 * t3 - 0.1124 * t4 - 0.00009 * t5 + 630 * Math.Cos(6 + 0.3 * t)) / 1000000000 + Math.PI - 20.5 / LunarHelper.rad; double E, dE, dL; double[] z = new double[2]; // C#: 待定(?) dL = -17.2 * Math.Sin(2.1824 - 33.75705 * t) / LunarHelper.rad; //黄经章 dE = 9.2 * Math.Cos(2.1824 - 33.75705 * t) / LunarHelper.rad; //交角章 E = ZB.hcjj(t) + dE; //真黄赤交角 //地球坐标 z[0] = XL.E_Lon(t, 50) + Math.PI + ZB.gxc_sunLon(t) + dL; z[1] = -(2796 * Math.Cos(3.1987 + 8433.46616 * t) + 1016 * Math.Cos(5.4225 + 550.75532 * t) + 804 * Math.Cos(3.88 + 522.3694 * t)) / 1000000000; ZB.llrConv(z, E); //z太阳地心赤道坐标 z[0] -= dL * Math.Cos(E); L = LunarHelper.rad2mrad(L - z[0]); if (L > Math.PI) { L -= LunarHelper.pi2; } return(L / LunarHelper.pi2); //单位是周(天) }
/// <summary> /// 章动同时影响恒星时和天体坐标,所以不计算章动。返回时角及赤经纬 /// </summary> /// <param name="jd"></param> /// <param name="H0"></param> /// <param name="z"></param> public static void Mcoord(double jd, double H0, LunarInfoListT <double> z) { XL.M_coord((jd + SZJ.dt) / 36525, z, 30, 20, 8); //低精度月亮赤经纬 ZB.llrConv(z, SZJ.E); //转为赤道坐标 z.H = LunarHelper.rad2mrad(ZB.gst(jd, SZJ.dt) - SZJ.L - z[0]); if (z.H > Math.PI) { z.H -= LunarHelper.pi2; //得到此刻天体时角 } if (H0 != 0) { z.H0 = SZJ.getH(0.7275 * LunarHelper.cs_rEar / z[2] - 34 * 60 / LunarHelper.rad, z[1]); //升起对应的时角 } }
/// <summary> /// 章动同时影响恒星时和天体坐标,所以不计算章动。返回时角及赤经纬 /// </summary> /// <param name="jd"></param> /// <param name="H0"></param> /// <param name="H1"></param> /// <param name="z"></param> public static void Scoord(double jd, double H0, double H1, LunarInfoListT <double> z) { z[0] = XL.E_Lon((jd + SZJ.dt) / 36525, 5) + Math.PI - 20.5 / LunarHelper.rad; //太阳坐标(修正了光行差) z[1] = 0d; z[2] = 1d; // C#: 添加 d, 强制为 double 类型, 否则在把该元素显式转换为 double 时会出错 ZB.llrConv(z, SZJ.E); // 转为赤道坐标 z.H = LunarHelper.rad2rrad(ZB.gst(jd, SZJ.dt) - SZJ.L - z[0]); //得到此刻天体时角 if (H0 != 0) { z.H0 = SZJ.getH(-50 * 60 / LunarHelper.rad, z[1]); //地平以下50分 } if (H1 != 0) { z.H1 = SZJ.getH(-Math.PI / 30, z[1]); // 地平以下6度 } }
/// <summary> /// 时差计算(低精度),误差约在1秒以内 /// </summary> /// <param name="t"></param> /// <returns></returns> public static double shiCha2(double t) { double L = (1753469512 + 628331965331.8 * t + 5296.74 * t * t) / 1000000000 + Math.PI; double[] z = new double[2]; // C#: 待定(?) double E = (84381.4088 - 46.836051 * t) / LunarHelper.rad; z[0] = XL.E_Lon(t, 5) + Math.PI; z[1] = 0; // 地球坐标 ZB.llrConv(z, E); // z太阳地心赤道坐标 L = LunarHelper.rad2mrad(L - z[0]); if (L > Math.PI) { L -= LunarHelper.pi2; } return(L / LunarHelper.pi2); // 单位是周(天) }
/// <summary> /// 月亮到中升降时刻计算,传入jd含义与St()函数相同 /// </summary> /// <param name="jd"></param> /// <returns></returns> public static LunarInfoListT <double> Mt(double jd) { SZJ.dt = JD.deltatT2(jd); SZJ.E = ZB.hcjj(jd / 36525); jd -= LunarHelper.mod2(0.1726222 + 0.966136808032357 * jd - 0.0366 * SZJ.dt - SZJ.L / LunarHelper.pi2, 1); //查找最靠近当日中午的月上中天,mod2的第1参数为本地时角近似值 LunarInfoListT <double> r = new LunarInfoListT <double>(3, 0d); double sv = LunarHelper.pi2 * 0.966; r.z__ = r.s__ = r.j__ = r.c__ = r.h__ = jd; SZJ.Mcoord(jd, 1, r); //月亮坐标 r.s__ += (-r.H0 - r.H) / sv; r.j__ += (r.H0 - r.H) / sv; r.z__ += (0 - r.H) / sv; SZJ.Mcoord(r.s__, 1, r); r.s__ += (-r.H0 - r.H) / sv; SZJ.Mcoord(r.j__, 1, r); r.j__ += (+r.H0 - r.H) / sv; SZJ.Mcoord(r.z__, 0, r); r.z__ += (0 - r.H) / sv; return(r); }
/// <summary> /// 太阳到中升降时刻计算,传入jd是当地中午12点时间对应的2000年首起算的格林尼治时间UT /// </summary> /// <param name="jd"></param> /// <returns></returns> public static LunarInfoListT <double> St(double jd) { SZJ.dt = JD.deltatT2(jd); SZJ.E = ZB.hcjj(jd / 36525); jd -= LunarHelper.mod2(jd - SZJ.L / LunarHelper.pi2, 1); //查找最靠近当日中午的日上中天,mod2的第1参数为本地时角近似值 LunarInfoListT <double> r = new LunarInfoListT <double>(3, 0d); double sv = LunarHelper.pi2; r.z__ = r.s__ = r.j__ = r.c__ = r.h__ = jd; SZJ.Scoord(jd, 1, 1, r); //太阳坐标 r.s__ += (-r.H0 - r.H) / sv; //升起 r.j__ += (r.H0 - r.H) / sv; //降落 r.c__ += (-r.H1 - r.H) / sv; //民用晨 r.h__ += (r.H1 - r.H) / sv; //民用昏 r.z__ += (0 - r.H) / sv; //中天 SZJ.Scoord(r.s__, 1, 0, r); r.s__ += (-r.H0 - r.H) / sv; SZJ.Scoord(r.j__, 1, 0, r); r.j__ += (+r.H0 - r.H) / sv; SZJ.Scoord(r.c__, 0, 1, r); r.c__ += (-r.H1 - r.H) / sv; SZJ.Scoord(r.h__, 0, 1, r); r.h__ += (+r.H1 - r.H) / sv; SZJ.Scoord(r.z__, 0, 0, r); r.z__ += (0 - r.H) / sv; return(r); }
/// <summary> /// 视差修正 /// </summary> /// <param name="z">赤道坐标</param> /// <param name="H">时角</param> /// <param name="fa">地理纬度</param> /// <param name="high">海拔(千米)</param> public static void parallax(double[] z, double H, double fa, double high) { double dw = 1d; if (z[2] < 500) { dw = LunarHelper.cs_AU; } z[2] *= dw; double r0, x0, y0, z0, f = 0.99664719; double u = Math.Atan(f * Math.Tan(fa)); double g = z[0] + H; r0 = LunarHelper.cs_rEar * Math.Cos(u) + high * Math.Cos(fa); //站点与地地心向径的赤道投影长度 z0 = LunarHelper.cs_rEar * Math.Sin(u) * f + high * Math.Sin(fa); //站点与地地心向径的轴向投影长度 x0 = r0 * Math.Cos(g); y0 = r0 * Math.Sin(g); ZB.llr2xyz(z[0], z[1], z[2], z); z[0] -= x0; z[1] -= y0; z[2] -= z0; ZB.xyz2llr(z[0], z[1], z[2], z); z[2] /= dw; }
/// <summary> /// 太阳视黄经 /// </summary> /// <param name="t"></param> /// <param name="n"></param> /// <returns></returns> public static double S_aLon(double t, double n) { return(XL.E_Lon(t, n) + ZB.nutationLon(t) + ZB.gxc_sunLon(t) + Math.PI); //注意,这里的章动计算很耗时 }
/// <summary> /// 月日视黄经的差值 /// </summary> /// <param name="t"></param> /// <param name="Mn"></param> /// <param name="Sn"></param> /// <returns></returns> public static double MS_aLon(double t, double Mn, double Sn) { return(XL.M_Lon(t, Mn) + ZB.gxc_moonLon(t) - (XL.E_Lon(t, Sn) + ZB.gxc_sunLon(t) + Math.PI)); }
} // = 0; #endregion #endregion 公共属性 #region 公共方法 /// <summary> /// 计算 sun_moon 类的成员。参数:T是力学时,站点经度L,纬度fa,海拔high(千米) /// </summary> /// <param name="T">力学时</param> /// <param name="L">站点经度</param> /// <param name="fa">站点纬度</param> /// <param name="high">海拔</param> public void calc(double T, double L, double fa, double high) { //基本参数计算 this.T = T; this.L = L; this.fa = fa; this.dt = JD.deltatT2(T); //TD-UT this.jd = T - this.dt; //UT T /= 36525; ZB.nutation(T); this.dL = ZB.dL; //黄经章 this.dE = ZB.dE; //交角章动 this.E = ZB.hcjj(T) + this.dE; //真黄赤交角 this.gst = ZB.gst(this.jd, this.dt) + this.dL * Math.Cos(this.E); //真恒星时(不考虑非多项式部分) double[] z = new double[4]; //=======月亮======== //月亮黄道坐标 XL.M_coord(T, z, -1, -1, -1); //月球坐标 z[0] = LunarHelper.rad2mrad(z[0] + ZB.gxc_moonLon(T) + this.dL); z[1] += ZB.gxc_moonLat(T); //补上月球光行差及章动 this.mHJ = z[0]; this.mHW = z[1]; this.mR = z[2]; //月球视黄经,视黄纬,地月质心距 //月球赤道坐标 ZB.llrConv(z, this.E); //转为赤道坐标 this.mCJ = z[0]; this.mCW = z[1]; //月球视赤经,月球赤纬 //月亮时角计算 this.mShiJ = LunarHelper.rad2mrad(this.gst - L - z[0]); //得到此刻天体时角 if (this.mShiJ > Math.PI) { this.mShiJ -= LunarHelper.pi2; } //修正了视差的赤道坐标 ZB.parallax(z, this.mShiJ, fa, high); //视差修正 this.mCJ2 = z[0]; this.mCW2 = z[1]; this.mR2 = z[2]; //月亮时角坐标 z[0] += Math.PI / 2d - this.gst + L; //转到相对于地平赤道分点的赤道坐标(时角坐标) //月亮地平坐标 ZB.llrConv(z, Math.PI / 2 - fa); //转到地平坐标(只改经纬度) z[0] = LunarHelper.rad2mrad(Math.PI / 2 - z[0]); this.mDJ = z[0]; this.mDW = z[1]; //方位角,高度角 if (z[1] > 0) { z[1] += ZB.AR2(z[1]); //大气折射修正 } this.mPJ = z[0]; this.mPW = z[1]; //方位角,高度角 //=======太阳======== //太阳黄道坐标 XL.E_coord(T, z, -1, -1, -1); //地球坐标 z[0] = LunarHelper.rad2mrad(z[0] + Math.PI + ZB.gxc_sunLon(T) + this.dL); //补上太阳光行差及章动 z[1] = -z[1] + ZB.gxc_sunLat(T); //z数组为太阳地心黄道视坐标 this.sHJ = z[0]; this.sHW = z[1]; this.sR = z[2]; //太阳视黄经,视黄纬,日地质心距 //太阳赤道坐标 ZB.llrConv(z, this.E); //转为赤道坐标 this.sCJ = z[0]; this.sCW = z[1]; //太阳视赤经,视赤纬 //太阳时角计算 this.sShiJ = LunarHelper.rad2mrad(this.gst - L - z[0]); //得到此刻天体时角 if (this.sShiJ > Math.PI) { this.sShiJ -= LunarHelper.pi2; } //修正了视差的赤道坐标 ZB.parallax(z, this.sShiJ, fa, high); //视差修正 this.sCJ2 = z[0]; this.sCW2 = z[1]; this.sR2 = z[2]; //太阳时角坐标 z[0] += Math.PI / 2 - this.gst + L; //转到相对于地平赤道分点的赤道坐标 //太阳地平坐标 ZB.llrConv(z, Math.PI / 2 - fa); z[0] = LunarHelper.rad2mrad(Math.PI / 2 - z[0]); //z[1] -= 8.794/rad/z[2]*Math.cos(z[1]); //直接在地平坐标中视差修正(这里把地球看为球形,精度比ZB.parallax()稍差一些) this.sDJ = z[0]; this.sDW = z[1]; //方位角,高度角 if (z[1] > 0) { z[1] += ZB.AR2(z[1]); //大气折射修正 } this.sPJ = z[0]; this.sPW = z[1]; //方位角,高度角 //=======其它======== //时差计算 double t = T / 10; double t2 = t * t, t3 = t2 * t, t4 = t3 * t, t5 = t4 * t; double Lon = (1753469512 + 6283319653318 * t + 529674 * t2 + 432 * t3 - 1124 * t4 - 9 * t5 + 630 * Math.Cos(6 + 3 * t)) / 1000000000 + Math.PI - 20.5 / LunarHelper.rad; //修正了光行差的太阳平黄经 Lon = LunarHelper.rad2mrad(Lon - (this.sCJ - this.dL * Math.Cos(this.E))); //(修正了光行差的平黄经)-(不含dL*cos(E)的视赤经) if (Lon > Math.PI) { Lon -= LunarHelper.pi2; //得到时差,单位是弧度 } this.sc = Lon / LunarHelper.pi2; //时差(单位:日) //真太阳与平太阳 this.pty = this.jd - L / LunarHelper.pi2; //平太阳时 this.zty = this.jd - L / LunarHelper.pi2 + this.sc; //真太阳时 //视半径 //this.mRad = XL.moonRad(this.mR,this.mDW); //月亮视半径(角秒) this.mRad = 358473400d / this.mR2; //月亮视半径(角秒) this.sRad = 959.63 / this.sR2; //太阳视半径(角秒) this.e_mRad = 358473400d / this.mR; //月亮地心视半径(角秒) this.eShadow = (LunarHelper.cs_rEarA / this.mR * LunarHelper.rad - (959.63 - 8.794) / this.sR) * 51 / 50; //地本影在月球向径处的半径(角秒),式中51/50是大气厚度补偿 this.eShadow2 = (LunarHelper.cs_rEarA / this.mR * LunarHelper.rad + (959.63 + 8.794) / this.sR) * 51 / 50; //地半影在月球向径处的半径(角秒),式中51/50是大气厚度补偿 this.mIll = XL.moonIll(T); //月亮被照面比例 //中心食计算 if (Math.Abs(LunarHelper.rad2rrad(this.mCJ - this.sCJ)) < 50 / 180 * Math.PI) { ZB.line_earth(this.mCJ, this.mCW, this.mR, this.sCJ, this.sCW, this.sR * LunarHelper.cs_AU); this.zx_J = LunarHelper.rad2rrad(this.gst - ZB.le_J); this.zx_W = ZB.le_W; //无解返回值是100 } else { this.zx_J = this.zx_W = 100; } }