189 lines
6.0 KiB
C++
189 lines
6.0 KiB
C++
#pragma once
|
|
|
|
/* MOUNT CONTROL COMPONENTS LIBRARY */
|
|
|
|
/* PROHIBITED ZONE IMPLEMENTATION */
|
|
|
|
#include <chrono>
|
|
#include <string_view>
|
|
|
|
#include "mcc_mount_coord.h"
|
|
#include "mcc_traits.h"
|
|
|
|
namespace mcc
|
|
{
|
|
|
|
class MccProhibitedZone
|
|
{
|
|
public:
|
|
static constexpr MccCoordPairKind preferedCoordKind = MccCoordPairKind::COORDS_KIND_AZALT;
|
|
|
|
|
|
// floating-point time duration (seconds)
|
|
typedef std::chrono::duration<double> pz_duration_t;
|
|
|
|
|
|
struct pz_request_t {
|
|
bool in_zone{false}; // true if given coordinates are within the zone
|
|
pz_duration_t time_to{0.0}; // a time duration to reach the zone
|
|
pz_duration_t time_from{0.0}; // a time duration to exit the zone
|
|
};
|
|
|
|
|
|
virtual ~MccProhibitedZone() = default;
|
|
|
|
std::string_view name() const
|
|
{
|
|
return _name;
|
|
}
|
|
|
|
// check if given position (x,y) in the zone
|
|
template <std::derived_from<MccAngle> XT, std::derived_from<MccAngle> YT>
|
|
bool inZone(this auto&& self,
|
|
const XT& x,
|
|
const YT& y,
|
|
traits::mcc_systime_c auto const& utc = std::chrono::system_clock::now())
|
|
{
|
|
return std::forward<decltype(self)>(self).inZoneImpl(x, y, utc);
|
|
}
|
|
|
|
// returns a time duration to reach the zone
|
|
// 0 - if already within
|
|
// Inf - if it never reaches the zone
|
|
template <std::derived_from<MccAngle> XT, std::derived_from<MccAngle> YT>
|
|
pz_duration_t timeTo(this auto&& self,
|
|
const XT& x,
|
|
const YT& y,
|
|
traits::mcc_systime_c auto const& utc = std::chrono::system_clock::now())
|
|
{
|
|
return std::forward<decltype(self)>(self).timeToImpl(x, y, utc);
|
|
}
|
|
|
|
// returns a time duration to exit from the zone
|
|
// 0 - if given position (x,y) is out of the zone
|
|
// Inf - if (x,y) is always within the zone
|
|
template <std::derived_from<MccAngle> XT, std::derived_from<MccAngle> YT>
|
|
pz_duration_t timeFrom(this auto&& self,
|
|
const XT& x,
|
|
const YT& y,
|
|
traits::mcc_systime_c auto const& utc = std::chrono::system_clock::now())
|
|
{
|
|
return std::forward<decltype(self)>(self).timeFromImpl(x, y, utc);
|
|
}
|
|
|
|
|
|
// all-in-one request (call three methods above)
|
|
template <std::derived_from<MccAngle> XT, std::derived_from<MccAngle> YT>
|
|
pz_request_t request(const XT& x,
|
|
const YT& y,
|
|
traits::mcc_systime_c auto const& utc = std::chrono::system_clock::now())
|
|
{
|
|
pz_request_t res{.in_zone = false, .time_to = pz_duration_t{0.0}, .time_from{0.0}};
|
|
|
|
res.in_zone = inZone(x, y, utc);
|
|
|
|
if (res.in_zone) {
|
|
res.time_from = timeFrom(x, y, utc);
|
|
} else {
|
|
res.time_to = timeFrom(x, y, utc);
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
protected:
|
|
MccProhibitedZone(std::string_view name) : _name(name) {}
|
|
|
|
std::string_view _name;
|
|
|
|
|
|
template <std::derived_from<MccAngle> XT, std::derived_from<MccAngle> YT>
|
|
bool inZoneImpl(const XT&, const YT&, traits::mcc_systime_c auto const&)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
|
|
template <std::derived_from<MccAngle> XT, std::derived_from<MccAngle> YT>
|
|
pz_duration_t timeToImpl(const XT&, const YT&, traits::mcc_systime_c auto const&)
|
|
{
|
|
return pz_duration_t{std::numeric_limits<double>::infinity()};
|
|
}
|
|
|
|
|
|
template <std::derived_from<MccAngle> XT, std::derived_from<MccAngle> YT>
|
|
pz_duration_t timeFromImpl(const XT&, const YT&, traits::mcc_systime_c auto const&)
|
|
{
|
|
return pz_duration_t{0.0};
|
|
}
|
|
};
|
|
|
|
|
|
/* SOME PROHIBITED ZONE IMPLEMENTATIONS */
|
|
|
|
|
|
// minimal or maximal altitude prohibited zones
|
|
|
|
enum class MccAltLimitKind { MIN_ALT_LIMIT, MAX_ALT_LIMIT };
|
|
|
|
template <MccAltLimitKind KIND = MccAltLimitKind::MIN_ALT_LIMIT>
|
|
class MccAltLimitPZ : public MccProhibitedZone
|
|
{
|
|
public:
|
|
static constexpr MccAltLimitKind altLimitKind = KIND;
|
|
|
|
MccAltLimitPZ(const MccAngle& alt_limit)
|
|
: MccProhibitedZone(KIND == MccAltLimitKind::MIN_ALT_LIMIT ? "MINALT-ZONE"
|
|
: KIND == MccAltLimitKind::MAX_ALT_LIMIT ? "MAXALT-ZONE"
|
|
: "ALTLIMIT-UNKNOWN"),
|
|
_altLimit(alt_limit)
|
|
{
|
|
_altLimit.normalize<MccAngle::NORM_KIND_90_90>();
|
|
}
|
|
|
|
private:
|
|
MccAngle _altLimit;
|
|
|
|
template <std::derived_from<MccAngle> XT, std::derived_from<MccAngle> YT>
|
|
bool inZoneImpl(const XT& x, const YT& y, traits::mcc_systime_c auto const& utc)
|
|
{
|
|
static constexpr MccCoordPairKind coord_kind = traits::mcc_type_pair_hash<XT, YT>();
|
|
|
|
if constexpr (coord_kind == MccCoordPairKind::COORDS_KIND_AZALT) { // trivial case
|
|
if constexpr (KIND == MccAltLimitKind::MIN_ALT_LIMIT) {
|
|
return y <= _altLimit;
|
|
} else if constexpr (KIND == MccAltLimitKind::MAX_ALT_LIMIT) {
|
|
return y >= _altLimit;
|
|
}
|
|
} else if constexpr (coord_kind == MccCoordPairKind::COORDS_KIND_AZZD) { // trivial case
|
|
return inZoneImpl(x, MccAngleALT(std::numbers::pi / 2 - (double)y), utc);
|
|
} else if constexpr (coord_kind == MccCoordPairKind::COORDS_KIND_HADEC_APP) {
|
|
// implementation ...
|
|
return false;
|
|
} else if constexpr (coord_kind == MccCoordPairKind::COORDS_KIND_RADEC_APP) {
|
|
// implementation ...
|
|
return false;
|
|
} else {
|
|
throw std::system_error(std::make_error_code(std::errc::operation_not_supported));
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
template <std::derived_from<MccAngle> XT, std::derived_from<MccAngle> YT>
|
|
pz_duration_t timeToImpl(const XT&, const YT&, traits::mcc_systime_c auto const&)
|
|
{
|
|
return pz_duration_t{std::numeric_limits<double>::infinity()};
|
|
}
|
|
|
|
|
|
template <std::derived_from<MccAngle> XT, std::derived_from<MccAngle> YT>
|
|
pz_duration_t timeFromImpl(const XT&, const YT&, traits::mcc_systime_c auto const&)
|
|
{
|
|
return pz_duration_t{0.0};
|
|
}
|
|
};
|
|
|
|
} // namespace mcc
|