...
This commit is contained in:
267
cxx/mcc_mount_pz_container.h
Normal file
267
cxx/mcc_mount_pz_container.h
Normal file
@@ -0,0 +1,267 @@
|
||||
#pragma once
|
||||
|
||||
/* MOUNT CONTROL COMPONENTS LIBRARY */
|
||||
|
||||
|
||||
/* A DEFAULT IMPLEMENTATION OF PROHIBITED ZONES HOLDER */
|
||||
|
||||
#include "mcc_mount_concepts.h"
|
||||
|
||||
namespace mcc
|
||||
{
|
||||
|
||||
template <traits::mcc_mount_telemetry_data_c TelemetryDataT>
|
||||
class MccPZoneContainer : public traits::MccPZoneAbstractContainer<TelemetryDataT>
|
||||
{
|
||||
public:
|
||||
typedef TelemetryDataT telemetry_data_t;
|
||||
|
||||
// a type to which the result of calling prohibited zone class methods 'timeTo' and 'timeFrom' will be converted
|
||||
typedef std::chrono::duration<double> duration_t; // seconds as floating-point number
|
||||
|
||||
// adaptor class for prohibited zones
|
||||
struct MccPZoneWrapper {
|
||||
using duration_t = MccPZoneContainer::duration_t;
|
||||
|
||||
static constexpr duration_t infiniteDuration{std::numeric_limits<double>::infinity()};
|
||||
static constexpr duration_t zeroDuration{0.0};
|
||||
|
||||
typedef std::function<bool(const TelemetryDataT&)> pz_inzone_func_t;
|
||||
typedef std::function<duration_t(const TelemetryDataT&)> pz_timeto_func_t;
|
||||
typedef std::function<duration_t(const TelemetryDataT&)> pz_timefrom_func_t;
|
||||
|
||||
MccCoordPairKind coordPairKind;
|
||||
const std::function<std::string()> name;
|
||||
pz_inzone_func_t inZone;
|
||||
pz_timeto_func_t timeTo;
|
||||
pz_timefrom_func_t timeFrom;
|
||||
|
||||
MccPZoneWrapper(MccPZoneWrapper&& other)
|
||||
: inZone(std::move(other.inZone)), timeTo(std::move(other.timeTo)), timeFrom(std::move(other.timeFrom)) {};
|
||||
|
||||
MccPZoneWrapper& operator=(MccPZoneWrapper&& other)
|
||||
{
|
||||
if (this != &other) {
|
||||
inZone = std::move(other.inZone);
|
||||
timeTo = std::move(other.timeTo);
|
||||
timeFrom = std::move(other.timeFrom);
|
||||
}
|
||||
|
||||
return *this;
|
||||
};
|
||||
|
||||
MccPZoneWrapper() = default;
|
||||
};
|
||||
|
||||
MccPZoneContainer() = default;
|
||||
virtual ~MccPZoneContainer() = default;
|
||||
|
||||
|
||||
size_t pzSize() const { return _pzWrapperVec.size(); }
|
||||
|
||||
// add zone/zones
|
||||
template <traits::mcc_prohibited_zone_c<telemetry_data_t> ZT,
|
||||
traits::mcc_prohibited_zone_c<telemetry_data_t>... ZTs>
|
||||
size_t pzAddZone(ZT zone, ZTs... zones)
|
||||
{
|
||||
auto zone_ptr = std::make_shared<ZT>(std::move(zone));
|
||||
|
||||
using d_t = typename MccPZoneWrapper::duration_t;
|
||||
|
||||
_pzWrapperVec.emplace_back(
|
||||
{.coordPairKind = ZT::zoneCoordPairKind,
|
||||
.name = [zone_ptr]() { return std::format("{}", zone_ptr->name()); },
|
||||
.inZone = [zone_ptr](const telemetry_data_t& tmry_data) { return zone_ptr->inZone(tmry_data); },
|
||||
.timeTo =
|
||||
[zone_ptr](const telemetry_data_t& tmry_data) {
|
||||
auto d = zone_ptr->timeTo(tmry_data);
|
||||
|
||||
if constexpr (std::same_as<typename ZT::duration_t, d_t>) {
|
||||
return d;
|
||||
} else {
|
||||
if (d == ZT::infiniteDuration) {
|
||||
return MccPZoneWrapper::infiniteDuration;
|
||||
} else if (d == ZT::zeroDuration) {
|
||||
return MccPZoneWrapper::zeroDuration;
|
||||
}
|
||||
return std::chrono::duration_cast<d_t>(d);
|
||||
}
|
||||
},
|
||||
.timeFrom =
|
||||
[zone_ptr](const telemetry_data_t& tmry_data) {
|
||||
auto d = zone_ptr->timeFrom(tmry_data);
|
||||
|
||||
if constexpr (std::same_as<typename ZT::duration_t, d_t>) {
|
||||
return d;
|
||||
} else {
|
||||
if (d == ZT::infiniteDuration) {
|
||||
return MccPZoneWrapper::infiniteDuration;
|
||||
} else if (d == ZT::zeroDuration) {
|
||||
return MccPZoneWrapper::zeroDuration;
|
||||
}
|
||||
return std::chrono::duration_cast<d_t>(d);
|
||||
}
|
||||
}});
|
||||
|
||||
|
||||
if constexpr (sizeof...(ZTs)) {
|
||||
pzAddZone(std::move(zones)...);
|
||||
}
|
||||
|
||||
return _pzWrapperVec.size();
|
||||
}
|
||||
|
||||
void pzClearZones()
|
||||
{
|
||||
// stop mount here?!!
|
||||
_pzWrapperVec.clear();
|
||||
}
|
||||
|
||||
|
||||
// visitors
|
||||
template <std::invocable<MccPZoneWrapper> FT>
|
||||
auto pzForeachZone(FT&& func)
|
||||
requires std::same_as<std::invoke_result_t<FT, MccPZoneWrapper>, void>
|
||||
{
|
||||
for (auto& wr : _pzWrapperVec) {
|
||||
std::forward<FT>(func)(wr);
|
||||
}
|
||||
}
|
||||
|
||||
template <std::invocable<MccPZoneWrapper> FT,
|
||||
std::ranges::output_range<std::invoke_result_t<FT, MccPZoneWrapper>> ResT =
|
||||
std::vector<std::invoke_result_t<FT, MccPZoneWrapper>>>
|
||||
auto pzForeachZone(FT&& func)
|
||||
requires(!std::same_as<std::invoke_result_t<FT, MccPZoneWrapper>, void>)
|
||||
{
|
||||
ResT result;
|
||||
|
||||
for (auto& wr : _pzWrapperVec) {
|
||||
std::back_inserter(result) = std::forward<FT>(func)(wr);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template <std::ranges::output_range<bool> RT>
|
||||
bool pzInZone(const telemetry_data_t& tdata, RT& result)
|
||||
{
|
||||
bool in_zone = false;
|
||||
|
||||
auto const p_tdata = &tdata;
|
||||
|
||||
result = pzForeachZone<RT>([&in_zone, p_tdata](auto& wr) {
|
||||
bool r = wr.inZone(*p_tdata);
|
||||
in_zone |= r;
|
||||
|
||||
return r;
|
||||
});
|
||||
|
||||
return in_zone;
|
||||
}
|
||||
|
||||
template <std::ranges::output_range<bool> RT>
|
||||
bool pzInZone(traits::mcc_celestial_point_c auto const& target, RT& result)
|
||||
{
|
||||
bool in_zone = false;
|
||||
|
||||
auto const p_target = ⌖
|
||||
|
||||
result = pzForeachZone<RT>([&in_zone, p_target](auto& wr) {
|
||||
bool r = wr.inZone(*p_target);
|
||||
in_zone |= r;
|
||||
|
||||
return r;
|
||||
});
|
||||
|
||||
return in_zone;
|
||||
}
|
||||
|
||||
protected:
|
||||
std::vector<MccPZoneWrapper> _pzWrapperVec{};
|
||||
};
|
||||
|
||||
|
||||
|
||||
class PZC
|
||||
{
|
||||
protected:
|
||||
struct point_t {
|
||||
typedef std::chrono::system_clock::time_point time_point_t;
|
||||
typedef double coord_t;
|
||||
|
||||
time_point_t time_point;
|
||||
MccCoordPairKind coordPairKind;
|
||||
coord_t x, y;
|
||||
};
|
||||
|
||||
static_assert(traits::mcc_celestial_point_c<point_t>);
|
||||
|
||||
template <typename ZT>
|
||||
static inline std::unordered_map<const PZC*, std::vector<std::shared_ptr<ZT>>> _zones{};
|
||||
|
||||
std::vector<std::function<void()>> _clearFunc{};
|
||||
|
||||
// template <typename ZT, typename CPT>
|
||||
// static inline std::unordered_map<const PZC*, std::function<std::vector<bool>(const CPT&)>> _inZoneFunc = [](){
|
||||
|
||||
// };
|
||||
// template <typename ZT, typename CPT>
|
||||
// static inline std::function<std::vector<bool>(const PZC*, const CPT&)> _inZoneFunc =
|
||||
// [](const PZC* cont, const CPT& cp) {
|
||||
// std::vector<bool> res;
|
||||
|
||||
// for (ZT& zone : _zones<ZT>[cont]) {
|
||||
// res.emplace_back(zone.inZone(cp));
|
||||
// }
|
||||
|
||||
// return res;
|
||||
// };
|
||||
|
||||
std::vector<std::function<bool(const point_t&)>> _inZoneFunc;
|
||||
|
||||
public:
|
||||
template <typename ZT>
|
||||
size_t addZone(ZT zone)
|
||||
{
|
||||
auto sptr = std::make_shared<ZT>(std::move(zone));
|
||||
|
||||
_zones<ZT>[this].emplace_back(sptr);
|
||||
|
||||
if (_zones<ZT>[this].size() == 1) {
|
||||
_clearFunc.emplace_back([this]() { _zones<ZT>[this].clear(); });
|
||||
|
||||
_inZoneFunc.emplace_back([sptr](const point_t& cp) { return sptr->inZone(cp); });
|
||||
}
|
||||
}
|
||||
|
||||
template <typename CPT, std::ranges::output_range<bool> RT>
|
||||
bool inZone(const CPT& cp, RT& res)
|
||||
{
|
||||
using tp_t = typename point_t::time_point_t;
|
||||
using cp_tp_t = typename CPT::time_point_t;
|
||||
|
||||
bool in_zone = false, r;
|
||||
|
||||
point_t pt{.coordPairKind = cp.coordPairKind, .x = cp.x, .y = cp.y};
|
||||
if constexpr (traits::mcc_systime_c<cp_tp_t>) {
|
||||
pt.time_point = std::chrono::time_point_cast<tp_t>(cp.time_point);
|
||||
} else if constexpr (std::is_arithmetic_v<cp_tp_t>) {
|
||||
pt.time_point = tp_t{std::chrono::duration<tp_t::rep>(static_cast<tp_t::rep>(cp.time_point))};
|
||||
} else {
|
||||
static_assert(false, "INVALID TYPE!");
|
||||
}
|
||||
|
||||
res = RT();
|
||||
for (auto& func : _inZoneFunc) {
|
||||
r = func(pt);
|
||||
in_zone |= r;
|
||||
|
||||
std::back_inserter(res) = r;
|
||||
}
|
||||
|
||||
return in_zone;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mcc
|
||||
Reference in New Issue
Block a user