16 #ifndef OPENKALMAN_SPHERICAL_HPP 17 #define OPENKALMAN_SPHERICAL_HPP 19 #include <type_traits> 24 #include "coordinates/interfaces/coordinate_descriptor_traits.hpp" 47 template<
typename C1 = Distance,
typename C2 = inclination::Radians,
typename C3 = angle::Radians>
50 (std::same_as<C1, Distance> and inclination::inclination<C2> and angle::angle<C3>) or
51 (std::same_as<C1, Distance> and inclination::inclination<C3> and angle::angle<C2>) or
52 (std::same_as<C2, Distance> and inclination::inclination<C1> and angle::angle<C3>) or
53 (std::same_as<C2, Distance> and inclination::inclination<C3> and angle::angle<C1>) or
54 (std::same_as<C3, Distance> and inclination::inclination<C1> and angle::angle<C2>) or
55 (std::same_as<C3, Distance> and inclination::inclination<C2> and angle::angle<C1>)
59 #ifndef __cpp_concepts 61 (std::is_same_v<C1, Distance> and inclination::inclination<C2> and angle::angle<C3>) or
62 (std::is_same_v<C1, Distance> and inclination::inclination<C3> and angle::angle<C2>) or
63 (std::is_same_v<C2, Distance> and inclination::inclination<C1> and angle::angle<C3>) or
64 (std::is_same_v<C2, Distance> and inclination::inclination<C3> and angle::angle<C1>) or
65 (std::is_same_v<C3, Distance> and inclination::inclination<C1> and angle::angle<C2>) or
66 (std::is_same_v<C3, Distance> and inclination::inclination<C2> and angle::angle<C1>));
78 template<
typename T,
typename Min,
typename Max,
typename Down, std::
size_t d_i, std::
size_t a_i, std::
size_t i_i>
83 static constexpr
auto min = values::fixed_value_of_v<Min>;
84 static constexpr
auto max = values::fixed_value_of_v<Max>;
85 static constexpr
auto down = values::fixed_value_of_v<Down>;
86 static constexpr std::size_t d2_i = 0, x_i = 1, y_i = 2, z_i = 3;
90 static constexpr
bool is_specialized =
true;
93 static constexpr
auto dimension = [](
const T&) {
return std::integral_constant<std::size_t, 3>{}; };
96 static constexpr
auto stat_dimension = [](
const T&) {
return std::integral_constant<std::size_t, 4>{}; };
99 static constexpr
auto is_euclidean = [](
const T&) {
return std::false_type{}; };
102 static constexpr
auto hash_code = [](
const T&) -> std::size_t
106 constexpr std::size_t f = (a_i * 2 + i_i * 3 - 2);
107 constexpr
auto bits = std::numeric_limits<std::size_t>::digits;
108 if constexpr (bits < 32)
109 return std::integral_constant<std::size_t, (a - 0x83B0_uz) + (b - 0x83B0_uz) + f * 0x1000_uz>{};
110 else if constexpr (bits < 64)
111 return std::integral_constant<std::size_t, (a - 0x83B023AB_uz) + (b - 0x83B023AB_uz) + f * 0x10000000_uz>{};
113 return std::integral_constant<std::size_t, (a - 0x83B023AB3EEFB99A_uz) + (b - 0x83B023AB3EEFB99A_uz) + f * 0x1000000000000000_uz>{};
121 constexpr std::decay_t<R> operator()(
bool f, R&& r)
const 126 return std::forward<R>(r);
131 template<
typename...Args>
132 static constexpr
auto make_range(Args&&...args)
134 if constexpr ((... or values::fixed<Args>))
136 return std::tuple {std::forward<Args>(args)...};
140 using C = std::common_type_t<Args...>;
141 return std::array {
static_cast<C
>(std::forward<Args>(args))...};
152 static constexpr
auto 155 decltype(
auto) d = collections::get<d_i>(std::forward<decltype(data_view)>(data_view));
156 decltype(
auto) i = collections::get<i_i>(std::forward<decltype(data_view)>(data_view));
157 decltype(
auto) a = collections::get<a_i>(std::forward<decltype(data_view)>(data_view));
161 auto theta = [](
auto&& i)
163 if constexpr (down == stdex::numbers::pi_v<R>)
165 return std::forward<decltype(i)>(i);
170 return values::operation(std::multiplies{}, std::forward<decltype(i)>(i), scale);
172 }(std::forward<decltype(i)>(i));
174 auto phi = [](
auto&& a)
176 if constexpr (min == -stdex::numbers::pi_v<R> and max == stdex::numbers::pi_v<R>)
178 return std::forward<decltype(a)>(a);
182 constexpr
auto period = values::cast_to<R>(
values::operation(std::minus{}, Max{}, Min{}));
184 return values::operation(std::multiplies{}, std::forward<decltype(a)>(a), scale);
186 }(std::forward<decltype(a)>(a));
206 constexpr
auto operator()(R h,
const R& z)
const 208 return (R{down} / stdex::numbers::pi_v<R>) * (h == R{0} ? std::move(h) :
values::acos(z/h));
216 constexpr
auto operator()(R hypot_xy,
const R& x,
const R& signed_scale)
const 218 return signed_scale * (hypot_xy == R{0} ? std::move(hypot_xy) :
values::acos(x / hypot_xy));
226 constexpr
auto operator()(
const R& phi_real)
const 228 constexpr R period = max - min;
229 if (phi_real < R{min})
return phi_real + period;
230 if (phi_real >= R{max})
return phi_real - period;
236 template<
typename D,
typename I,
typename A>
237 static constexpr
auto make_ordered_range(D d, I i, A a)
239 if constexpr (d_i == 0 and i_i == 1 and a_i == 2)
240 return make_range(std::move(d), std::move(i), std::move(a));
241 else if constexpr (d_i == 0 and a_i == 1 and i_i == 2)
242 return make_range(std::move(d), std::move(a), std::move(i));
243 else if constexpr (i_i == 0 and d_i == 1 and a_i == 2)
244 return make_range(std::move(i), std::move(d), std::move(a));
245 else if constexpr (a_i == 0 and d_i == 1 and i_i == 2)
246 return make_range(std::move(a), std::move(d), std::move(i));
247 else if constexpr (i_i == 0 and a_i == 1 and d_i == 2)
248 return make_range(std::move(i), std::move(a), std::move(d));
250 return make_range(std::move(a), std::move(i), std::move(d));
260 static constexpr
auto 263 decltype(
auto) d = collections::get<d2_i>(std::forward<decltype(data_view)>(data_view));
264 decltype(
auto) x = collections::get<x_i>(std::forward<decltype(data_view)>(data_view));
265 decltype(
auto) y = collections::get<y_i>(std::forward<decltype(data_view)>(data_view));
266 decltype(
auto) z = collections::get<z_i>(std::forward<decltype(data_view)>(data_view));
270 constexpr
auto period = values::cast_to<R>(
values::operation(std::minus{}, Max{}, Min{}));
276 auto hypot_xy =
values::hypot(x, std::forward<decltype(y)>(y));
284 return make_ordered_range(
285 std::forward<decltype(d)>(d),
295 constexpr
auto operator()(
bool flip_d, R i_a)
const 297 constexpr R half_period {down};
298 if (i_a > half_period)
return flip_d ? i_a - half_period : R{down * 2} - i_a;
299 return flip_d ? half_period - i_a : std::move(i_a);
307 constexpr
auto operator()(
bool flip_a, R a_r)
const 309 constexpr R period = max - min;
310 R a_real = flip_a ? a_r + period * R{0.5} : std::move(a_r);
312 return (ar < 0 ? ar + period : std::move(ar)) + R{min};
322 static constexpr
auto 323 wrap = [](
const T&,
auto&& data_view)
325 decltype(
auto) d = collections::get<d_i>(std::forward<decltype(data_view)>(data_view));
326 decltype(
auto) i = collections::get<i_i>(std::forward<decltype(data_view)>(data_view));
327 decltype(
auto) a = collections::get<a_i>(std::forward<decltype(data_view)>(data_view));
332 auto d_new = values::internal::update_real_part(std::forward<decltype(d)>(d),
values::abs(d_real));
338 auto high_i =
values::operation(std::greater{}, iabs, values::cast_to<R>(Down{}));
340 auto i_new = values::internal::update_real_part(std::forward<decltype(i)>(i),
values::operation(wrap_theta{}, flip_d, std::move(iabs)));
344 auto a_new = values::internal::update_real_part(std::forward<decltype(a)>(a), aw);
346 return make_ordered_range(std::move(d_new), std::move(i_new), std::move(a_new));
358 template<
typename Down,
typename Min,
typename Max>
360 :
detail::SphericalBase<coordinates::Spherical<coordinates::Distance, coordinates::Inclination<Down>, coordinates::Angle<Min, Max>>, Min, Max, Down, 0, 2, 1>
368 template<
typename Min,
typename Max,
typename Down>
370 :
detail::SphericalBase<coordinates::Spherical<coordinates::Distance, coordinates::Angle<Min, Max>, coordinates::Inclination<Down>>, Min, Max, Down, 0, 1, 2>
378 template<
typename Min,
typename Max,
typename Down>
380 :
detail::SphericalBase<coordinates::Spherical<coordinates::Angle<Min, Max>, coordinates::Distance, coordinates::Inclination<Down>>, Min, Max, Down, 1, 0, 2>
388 template<
typename Down,
typename Min,
typename Max>
390 :
detail::SphericalBase<coordinates::Spherical<coordinates::Inclination<Down>, coordinates::Distance, coordinates::Angle<Min, Max>>, Min, Max, Down, 1, 2, 0>
398 template<
typename Min,
typename Max,
typename Down>
400 :
detail::SphericalBase<coordinates::Spherical<coordinates::Angle<Min, Max>, coordinates::Inclination<Down>, coordinates::Distance>, Min, Max, Down, 2, 0, 1>
408 template<
typename Down,
typename Min,
typename Max>
410 :
detail::SphericalBase<coordinates::Spherical<coordinates::Inclination<Down>, coordinates::Angle<Min, Max>, coordinates::Distance>, Min, Max, Down, 2, 1, 0>
419 template<
typename Min1,
typename Max1,
typename Min2,
typename Max2,
typename Down1,
typename Down2>
422 OpenKalman::coordinates::Distance,
423 OpenKalman::coordinates::Inclination<Down1>,
424 OpenKalman::coordinates::Angle<Min1, Max1>>,
426 OpenKalman::coordinates::Distance,
427 OpenKalman::coordinates::Inclination<Down2>,
428 OpenKalman::coordinates::Angle<Min2, Max2>>>
430 OpenKalman::values::fixed_value_of_v<Min1> == OpenKalman::values::fixed_value_of_v<Min2> and
431 OpenKalman::values::fixed_value_of_v<Max1> == OpenKalman::values::fixed_value_of_v<Max2> and
432 OpenKalman::values::fixed_value_of_v<Down1> == OpenKalman::values::fixed_value_of_v<Down2>,
433 OpenKalman::coordinates::Spherical<
434 OpenKalman::coordinates::Distance,
435 OpenKalman::coordinates::Inclination<Down1>,
436 OpenKalman::coordinates::Angle<Min1, Max1>>,
437 OpenKalman::coordinates::Any<>> {};
440 template<
typename Min1,
typename Max1,
typename Min2,
typename Max2,
typename Down1,
typename Down2>
442 OpenKalman::coordinates::Spherical<
443 OpenKalman::coordinates::Distance,
444 OpenKalman::coordinates::Angle<Min1, Max1>,
445 OpenKalman::coordinates::Inclination<Down1>>,
447 OpenKalman::coordinates::Distance,
448 OpenKalman::coordinates::Angle<Min2, Max2>,
449 OpenKalman::coordinates::Inclination<Down2>>>
451 OpenKalman::values::fixed_value_of_v<Min1> == OpenKalman::values::fixed_value_of_v<Min2> and
452 OpenKalman::values::fixed_value_of_v<Max1> == OpenKalman::values::fixed_value_of_v<Max2> and
453 OpenKalman::values::fixed_value_of_v<Down1> == OpenKalman::values::fixed_value_of_v<Down2>,
454 OpenKalman::coordinates::Spherical<
455 OpenKalman::coordinates::Distance,
456 OpenKalman::coordinates::Angle<Min1, Max1>,
457 OpenKalman::coordinates::Inclination<Down1>>,
458 OpenKalman::coordinates::Any<>> {};
461 template<
typename Min1,
typename Max1,
typename Min2,
typename Max2,
typename Down1,
typename Down2>
463 OpenKalman::coordinates::Spherical<
464 OpenKalman::coordinates::Inclination<Down1>,
465 OpenKalman::coordinates::Distance,
466 OpenKalman::coordinates::Angle<Min1, Max1>>,
468 OpenKalman::coordinates::Inclination<Down2>,
469 OpenKalman::coordinates::Distance,
470 OpenKalman::coordinates::Angle<Min2, Max2>>>
472 OpenKalman::values::fixed_value_of_v<Min1> == OpenKalman::values::fixed_value_of_v<Min2> and
473 OpenKalman::values::fixed_value_of_v<Max1> == OpenKalman::values::fixed_value_of_v<Max2> and
474 OpenKalman::values::fixed_value_of_v<Down1> == OpenKalman::values::fixed_value_of_v<Down2>,
475 OpenKalman::coordinates::Spherical<
476 OpenKalman::coordinates::Inclination<Down1>,
477 OpenKalman::coordinates::Distance,
478 OpenKalman::coordinates::Angle<Min1, Max1>>,
479 OpenKalman::coordinates::Any<>> {};
482 template<
typename Min1,
typename Max1,
typename Min2,
typename Max2,
typename Down1,
typename Down2>
484 OpenKalman::coordinates::Spherical<
485 OpenKalman::coordinates::Inclination<Down1>,
486 OpenKalman::coordinates::Angle<Min1, Max1>,
487 OpenKalman::coordinates::Distance>,
489 OpenKalman::coordinates::Inclination<Down2>,
490 OpenKalman::coordinates::Angle<Min2, Max2>,
491 OpenKalman::coordinates::Distance>>
493 OpenKalman::values::fixed_value_of_v<Min1> == OpenKalman::values::fixed_value_of_v<Min2> and
494 OpenKalman::values::fixed_value_of_v<Max1> == OpenKalman::values::fixed_value_of_v<Max2> and
495 OpenKalman::values::fixed_value_of_v<Down1> == OpenKalman::values::fixed_value_of_v<Down2>,
496 OpenKalman::coordinates::Spherical<
497 OpenKalman::coordinates::Inclination<Down1>,
498 OpenKalman::coordinates::Angle<Min1, Max1>,
499 OpenKalman::coordinates::Distance>,
500 OpenKalman::coordinates::Any<>> {};
503 template<
typename Min1,
typename Max1,
typename Min2,
typename Max2,
typename Down1,
typename Down2>
505 OpenKalman::coordinates::Spherical<
506 OpenKalman::coordinates::Angle<Min1, Max1>,
507 OpenKalman::coordinates::Distance,
508 OpenKalman::coordinates::Inclination<Down1>>,
510 OpenKalman::coordinates::Angle<Min2, Max2>,
511 OpenKalman::coordinates::Distance,
512 OpenKalman::coordinates::Inclination<Down2>>>
514 OpenKalman::values::fixed_value_of_v<Min1> == OpenKalman::values::fixed_value_of_v<Min2> and
515 OpenKalman::values::fixed_value_of_v<Max1> == OpenKalman::values::fixed_value_of_v<Max2> and
516 OpenKalman::values::fixed_value_of_v<Down1> == OpenKalman::values::fixed_value_of_v<Down2>,
517 OpenKalman::coordinates::Spherical<
518 OpenKalman::coordinates::Angle<Min1, Max1>,
519 OpenKalman::coordinates::Distance,
520 OpenKalman::coordinates::Inclination<Down1>>,
521 OpenKalman::coordinates::Any<>> {};
524 template<
typename Min1,
typename Max1,
typename Min2,
typename Max2,
typename Down1,
typename Down2>
526 OpenKalman::coordinates::Spherical<
527 OpenKalman::coordinates::Angle<Min1, Max1>,
528 OpenKalman::coordinates::Inclination<Down1>,
529 OpenKalman::coordinates::Distance>,
531 OpenKalman::coordinates::Angle<Min2, Max2>,
532 OpenKalman::coordinates::Inclination<Down2>,
533 OpenKalman::coordinates::Distance>>
535 OpenKalman::values::fixed_value_of_v<Min1> == OpenKalman::values::fixed_value_of_v<Min2> and
536 OpenKalman::values::fixed_value_of_v<Max1> == OpenKalman::values::fixed_value_of_v<Max2> and
537 OpenKalman::values::fixed_value_of_v<Down1> == OpenKalman::values::fixed_value_of_v<Down2>,
538 OpenKalman::coordinates::Spherical<
539 OpenKalman::coordinates::Angle<Min1, Max1>,
540 OpenKalman::coordinates::Inclination<Down1>,
541 OpenKalman::coordinates::Distance>,
542 OpenKalman::coordinates::Any<>> {};
545 template<
typename C1,
typename C2,
typename C3,
typename Scalar>
547 : common_type<OpenKalman::coordinates::Any<Scalar>, OpenKalman::coordinates::Spherical<C1, C2, C3>> {};
550 template<
typename C1,
typename C2,
typename C3,
typename T>
551 struct common_type<OpenKalman::coordinates::Spherical<C1, C2, C3>, T>
552 : std::conditional_t<
553 OpenKalman::coordinates::descriptor<T>,
554 OpenKalman::stdex::type_identity<OpenKalman::coordinates::Any<>>,
A fixed version of pi.
Definition: fixed-constants.hpp:33
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
A non-negative real number φ representing an inclination (angle from the positive z axis)...
Definition: Inclination.hpp:40
typename real_type_of< T >::type real_type_of_t
Helper template for real_type_of.
Definition: real_type_of.hpp:55
Definition: fixed_value.hpp:41
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 copysign(const Mag &mag, const Sgn &sgn)
A constexpr function for copysign.
Definition: copysign.hpp:48
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 sqrt(const Arg &arg)
A constexpr alternative to std::sqrt.
Definition: sqrt.hpp:46
A coordinates::descriptor reflecting spherical coordinates according to the ISO 80000-2:2019 conventi...
Definition: Spherical.hpp:57
Definition: Spherical.hpp:79
constexpr auto real(const Arg &arg)
A constexpr function to obtain the real part of a (complex) number.
Definition: real.hpp:40
constexpr auto acos(const Arg &arg)
Constexpr alternative to the std::acos function.
Definition: acos.hpp:41
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
Definition of the Inclination class and related limits.
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
constexpr bool fixed
T is a value that is determinable at compile time.
Definition: fixed.hpp:66
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
constexpr auto hypot(const Args &...args)
A constexpr alternative to std::hypot.
Definition: hypot.hpp:45
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