#pragma once /* MOUNT CONTROL COMPONENTS LIBRARY */ /* PROHIBITED ZONE IMPLEMENTATION */ #include #include #include "mcc_mount_coord.h" #include "mcc_traits.h" namespace mcc { class MccProhibitedZone { public: static constexpr MccCoordPairKind preferedCoordKind = MccCoordPairKind::COORDS_KIND_AZALT; // floating-point time duration (seconds) typedef std::chrono::duration pz_duration_t; struct pz_request_t { bool in_zone{false}; // true if given coordinates are within the zone pz_duration_t time_to{0.0}; // a time duration to reach the zone pz_duration_t time_from{0.0}; // a time duration to exit the zone }; virtual ~MccProhibitedZone() = default; std::string_view name() const { return _name; } // check if given position (x,y) in the zone template XT, std::derived_from YT> bool inZone(const XT&, const YT&, traits::mcc_systime_c auto const&) { return false; } // returns a time duration to reach the zone // 0 - if already within // Inf - if it never reaches the zone template XT, std::derived_from YT> pz_duration_t timeTo(const XT&, const YT&, traits::mcc_systime_c auto const&) { return pz_duration_t{std::numeric_limits::infinity()}; } // returns a time duration to exit from the zone // 0 - if given position (x,y) is out of the zone // Inf - if (x,y) is always within the zone template XT, std::derived_from YT> pz_duration_t timeFrom(const XT&, const YT&, traits::mcc_systime_c auto const&) { return pz_duration_t{0.0}; } // all-in-one request (call three methods above) template XT, std::derived_from YT> pz_request_t request(this auto&& self, const XT& x, const YT& y, traits::mcc_systime_c auto const& utc = std::chrono::system_clock::now()) { using self_t = decltype(self); pz_request_t res{.in_zone = false, .time_to = pz_duration_t{0.0}, .time_from{0.0}}; res.in_zone = std::forward(self).inZone(x, y, utc); if (res.in_zone) { res.time_from = std::forward(self).timeFrom(x, y, utc); } else { res.time_to = std::forward(self).timeTo(x, y, utc); } return res; } protected: MccProhibitedZone(std::string_view name) : _name(name) {} std::string_view _name; }; /* SOME PROHIBITED ZONE IMPLEMENTATIONS */ // minimal or maximal altitude prohibited zones enum class MccAltLimitKind { MIN_ALT_LIMIT, MAX_ALT_LIMIT }; template class MccAltLimitPZ : public MccProhibitedZone { public: static constexpr MccCoordPairKind preferedCoordKind = MccCoordPairKind::COORDS_KIND_AZALT; static constexpr MccAltLimitKind altLimitKind = KIND; // // TODO: add context (e.g. TT-TAI, UT1-UTC, geo location and so on)!!! MccAltLimitPZ(const MccAngle& alt_limit) : MccProhibitedZone(KIND == MccAltLimitKind::MIN_ALT_LIMIT ? "MINALT-ZONE" : KIND == MccAltLimitKind::MAX_ALT_LIMIT ? "MAXALT-ZONE" : "ALTLIMIT-UNKNOWN"), _altLimit(alt_limit) { _altLimit.normalize(); } template XT, std::derived_from YT> bool inZone(const XT& x, const YT& y, traits::mcc_systime_c auto const& utc = std::chrono::system_clock::now()) { static constexpr MccCoordPairKind coord_kind = traits::mcc_type_pair_hash(); if constexpr (coord_kind == MccCoordPairKind::COORDS_KIND_AZALT) { // trivial case if constexpr (KIND == MccAltLimitKind::MIN_ALT_LIMIT) { return y <= _altLimit; } else if constexpr (KIND == MccAltLimitKind::MAX_ALT_LIMIT) { return y >= _altLimit; } } else if constexpr (coord_kind == MccCoordPairKind::COORDS_KIND_AZZD) { // trivial case return inZone(x, MccAngleALT(std::numbers::pi / 2 - (double)y), utc); } else if constexpr (coord_kind == MccCoordPairKind::COORDS_KIND_HADEC_APP) { // implementation ... return false; } else if constexpr (coord_kind == MccCoordPairKind::COORDS_KIND_RADEC_APP) { // implementation ... return false; } else { throw std::system_error(std::make_error_code(std::errc::operation_not_supported)); } return false; } template XT, std::derived_from YT> pz_duration_t timeTo(const XT& x, const YT& y, traits::mcc_systime_c auto const& utc = std::chrono::system_clock::now()) { return pz_duration_t{std::numeric_limits::infinity()}; } template XT, std::derived_from YT> pz_duration_t timeFrom(const XT& x, const YT& y, traits::mcc_systime_c auto const& utc = std::chrono::system_clock::now()) { return pz_duration_t{0.0}; } private: MccAngle _altLimit; }; } // namespace mcc