...
This commit is contained in:
parent
a43b6587b6
commit
98d5fa007f
@ -154,4 +154,17 @@ if (WITH_TESTS)
|
||||
set(FSM_TEST_APP fsm_test)
|
||||
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()
|
||||
|
||||
@ -70,15 +70,34 @@ public:
|
||||
MccAngle() = default;
|
||||
|
||||
// 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.:
|
||||
// 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.:
|
||||
// auto ang = MccAngle{"-12:34:56.789"}; // from degrees:minutes:seconds
|
||||
// auto ang = MccAngle{"123.574698"}; // from degrees
|
||||
@ -144,23 +163,17 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
MccAngle& normalize()
|
||||
{
|
||||
return normalize<NORM_KIND_0_360>();
|
||||
}
|
||||
MccAngle& normalize() { return normalize<NORM_KIND_0_360>(); }
|
||||
|
||||
|
||||
template <typename T>
|
||||
operator T() const
|
||||
requires std::is_arithmetic_v<T>
|
||||
{
|
||||
return _angleInRads;
|
||||
}
|
||||
// template <typename T>
|
||||
// operator T() const
|
||||
// requires std::is_arithmetic_v<T>
|
||||
// {
|
||||
// return _angleInRads;
|
||||
// }
|
||||
|
||||
operator double() const
|
||||
{
|
||||
return _angleInRads;
|
||||
}
|
||||
operator double() const { return _angleInRads; }
|
||||
|
||||
|
||||
template <typename T>
|
||||
@ -169,21 +182,15 @@ public:
|
||||
return _angleInRads * 180.0 / std::numbers::pi;
|
||||
}
|
||||
|
||||
double degrees() const
|
||||
{
|
||||
return degrees<double>();
|
||||
}
|
||||
double degrees() const { return degrees<double>(); }
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
std::string sexagesimal(bool hms, int prec = 2) const
|
||||
{
|
||||
return sexagesimal<std::string>(hms, prec);
|
||||
}
|
||||
std::string sexagesimal(bool hms = false, int prec = 2) const { return sexagesimal<std::string>(hms, prec); }
|
||||
|
||||
|
||||
// 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!");
|
||||
|
||||
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};
|
||||
}
|
||||
@ -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!");
|
||||
|
||||
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};
|
||||
}
|
||||
@ -324,23 +331,18 @@ class MccAngleAZ : public MccAngle
|
||||
using MccAngle::MccAngle;
|
||||
};
|
||||
|
||||
class MccAngleALT;
|
||||
struct MccAngleALT; // just forward declaration
|
||||
|
||||
class MccAngleZD : public MccAngle
|
||||
{
|
||||
struct MccAngleZD : public MccAngle {
|
||||
using MccAngle::MccAngle;
|
||||
|
||||
MccAngleZD(const MccAngleALT&);
|
||||
};
|
||||
|
||||
class MccAngleALT : public MccAngle
|
||||
{
|
||||
struct MccAngleALT : public MccAngle {
|
||||
using MccAngle::MccAngle;
|
||||
|
||||
MccAngleALT(const MccAngleZD& zd)
|
||||
{
|
||||
_angleInRads = std::numbers::pi / 2.0 - (double)zd;
|
||||
}
|
||||
MccAngleALT(const MccAngleZD& 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 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 };
|
||||
|
||||
template <std::ranges::contiguous_range R>
|
||||
@ -224,10 +231,26 @@ static R rad2sxg(double ang, bool hms = false, int prec = 2)
|
||||
degs /= 15.0;
|
||||
}
|
||||
|
||||
auto term = 10.0;
|
||||
for (int i = 1; i < prec; ++i) {
|
||||
term *= 10.0;
|
||||
}
|
||||
|
||||
auto d = std::trunc(degs);
|
||||
auto s = (degs - d) * 60.0;
|
||||
auto m = std::trunc(s);
|
||||
|
||||
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) {
|
||||
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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user