diff --git a/cxx/CMakeLists.txt b/cxx/CMakeLists.txt index 5f5bc03..540c954 100644 --- a/cxx/CMakeLists.txt +++ b/cxx/CMakeLists.txt @@ -137,6 +137,7 @@ if (WITH_TESTS) add_executable(${CFGFILE_TEST_APP} tests/configfile_test.cpp) set(ASTROM_TEST_APP astrom_test) - add_executable(${ASTROM_TEST_APP} tests/astrom_test.cpp) + add_executable(${ASTROM_TEST_APP} tests/astrom_test.cpp + mount_pz.h) target_link_libraries(${ASTROM_TEST_APP} ERFA_LIB) endif() diff --git a/cxx/mcc_coord.h b/cxx/mcc_coord.h index 38bc313..b54b4b4 100644 --- a/cxx/mcc_coord.h +++ b/cxx/mcc_coord.h @@ -129,15 +129,26 @@ public: return sexagesimal(hms, prec); } - friend MccCoordinate operator+(const MccCoordinate& left, const MccCoordinate& right) + friend MccCoordinate operator+(std::convertible_to auto&& left, + std::convertible_to auto&& right) { - return left._angleInRads + right._angleInRads; + return std::forward(left)._angleInRads + std::forward(right)._angleInRads; } + // friend MccCoordinate operator+(const MccCoordinate& left, const MccCoordinate& right) + // { + // return left._angleInRads + right._angleInRads; + // } - friend MccCoordinate operator-(const MccCoordinate& left, const MccCoordinate& right) + + friend MccCoordinate operator-(std::convertible_to auto&& left, + std::convertible_to auto&& right) { - return left._angleInRads + right._angleInRads; + return std::forward(left)._angleInRads - std::forward(right)._angleInRads; } + // friend MccCoordinate operator-(const MccCoordinate& left, const MccCoordinate& right) + // { + // return left._angleInRads + right._angleInRads; + // } template MccCoordinate operator*(T&& scalar) @@ -187,6 +198,26 @@ public: _angleInRads /= scalar; return *this; } + + auto operator<=>(const MccCoordinate& other) const + { + return _angleInRads <=> other._angleInRads; + } + + auto operator==(const MccCoordinate& other) const + { + return _angleInRads == other._angleInRads; + } + + auto operator<=>(double other) const + { + return _angleInRads <=> other; + } + + auto operator==(double other) const + { + return _angleInRads == other; + } }; diff --git a/cxx/mount.h b/cxx/mount.h index 7e1bb37..86a3cec 100644 --- a/cxx/mount.h +++ b/cxx/mount.h @@ -155,6 +155,28 @@ struct MccProhibitedZoneContext { pzcoords_t coordType; }; + + +struct MccProhibitedZone1 { + // type of prohibited zone + enum pztype_t { + PZ_MINALT, // trivial minimal altitude + PZ_MAXALT, // trivial maximal altitude (e.g. near-zenith zone for alt-azimuthal types) + PZ_ELLIPSE, // simple circular/elliptical zone + PZ_PIER_MERIDIAN, // pier-side or cross-meridian + PZ_CONVEXHULL // general convex hull polygonal zone + }; + + pztype_t type; + + struct pzminalt_t { + double minalt{0.0}; + }; + + union { + } geometry; +}; + /* MOUNT BASE TEMPLATED CLASS WITH BASIC FUNCTIONALITY */ // implements a Finite State Machine Pattern @@ -337,18 +359,15 @@ public: // .time_from = time duration to exit the zone (0 - if already out of the zone, chrono::duration<>::max() if // never exit the zone) - auto pzCheck(const MccCoordinate& xcoord, + auto pzCheck(this auto&& self, + const MccCoordinate& xcoord, const MccCoordinate& ycoord, std::derived_from auto const& context, traits::mcc_systime_c auto const& utc = std::chrono::system_clock::now()) { - using d_t = std::remove_cvref_t::duration; - - return pzcheck_result_t{.inzone = false, .time_to = d_t::max(), .time_from = d_t{0}}; + return std::forward(self).pzCheckImpl(xcoord, ycoord, context, utc); } - // template OR, std::ranges::input_range R1, std::ranges::input_range - // R2> template auto pzCheckRange(const R1& xcoord, const R2& ycoord, @@ -424,6 +443,17 @@ protected: std::atomic _geoLocation; std::atomic _currentMeteo; + + // default implementation + auto pzCheckImpl(const MccCoordinate& xcoord, + const MccCoordinate& ycoord, + std::derived_from auto const& context, + traits::mcc_systime_c auto const& utc = std::chrono::system_clock::now()) + { + using d_t = std::remove_cvref_t::duration; + + return pzcheck_result_t{.inzone = false, .time_to = d_t::max(), .time_from = d_t{0}}; + } }; } // namespace mcc diff --git a/cxx/mount_pz.h b/cxx/mount_pz.h new file mode 100644 index 0000000..483187b --- /dev/null +++ b/cxx/mount_pz.h @@ -0,0 +1,91 @@ +#pragma once + +#include "mcc_coord.h" + +namespace mcc +{ +class MccProhibitedZone +{ +public: + virtual ~MccProhibitedZone() = default; + + bool inZone(this auto&& self, const MccCoordinate& x, const MccCoordinate& y) + { + return std::forward(self).inZoneImpl(x, y); + } + +protected: + bool inZoneImpl(const MccCoordinate&, const MccCoordinate&) + { + return false; + } +}; + +class MccMinAltPZ : public MccProhibitedZone +{ +public: + MccMinAltPZ(const MccCoordinate& min_alt) : _minAlt(min_alt) {} + + MccCoordinate minAlt() const + { + return _minAlt; + } + +private: + double _minAlt; + + bool inZoneImpl(const MccCoordinate& alt, const MccCoordinate&) + { + return alt <= _minAlt; + } +}; + + +class MccMaxAltPZ +{ +public: + MccMaxAltPZ(double max_alt) : _maxAlt(max_alt) {} + + double maxAlt() const + { + return _maxAlt; + } + +private: + double _maxAlt; + + bool inZoneImpl(const MccCoordinate& alt, const MccCoordinate&) + { + return alt >= _maxAlt; + } +}; + + +class MccElliipsePZ +{ +public: + MccElliipsePZ(const MccCoordinate& xc, const MccCoordinate& yc, const MccCoordinate& a, const MccCoordinate& b) + : _xc(xc), _yc(yc), _a(a), _b(b), _a2(a * a), _b2(b * b) + { + } + + // circle + MccElliipsePZ(const MccCoordinate& xc, const MccCoordinate& yc, const MccCoordinate& a) + : mcc::MccElliipsePZ(xc, yc, a, a) + { + } + + +private: + double _xc, _yc, _a, _b, _a2, _b2; + + bool inZoneImpl(const MccCoordinate& alt, const MccCoordinate& zd) + { + auto x2 = alt - _xc; + auto y2 = zd - _yc; + + return (x2 * x2 / _a2 + y2 * y2 / _b2) <= 1.0; + } +}; + +} // namespace mcc