16 #ifndef OPENKALMAN_POLAR_HPP 17 #define OPENKALMAN_POLAR_HPP 19 #include <type_traits> 23 #include "coordinates/interfaces/coordinate_descriptor_traits.hpp" 41 template<
typename C1 = Distance,
typename C2 = angle::Radians>
43 requires (std::same_as<C1, Distance> and angle::angle<C2>) or (std::same_as<C2, Distance> and angle::angle<C1>)
47 #ifndef __cpp_concepts 48 static_assert((std::is_same_v<C1, Distance> and angle::angle<C2>) or (std::is_same_v<C2, Distance> and angle::angle<C1>));
60 template<
typename T,
typename Min,
typename Max,
61 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>
66 static constexpr
auto min = values::fixed_value_of_v<Min>;
67 static constexpr
auto max = values::fixed_value_of_v<Max>;
71 static constexpr
bool is_specialized =
true;
74 static constexpr
auto dimension = [](
const T&) {
return std::integral_constant<std::size_t, 2>{}; };
77 static constexpr
auto stat_dimension = [](
const T&) {
return std::integral_constant<std::size_t, 3>{}; };
80 static constexpr
auto is_euclidean = [](
const T&) {
return std::false_type{}; };
83 static constexpr
auto hash_code = [](
const T&)
86 constexpr
auto bits = std::numeric_limits<std::size_t>::digits;
87 if constexpr (bits < 32)
88 return std::integral_constant<std::size_t, a - 0x97C1_uz + d_i * 0x1000_uz>{};
89 else if constexpr (bits < 64)
90 return std::integral_constant<std::size_t, a - 0x97C195FE_uz + d_i * 0x10000000_uz>{};
92 return std::integral_constant<std::size_t, a - 0x97C195FEC488C0BC_uz + d_i * 0x1000000000000000_uz>{};
100 constexpr
auto operator()(
bool flip_, R a_)
const {
return flip_ ? -std::move(a_) : std::move(a_); }
104 template<
typename...Args>
105 static constexpr
auto make_range(Args&&...args)
107 if constexpr ((... or values::fixed<Args>))
109 return std::tuple {std::forward<Args>(args)...};
113 using C = std::common_type_t<Args...>;
114 return std::array {
static_cast<C
>(std::forward<Args>(args))...};
125 static constexpr
auto 128 decltype(
auto) d = collections::get<d_i>(std::forward<decltype(data_view)>(data_view));
129 decltype(
auto) a = collections::get<a_i>(std::forward<decltype(data_view)>(data_view));
131 auto phi = [](
auto&& a)
133 if constexpr (min == -stdex::numbers::pi_v<R> and max == stdex::numbers::pi_v<R>)
135 return std::forward<decltype(a)>(a);
139 constexpr
auto period = values::cast_to<R>(
values::operation(std::minus{}, Max{}, Min{}));
141 return values::operation(std::multiplies{}, std::forward<decltype(a)>(a), scale);
143 }(std::forward<decltype(a)>(a));
149 auto d_flip = values::internal::update_real_part(std::forward<decltype(d)>(d),
values::abs(d_real));
152 if constexpr (d2_i == 0)
153 return make_range(std::move(d_flip), std::move(x_flip), std::move(y_flip));
155 return make_range(std::move(x_flip), std::move(y_flip), std::move(d_flip));
163 constexpr R operator()(
const R& phi_real)
const 165 constexpr R period = max - min;
166 if (phi_real < R{min})
return phi_real + period;
167 if (phi_real >= R{max})
return phi_real - period;
173 template<
typename D,
typename Phi>
174 static constexpr
auto make_ordered_range(D d, Phi phi)
176 if constexpr (d_i == 0)
177 return make_range(std::move(d), std::move(phi));
179 return make_range(std::move(phi), std::move(d));
190 static constexpr
auto 193 decltype(
auto) d = collections::get<d2_i>(std::forward<decltype(data_view)>(data_view));
194 decltype(
auto) x = collections::get<x_i>(std::forward<decltype(data_view)>(data_view));
195 decltype(
auto) y = collections::get<y_i>(std::forward<decltype(data_view)>(data_view));
197 if constexpr (min == -stdex::numbers::pi_v<R> and max == stdex::numbers::pi_v<R>)
199 return make_ordered_range(std::forward<decltype(d)>(d),
values::atan2(std::forward<decltype(y)>(y), std::forward<decltype(x)>(x)));
203 constexpr
auto period = values::cast_to<R>(
values::operation(std::minus{}, Max{}, Min{}));
206 return make_ordered_range(std::forward<decltype(d)>(d),
216 constexpr R operator()(
const R& d_r,
const R& phi_r)
const 218 constexpr R period = max - min;
219 R phi_flip_real =
values::signbit(d_r) ? phi_r + period * R{0.5} : phi_r;
220 if (phi_flip_real >= R{min} and phi_flip_real < max)
return phi_flip_real;
221 R phi_real_mod =
values::fmod(phi_flip_real - R{min}, period);
222 if (phi_real_mod < 0)
return R{min} + phi_real_mod + period;
223 return R{min} + phi_real_mod;
233 static constexpr
auto 234 wrap = [](
const T&,
auto&& data_view)
236 decltype(
auto) d = collections::get<d_i>(std::forward<decltype(data_view)>(data_view));
237 decltype(
auto) phi = collections::get<a_i>(std::forward<decltype(data_view)>(data_view));
242 return make_ordered_range(
243 values::internal::update_real_part(std::forward<decltype(d)>(d),
values::abs(d_real)),
244 values::internal::update_real_part(std::forward<decltype(phi)>(phi),
values::operation(wrap_phi_mod{}, std::move(d_real), std::move(phi_real))));
256 template<
typename Min,
typename Max>
258 :
detail::PolarBase<coordinates::Polar<coordinates::Distance, coordinates::Angle<Min, Max>>, Min, Max, 0, 1, 0, 1, 2>
266 template<
typename Min,
typename Max>
268 :
detail::PolarBase<coordinates::Polar<coordinates::Angle<Min, Max>, coordinates::Distance>, Min, Max, 1, 0, 2, 0, 1>
276 template<
typename Min1,
typename Max1,
typename Min2,
typename Max2>
278 OpenKalman::coordinates::Polar<OpenKalman::coordinates::Distance, OpenKalman::coordinates::Angle<Min1, Max1>>,
281 OpenKalman::values::fixed_value_of_v<Min1> == OpenKalman::values::fixed_value_of_v<Min2> and
282 OpenKalman::values::fixed_value_of_v<Max1> == OpenKalman::values::fixed_value_of_v<Max2>,
283 OpenKalman::coordinates::Polar<OpenKalman::coordinates::Distance, OpenKalman::coordinates::Angle<Min1, Max1>>,
284 OpenKalman::coordinates::Any<>> {};
287 template<
typename Min1,
typename Max1,
typename Min2,
typename Max2>
289 OpenKalman::coordinates::Polar<OpenKalman::coordinates::Angle<Min1, Max1>, OpenKalman::coordinates::Distance>,
292 OpenKalman::values::fixed_value_of_v<Min1> == OpenKalman::values::fixed_value_of_v<Min2> and
293 OpenKalman::values::fixed_value_of_v<Max1> == OpenKalman::values::fixed_value_of_v<Max2>,
294 OpenKalman::coordinates::Polar<OpenKalman::coordinates::Angle<Min1, Max1>, OpenKalman::coordinates::Distance>,
295 OpenKalman::coordinates::Any<>> {};
298 template<
typename C1,
typename C2,
typename Scalar>
300 : common_type<OpenKalman::coordinates::Any<Scalar>, OpenKalman::coordinates::Polar<C1, C2>> {};
303 template<
typename C1,
typename C2,
typename T>
304 struct common_type<OpenKalman::coordinates::Polar<C1, C2>, T>
305 : std::conditional_t<
306 OpenKalman::coordinates::descriptor<T>,
307 OpenKalman::stdex::type_identity<OpenKalman::coordinates::Any<>>,
constexpr auto fmod(const X &x, const Y &y)
A constexpr function for fmod.
Definition: fmod.hpp:44
Definition of the Distance class.
Definition: basics.hpp:41
decltype(auto) constexpr to_stat_space(const T &t, R &&data_view)
Maps a range reflecting vector-space data to a corresponding range in a vector space for directional ...
Definition: to_stat_space.hpp:44
A fixed version of 2*pi.
Definition: fixed-constants.hpp:73
typename real_type_of< T >::type real_type_of_t
Helper template for real_type_of.
Definition: real_type_of.hpp:55
decltype(auto) constexpr wrap(const T &t, R &&data_view)
wraps a range reflecting vector-space data to its primary range.
Definition: wrap.hpp:59
constexpr auto cos(const Arg &arg)
Constexpr alternative to the std::cos function.
Definition: cos.hpp:42
constexpr auto sin(const Arg &arg)
Constexpr alternative to the std::sin function.
Definition: sin.hpp:43
The root namespace for OpenKalman.
Definition: basics.hpp:34
The namespace for features relating to coordinates::pattern object.
Definition: compares_with.hpp:25
Definition for get_descriptor_hash_code.
Inclusion file for collections.
constexpr auto atan2(const Y &y_arg, const X &x_arg)
Constexpr alternative to the std::atan2 function.
Definition: atan2.hpp:46
An atomic coordinates::descriptor reflecting polar coordinates.
Definition: Polar.hpp:45
constexpr auto real(const Arg &arg)
A constexpr function to obtain the real part of a (complex) number.
Definition: real.hpp:40
Traits for coordinates::pattern objects.
Definition: coordinate_descriptor_traits.hpp:36
constexpr auto signbit(const Arg &arg)
A constexpr function analogous to std::signbit.
Definition: signbit.hpp:41
constexpr auto abs(const Arg &arg)
A constexpr alternative to std::abs.
Definition: abs.hpp:38
decltype(auto) constexpr from_stat_space(const T &t, R &&stat_data_view)
Maps a range in a vector space for directional-statistics back to a range reflecting vector-space dat...
Definition: from_stat_space.hpp:44
auto scale(M &&m, const S s)
Scale a covariance by a factor.
Definition: covariance-arithmetic.hpp:518
An angle or any other simple modular value.
Definition: Angle.hpp:46
Definition of the Angle class and related limits.
constexpr auto operation(Operation &&op, Args &&...args)
A potentially constant-evaluated operation involving some number of values.
Definition: operation.hpp:98