...
This commit is contained in:
parent
a43b6587b6
commit
98d5fa007f
@ -154,4 +154,17 @@ if (WITH_TESTS)
|
|||||||
set(FSM_TEST_APP fsm_test)
|
set(FSM_TEST_APP fsm_test)
|
||||||
add_executable(${FSM_TEST_APP} tests/fsm_test.cpp)
|
add_executable(${FSM_TEST_APP} tests/fsm_test.cpp)
|
||||||
|
|
||||||
|
|
||||||
|
# set(TESTS_SRC tests/configfile_test.cpp tests/astrom_test.cpp tests/fitpack_test.cpp tests/fsm_test.cpp)
|
||||||
|
set(TESTS_SRC tests/coord.cpp)
|
||||||
|
create_test_sourcelist(Tests common_tests.cpp ${TESTS_SRC})
|
||||||
|
add_executable(common_tests ${Tests})
|
||||||
|
# target_include_directories(common_tests PRIVATE ${FITPACK_INCLUDE_DIR})
|
||||||
|
|
||||||
|
foreach (test ${TESTS_SRC})
|
||||||
|
get_filename_component (TName ${test} NAME_WE)
|
||||||
|
add_test (NAME ${TName} COMMAND common_tests tests/${TName})
|
||||||
|
endforeach ()
|
||||||
|
|
||||||
|
enable_testing()
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@ -70,15 +70,34 @@ public:
|
|||||||
MccAngle() = default;
|
MccAngle() = default;
|
||||||
|
|
||||||
// by default angle is in radians
|
// by default angle is in radians
|
||||||
MccAngle(std::convertible_to<double> auto const& val, const MccRadianTag = MccRadianTag{}) : _angleInRads(val) {}
|
// MccAngle(std::convertible_to<double> auto const& val, const MccRadianTag = MccRadianTag{}) : _angleInRads(val) {}
|
||||||
|
|
||||||
// construct angle in degrees, e.g.:
|
// construct angle in degrees, e.g.:
|
||||||
// auto ang = MccAngle{180.0, mcc_degrees};
|
// auto ang = MccAngle{180.0, mcc_degrees};
|
||||||
MccAngle(std::convertible_to<double> auto const& val, const MccDegreeTag)
|
// MccAngle(std::convertible_to<double> auto const& val, const MccDegreeTag)
|
||||||
|
// {
|
||||||
|
// _angleInRads = val * utils::deg2radCoeff;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// by default angle is in radians
|
||||||
|
template <typename T>
|
||||||
|
MccAngle(const T& val, const MccRadianTag = MccRadianTag{})
|
||||||
|
requires std::is_arithmetic_v<T>
|
||||||
|
: _angleInRads(val)
|
||||||
{
|
{
|
||||||
_angleInRads = val * utils::deg2radCoeff;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// construct angle in degrees, e.g.:
|
||||||
|
// auto ang = MccAngle{180.0, mcc_degrees};
|
||||||
|
template <typename T>
|
||||||
|
MccAngle(const T& val, const MccDegreeTag)
|
||||||
|
requires std::is_arithmetic_v<T>
|
||||||
|
: _angleInRads(val * utils::deg2radCoeff)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// constuct angle from sexagesimal representation or floating-point number of degrees, e.g.:
|
// constuct angle from sexagesimal representation or floating-point number of degrees, e.g.:
|
||||||
// auto ang = MccAngle{"-12:34:56.789"}; // from degrees:minutes:seconds
|
// auto ang = MccAngle{"-12:34:56.789"}; // from degrees:minutes:seconds
|
||||||
// auto ang = MccAngle{"123.574698"}; // from degrees
|
// auto ang = MccAngle{"123.574698"}; // from degrees
|
||||||
@ -144,23 +163,17 @@ public:
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
MccAngle& normalize()
|
MccAngle& normalize() { return normalize<NORM_KIND_0_360>(); }
|
||||||
{
|
|
||||||
return normalize<NORM_KIND_0_360>();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
// template <typename T>
|
||||||
operator T() const
|
// operator T() const
|
||||||
requires std::is_arithmetic_v<T>
|
// requires std::is_arithmetic_v<T>
|
||||||
{
|
// {
|
||||||
return _angleInRads;
|
// return _angleInRads;
|
||||||
}
|
// }
|
||||||
|
|
||||||
operator double() const
|
operator double() const { return _angleInRads; }
|
||||||
{
|
|
||||||
return _angleInRads;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@ -169,21 +182,15 @@ public:
|
|||||||
return _angleInRads * 180.0 / std::numbers::pi;
|
return _angleInRads * 180.0 / std::numbers::pi;
|
||||||
}
|
}
|
||||||
|
|
||||||
double degrees() const
|
double degrees() const { return degrees<double>(); }
|
||||||
{
|
|
||||||
return degrees<double>();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <traits::mcc_output_char_range T>
|
template <traits::mcc_output_char_range T>
|
||||||
T sexagesimal(bool hms, int prec = 2) const
|
T sexagesimal(bool hms = false, int prec = 2) const
|
||||||
{
|
{
|
||||||
return utils::rad2sxg(_angleInRads, hms, prec >= 0 ? prec : _precision);
|
return utils::rad2sxg(_angleInRads, hms, prec >= 0 ? prec : _precision);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string sexagesimal(bool hms, int prec = 2) const
|
std::string sexagesimal(bool hms = false, int prec = 2) const { return sexagesimal<std::string>(hms, prec); }
|
||||||
{
|
|
||||||
return sexagesimal<std::string>(hms, prec);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// arithmetics
|
// arithmetics
|
||||||
@ -256,7 +263,7 @@ auto operator+(const T1& v1, const T2& v2)
|
|||||||
{
|
{
|
||||||
static_assert(std::convertible_to<T1, T2> || std::convertible_to<T2, T1>, "INCOMPATIBLE TYPES!");
|
static_assert(std::convertible_to<T1, T2> || std::convertible_to<T2, T1>, "INCOMPATIBLE TYPES!");
|
||||||
|
|
||||||
using res_t = std::conditional_t<std::convertible_to<T1, T2>, T1, T2>;
|
using res_t = std::conditional_t<std::convertible_to<T1, T2> && std::derived_from<T1, MccAngle>, T1, T2>;
|
||||||
|
|
||||||
return res_t{(double)v1 + (double)v2};
|
return res_t{(double)v1 + (double)v2};
|
||||||
}
|
}
|
||||||
@ -266,7 +273,7 @@ auto operator-(const T1& v1, const T2& v2)
|
|||||||
{
|
{
|
||||||
static_assert(std::convertible_to<T1, T2> || std::convertible_to<T2, T1>, "INCOMPATIBLE TYPES!");
|
static_assert(std::convertible_to<T1, T2> || std::convertible_to<T2, T1>, "INCOMPATIBLE TYPES!");
|
||||||
|
|
||||||
using res_t = std::conditional_t<std::convertible_to<T1, T2>, T1, T2>;
|
using res_t = std::conditional_t<std::convertible_to<T1, T2> && std::derived_from<T1, MccAngle>, T1, T2>;
|
||||||
|
|
||||||
return res_t{(double)v1 - (double)v2};
|
return res_t{(double)v1 - (double)v2};
|
||||||
}
|
}
|
||||||
@ -324,23 +331,18 @@ class MccAngleAZ : public MccAngle
|
|||||||
using MccAngle::MccAngle;
|
using MccAngle::MccAngle;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MccAngleALT;
|
struct MccAngleALT; // just forward declaration
|
||||||
|
|
||||||
class MccAngleZD : public MccAngle
|
struct MccAngleZD : public MccAngle {
|
||||||
{
|
|
||||||
using MccAngle::MccAngle;
|
using MccAngle::MccAngle;
|
||||||
|
|
||||||
MccAngleZD(const MccAngleALT&);
|
MccAngleZD(const MccAngleALT&);
|
||||||
};
|
};
|
||||||
|
|
||||||
class MccAngleALT : public MccAngle
|
struct MccAngleALT : public MccAngle {
|
||||||
{
|
|
||||||
using MccAngle::MccAngle;
|
using MccAngle::MccAngle;
|
||||||
|
|
||||||
MccAngleALT(const MccAngleZD& zd)
|
MccAngleALT(const MccAngleZD& zd) { _angleInRads = std::numbers::pi / 2.0 - (double)zd; }
|
||||||
{
|
|
||||||
_angleInRads = std::numbers::pi / 2.0 - (double)zd;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
57
cxx/tests/coord.cpp
Normal file
57
cxx/tests/coord.cpp
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "../mcc_mount_coord.h"
|
||||||
|
|
||||||
|
struct Q {
|
||||||
|
};
|
||||||
|
|
||||||
|
int tests_coord(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
using namespace mcc;
|
||||||
|
|
||||||
|
std::cout << "\n\n\n------- mcc_mount_coords.h -------\n";
|
||||||
|
|
||||||
|
|
||||||
|
MccAngle ang("90:30:00"_dms);
|
||||||
|
std::cout << "ang_degs = " << ang.degrees() << "\n";
|
||||||
|
std::cout << "ang_rads = " << (float)ang << "\n";
|
||||||
|
|
||||||
|
MccAngleALT alt(30.0_degs);
|
||||||
|
MccAngleZD zd(alt);
|
||||||
|
|
||||||
|
std::cout << "alt = " << alt.degrees() << "\n";
|
||||||
|
std::cout << "zd (from alt) = " << zd.degrees() << "\n";
|
||||||
|
|
||||||
|
std::cout << "\n";
|
||||||
|
|
||||||
|
MccAngleRA_APP ra(10.0_degs);
|
||||||
|
MccAngleDEC_APP dec(20.0_degs);
|
||||||
|
|
||||||
|
ang = 45.500_degs;
|
||||||
|
auto rr = ra + ang;
|
||||||
|
std::cout << "ra (" << ra.degrees() << "_degs) = " << ra.sexagesimal(true) << " in HH::MM::SS.SS\n";
|
||||||
|
std::cout << "ang (" << ang.degrees() << "_degs) = " << ang.sexagesimal(true) << " in HH::MM::SS.SS\n";
|
||||||
|
std::cout << "rr = ra + ang = " << rr.sexagesimal(true) << "\n";
|
||||||
|
|
||||||
|
auto r = 1.1 + ra;
|
||||||
|
std::cout << "r = ra + 1.1 = " << r.sexagesimal(true) << "\n";
|
||||||
|
std::cout << "(int)ra = " << (int)ra << " in radians\n";
|
||||||
|
|
||||||
|
MccAngleY y{123.457};
|
||||||
|
|
||||||
|
// should not compiled
|
||||||
|
// auto r1 = ra + y;
|
||||||
|
|
||||||
|
auto yy = y - 243.234;
|
||||||
|
std::cout << "yy = " << yy.degrees() << "\n";
|
||||||
|
|
||||||
|
yy.normalize<mcc::MccAngle::NORM_KIND_0_360>();
|
||||||
|
std::cout << "yy_norm = " << yy.degrees() << "\n";
|
||||||
|
std::cout << "(unsigned long)yy_norm = " << static_cast<unsigned long>(yy) << " in radians\n";
|
||||||
|
|
||||||
|
std::cout << "std::cos(yy_norm) = " << std::cos(yy) << "\n";
|
||||||
|
|
||||||
|
MccAngle ha(MccAngle{0.111});
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
30
cxx/utils.h
30
cxx/utils.h
@ -14,6 +14,13 @@ namespace mcc::utils
|
|||||||
static const std::regex decimalNumberRx{" *[-+]?([0-9]*[.])?[0-9]+([eE][-+]?[0-9]+)? *"};
|
static const std::regex decimalNumberRx{" *[-+]?([0-9]*[.])?[0-9]+([eE][-+]?[0-9]+)? *"};
|
||||||
static const std::regex sexagesimalReprRx{" *[-+]?[0-9]{1,2}:[0-9]{1,2}:([0-9]{0,2}[.])?[0-9]+ *"};
|
static const std::regex sexagesimalReprRx{" *[-+]?[0-9]{1,2}:[0-9]{1,2}:([0-9]{0,2}[.])?[0-9]+ *"};
|
||||||
|
|
||||||
|
static bool isEqual(std::floating_point auto const& v1, std::floating_point auto const& v2)
|
||||||
|
{
|
||||||
|
constexpr auto eps = std::numeric_limits<std::common_type_t<decltype(v1), decltype(v2)>>::epsilon();
|
||||||
|
|
||||||
|
return std::fabs(v1 - v2) <= eps * std::fmax(std::fabs(v1), std::fabs(v2));
|
||||||
|
}
|
||||||
|
|
||||||
enum class TrimType { TRIM_LEFT, TRIM_RIGHT, TRIM_BOTH };
|
enum class TrimType { TRIM_LEFT, TRIM_RIGHT, TRIM_BOTH };
|
||||||
|
|
||||||
template <std::ranges::contiguous_range R>
|
template <std::ranges::contiguous_range R>
|
||||||
@ -224,10 +231,26 @@ static R rad2sxg(double ang, bool hms = false, int prec = 2)
|
|||||||
degs /= 15.0;
|
degs /= 15.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto term = 10.0;
|
||||||
|
for (int i = 1; i < prec; ++i) {
|
||||||
|
term *= 10.0;
|
||||||
|
}
|
||||||
|
|
||||||
auto d = std::trunc(degs);
|
auto d = std::trunc(degs);
|
||||||
auto s = (degs - d) * 60.0;
|
auto s = (degs - d) * 60.0;
|
||||||
auto m = std::trunc(s);
|
auto m = std::trunc(s);
|
||||||
|
|
||||||
s = (s - m) * 60.0;
|
s = (s - m) * 60.0;
|
||||||
|
// round to given precision
|
||||||
|
s = std::round(s * term) / term;
|
||||||
|
if (isEqual(s, 60.0)) {
|
||||||
|
m += 1.0;
|
||||||
|
s = 0.0;
|
||||||
|
if (isEqual(m, 60.0)) {
|
||||||
|
d += 1.0;
|
||||||
|
m = 0.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (ang < 0) {
|
if (ang < 0) {
|
||||||
std::ranges::copy(std::string_view("-"), std::back_inserter(res));
|
std::ranges::copy(std::string_view("-"), std::back_inserter(res));
|
||||||
@ -285,11 +308,4 @@ static std::string AZZD_rad2sxg(double az, double zd, std::string_view delim = "
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool isEqual(std::floating_point auto const& v1, std::floating_point auto const& v2)
|
|
||||||
{
|
|
||||||
constexpr auto eps = std::numeric_limits<std::common_type_t<decltype(v1), decltype(v2)>>::epsilon();
|
|
||||||
|
|
||||||
return std::fabs(v1 - v2) <= eps * std::fmax(std::fabs(v1), std::fabs(v2));
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace mcc::utils
|
} // namespace mcc::utils
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user