#pragma once /* MOUNT CONTROL COMPONENTS LIBRARY */ /* IMPLEMENTATION OF PROHIBITED ZONES CONTAINER */ #include "mcc_defaults.h" namespace mcc { enum class MccPZoneContainerErrorCode : int { ERROR_OK, ERROR_NULLPTR, ERROR_INVALID_SIZE, ERROR_INZONE_FUNC, ERROR_TIMETO_FUNC, ERROR_TIMEFROM_FUNC, ERROR_INTERSECT_FUNC }; } // namespace mcc namespace std { template <> class is_error_code_enum : public true_type { }; } // namespace std namespace mcc { /* error category definition */ // error category struct MccPZoneContainerCategory : public std::error_category { MccPZoneContainerCategory() : std::error_category() {} const char* name() const noexcept { return "ALTITUDE-LIMIT-PZ"; } std::string message(int ec) const { MccPZoneContainerErrorCode err = static_cast(ec); switch (err) { case MccPZoneContainerErrorCode::ERROR_OK: return "OK"; case MccPZoneContainerErrorCode::ERROR_NULLPTR: return "nullptr argument"; case MccPZoneContainerErrorCode::ERROR_INVALID_SIZE: return "invalid range size of input argument"; case MccPZoneContainerErrorCode::ERROR_INZONE_FUNC: return "inPZone method error"; case MccPZoneContainerErrorCode::ERROR_TIMETO_FUNC: return "timeToPZone method error"; case MccPZoneContainerErrorCode::ERROR_TIMEFROM_FUNC: return "timeFromPZone method error"; case MccPZoneContainerErrorCode::ERROR_INTERSECT_FUNC: return "intersectPZone method error"; default: return "UNKNOWN"; } } static const MccPZoneContainerCategory& get() { static const MccPZoneContainerCategory constInst; return constInst; } }; inline std::error_code make_error_code(MccPZoneContainerErrorCode ec) { return std::error_code(static_cast(ec), MccPZoneContainerCategory::get()); } template class MccPZoneContainer : public mcc_pzone_container_interface_t { public: typedef std::error_code error_t; typedef DurT duration_t; MccPZoneContainer() = default; MccPZoneContainer(MccPZoneContainer&&) = default; MccPZoneContainer(const MccPZoneContainer&) = default; MccPZoneContainer& operator=(MccPZoneContainer&&) = default; MccPZoneContainer& operator=(const MccPZoneContainer&) = default; virtual ~MccPZoneContainer() = default; size_t addPZone(mcc_prohibited_zone_c auto zone) { auto sptr = std::make_shared(std::move(zone)); _inZoneFuncCPT.emplace_back([sptr](const MccCelestialPoint& pt, bool* res) -> error_t { auto ret = sptr->inPZone(pt, res); if (ret) { return mcc_deduce_error_code(ret, MccPZoneContainerErrorCode::ERROR_INZONE_FUNC); } return mcc_deduce_error_code(ret, MccPZoneContainerErrorCode::ERROR_OK); }); _inZoneFuncEHC.emplace_back([sptr](const MccEqtHrzCoords& pt, bool* res) -> error_t { auto ret = sptr->inPZone(pt, res); if (ret) { return mcc_deduce_error_code(ret, MccPZoneContainerErrorCode::ERROR_INZONE_FUNC); } return MccPZoneContainerErrorCode::ERROR_OK; }); _timeToZoneFuncCPT.emplace_back([sptr](const MccCelestialPoint& pt, duration_t* res_time) -> error_t { auto ret = sptr->timeToPZone(pt, res_time); if (ret) { return mcc_deduce_error_code(ret, MccPZoneContainerErrorCode::ERROR_TIMETO_FUNC); } return MccPZoneContainerErrorCode::ERROR_OK; }); _timeToZoneFuncEHC.emplace_back([sptr](const MccEqtHrzCoords& pt, duration_t* res_time) -> error_t { auto ret = sptr->timeToPZone(pt, res_time); if (ret) { return mcc_deduce_error_code(ret, MccPZoneContainerErrorCode::ERROR_TIMETO_FUNC); } return MccPZoneContainerErrorCode::ERROR_OK; }); _timeFromZoneFuncCPT.emplace_back([sptr](const MccCelestialPoint& pt, duration_t* res_time) -> error_t { auto ret = sptr->timeFromPZone(pt, res_time); if (ret) { return mcc_deduce_error_code(ret, MccPZoneContainerErrorCode::ERROR_TIMEFROM_FUNC); } return MccPZoneContainerErrorCode::ERROR_OK; }); _timeFromZoneFuncEHC.emplace_back([sptr](const MccEqtHrzCoords& pt, duration_t* res_time) -> error_t { auto ret = sptr->timeFromPZone(pt, res_time); if (ret) { return mcc_deduce_error_code(ret, MccPZoneContainerErrorCode::ERROR_TIMEFROM_FUNC); } return MccPZoneContainerErrorCode::ERROR_OK; }); // _intersectZoneFuncCPT.emplace_back([sptr](const MccCelestialPoint& pt, MccCelestialPoint* res_pt) { // auto ret = sptr->intersectPZone(pt, res_pt); // return mcc_deduce_error_code(ret, // mcc::make_error_code(MccPZoneContainerErrorCode::ERROR_INTERSECT_FUNC)); // }); // _intersectZoneFuncEHC.emplace_back([sptr](const MccEqtHrzCoords& pt, MccCelestialPoint* res_pt) { // auto ret = sptr->intersectPZone(pt, res_pt); // return mcc_deduce_error_code(ret, // mcc::make_error_code(MccPZoneContainerErrorCode::ERROR_INTERSECT_FUNC)); // }); _intersectZoneFuncCPT2CPT.emplace_back( [sptr](const MccCelestialPoint& pt, MccCelestialPoint* res_pt) -> error_t { auto ret = sptr->intersectPZone(pt, res_pt); if (ret) { return mcc_deduce_error_code(ret, MccPZoneContainerErrorCode::ERROR_INTERSECT_FUNC); } return MccPZoneContainerErrorCode::ERROR_OK; }); _intersectZoneFuncEHC2CPT.emplace_back([sptr](const MccEqtHrzCoords& pt, MccCelestialPoint* res_pt) -> error_t { auto ret = sptr->intersectPZone(pt, res_pt); if (ret) { return mcc_deduce_error_code(ret, MccPZoneContainerErrorCode::ERROR_INTERSECT_FUNC); } return MccPZoneContainerErrorCode::ERROR_OK; }); _intersectZoneFuncCPT2EHC.emplace_back([sptr](const MccCelestialPoint& pt, MccEqtHrzCoords* res_pt) -> error_t { auto ret = sptr->intersectPZone(pt, res_pt); if (ret) { return mcc_deduce_error_code(ret, MccPZoneContainerErrorCode::ERROR_INTERSECT_FUNC); } return MccPZoneContainerErrorCode::ERROR_OK; }); _intersectZoneFuncEHC2EHC.emplace_back([sptr](const MccEqtHrzCoords& pt, MccEqtHrzCoords* res_pt) -> error_t { auto ret = sptr->intersectPZone(pt, res_pt); if (ret) { return mcc_deduce_error_code(ret, MccPZoneContainerErrorCode::ERROR_INTERSECT_FUNC); } return MccPZoneContainerErrorCode::ERROR_OK; }); return _inZoneFuncCPT.size(); } void clearPZones() { _inZoneFuncCPT.clear(); _inZoneFuncEHC.clear(); _timeToZoneFuncCPT.clear(); _timeToZoneFuncEHC.clear(); _timeFromZoneFuncCPT.clear(); _timeFromZoneFuncEHC.clear(); // _intersectZoneFuncCPT.clear(); // _intersectZoneFuncEHC.clear(); _intersectZoneFuncCPT2CPT.clear(); _intersectZoneFuncEHC2CPT.clear(); _intersectZoneFuncCPT2EHC.clear(); _intersectZoneFuncEHC2EHC.clear(); } size_t sizePZones() const { return _inZoneFuncCPT.size(); } template error_t inPZone(InputT coords, bool* common_result, std::ranges::output_range auto* result = nullptr) requires(mcc_eqt_hrz_coord_c || mcc_celestial_point_c) { if (common_result == nullptr) { return MccPZoneContainerErrorCode::ERROR_NULLPTR; } *common_result = false; auto apply_func = [&](auto& func, auto& pt_arg, size_t i) { bool res; error_t ret = func(pt_arg, &res); if (!ret) { *common_result |= res; if (result) { if (traits::mcc_range_size(*result) == i) { std::back_inserter(*result) = res; } else { auto ptr = result->begin(); std::ranges::advance(ptr, i); *ptr = res; } } } return ret; }; return forEach(coords, apply_func, _inZoneFuncCPT, _inZoneFuncEHC); } // template // error_t timeToPZone(InputT coords, std::ranges::output_range
auto* res_time) // requires(mcc_eqt_hrz_coord_c || mcc_celestial_point_c) template error_t timeToPZone(InputT coords, R* res_time) requires(mcc_eqt_hrz_coord_c || mcc_celestial_point_c) && traits::mcc_output_duration_range_c { if (res_time == nullptr) { return MccPZoneContainerErrorCode::ERROR_NULLPTR; } using DT = std::ranges::range_value_t; duration_t res; auto apply_func = [&](auto& func, auto& pt_arg, size_t i) { error_t ret = func(pt_arg, &res); DT val; if (res == mcc_infinite_duration_v) { val = mcc_infinite_duration_v
; } else { val = std::chrono::duration_cast
(res); } if (!ret) { if (traits::mcc_range_size(*res_time) == i) { std::back_inserter(*res_time) = val; } else { auto ptr = res_time->begin(); std::ranges::advance(ptr, i); *ptr = val; } } return ret; }; return forEach(coords, apply_func, _timeToZoneFuncCPT, _timeToZoneFuncEHC); } // template // error_t timeFromPZone(InputT coords, std::ranges::output_range
auto* res_time) // requires(mcc_eqt_hrz_coord_c || mcc_celestial_point_c) template error_t timeFromPZone(InputT coords, R* res_time) requires(mcc_eqt_hrz_coord_c || mcc_celestial_point_c) && traits::mcc_output_duration_range_c { if (res_time == nullptr) { return MccPZoneContainerErrorCode::ERROR_NULLPTR; } using DT = std::ranges::range_value_t; duration_t res; auto apply_func = [&](auto& func, auto& pt_arg, size_t i) { error_t ret = func(pt_arg, &res); if (!ret) { if (traits::mcc_range_size(*res_time) == i) { std::back_inserter(*res_time) = std::chrono::duration_cast
(res); } else { auto ptr = res_time->begin(); std::ranges::advance(ptr, i); *ptr = std::chrono::duration_cast
(res); } } return ret; }; return forEach(coords, apply_func, _timeFromZoneFuncCPT, _timeFromZoneFuncEHC); } // template // error_t intersectPZone(InputT coords, R* result) // requires(mcc_eqt_hrz_coord_c || mcc_celestial_point_c) && // std::ranges::output_range> && // mcc_celestial_point_c> // { // if (result == nullptr) { // return MccPZoneContainerErrorCode::ERROR_NULLPTR; // } // if (traits::mcc_range_size(*result) < sizePZones()) { // return MccPZoneContainerErrorCode::ERROR_INVALID_SIZE; // } // // using CPT = std::ranges::range_value_t; // MccCelestialPoint pt; // auto apply_func = [&](auto& func, auto& pt_arg, size_t i) { // auto ptr = result->begin(); // std::ranges::advance(ptr, i); // pt.pair_kind = ptr->pair_kind; // pt.time_point = ptr->time_point; // error_t ret = func(pt_arg, &pt); // if (!ret) { // // if (traits::mcc_range_size(*result) == i) { // // std::back_inserter(*result) = CPT(); // // } // mcc_copy_celestial_point(pt, &(*ptr)); // } // return ret; // }; // return forEach(coords, apply_func, _intersectZoneFuncCPT, _intersectZoneFuncEHC); // } template error_t intersectPZone(InputT coords, ResultT* result) requires((mcc_eqt_hrz_coord_c || mcc_celestial_point_c) && std::ranges::output_range> && (mcc_eqt_hrz_coord_c> || mcc_celestial_point_c>)) { if (result == nullptr) { return MccPZoneContainerErrorCode::ERROR_NULLPTR; } if (traits::mcc_range_size(*result) < sizePZones()) { return MccPZoneContainerErrorCode::ERROR_INVALID_SIZE; } auto apply_func = [&](auto& func, auto& pt_arg, size_t i) { auto ptr = result->begin(); std::ranges::advance(ptr, i); error_t ret; if constexpr (mcc_eqt_hrz_coord_c) { MccEqtHrzCoords pt; mcc_tp2tp(ptr->time_point, pt.time_point); ret = func(pt_arg, &pt); if (!ret) { mcc_copy_eqt_hrz_coord(pt, &(*ptr)); } } else { MccCelestialPoint pt; pt.pair_kind = ptr->pair_kind; mcc_tp2tp(ptr->time_point, pt.time_point); ret = func(pt_arg, &pt); if (!ret) { mcc_copy_celestial_point(pt, &(*ptr)); } } return ret; }; if constexpr (mcc_eqt_hrz_coord_c) { return forEach(coords, apply_func, _intersectZoneFuncCPT2EHC, _intersectZoneFuncEHC2EHC); } else { return forEach(coords, apply_func, _intersectZoneFuncCPT2CPT, _intersectZoneFuncEHC2CPT); } } protected: std::vector> _inZoneFuncCPT; std::vector> _inZoneFuncEHC; std::vector> _timeToZoneFuncCPT; std::vector> _timeToZoneFuncEHC; std::vector> _timeFromZoneFuncCPT; std::vector> _timeFromZoneFuncEHC; // std::vector> _intersectZoneFuncCPT; // std::vector> _intersectZoneFuncEHC; std::vector> _intersectZoneFuncCPT2CPT; std::vector> _intersectZoneFuncEHC2CPT; std::vector> _intersectZoneFuncCPT2EHC; std::vector> _intersectZoneFuncEHC2EHC; error_t forEach(auto const& coords, auto& apply_func, auto& containerCPT, auto& containerEHC) { using coords_t = std::remove_cvref_t; error_t ret = MccPZoneContainerErrorCode::ERROR_OK; size_t i = 0; if constexpr (mcc_eqt_hrz_coord_c) { MccEqtHrzCoords pt; mcc_copy_eqt_hrz_coord(coords, &pt); for (auto& func : containerEHC) { ret = apply_func(func, pt, i); if (ret) { break; } ++i; } } else { MccCelestialPoint pt; mcc_copy_celestial_point(coords, &pt); for (auto& func : containerCPT) { ret = apply_func(func, pt, i); if (ret) { break; } ++i; } } return ret; } }; } // namespace mcc