...
This commit is contained in:
231
mcc_pzone_container.h
Normal file
231
mcc_pzone_container.h
Normal file
@@ -0,0 +1,231 @@
|
||||
#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
|
||||
Reference in New Issue
Block a user