16 #ifndef OPENKALMAN_POLAR_HPP 17 #define OPENKALMAN_POLAR_HPP 19 #include <type_traits> 23 #include "../../../basics/compatibility/language-features.hpp" 26 #include "values/functions/internal/update_real_part.hpp" 27 #include "values/math/signbit.hpp" 28 #include "values/math/abs.hpp" 29 #include "values/math/cos.hpp" 30 #include "values/math/sin.hpp" 31 #include "values/math/atan2.hpp" 32 #include "linear-algebra/coordinates/interfaces/coordinate_descriptor_traits.hpp" 50 template<
typename C1 = Distance,
typename C2 = angle::Radians>
52 requires (std::same_as<C1, Distance> and angle::angle<C2>) or (std::same_as<C2, Distance> and angle::angle<C1>)
56 #ifndef __cpp_concepts 57 static_assert((std::is_same_v<C1, Distance> and angle::angle<C2>) or (std::is_same_v<C2, Distance> and angle::angle<C1>));
69 template<
typename T,
typename Min,
typename Max,
70 std::size_t d_i, std::size_t a_i, std::size_t d2_i, std::size_t x_i, std::size_t y_i>
75 static constexpr
auto min = values::fixed_number_of_v<Min>;
76 static constexpr
auto max = values::fixed_number_of_v<Max>;
80 static constexpr
bool is_specialized =
true;
84 dimension(
const T&) {
return std::integral_constant<std::size_t, 2>{}; };
88 stat_dimension(
const T&) {
return std::integral_constant<std::size_t, 3>{}; };
92 is_euclidean(
const T&) {
return std::false_type{}; }
95 static constexpr std::size_t
99 constexpr
auto bits = std::numeric_limits<std::size_t>::digits;
100 if constexpr (bits < 32)
return a - 0x97C1_uz + d_i * 0x1000_uz;
101 else if constexpr (bits < 64)
return a - 0x97C195FE_uz + d_i * 0x10000000_uz;
102 else return a - 0x97C195FEC488C0BC_uz + d_i * 0x1000000000000000_uz;
114 #ifdef __cpp_concepts 116 to_euclidean_component(
const T& t,
const auto& g,
const values::index auto& euclidean_local_index)
119 template<
typename Getter,
typename L, std::enable_if_t<values::index<L> and
120 values::value<
typename std::invoke_result<const Getter&, std::
size_t>::type>,
int> = 0>
121 static constexpr
auto 125 using Scalar = std::decay_t<decltype(g(std::declval<std::size_t>()))>;
127 if (euclidean_local_index == d2_i)
133 using R = std::decay_t<decltype(values::real(std::declval<Scalar>()))>;
134 const Scalar cf {2 * numbers::pi_v<R> / (max - min)};
135 const Scalar mid {R{max + min} * R{0.5}};
137 Scalar theta = cf * g(a_i) - mid;
138 switch(euclidean_local_index)
155 #ifdef __cpp_concepts 157 from_euclidean_component(
const T& t,
const auto& g,
const values::index auto& local_index)
160 template<
typename Getter,
typename L, std::enable_if_t<values::index<L> and
161 values::value<
typename std::invoke_result<const Getter&, std::
size_t>::type>,
int> = 0>
162 static constexpr
auto 166 using Scalar = std::decay_t<decltype(g(std::declval<std::size_t>()))>;
169 if (local_index == d_i)
172 return values::internal::update_real_part(d,
values::abs(dr));
176 using R = std::decay_t<decltype(values::real(std::declval<Scalar>()))>;
177 const Scalar cf {2 * numbers::pi_v<R> / (max - min)};
178 const Scalar mid {R{max + min} * R{0.5}};
184 if constexpr (values::complex<Scalar>)
return values::atan2(y, x) / cf + mid;
191 #ifdef __cpp_concepts 192 static constexpr
auto 193 polar_angle_wrap_impl(
bool distance_is_negative,
auto&& a) -> std::decay_t<decltype(a)>
195 template<
typename Scalar>
196 static constexpr std::decay_t<Scalar>
197 polar_angle_wrap_impl(
bool distance_is_negative, Scalar&& a)
200 using R = std::decay_t<decltype(values::real(std::declval<decltype(a)>()))>;
201 constexpr R period {max - min};
204 if (ap >= min and ap < max)
206 return values::internal::update_real_part(std::forward<decltype(a)>(a), ap);;
211 auto ar = fmod(ap - R{min}, period);
212 if (ar < 0)
return values::internal::update_real_part(std::forward<decltype(a)>(a), R{min} + ar + period);
213 else return values::internal::update_real_part(std::forward<decltype(a)>(a), R{min} + ar);
226 #ifdef __cpp_concepts 228 get_wrapped_component(
const T& t,
const auto& g,
const values::index auto& local_index)
231 template<
typename Getter,
typename L, std::enable_if_t<values::index<L> and
232 values::value<
typename std::invoke_result<const Getter&, std::
size_t>::type>,
int> = 0>
233 static constexpr
auto 255 #ifdef __cpp_concepts 256 static constexpr
void 257 set_wrapped_component(
const T& t,
const auto& s,
const auto& g,
const values::value auto& x,
const values::index auto& local_index)
258 requires requires(std::size_t i){ s(x, i); s(g(i), i); }
260 template<
typename Setter,
typename Getter,
typename X,
typename L, std::enable_if_t<values::value<X> and values::index<L> and
261 std::is_invocable<const Setter&, const X&, std::
size_t>::value and
262 std::is_invocable<const Setter&,
typename std::invoke_result<const Getter&, std::
size_t>::type, std::
size_t>::value,
int> = 0>
263 static constexpr
void 272 s(values::internal::update_real_part(x,
values::abs(xp)), d_i);
278 s(polar_angle_wrap_impl(
false, x), a_i);
293 template<
typename Min,
typename Max>
295 :
detail::PolarBase<coordinates::Polar<coordinates::Distance, coordinates::Angle<Min, Max>>, Min, Max, 0, 1, 0, 1, 2>
303 template<
typename Min,
typename Max>
305 :
detail::PolarBase<coordinates::Polar<coordinates::Angle<Min, Max>, coordinates::Distance>, Min, Max, 1, 0, 2, 0, 1>
311 #endif //OPENKALMAN_POLAR_HPP Definition for get_hash_code.
Definition of the Distance class.
Definition: basics.hpp:41
static constexpr void set_wrapped_component(const T &t, const Setter &s, const Getter &g, const X &x, const L &local_index)
Set an element and then perform any necessary modular wrapping.
Definition: Polar.hpp:264
static constexpr auto from_euclidean_component(const T &t, const Getter &g, const L &local_index)
Maps a coordinate in Euclidean space to an element.
Definition: Polar.hpp:163
constexpr bool value
T is numerical value or is reducible to a numerical value.
Definition: value.hpp:31
constexpr auto sin(const Arg &arg)
Constexpr alternative to the std::sin function.
Definition: sin.hpp:43
constexpr auto cos(const Arg &arg, std::enable_if_t< values::value< Arg >, int >=0)
Constexpr alternative to the std::cos function.
Definition: cos.hpp:43
Definition: compares_with.hpp:28
constexpr auto atan2(const Y &y_arg, const X &x_arg)
Constexpr alternative to the std::atan2 function.
Definition: atan2.hpp:46
constexpr bool signbit(const Arg &arg)
A constexpr function analogous to std::signbit.
Definition: signbit.hpp:39
constexpr auto real(Arg arg)
A constexpr function to obtain the real part of a (complex) number.
Definition: real.hpp:40
An atomic coordinates::descriptor reflecting polar coordinates.
Definition: Polar.hpp:54
Traits for coordinates::pattern objects.
Definition: coordinate_descriptor_traits.hpp:41
static constexpr auto get_wrapped_component(const T &t, const Getter &g, const L &local_index)
Perform modular wrapping of polar coordinates.
Definition: Polar.hpp:234
constexpr auto abs(const Arg &arg)
A constexpr alternative to std::abs.
Definition: abs.hpp:38
static constexpr auto to_euclidean_component(const T &t, const Getter &g, const L &euclidean_local_index)
Maps a polar coordinate to coordinates in Euclidean space.
Definition: Polar.hpp:122
constexpr bool index
T is an index value.
Definition: index.hpp:56
Definition for values::number.
An angle or any other simple modular value.
Definition: Angle.hpp:62
Definition of the Angle class and related limits.
Definition for ::complex.