232 lines
6.6 KiB
C++
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
|