diff --git a/cxx/CMakeLists.txt b/cxx/CMakeLists.txt index 6771a1c..d83ec2d 100644 --- a/cxx/CMakeLists.txt +++ b/cxx/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.14) # set(CMAKE_BUILD_TYPE Release) -set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD 23) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake") @@ -122,7 +122,8 @@ add_library(${CNTR_PROTO_LIB} STATIC ${CNTR_PROTO_LIB_SRC}) set(MOUNT_SERVER_APP_SRC mount.h mount_state.h mount_server.cpp comm_server.h comm_server_endpoint.h comm_server_configfile.h mount_astrom.h mount_astrom_default.h) set(MOUNT_SERVER_APP mount_server) -add_executable(${MOUNT_SERVER_APP} ${MOUNT_SERVER_APP_SRC}) +add_executable(${MOUNT_SERVER_APP} ${MOUNT_SERVER_APP_SRC} + mcc_coord.h) # target_include_directories(${MOUNT_SERVER_APP} PUBLIC ${ERFA_INCLUDE_DIR}) target_link_libraries(${MOUNT_SERVER_APP} ${CNTR_PROTO_LIB} spdlog::spdlog_header_only ERFA_LIB) diff --git a/cxx/mcc_coord.h b/cxx/mcc_coord.h new file mode 100644 index 0000000..6e4a895 --- /dev/null +++ b/cxx/mcc_coord.h @@ -0,0 +1,189 @@ +#pragma once + +#include "mcc_traits.h" +#include "utils.h" + +namespace mcc +{ + +/* MCC-LIBRARY COORDINATES REPRESENTATION DEFINITIONS AND CLASS */ + +constexpr double operator""_rads(long double val) // angle in radians (no conversion) +{ + return val; +} + +constexpr double operator""_degs(long double val) // angle in degrees +{ + return val * std::numbers::pi / 180.0; +} + +constexpr double operator""_dms(const char* s, size_t size) // as a string "DEGREES:MINUTES:SECONDS" +{ + auto res = utils::parsAngleString(std::span{s, size}); + if (res.has_value()) { + return res.value() * std::numbers::pi / 180.0; + } else { + throw std::invalid_argument("invalid sexagesimal representation"); + } +} + +constexpr double operator""_hms(const char* s, size_t size) // as a string "HOURS:MINUTES:SECONDS" +{ + auto res = utils::parsAngleString(std::span{s, size}, true); + if (res.has_value()) { + return res.value() * std::numbers::pi / 180.0; + } else { + throw std::invalid_argument("invalid sexagesimal representation"); + } +} + + +// tags for MccCoordinate class construction + +struct MccRadianTag { +}; +struct MccDegreeTag { +}; +static constexpr MccDegreeTag mcc_degrees{}; +struct MccHMSTag { +}; +static constexpr MccHMSTag mcc_hms{}; + + +// coordinate representation class + +class MccCoordinate +{ + double _angleInRads{0.0}; + int _precision{2}; + +public: + MccCoordinate() = default; + + // by default angle is in radians + MccCoordinate(std::convertible_to auto const& val, const MccRadianTag tag = MccRadianTag{}) + : _angleInRads(val) + { + } + + // construct angle in degrees, e.g.: + // auto ang = MccCoordinate{180.0, mcc_degrees}; + MccCoordinate(std::convertible_to auto const& val, const MccDegreeTag tag) + { + _angleInRads = val * std::numbers::pi / 180.0; + } + + // constuct angle from sexagesimal representation, e.g.: + // auto ang = MccCoordinate{"-12:34:56.789"}; // from degrees:minutes:seconds + MccCoordinate(traits::mcc_input_char_range auto const& val) + { + auto res = utils::parsAngleString(val); + if (res.has_value()) { + _angleInRads = res.value() * std::numbers::pi / 180.0; + } else { + throw std::invalid_argument("invalid sexagesimal representation"); + } + } + + // construct angle from sexagesimal representation, e.g.: + // auto ang = MccCoordinate{"01:23:45.6789", mcc_hms}; // from hours:minutes:seconds + MccCoordinate(traits::mcc_input_char_range auto const& val, const MccHMSTag) + { + auto res = utils::parsAngleString(val, true); + if (res.has_value()) { + _angleInRads = res.value() * std::numbers::pi / 180.0; + } else { + throw std::invalid_argument("invalid sexagesimal representation"); + } + } + + operator double() const + { + return _angleInRads; + } + + template + T degrees() const + { + return _angleInRads * 180.0 / std::numbers::pi; + } + + double degrees() const + { + return degrees(); + } + + template + T sexagesimal(bool hms, int prec = 2) const + { + return utils::rad2sxg(_angleInRads, hms, prec >= 0 ? prec : _precision); + } + + std::string sexagesimal(bool hms, int prec = 2) const + { + return sexagesimal(hms, prec); + } + + friend MccCoordinate operator+(const MccCoordinate& left, const MccCoordinate& right) + { + return left._angleInRads + right._angleInRads; + } + + friend MccCoordinate operator-(const MccCoordinate& left, const MccCoordinate& right) + { + return left._angleInRads + right._angleInRads; + } + + template + MccCoordinate operator*(T&& scalar) + requires std::is_arithmetic_v> + { + return _angleInRads * scalar; + } + + template + MccCoordinate operator/(T&& scalar) + requires std::is_arithmetic_v> + { + return _angleInRads / scalar; + } + + template + MccCoordinate operator-() // unary '-' + requires std::is_arithmetic_v> + { + return -_angleInRads; + } + + MccCoordinate& operator+=(const MccCoordinate& v) + { + _angleInRads += v._angleInRads; + return *this; + } + + MccCoordinate& operator-=(const MccCoordinate& v) + { + _angleInRads += v._angleInRads; + return *this; + } + + template + MccCoordinate& operator*=(T&& scalar) + requires std::is_arithmetic_v> + { + _angleInRads *= scalar; + return *this; + } + + template + MccCoordinate& operator/=(T&& scalar) + requires std::is_arithmetic_v> + { + _angleInRads /= scalar; + return *this; + } +}; + + +} // namespace mcc diff --git a/cxx/mount.h b/cxx/mount.h index 44ca65a..1459422 100644 --- a/cxx/mount.h +++ b/cxx/mount.h @@ -10,6 +10,7 @@ #include #include "spdlog/sinks/null_sink.h" +#include "mcc_coord.h" #include "mcc_spdlog.h" #include "mcc_traits.h" #include "mount_astrom.h" @@ -45,6 +46,7 @@ concept mcc_mount_state_c = requires(T t, const T t_const) { } // namespace traits + /* SOME BASIC DATA STRUCTURES DEFINITIONS */ // meteo parameters (e.g. to compute refraction) @@ -195,32 +197,48 @@ public: _geoLocation.store(geoloc); } - void setSiteLatitude(auto const& lat) + void setSiteLatitude(const MccCoordinate& lat) { - auto v = utils::parsAngleString(lat); - if (v.has_value()) { - auto st = _geoLocation.load(); - st.latitude = v.value() * utils::deg2radCoeff; // to radians - logInfo("Set current site latitude to {} radians", st.latitude); - _geoLocation.store(st); - } else { - logError("Invalid user latitude value! Do not change the current value!"); - } + auto st = _geoLocation.load(); + st.latitude = lat; + logInfo("Set current site latitude to {} radians", st.latitude); + _geoLocation.store(st); } - void setSiteLongitude(auto const& lon) + void setSiteLongitude(const MccCoordinate& lon) { - auto v = utils::parsAngleString(lon); - if (v.has_value()) { - auto st = _geoLocation.load(); - st.longitude = v.value() * utils::deg2radCoeff; // to radians - logInfo("Set current site longitude to {} radians", st.longitude); - _geoLocation.store(st); - } else { - logError("Invalid user longitude value! Do not change the current value!"); - } + auto st = _geoLocation.load(); + st.longitude = lon; + logInfo("Set current site longitude to {} radians", st.longitude); + _geoLocation.store(st); } + // void setSiteLatitude(auto const& lat) + // { + // auto v = utils::parsAngleString(lat); + // if (v.has_value()) { + // auto st = _geoLocation.load(); + // st.latitude = v.value() * utils::deg2radCoeff; // to radians + // logInfo("Set current site latitude to {} radians", st.latitude); + // _geoLocation.store(st); + // } else { + // logError("Invalid user latitude value! Do not change the current value!"); + // } + // } + + // void setSiteLongitude(auto const& lon) + // { + // auto v = utils::parsAngleString(lon); + // if (v.has_value()) { + // auto st = _geoLocation.load(); + // st.longitude = v.value() * utils::deg2radCoeff; // to radians + // logInfo("Set current site longitude to {} radians", st.longitude); + // _geoLocation.store(st); + // } else { + // logError("Invalid user longitude value! Do not change the current value!"); + // } + // } + void setSiteElevation(MccMountSiteInfo::mnt_site_elev_t elev) { auto st = _geoLocation.load(); @@ -249,22 +267,34 @@ public: } - // prohibited zone related methods + /* prohibited zone related methods */ - bool pzCheck(traits::mcc_real_or_char_range auto const& xcoord, traits::mcc_real_or_char_range auto const& ycoord) + // returns a time to reach the prohibited area: + // 0 - already in the zone + // std::chrono::sys_time<>::max() - never reach the zone + // the kind of cordinates (e.g. IRCS or apparent, equatorial or horizontal) is a subject of implementation + auto pzTimeTo(const MccCoordinate& xcoord, + const MccCoordinate& ycoord, + traits::mcc_systime_c auto const& utc = std::chrono::system_clock::now()) { - return true; - } - - auto pzPredict(traits::mcc_systime_c auto const& time_point, - traits::mcc_real_or_char_range auto const& xcoord, - traits::mcc_real_or_char_range auto const& ycoord) - { - using d_t = std::remove_cvref_t::duration; + using d_t = std::remove_cvref_t::duration; return d_t::max(); } + // returns a time to exit the prohibited area: + // 0 - already out of the zone + // std::chrono::sys_time<>::max() - the zone itself + // the kind of cordinates (e.g. IRCS or apparent, equatorial or horizontal) is a subject of implementation + auto pzTimeFrom(const MccCoordinate& xcoord, + const MccCoordinate& ycoord, + traits::mcc_systime_c auto const& utc = std::chrono::system_clock::now()) + { + using d_t = std::remove_cvref_t::duration; + + return d_t{0}; + } + // IERS databases updater diff --git a/cxx/mount_state.h b/cxx/mount_state.h index 2effc3b..3c356b8 100644 --- a/cxx/mount_state.h +++ b/cxx/mount_state.h @@ -16,7 +16,7 @@ namespace mcc class MccMountAbstractState { - std::function _getMountStateFunc{[]() {}}; + std::function _getMountDataFunc{[]() {}}; public: typedef std::error_code mount_state_error_t; @@ -34,7 +34,7 @@ public: std::convertible_to auto&& exit_callback, std::convertible_to auto&& error_callback) { - _getMountStateFunc = [&mount_ptr, this]() { auto mstate = mount_ptr->getMountData(); }; + _getMountDataFunc = [&mount_ptr, this]() { auto mstate = mount_ptr->getMountData(); }; } @@ -43,7 +43,7 @@ public: std::string_view ident() const { - return "MCC-ABSTRACT-MOUNT-STATE"; + return "MCC-MOUNT-ABSTRACT-STATE"; } @@ -51,6 +51,12 @@ public: void exit() {} + // #ifdef __cpp_explicit_this_parameter + // #if __cpp_explicit_this_parameter >= 202110L + // void aaa() {} + // #endif + // #endif + protected: enter_callback_t _enterCallback{[](const mount_state_error_t&) {}}; exit_callback_t _exitCallback{[](const mount_state_error_t&) {}}; diff --git a/cxx/utils.h b/cxx/utils.h index 9076f4e..7ca2839 100644 --- a/cxx/utils.h +++ b/cxx/utils.h @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -147,6 +148,11 @@ static std::optional parsAngleString(R&& r, bool hms = false) return std::nullopt; } +static std::optional parsAngleString(const char* s, bool hms = false) +{ + return parsAngleString(std::span{s, std::strlen(s)}, hms); +} + static constexpr auto deg2radCoeff = std::numbers::pi / 180.0;