...
This commit is contained in:
@@ -14,6 +14,12 @@
|
||||
#include "mount_astrom_default.h"
|
||||
#include "utils.h"
|
||||
|
||||
namespace erfa
|
||||
{
|
||||
#include <erfa.h>
|
||||
#include <erfam.h>
|
||||
} // namespace erfa
|
||||
|
||||
namespace mcc::traits
|
||||
{
|
||||
|
||||
@@ -36,6 +42,14 @@ concept mcc_real_or_char_range =
|
||||
namespace mcc::astrom
|
||||
{
|
||||
|
||||
// a time duration represented in radians (the precision is near 1 nanosecond)
|
||||
// typedef std::chrono::duration<double, std::ratio<134670467, 10000000000000000>> mcc_radsec_duration_t;
|
||||
typedef std::chrono::duration<double, std::ratio<134670467, 10000000000000000>> mcc_chrono_radians;
|
||||
|
||||
|
||||
// https://gssc.esa.int/navipedia/index.php?title=CEP_to_ITRF
|
||||
static constexpr double mcc_UT1_to_sideral_ratio = 1.002737909350795; // UT1/sideral
|
||||
|
||||
|
||||
// modified Julian date (based on ERFA eraCal2jd)
|
||||
template <traits::mcc_real_scalar_or_real_range_c ResT>
|
||||
@@ -132,24 +146,34 @@ static int mcc_julday(const std::chrono::system_clock::time_point& start_time,
|
||||
|
||||
/*
|
||||
* angles are in degrees or sexagimal string form
|
||||
* RA and DEC are apparent!
|
||||
*
|
||||
* returns
|
||||
* NaN if object is non-rising or "alt_limit" < 0, Inf is circumpolar
|
||||
*/
|
||||
template <traits::mcc_real_or_char_range AT,
|
||||
traits::mcc_real_or_char_range RT,
|
||||
traits::mcc_real_or_char_range DT,
|
||||
traits::mcc_real_or_char_range LT>
|
||||
double mcc_time_to_alt_limit(const AT& alt_limit,
|
||||
const RT& RA,
|
||||
const DT& DEC,
|
||||
const LT& LAT,
|
||||
const std::chrono::system_clock::time_point& now)
|
||||
|
||||
double mcc_time_to_alt_limit(traits::mcc_real_or_char_range auto const& alt_limit,
|
||||
traits::mcc_real_or_char_range auto const& RA,
|
||||
traits::mcc_real_or_char_range auto const& DEC,
|
||||
traits::mcc_real_or_char_range auto const& LAT,
|
||||
traits::mcc_real_or_char_range auto const& LON,
|
||||
const std::chrono::system_clock::time_point& now,
|
||||
traits::mcc_time_duration_c auto const& dut1, // UT1-UTC
|
||||
traits::mcc_time_duration_c auto const& tt_tai, // TT-TAI
|
||||
// TAI-UTC (leap seconds)
|
||||
traits::mcc_time_duration_c auto const& tai_utc)
|
||||
{
|
||||
// sin(alt) = sin(DEC)*sin(phi) + cos(DEC)*cos(phi)*cos(HA)
|
||||
// HA = LST - RA
|
||||
// cos(HA) = cos(LST)*cos(RA) + sin(LST)*sin(RA)
|
||||
|
||||
double ra, dec, lat, alt;
|
||||
using AT = std::decay_t<decltype(alt_limit)>;
|
||||
using RT = std::decay_t<decltype(RA)>;
|
||||
using DT = std::decay_t<decltype(DEC)>;
|
||||
using LT = std::decay_t<decltype(LAT)>;
|
||||
using LGT = std::decay_t<decltype(LON)>;
|
||||
|
||||
double ra, dec, lat, lon, alt;
|
||||
|
||||
if constexpr (std::floating_point<AT>) {
|
||||
alt = alt_limit * utils::deg2radCoeff;
|
||||
@@ -183,25 +207,53 @@ double mcc_time_to_alt_limit(const AT& alt_limit,
|
||||
lat *= utils::deg2radCoeff;
|
||||
}
|
||||
|
||||
if constexpr (std::floating_point<LGT>) {
|
||||
lon = LON * utils::deg2radCoeff;
|
||||
} else {
|
||||
lon = utils::parsAngleString(LON);
|
||||
lon *= utils::deg2radCoeff;
|
||||
}
|
||||
|
||||
if (lat >= 0.0) { // north hemisphere
|
||||
if (dec < (lat - std::numbers::pi / 2.0)) { // never rises above horizont
|
||||
if (dec < (lat - std::numbers::pi / 2.0)) { // never rises above horizon
|
||||
return std::numeric_limits<double>::quiet_NaN();
|
||||
}
|
||||
} else { // south hemisphere
|
||||
if (dec > (lat + std::numbers::pi / 2.0)) { // never rises above horizont
|
||||
if (dec > (lat + std::numbers::pi / 2.0)) { // never rises above horizon
|
||||
return std::numeric_limits<double>::quiet_NaN();
|
||||
}
|
||||
}
|
||||
|
||||
double cos_ha = (std::sin(alt) - std::sin(dec) * std::sin(lat)) / std::cos(dec) / std::cos(lat);
|
||||
if (std::abs(cos_ha) > 1.0) { // circumpolar (it never sets below horizon)
|
||||
if (std::abs(cos_ha) > 1.0) { // it never sets below given altitude
|
||||
return std::numeric_limits<double>::infinity();
|
||||
}
|
||||
|
||||
double lst = std::acos(cos_ha) + ra;
|
||||
|
||||
auto ut1 = now + dut1;
|
||||
auto tt = now + tai_utc + tt_tai;
|
||||
|
||||
return 0.0;
|
||||
double ut1_mjd, tt_mjd, result;
|
||||
int ret = mcc_julday(ut1, ut1_mjd);
|
||||
if (ret) {
|
||||
return std::numeric_limits<double>::quiet_NaN();
|
||||
}
|
||||
ret = mcc_julday(tt, tt_mjd);
|
||||
if (ret) {
|
||||
return std::numeric_limits<double>::quiet_NaN();
|
||||
}
|
||||
|
||||
double lst_now = erfa::eraGst06a(ERFA_DJM0, ut1_mjd, ERFA_DJM0, tt_mjd) + lon;
|
||||
|
||||
result = lst - lst_now;
|
||||
if (result < 0.0) { // the next sideral day
|
||||
result += 2.0 * std::numbers::pi;
|
||||
}
|
||||
|
||||
result *= mcc_UT1_to_sideral_ratio; // to UT1 scale
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -218,6 +270,7 @@ class MccLeapSeconds final
|
||||
{
|
||||
public:
|
||||
typedef std::chrono::system_clock::time_point time_point_t;
|
||||
typedef std::chrono::duration<double> real_secs_t; // seconds duration in double
|
||||
|
||||
MccLeapSeconds()
|
||||
{
|
||||
@@ -308,7 +361,8 @@ public:
|
||||
}
|
||||
|
||||
|
||||
std::optional<double> operator[](const time_point_t& tp) const
|
||||
// std::optional<double> operator[](const time_point_t& tp) const
|
||||
std::optional<real_secs_t> operator[](const time_point_t& tp) const
|
||||
{
|
||||
if (tp > _expireDate) { // ???????!!!!!!!!!!!
|
||||
return std::nullopt;
|
||||
@@ -319,14 +373,16 @@ public:
|
||||
|
||||
for (auto const& el : _db | std::views::reverse) {
|
||||
if (ymd >= el.ymd) {
|
||||
return el.tai_utc;
|
||||
// return el.tai_utc;
|
||||
return real_secs_t{el.tai_utc};
|
||||
}
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<double> operator[](const double& mjd) const
|
||||
// std::optional<double> operator[](const double& mjd) const
|
||||
std::optional<real_secs_t> operator[](const double& mjd) const
|
||||
{
|
||||
double e_mjd;
|
||||
|
||||
@@ -338,7 +394,7 @@ public:
|
||||
|
||||
for (auto const& el : _db | std::views::reverse) {
|
||||
if (mjd >= el.mjd) {
|
||||
return el.tai_utc;
|
||||
return real_secs_t{el.tai_utc};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -379,6 +435,7 @@ class MccIersBulletinA final
|
||||
{
|
||||
public:
|
||||
typedef std::chrono::system_clock::time_point time_point_t;
|
||||
typedef std::chrono::duration<double> real_secs_t; // seconds duration in double
|
||||
|
||||
struct pole_pos_t {
|
||||
double x, y;
|
||||
@@ -421,13 +478,15 @@ public:
|
||||
}
|
||||
|
||||
|
||||
double TT_TAI() const
|
||||
// double TT_TAI() const
|
||||
real_secs_t TT_TAI() const
|
||||
{
|
||||
return _tt_tai;
|
||||
return real_secs_t{_tt_tai};
|
||||
}
|
||||
|
||||
// DUT1 = UT1 - UTC
|
||||
std::optional<double> DUT1(const time_point_t& tp) const
|
||||
// std::optional<double> DUT1(const time_point_t& tp) const
|
||||
std::optional<real_secs_t> DUT1(const time_point_t& tp) const
|
||||
{
|
||||
// use of the closest date
|
||||
std::chrono::year_month_day ymd{std::chrono::round<std::chrono::days>(tp)};
|
||||
@@ -443,14 +502,15 @@ public:
|
||||
auto el_prev = _db.front();
|
||||
for (auto const& el : _db) {
|
||||
if (ymd <= el.ymd) {
|
||||
return el.dut1;
|
||||
return real_secs_t{el.dut1};
|
||||
}
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<double> DUT1(double mjd) const
|
||||
// std::optional<double> DUT1(double mjd) const
|
||||
std::optional<real_secs_t> DUT1(double mjd) const
|
||||
{
|
||||
mjd = std::round(mjd); // round to closest integer MJD
|
||||
|
||||
@@ -464,7 +524,7 @@ public:
|
||||
|
||||
for (auto const& el : _db) {
|
||||
if (mjd <= el.mjd) {
|
||||
return el.dut1;
|
||||
return real_secs_t{el.dut1};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user