diff --git a/cxx/CMakeLists.txt b/cxx/CMakeLists.txt index a23af11..6771a1c 100644 --- a/cxx/CMakeLists.txt +++ b/cxx/CMakeLists.txt @@ -79,7 +79,7 @@ endif() # ERFA library include(ExternalProject) -ExternalProject_Add(erfa_lib +ExternalProject_Add(erfalib PREFIX ${CMAKE_BINARY_DIR}/erfa_lib GIT_REPOSITORY "https://github.com/liberfa/erfa.git" GIT_TAG "v2.0.1" @@ -89,13 +89,17 @@ ExternalProject_Add(erfa_lib # SOURCE_DIR erfa # INSTALL_DIR LOG_CONFIGURE 1 - CONFIGURE_COMMAND meson setup --reconfigure -Ddefault_library=static -Dbuildtype=release -Dc_args='-march=native' -Doptimization=3 + CONFIGURE_COMMAND meson setup --reconfigure -Ddefault_library=static -Dbuildtype=release -Dprefix=${CMAKE_BINARY_DIR}/erfa_lib -Dlibdir= -Dincludedir= -Ddatadir= + # CONFIGURE_COMMAND meson setup --reconfigure -Ddefault_library=static -Dbuildtype=release -Dc_args='-march=native' -Doptimization=3 + # -Dprefix=${CMAKE_BINARY_DIR}/erfa_lib -Dlibdir= -Dincludedir= -Ddatadir= BUILD_COMMAND ninja -C INSTALL_COMMAND meson install -C + BUILD_BYPRODUCTS ${CMAKE_BINARY_DIR}/erfa_lib/liberfa.a ) add_library(ERFA_LIB STATIC IMPORTED) set_target_properties(ERFA_LIB PROPERTIES IMPORTED_LOCATION ${CMAKE_BINARY_DIR}/erfa_lib/liberfa.a) +add_dependencies(ERFA_LIB erfalib) set(ERFA_INCLUDE_DIR ${CMAKE_BINARY_DIR}/erfa_lib) include_directories(${ERFA_INCLUDE_DIR}) diff --git a/cxx/mcc_traits.h b/cxx/mcc_traits.h index 4cb910d..5369df9 100644 --- a/cxx/mcc_traits.h +++ b/cxx/mcc_traits.h @@ -39,8 +39,8 @@ concept mcc_formattable = requires(T v, std::format_context ctx) { std::formatter>().format(v, ctx); }; -template // from https://stackoverflow.com/questions/74383254/concept-that-models-only-the-stdchrono-duration-types +template concept mcc_time_duration_c = requires { [](std::type_identity>) { @@ -48,6 +48,12 @@ concept mcc_time_duration_c = requires { }; +template +concept mcc_systime_c = requires { + [](std::type_identity>) {}(std::type_identity>()); +}; + + /* a callable concept and its signature traits */ template diff --git a/cxx/mount_astrom.h b/cxx/mount_astrom.h index 93dfea3..8e9eac5 100644 --- a/cxx/mount_astrom.h +++ b/cxx/mount_astrom.h @@ -51,10 +51,10 @@ static constexpr double mcc_UT1_to_sideral_ratio = 1.002737909350795; // UT1/si // modified Julian date (based on ERFA eraCal2jd) -template -static int mcc_julday(const std::chrono::system_clock::time_point& start_time, +template +static int mcc_julday(traits::mcc_systime_c auto const& start_time, ResT& mjd, - const std::chrono::system_clock::duration& step = std::chrono::milliseconds(100)) + const DT& step = std::chrono::milliseconds(100)) { size_t mjd_size = 0; if constexpr (std::ranges::range) { @@ -124,7 +124,7 @@ static int mcc_julday(const std::chrono::system_clock::time_point& start_time, if constexpr (std::ranges::random_access_range) { ptr += reg_size; } else { - for (int k = 0; k < reg_size; ++k) { + for (size_t k = 0; k < reg_size; ++k) { ++ptr; } } @@ -156,7 +156,7 @@ double mcc_time_to_alt_limit(traits::mcc_real_or_char_range auto const& alt_limi 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_systime_c auto const& 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) @@ -166,51 +166,58 @@ double mcc_time_to_alt_limit(traits::mcc_real_or_char_range auto const& alt_limi // HA = LST - RA // cos(HA) = cos(LST)*cos(RA) + sin(LST)*sin(RA) - using AT = std::decay_t; - using RT = std::decay_t; - using DT = std::decay_t; - using LT = std::decay_t; - using LGT = std::decay_t; + // using AT = std::decay_t; + // using RT = std::decay_t; + // using DT = std::decay_t; + // using LT = std::decay_t; + // using LGT = std::decay_t; double ra, dec, lat, lon, alt; - if constexpr (std::floating_point) { - alt = alt_limit * utils::deg2radCoeff; - } else { - alt = utils::parsAngleString(alt_limit); - alt *= utils::deg2radCoeff; + auto to_rads = [](const auto& v, bool hms = false) { + // using v_t = std::remove_cvref; + using v_t = std::remove_cvref_t; + double res; + if constexpr (!std::floating_point) { + res = utils::parsAngleString(v, hms).value_or(std::numeric_limits::quiet_NaN()); + } else { + res = v; + } + + if (!std::isfinite(res)) { + return res; + } + + return res * utils::deg2radCoeff; + }; + + alt = to_rads(alt_limit); + if (!std::isfinite(alt)) { + return alt; } if (alt < 0.0) { return std::numeric_limits::quiet_NaN(); } - if constexpr (std::floating_point) { - ra = RA * utils::deg2radCoeff; - } else { - ra = utils::parsAngleString(RA, true); - ra *= utils::deg2radCoeff; + ra = to_rads(RA, true); + if (!std::isfinite(ra)) { + return ra; } - if constexpr (std::floating_point
) { - dec = DEC * utils::deg2radCoeff; - } else { - dec = utils::parsAngleString(DEC); - dec *= utils::deg2radCoeff; + dec = to_rads(DEC); + if (!std::isfinite(dec)) { + return dec; } - if constexpr (std::floating_point) { - lat = LAT * utils::deg2radCoeff; - } else { - lat = utils::parsAngleString(LAT); - lat *= utils::deg2radCoeff; + lat = to_rads(LAT); + if (!std::isfinite(lat)) { + return lat; } - if constexpr (std::floating_point) { - lon = LON * utils::deg2radCoeff; - } else { - lon = utils::parsAngleString(LON); - lon *= utils::deg2radCoeff; + lon = to_rads(LON); + if (!std::isfinite(lon)) { + return lon; } if (lat >= 0.0) { // north hemisphere @@ -243,13 +250,18 @@ double mcc_time_to_alt_limit(traits::mcc_real_or_char_range auto const& alt_limi return std::numeric_limits::quiet_NaN(); } - double lst_now = erfa::eraGst06a(ERFA_DJM0, ut1_mjd, ERFA_DJM0, tt_mjd) + lon; + double lst_now = erfa::eraGst06a(ERFA_DJM0, ut1_mjd, ERFA_DJM0, tt_mjd); + lst_now += lon; result = lst - lst_now; if (result < 0.0) { // the next sideral day result += 2.0 * std::numbers::pi; } + if (result > std::numbers::pi) { // object is already below the limit + return 0.0; + } + result *= mcc_UT1_to_sideral_ratio; // to UT1 scale return result; @@ -498,7 +510,6 @@ public: return std::nullopt; } - auto el_prev = _db.front(); for (auto const& el : _db) { if (ymd <= el.ymd) { return real_secs_t{el.dut1}; diff --git a/cxx/tests/astrom_test.cpp b/cxx/tests/astrom_test.cpp index b897579..53b0c37 100644 --- a/cxx/tests/astrom_test.cpp +++ b/cxx/tests/astrom_test.cpp @@ -68,6 +68,12 @@ int main(int argc, char* argv[]) // const double rr = 180.0 / std::numbers::pi * 60.0; // std::cout << "A(arcmin) = " << A * rr << "; B(arcmin) = " << B * rr << "\n"; + using namespace std::chrono_literals; + double stm = mcc::astrom::mcc_time_to_alt_limit(10.0, "06:30:00.0", "00:00:00.0", 43.646711, 41.440732, + std::chrono::system_clock::now(), 0.041s, 32.184s, 37.0s); + + // auto stm_d = mcc::astrom::mcc_chrono_radians{stm}; + std::cout << "STM: " << stm * 12.0 / std::numbers::pi * 60.0 << " minutes\n"; return ecode; } diff --git a/cxx/utils.h b/cxx/utils.h index 1b0c27f..9076f4e 100644 --- a/cxx/utils.h +++ b/cxx/utils.h @@ -49,6 +49,10 @@ static std::string_view trimSpaces(R&& r, TrimType type = TrimType::TRIM_BOTH) return std::string_view(f1, f2); } +static std::string_view trimSpaces(const char* r, TrimType type = TrimType::TRIM_BOTH) +{ + return trimSpaces(std::string_view(r), type); +} template std::optional numFromStr(R&& r)