#pragma once /**************************************************************************************** * * * MOUNT CONTROL COMPONENTS LIBRARY * * * * * * IMPLEMENTATION OF PROHIBITED ZONES CONTAINER * * * ****************************************************************************************/ #include "mcc_concepts.h" #include "mcc_coordinate.h" namespace mcc::impl { 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::impl namespace std { template <> class is_error_code_enum : public true_type { }; } // namespace std namespace mcc::impl { // 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; 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_pzone_c auto zone) { auto sptr = std::make_shared(std::move(zone)); _inZoneFunc.emplace_back([sptr](MccSkyPoint const& pt, bool* res) { auto err = sptr->inPZone(pt, res); if (err) { return mcc_deduced_err(err, MccPZoneContainerErrorCode::ERROR_INZONE_FUNC); } return MccPZoneContainerErrorCode::ERROR_OK; }); _timeToZoneFunc.emplace_back([sptr](MccSkyPoint const& pt, duration_t* res) { auto err = sptr->timeToPZone(pt, res); if (err) { return mcc_deduced_err(err, MccPZoneContainerErrorCode::ERROR_TIMETO_FUNC); } return MccPZoneContainerErrorCode::ERROR_OK; }); _timeFromZoneFunc.emplace_back([sptr](MccSkyPoint const& pt, duration_t* res) { auto err = sptr->timeFromPZone(pt, res); if (err) { return mcc_deduced_err(err, MccPZoneContainerErrorCode::ERROR_TIMEFROM_FUNC); } return MccPZoneContainerErrorCode::ERROR_OK; }); return _inZoneFunc.size(); } void clearZones() { _inZoneFunc.clear(); _timeToZoneFunc.clear(); _timeFromZoneFunc.clear(); } error_t inPZone(mcc_skypoint_c auto const& coords, bool* at_least_one, std::ranges::output_range auto* result) { auto err = forEach(_inZoneFunc, coords, result); if (!err) { *at_least_one = false; for (auto const& r : *result) { if (r) { *at_least_one = true; break; } } } return err; } template error_t timeToPZone(mcc_skypoint_c auto const& coords, std::ranges::output_range
auto* res_time) { return forEach(_timeToZoneFunc, coords, res_time); } template error_t timeFromPZone(mcc_skypoint_c auto const& coords, std::ranges::output_range
auto* res_time) { return forEach(_timeFromZoneFunc, coords, res_time); } protected: typedef std::chrono::nanoseconds duration_t; std::vector> _inZoneFunc; std::vector> _timeToZoneFunc; std::vector> _timeFromZoneFunc; error_t forEach(auto& func_cont, MccSkyPoint const& pt, auto* result) { if (result == nullptr) { return MccPZoneContainerErrorCode::ERROR_NULLPTR; } using res_t = std::decay_t; using res_elem_t = std::ranges::range_value_t; error_t err; res_elem_t res_elem; size_t res_sz = std::ranges::size(*result); auto it = result->begin(); for (auto& func : func_cont) { err = func(pt, &res_elem); if (err) { return err; } if (it == result->end()) { std::back_inserter(*result) = res_elem; it = result->end(); } else { *it = std::move(res_elem); ++it; } } return MccPZoneContainerErrorCode::ERROR_OK; } }; } // namespace mcc::impl