394 lines
12 KiB
C++
394 lines
12 KiB
C++
#pragma once
|
|
|
|
#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<mcc::MccPZoneContainerErrorCode> : 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<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;
|
|
|
|
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<decltype(zone)>(std::move(zone));
|
|
|
|
_inZoneFuncCPT.emplace_back([sptr](const MccCelestialPoint& pt, bool* res) {
|
|
auto ret = sptr->inPZone(pt, res);
|
|
|
|
return mcc_deduce_error(ret, mcc::make_error_code(MccPZoneContainerErrorCode::ERROR_INZONE_FUNC));
|
|
});
|
|
|
|
_inZoneFuncEHC.emplace_back([sptr](const MccEqtHrzCoords& pt, bool* res) {
|
|
auto ret = sptr->inPZone(pt, res);
|
|
|
|
return mcc_deduce_error(ret, mcc::make_error_code(MccPZoneContainerErrorCode::ERROR_INZONE_FUNC));
|
|
});
|
|
|
|
|
|
_timeToZoneFuncCPT.emplace_back([sptr](const MccCelestialPoint& pt, duration_t* res_time) {
|
|
auto ret = sptr->timeToPZone(pt, res_time);
|
|
|
|
return mcc_deduce_error(ret, mcc::make_error_code(MccPZoneContainerErrorCode::ERROR_TIMETO_FUNC));
|
|
});
|
|
|
|
_timeToZoneFuncEHC.emplace_back([sptr](const MccEqtHrzCoords& pt, duration_t* res_time) {
|
|
auto ret = sptr->timeToPZone(pt, res_time);
|
|
|
|
return mcc_deduce_error(ret, mcc::make_error_code(MccPZoneContainerErrorCode::ERROR_TIMETO_FUNC));
|
|
});
|
|
|
|
_timeFromZoneFuncCPT.emplace_back([sptr](const MccCelestialPoint& pt, duration_t* res_time) {
|
|
auto ret = sptr->timeFromPZone(pt, res_time);
|
|
|
|
return mcc_deduce_error(ret, mcc::make_error_code(MccPZoneContainerErrorCode::ERROR_TIMEFROM_FUNC));
|
|
});
|
|
|
|
_timeFromZoneFuncEHC.emplace_back([sptr](const MccEqtHrzCoords& pt, duration_t* res_time) {
|
|
auto ret = sptr->timeFromPZone(pt, res_time);
|
|
|
|
return mcc_deduce_error(ret, mcc::make_error_code(MccPZoneContainerErrorCode::ERROR_TIMEFROM_FUNC));
|
|
});
|
|
|
|
_intersectZoneFuncCPT.emplace_back([sptr](const MccCelestialPoint& pt, MccCelestialPoint* res_pt) {
|
|
auto ret = sptr->intersectPZone(pt, res_pt);
|
|
|
|
return mcc_deduce_error(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(ret, mcc::make_error_code(MccPZoneContainerErrorCode::ERROR_INTERSECT_FUNC));
|
|
});
|
|
|
|
return _inZoneFuncCPT.size();
|
|
}
|
|
|
|
|
|
void clearPZones()
|
|
{
|
|
_inZoneFuncCPT.clear();
|
|
_inZoneFuncEHC.clear();
|
|
|
|
_timeToZoneFuncCPT.clear();
|
|
_timeToZoneFuncEHC.clear();
|
|
|
|
_timeFromZoneFuncCPT.clear();
|
|
_timeFromZoneFuncEHC.clear();
|
|
|
|
_intersectZoneFuncCPT.clear();
|
|
_intersectZoneFuncEHC.clear();
|
|
}
|
|
|
|
|
|
size_t sizePZones() const
|
|
{
|
|
return _inZoneFuncCPT.size();
|
|
}
|
|
|
|
|
|
template <typename InputT>
|
|
error_t inPZone(InputT coords, bool* common_result, std::ranges::output_range<bool> auto* result = nullptr)
|
|
requires(mcc_eqt_hrz_coord_c<InputT> || mcc_celestial_point_c<InputT>)
|
|
{
|
|
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 <typename InputT, traits::mcc_time_duration_c DT>
|
|
// error_t timeToPZone(InputT coords, std::ranges::output_range<DT> auto* res_time)
|
|
// requires(mcc_eqt_hrz_coord_c<InputT> || mcc_celestial_point_c<InputT>)
|
|
template <typename InputT, typename R>
|
|
error_t timeToPZone(InputT coords, R* res_time)
|
|
requires(mcc_eqt_hrz_coord_c<InputT> || mcc_celestial_point_c<InputT>) && traits::mcc_output_duration_range_c<R>
|
|
{
|
|
if (res_time == nullptr) {
|
|
return MccPZoneContainerErrorCode::ERROR_NULLPTR;
|
|
}
|
|
|
|
using DT = std::ranges::range_value_t<R>;
|
|
|
|
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<duration_t>) {
|
|
val = mcc_infinite_duration_v<DT>;
|
|
} else {
|
|
val = std::chrono::duration_cast<DT>(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 <typename InputT, traits::mcc_time_duration_c DT>
|
|
// error_t timeFromPZone(InputT coords, std::ranges::output_range<DT> auto* res_time)
|
|
// requires(mcc_eqt_hrz_coord_c<InputT> || mcc_celestial_point_c<InputT>)
|
|
template <typename InputT, typename R>
|
|
error_t timeFromPZone(InputT coords, R* res_time)
|
|
requires(mcc_eqt_hrz_coord_c<InputT> || mcc_celestial_point_c<InputT>) && traits::mcc_output_duration_range_c<R>
|
|
{
|
|
if (res_time == nullptr) {
|
|
return MccPZoneContainerErrorCode::ERROR_NULLPTR;
|
|
}
|
|
|
|
using DT = std::ranges::range_value_t<R>;
|
|
|
|
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<DT>(res);
|
|
} else {
|
|
auto ptr = res_time->begin();
|
|
std::ranges::advance(ptr, i);
|
|
*ptr = std::chrono::duration_cast<DT>(res);
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
};
|
|
|
|
return forEach(coords, apply_func, _timeFromZoneFuncCPT, _timeFromZoneFuncEHC);
|
|
}
|
|
|
|
// template <typename InputT, mcc_celestial_point_c CPT>
|
|
// error_t intersectPZone(InputT coords, std::ranges::output_range<CPT> auto* result)
|
|
// requires(mcc_eqt_hrz_coord_c<InputT> || mcc_celestial_point_c<InputT>)
|
|
template <typename InputT, typename R>
|
|
error_t intersectPZone(InputT coords, R* result)
|
|
requires(mcc_eqt_hrz_coord_c<InputT> || mcc_celestial_point_c<InputT>) &&
|
|
std::ranges::output_range<R, std::ranges::range_value_t<R>> &&
|
|
mcc_celestial_point_c<std::ranges::range_value_t<R>>
|
|
{
|
|
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<R>;
|
|
|
|
MccCelestialPoint pt;
|
|
|
|
auto apply_func = [&](auto& func, auto& pt_arg, size_t i) {
|
|
error_t ret = func(pt_arg, &pt);
|
|
if (!ret) {
|
|
// if (traits::mcc_range_size(*result) == i) {
|
|
// std::back_inserter(*result) = CPT();
|
|
// }
|
|
|
|
auto ptr = result->begin();
|
|
std::ranges::advance(ptr, i);
|
|
mcc_copy_celestial_point(pt, &(*ptr));
|
|
}
|
|
|
|
return ret;
|
|
};
|
|
|
|
return forEach(coords, apply_func, _intersectZoneFuncCPT, _intersectZoneFuncEHC);
|
|
}
|
|
|
|
|
|
protected:
|
|
std::vector<std::function<error_t(MccCelestialPoint const&, bool*)>> _inZoneFuncCPT;
|
|
std::vector<std::function<error_t(MccEqtHrzCoords const&, bool*)>> _inZoneFuncEHC;
|
|
|
|
std::vector<std::function<error_t(MccCelestialPoint const&, duration_t*)>> _timeToZoneFuncCPT;
|
|
std::vector<std::function<error_t(MccEqtHrzCoords const&, duration_t*)>> _timeToZoneFuncEHC;
|
|
|
|
std::vector<std::function<error_t(MccCelestialPoint const&, duration_t*)>> _timeFromZoneFuncCPT;
|
|
std::vector<std::function<error_t(MccEqtHrzCoords const&, duration_t*)>> _timeFromZoneFuncEHC;
|
|
|
|
std::vector<std::function<error_t(MccCelestialPoint const&, MccCelestialPoint*)>> _intersectZoneFuncCPT;
|
|
std::vector<std::function<error_t(MccEqtHrzCoords const&, MccCelestialPoint*)>> _intersectZoneFuncEHC;
|
|
|
|
error_t forEach(auto const& coords, auto& apply_func, auto& containerCPT, auto& containerEHC)
|
|
{
|
|
using coords_t = std::remove_cvref_t<decltype(coords)>;
|
|
|
|
error_t ret = MccPZoneContainerErrorCode::ERROR_OK;
|
|
|
|
size_t i = 0;
|
|
|
|
if constexpr (mcc_eqt_hrz_coord_c<coords_t>) {
|
|
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
|