Files
mcc/mcc_pzone_container.h
Timur A. Fatkhullin a686731c0a ...
2026-01-30 22:20:42 +03:00

232 lines
6.6 KiB
C++

#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<mcc::impl::MccPZoneContainerErrorCode> : 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<MccPZoneContainerErrorCode>(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<int>(ec), MccPZoneContainerCategory::get());
}
// template <traits::mcc_time_duration_c DurT>
class MccPZoneContainer : public mcc_pzone_container_interface_t<std::error_code>
{
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<decltype(zone)>(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<bool> 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 <traits::mcc_time_duration_c DT>
error_t timeToPZone(mcc_skypoint_c auto const& coords, std::ranges::output_range<DT> auto* res_time)
{
return forEach(_timeToZoneFunc, coords, res_time);
}
template <traits::mcc_time_duration_c DT>
error_t timeFromPZone(mcc_skypoint_c auto const& coords, std::ranges::output_range<DT> auto* res_time)
{
return forEach(_timeFromZoneFunc, coords, res_time);
}
protected:
typedef std::chrono::nanoseconds duration_t;
std::vector<std::function<error_t(MccSkyPoint const& pt, bool*)>> _inZoneFunc;
std::vector<std::function<error_t(MccSkyPoint const& pt, duration_t*)>> _timeToZoneFunc;
std::vector<std::function<error_t(MccSkyPoint const& pt, duration_t*)>> _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<decltype(*result)>;
using res_elem_t = std::ranges::range_value_t<res_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