This commit is contained in:
2025-08-08 23:50:55 +03:00
parent c45d17b236
commit b99263a014
11 changed files with 709 additions and 197 deletions

View File

@@ -98,6 +98,43 @@ concept mcc_logger_c = requires(T t, const T t_const) {
};
/* A CONCEPT FOR COORDINATE REPRESENTATION */
// it is a fundametal floating-point type or
// a class that can be constructed from or converted to the double fundametal type
template <typename T>
concept mcc_coord_t = std::floating_point<T> || (std::convertible_to<T, double> && std::constructible_from<T, double>);
/* A CONCEPT FOR UTC TIME POINT REPRESENTATION */
// it is a std::chrono::sys_time<Duration> or
// fundamental arithmetic type that represent number of seconds after the 00:00:00 of 1 January 1970 (UNIX time)
template <typename T>
concept mcc_utc_time_point_c = mcc_systime_c<T> || std::is_arithmetic_v<T>;
/* A CONCEPT FOR CLASS TO REPRESENT CELESTIAL POINT */
template <typename T>
concept mcc_celestial_point_c = requires(T t) {
// a type to represent UTC time point of coordinates
// it's clear that this makes sense for apparent coordinates
typename T::time_point_t;
// coordinates pair type (e.g. IRCS RA,DEC, Az,Alt and so on)
requires std::same_as<decltype(t.coordPairKind), MccCoordPairKind>;
typename T::coord_t;
// co-longitude (e.g. RA or Az)
requires std::same_as<decltype(t.x), typename T::coord_t>;
// co-latitude (e.g. DEC or ZD)
requires std::same_as<decltype(t.y), typename T::coord_t>;
};
/* ASTROMETRY-RELATED COMPUTATION ENGINE */
template <typename T>
@@ -128,10 +165,10 @@ concept mcc_astrom_engine_c = requires(T t, const T t_const) {
} -> std::same_as<typename T::error_t>;
// observed place to ICRS RA and DEC: obs2icrs(type, x, y, jd, ra_icrs, dec_icrs)
// (x,y) = (AZ, ZD) if type = MccCoordPairKind::COORDS_KIND_AZZD
// (x,y) = (AZ, ALT) if type = MccCoordPairKind::COORDS_KIND_AZALT
// (x,y) = (HA, DEC) if type = MccCoordPairKind::COORDS_KIND_HADEC_APP
// (x,y) = (RA, DEC) if type = MccCoordPairKind::COORDS_KIND_RADEC_APP
// (x, y) = (AZ, ZD) if type == MccCoordPairKind::COORDS_KIND_AZZD
// (x, y) = (AZ, ALT) if type == MccCoordPairKind::COORDS_KIND_AZALT
// (x, y) = (HA, DEC) if type == MccCoordPairKind::COORDS_KIND_HADEC_APP
// (x, y) = (RA, DEC) if type == MccCoordPairKind::COORDS_KIND_RADEC_APP
{
t.obs2icrs(std::declval<MccCoordPairKind>(), std::declval<typename T::coord_t>(),
std::declval<typename T::coord_t>(), std::declval<typename T::juldate_t>(),
@@ -157,6 +194,26 @@ concept mcc_astrom_engine_c = requires(T t, const T t_const) {
std::declval<typename T::pa_t&>())
} -> std::same_as<typename T::error_t>;
// transform coordinates according to its pair types and time points (a high-level wrapper):
//
// coord2coord(coord_pair_kind_from, x_from, y_from, time_point_from, coord_pair_kind_to, x_to, y_to, time_point_to)
//
// (x_*, y_*) = (AZ, ZD) if coord_pair_kind_* == MccCoordPairKind::COORDS_KIND_AZZD
// (x_*, y_*) = (AZ, ALT) if coord_pair_kind_* == MccCoordPairKind::COORDS_KIND_AZALT
// (x_*, y_*) = (HA, DEC) if coord_pair_kind_* == MccCoordPairKind::COORDS_KIND_HADEC_APP (apparent)
// (x_*, y_*) = (RA, DEC) if coord_pair_kind_* == MccCoordPairKind::COORDS_KIND_RADEC_APP (apparent)
// (x_*, y_*) = (RA, DEC) if coord_pair_kind_* == MccCoordPairKind::COORDS_KIND_RADEC_ICRS (ICRS)
//
// if coord_pair_kind_* and time_point_* are equal then x_to = x_from, y_to = y_from
{
t.coord2coord(std::declval<MccCoordPairKind>(), std::declval<typename T::coord_t>(),
std::declval<typename T::coord_t>(), std::declval<typename T::time_point_t>(),
std::declval<MccCoordPairKind>(), std::declval<typename T::coord_t&>(),
std::declval<typename T::coord_t&>(), std::declval<typename T::time_point_t>())
} -> std::same_as<typename T::error_t>;
// compute equation of origins
{
t.eqOrigins(std::declval<typename T::juldate_t>(), std::declval<typename T::eo_t&>())
@@ -355,23 +412,6 @@ concept mcc_mount_telemetry_c = requires(T t, const T t_const) {
};
/* A CONCEPT FOR CLASS TO REPRESENT CELESTIAL POINT */
template <typename T>
concept mcc_celestial_point_c = requires(T t) {
// input coordinates pair type (e.g. IRCS RA,DEC, Az,Alt and so on)
requires std::same_as<decltype(t.coordPairKind), MccCoordPairKind>;
typename T::coord_t;
// co-longitude (e.g. RA or Az)
requires std::same_as<decltype(t.x), typename T::coord_t>;
// co-latitude (e.g. DEC or ZD)
requires std::same_as<decltype(t.y), typename T::coord_t>;
};
// /* SLEW PARAMETERS */
@@ -420,14 +460,85 @@ concept mcc_guiding_model_c = requires(T t) {
/* MOUNT PROHIBITED ZONE */
struct MccPzoneAbstractInterface {
bool inZone(this auto&& self, mcc_mount_telemetry_data_c auto const& telemetry_data)
{
using self_t = decltype(self);
if constexpr (std::same_as<std::remove_cvref_t<self_t>, MccPzoneAbstractInterface>) {
static_assert(false, "Call an empty MccPzoneAbstractInterface::inZone method");
} else {
return std::forward<self_t>(self).inZone(telemetry_data);
}
}
bool inZone(this auto&& self, mcc_celestial_point_c auto const& sky_point)
{
using self_t = decltype(self);
if constexpr (std::same_as<std::remove_cvref_t<self_t>, MccPzoneAbstractInterface>) {
static_assert(false, "Call an empty MccPzoneAbstractInterface::inZone method");
} else {
return std::forward<self_t>(self).inZone(sky_point);
}
}
// returns a time to reach the zone
auto timeTo(this auto&& self, mcc_mount_telemetry_data_c auto const& telemetry_data)
{
using self_t = decltype(self);
if constexpr (std::same_as<std::remove_cvref_t<self_t>, MccPzoneAbstractInterface>) {
static_assert(false, "Call an empty MccPzoneAbstractInterface::timeTo method");
} else {
return std::forward<self_t>(self).timeTo(telemetry_data);
}
}
auto timeTo(this auto&& self, mcc_celestial_point_c auto const& sky_point)
{
using self_t = decltype(self);
if constexpr (std::same_as<std::remove_cvref_t<self_t>, MccPzoneAbstractInterface>) {
static_assert(false, "Call an empty MccPzoneAbstractInterface::timeTo method");
} else {
return std::forward<self_t>(self).timeTo(sky_point);
}
}
// returns a time to exit from the zone
auto timeFrom(this auto&& self, mcc_mount_telemetry_data_c auto const& telemetry_data)
{
using self_t = decltype(self);
if constexpr (std::same_as<std::remove_cvref_t<self_t>, MccPzoneAbstractInterface>) {
static_assert(false, "Call an empty MccPzoneAbstractInterface::timeFrom method");
} else {
return std::forward<self_t>(self).timeFrom(telemetry_data);
}
}
auto timeFrom(this auto&& self, mcc_celestial_point_c auto const& sky_point)
{
using self_t = decltype(self);
if constexpr (std::same_as<std::remove_cvref_t<self_t>, MccPzoneAbstractInterface>) {
static_assert(false, "Call an empty MccPzoneAbstractInterface::timeFrom method");
} else {
return std::forward<self_t>(self).timeFrom(sky_point);
}
}
};
template <typename T, typename TelemetryDataT>
concept mcc_prohibited_zone_c =
mcc_mount_telemetry_data_c<TelemetryDataT> && std::movable<T> && requires(T t, const T t_const) {
// typename T::coord_t;
typename T::coord_t;
// typename T::time_point_t;
requires mcc_time_duration_c<typename T::duration_t>;
// static constexpr member to represent inifite duration
// static constexpr member to represent infinite duration
requires requires {
requires std::same_as<decltype(T::infiniteDuration), typename T::duration_t const>;
[]() {
@@ -446,46 +557,11 @@ concept mcc_prohibited_zone_c =
};
// the type 'T' must define a static constexpr member of type MccCoordPairKind
// to declarate type of coordinate pair used to describe the zone.
// This coordinate pair must be used as input in the 'inZone' class method.
// requires requires {
// requires std::same_as<decltype(T::zoneCoordPairKind), const MccCoordPairKind>;
// []() {
// constexpr MccCoordPairKind val = T::zoneCoordPairKind;
// return val;
// }(); // to ensure that 'zoneCoordPairKind' can be used at compile-time context
// };
// return a name of the zone
{ t_const.name() } -> mcc_formattable;
// check if given coordinates are into the zone.
// input coordinates interpretation is in according to 'zoneCoordPairKind' static constexpr member
// {
// t.inZone(std::declval<typename T::coord_t>(), std::declval<typename T::coord_t>())
// } -> std::convertible_to<bool>;
// // for given coordinates and time the method computes a time to reach the zone.
// // implementation of the method must assume that input coordinates are apparent RA and DEC at given time
// // point, while the time point is one from which computation should be performed (e.g. current time moment)
// {
// t.timeTo(std::declval<typename T::coord_t>(), std::declval<typename T::coord_t>(),
// std::declval<typename T::time_point_t>())
// } -> mcc_time_duration_c;
// // for given coordinates and time the method computes a time to exit from the zone
// {
// t.timeFrom(std::declval<typename T::coord_t>(), std::declval<typename T::coord_t>(),
// std::declval<typename T::time_point_t>())
// } -> mcc_time_duration_c;
// requires for the methods above with the first argument of type
// 'const mcc_mount_telemetry_data_c&' (const lvalue reference)
{ t.inZone(std::declval<const TelemetryDataT&>()) } -> std::convertible_to<bool>;
// a time duration to reach the zone.
@@ -500,12 +576,129 @@ concept mcc_prohibited_zone_c =
{ t.timeFrom(std::declval<const TelemetryDataT&>()) } -> std::same_as<typename T::duration_t>;
};
// an input range of prohibited zones
template <typename T, typename TelemetryDataT>
concept mcc_irange_of_pzones_c = mcc_mount_telemetry_data_c<TelemetryDataT> && std::ranges::input_range<T> &&
mcc_prohibited_zone_c<std::ranges::range_value_t<T>, TelemetryDataT>;
// // an input range of prohibited zones
// template <typename T, typename TelemetryDataT>
// concept mcc_irange_of_pzones_c = mcc_mount_telemetry_data_c<TelemetryDataT> && std::ranges::input_range<T> &&
// mcc_prohibited_zone_c<std::ranges::range_value_t<T>, TelemetryDataT>;
// // a concept for a callable with the first argument of type satisfied to 'mcc_prohibited_zone_c'
// template <typename T, typename TelemetryDataT>
// concept mcc_pzone_foreach_func_c = mcc_is_callable<T> && mcc_mount_telemetry_data_c<TelemetryDataT> &&
// mcc_prohibited_zone_c<mcc_func_arg1_t<T>, TelemetryDataT>;
// There is no way to declare a concept of class with templated method so one needs to define
// a generic interface of prohibited zones holder/container explicitly
template <mcc_mount_telemetry_data_c TelemetryDataT>
struct MccPZoneAbstractContainer {
virtual ~MccPZoneAbstractContainer() = default;
// must return a size of the container after the addition of the given zone
template <mcc_prohibited_zone_c<TelemetryDataT> ZT>
size_t pzAddZone(this auto&& self, ZT zone)
{
using self_t = decltype(self);
if constexpr (std::same_as<std::remove_cvref_t<self_t>, MccPZoneAbstractContainer>) {
static_assert(false, "Call an empty MccPZoneAbstractContainer::pzAddZone method");
} else {
return std::forward<self_t>(self).pzAddZone(std::move(zone));
}
}
// clear the container
auto pzClearZones(this auto&& self)
{
using self_t = decltype(self);
if constexpr (std::same_as<std::remove_cvref_t<self_t>, MccPZoneAbstractContainer>) {
static_assert(false, "Call an empty MccPZoneAbstractContainer::pzClearZones method");
} else {
return std::forward<self_t>(self).pzClearZones();
}
}
// must return the size of the container (number of zones)
size_t pzSize(this auto&& self)
{
using self_t = decltype(self);
if constexpr (std::same_as<std::remove_cvref_t<self_t>, MccPZoneAbstractContainer>) {
static_assert(false, "Call an empty MccPZoneAbstractContainer::pzSize method");
} else {
return std::forward<self_t>(self).pzSize();
}
}
// must return true if the given telemetry coordinates are in any of zones in the containe and
// false otherwise
template <typename RT>
bool pzInZone(this auto&& self, const TelemetryDataT& tdata, RT& result)
{
using self_t = decltype(self);
if constexpr (std::same_as<std::remove_cvref_t<self_t>, MccPZoneAbstractContainer>) {
static_assert(false, "Call an empty MccPZoneAbstractContainer::pzInZone method");
} else {
return std::forward<self_t>(self).pzInZone(tdata, result);
}
}
template <typename RT>
auto pzTimeTo(this auto&& self, const TelemetryDataT& tdata, RT& result)
{
using self_t = decltype(self);
if constexpr (std::same_as<std::remove_cvref_t<self_t>, MccPZoneAbstractContainer>) {
static_assert(false, "Call an empty MccPZoneAbstractContainer::pzInZone method");
} else {
return std::forward<self_t>(self).pzTimeTo(tdata, result);
}
}
template <typename RT>
auto pzTimeFrom(this auto&& self, const TelemetryDataT& tdata, RT& result)
{
using self_t = decltype(self);
if constexpr (std::same_as<std::remove_cvref_t<self_t>, MccPZoneAbstractContainer>) {
static_assert(false, "Call an empty MccPZoneAbstractContainer::pzInZone method");
} else {
return std::forward<self_t>(self).pzTimeFrom(tdata, result);
}
}
protected:
MccPZoneAbstractContainer() = default;
};
// a full concept for prohibited zones container
template <typename T, typename TelemetryDataT>
concept mcc_mount_pzones_container_c = std::derived_from<T, MccPZoneAbstractContainer<TelemetryDataT>> && requires {
// common time duration type for zones 'timeTo' and 'timeFrom' methods
requires mcc_time_duration_c<typename T::duration_t>;
// static constexpr member to represent infinite duration
requires requires {
requires std::same_as<decltype(T::infiniteDuration), typename T::duration_t const>;
[]() {
constexpr auto val = T::infiniteDuration;
return val;
};
};
// static constexpr member to represent zero duration
requires requires {
requires std::same_as<decltype(T::zeroDuration), typename T::duration_t const>;
[]() {
constexpr auto val = T::zeroDuration;
return val;
};
};
};
/* MOUNT GENERIC CONTROLS */