在天文学上,地方恒星时就是观测地的中天赤经坐标。在天文望远镜自动寻星系统中,地方恒星时是系统解算赤道仪姿态的重要依据,通过计算赤道仪的中天位置赤经坐标,自动寻星控制系统可以得知天文望远镜指向的方位角和高度角,从而得知赤道仪自动寻星路线和模式,还可以在导星时判断赤道仪中天翻转的时机,当观测天体越过中天时即进行中天翻转。以下代码可以较为准确的计算观测地的地方恒星时,利用Visual Studio 2019 C++编写,读者可下载天文通或者其他星图软件验证程序计算当地恒星时的准确性。
头文件:Time_Conversioner.h
#pragma once
#include<iostream>
#include<cmath>
class Angle_To_Time
{
public:
int Hour;
int Min;
int Sec;
/*显示时、分、秒单位制下的赤经坐标*/
void Printf_(){
std::cout << Hour << " h " << Min << " min " << Sec << " sec " << std::endl;
}
};
class Time_Conversioner
{
public:
/*得到地方恒星时,输出的是角度坐标表示*/
double Sidereal_time();
/*得到地方恒星时,输出的是赤径的时、分、秒坐标表示*/
Angle_To_Time RA_Zenith();
/*得到纬度*/
double Get_Altitude();
/** @brief 将赤经坐标转换为角度,1小时=15°,1分=0.25度,1秒=0.25/60度。
@param Hour_ 赤经小时
@param Min_ 赤经分钟
@param Sec_ 赤经秒
*/
double Time2Angle(double Hour_, double Min_, double Sec_);
/** @brief 将不在0~360°区间内的角度通过加减360°让其进入这个区间
@param Input_angle 需要转换的角度
*/
double Angle_in_0_360(double Input_angle);
/** @brief 设置当前观测地的经度、纬度
@param latitude 经度
@param altitude 纬度
*/
void set_observation_place(double latitude, double altitude);
private:
double latitude = 110;//经度
double altitude = 30;//纬度
double Date_Now;
double Mouth_Now;
double Year_Now;
double Hour_Now;
double Min_Now;
double Second_Now;
struct tm* ptminfo;
time_t rawtime;
Angle_To_Time Get_RA;
double Get_Year();
double Get_Mouth();
double Get_Date();
double Get_Hour();
double Get_Min();
double Get_Sec();
void Time_Update();
double JD_time();
/*0h UT平恒星时*/
double Sidereal_time_0_UT();
Angle_To_Time Angle2Time(double Input_Angle);
};
源文件:Time_Conversioner.cpp
#define _CRT_SECURE_NO_WARNINGS 1
#include"Time_Conversioner.h"
Angle_To_Time Time_Conversioner::RA_Zenith()
{
Angle_To_Time OUTPUT;
OUTPUT = Angle2Time(Sidereal_time());
return OUTPUT;
}
double Time_Conversioner::Get_Altitude() {
return this->altitude;
}
void Time_Conversioner::set_observation_place(double latitude, double altitude) {
this->latitude = latitude;
this->altitude = altitude;
}
double Time_Conversioner::JD_time(){
Time_Update();
double JD = 0;
double Mouth_Now_ = Mouth_Now;
double Year_Now_ = Year_Now;
double Date_Now_ = Date_Now;
if (Mouth_Now_ == 1 || Mouth_Now_ == 2){
Mouth_Now_ += 12;
Year_Now_ -= 1;
}
JD = floor(abs(365.25 * (Year_Now_ + 4716.0))) + floor(abs(30.6001 * (Mouth_Now_ + 1))) + \
2 - floor(Year_Now_ / 100.0) + floor(floor(Year_Now_ / 100.0) * 0.25) + Date_Now_ - 1524.5;
return JD;
}
double Time_Conversioner::Sidereal_time_0_UT(){
//求得的是角度值
double JD = 0;
double T = 0;
double ST = 0;
JD = JD_time();
T = (JD - 2451545.0) / 36525;
ST = 100.46061837 + 36000.770053608 * T + 0.000387933 * T * T - T * T * T / 38710000;
if (ST < 0 || ST>360){
if (ST < 0){
while (ST<0){
ST += 360;
}
}
else if(ST>360){
while (ST>360){
ST -= 360;
}
}
}
return ST;
}
double Time_Conversioner::Sidereal_time(){
double ST_UT0 = Sidereal_time_0_UT();
double m_ = Time2Angle(Hour_Now, Min_Now, Second_Now) + (latitude - 8.0 / 24.0 * 360);
double M_ = m_ - latitude;
double Mu = M_ / 365.2422;
double OUTPUT;
OUTPUT = m_ + ST_UT0 + Mu;
if (OUTPUT > 360.0){
while (OUTPUT>360.0){
OUTPUT -= 360.0;
}
}
if (OUTPUT < 0.0){
while (OUTPUT<0.0){
OUTPUT += 360.0;
}
}
return OUTPUT;
}
double Time_Conversioner::Get_Mouth(){
double MOUTH_ = 0;
MOUTH_ = double(ptminfo->tm_mon + 1.0);
return MOUTH_;
}
double Time_Conversioner::Get_Date(){
double DATE_;
DATE_ = double(ptminfo->tm_mday);
return DATE_;
}
double Time_Conversioner::Get_Year(){
double YEAR_;
YEAR_ = double(ptminfo->tm_year + 1900.0);
return YEAR_;
}
double Time_Conversioner::Get_Hour(){
double HOUR_;
HOUR_ = double(ptminfo->tm_hour);
return HOUR_;
}
double Time_Conversioner::Get_Min(){
double MIN_;
MIN_ = double(ptminfo->tm_min);
return MIN_;
}
double Time_Conversioner::Get_Sec(){
double SEC_;
SEC_ = double(ptminfo->tm_sec);
return SEC_;
}
void Time_Conversioner::Time_Update(){
time(&rawtime);
ptminfo = localtime(&rawtime);
Date_Now = Get_Date();
Mouth_Now = Get_Mouth();
Year_Now = Get_Year();
Hour_Now = Get_Hour();
Min_Now = Get_Min();
Second_Now = Get_Sec();
//std::cout << Year_Now << " " << Mouth_Now << " " << Date_Now << " " << Hour_Now << " " << Min_Now << " " << Second_Now << std::endl;
}
double Time_Conversioner::Time2Angle(double Hour_, double Min_, double Sec_){
return Hour_ / 24.0 * 360.0 + Min_ / (24.0 * 60.0) * 360.0 + Sec_ / (24.0 * 60.0 * 60.0) * 360.0;
}
double Time_Conversioner::Angle_in_0_360(double Input_angle){
double OUTPUT = Input_angle;
if (OUTPUT > 360.0){
while (OUTPUT > 360.0){
OUTPUT -= 360.0;
}
}
else if (OUTPUT < 0){
while (OUTPUT<0){
OUTPUT += 360.0;
}
}
return OUTPUT;
}
Angle_To_Time Time_Conversioner::Angle2Time(double Input_Angle){
Angle_To_Time OUTPUT;
int Hour_;
int Min_;
int Sec_;
double Angle = Input_Angle;
Hour_ = floor(Angle / 15.0);
Angle = Angle - Hour_ * 15.0;
Min_ = floor(Angle / (0.25));
Angle = Angle - Min_ * 0.25;
Sec_ = floor(Angle / (0.25 / 60));
OUTPUT.Hour = Hour_;
OUTPUT.Min = Min_;
OUTPUT.Sec = Sec_;
Get_RA = OUTPUT;
return OUTPUT;
}
示例代码:
void main()
{
Time_Conversioner Timer;
Timer.set_observation_place(102, 26);//设置观测地经度、纬度
while (1){
Timer.RA_Zenith().Printf_();//打印当前的当地恒星时,该值每秒更新一次
Sleep(1000);
}
}
运行结果: