16 #ifndef OPENKALMAN_SPHERICAL_HPP 17 #define OPENKALMAN_SPHERICAL_HPP 19 #include <type_traits> 26 #include "values/functions/internal/update_real_part.hpp" 27 #include "values/math/signbit.hpp" 28 #include "values/math/sqrt.hpp" 29 #include "values/math/abs.hpp" 30 #include "values/math/sin.hpp" 31 #include "values/math/cos.hpp" 32 #include "values/math/asin.hpp" 33 #include "values/math/atan2.hpp" 34 #include "linear-algebra/coordinates/interfaces/coordinate_descriptor_traits.hpp" 56 template<
typename C1 = Distance,
typename C2 = angle::Radians,
typename C3 = inclination::Radians>
59 (std::same_as<C1, Distance> and angle::angle<C2> and inclination::inclination<C3>) or
60 (std::same_as<C1, Distance> and angle::angle<C3> and inclination::inclination<C2>) or
61 (std::same_as<C2, Distance> and angle::angle<C1> and inclination::inclination<C3>) or
62 (std::same_as<C2, Distance> and angle::angle<C3> and inclination::inclination<C1>) or
63 (std::same_as<C3, Distance> and angle::angle<C1> and inclination::inclination<C2>) or
64 (std::same_as<C3, Distance> and angle::angle<C2> and inclination::inclination<C1>)
68 #ifndef __cpp_concepts 70 (std::is_same_v<C1, Distance> and angle::angle<C2> and inclination::inclination<C3>) or
71 (std::is_same_v<C1, Distance> and angle::angle<C3> and inclination::inclination<C2>) or
72 (std::is_same_v<C2, Distance> and angle::angle<C1> and inclination::inclination<C3>) or
73 (std::is_same_v<C2, Distance> and angle::angle<C3> and inclination::inclination<C1>) or
74 (std::is_same_v<C3, Distance> and angle::angle<C1> and inclination::inclination<C2>) or
75 (std::is_same_v<C3, Distance> and angle::angle<C2> and inclination::inclination<C1>));
87 template<
typename T,
typename Min,
typename Max,
typename Down,
typename Up, std::
size_t d_i, std::
size_t a_i, std::
size_t i_i>
92 static constexpr
auto min = values::fixed_number_of_v<Min>;
93 static constexpr
auto max = values::fixed_number_of_v<Max>;
94 static constexpr
auto down = values::fixed_number_of_v<Down>;
95 static constexpr
auto up = values::fixed_number_of_v<Up>;
99 static constexpr
bool is_specialized =
true;
102 static constexpr
auto 103 dimension(
const T&) {
return std::integral_constant<std::size_t, 3>{}; };
106 static constexpr
auto 107 stat_dimension(
const T&) {
return std::integral_constant<std::size_t, 4>{}; };
110 static constexpr
auto 111 is_euclidean(
const T&) {
return std::false_type{}; }
114 static constexpr std::size_t
119 constexpr std::size_t f = (a_i * 2 + i_i * 3 - 2);
120 constexpr
auto bits = std::numeric_limits<std::size_t>::digits;
121 if constexpr (bits < 32)
return (a - 0x83B0_uz) + (b - 0x83B0_uz) + f * 0x1000_uz;
122 else if constexpr (bits < 64)
return (a - 0x83B023AB_uz) + (b - 0x83B023AB_uz) + f * 0x10000000_uz;
123 else return (a - 0x83B023AB3EEFB99A_uz) + (b - 0x83B023AB3EEFB99A_uz) + f * 0x1000000000000000_uz;
128 static constexpr std::size_t d2_i = 0, x_i = 1, y_i = 2, z_i = 3;
140 #ifdef __cpp_concepts 142 to_euclidean_component(
const T& t,
const auto& g,
const values::index auto& euclidean_local_index)
145 template<
typename Getter,
typename L, std::enable_if_t<values::index<L> and
146 values::value<
typename std::invoke_result<const Getter&, std::
size_t>::type>,
int> = 0>
147 static constexpr
auto 151 if (euclidean_local_index == d2_i)
157 using Scalar = std::decay_t<decltype(g(std::declval<std::size_t>()))>;
158 using R = std::decay_t<decltype(values::real(std::declval<Scalar>()))>;
159 const Scalar cf_inc {numbers::pi_v<R> / (up - down)};
160 const Scalar horiz {R{up + down} * R{0.5}};
162 Scalar phi = cf_inc * (g(i_i) - horiz);
163 if (euclidean_local_index == z_i)
169 const Scalar cf_cir {2 * numbers::pi_v<R> / (max - min)};
170 const Scalar mid {R{max + min} * R{0.5}};
171 Scalar theta = cf_cir * (g(a_i) - mid);
188 #ifdef __cpp_concepts 190 from_euclidean_component(
const T& t,
const auto& g,
const values::index auto& local_index)
193 template<
typename Getter,
typename L, std::enable_if_t<values::index<L> and
194 values::value<
typename std::invoke_result<const Getter&, std::
size_t>::type>,
int> = 0>
195 static constexpr
auto 199 using Scalar = decltype(g(std::declval<std::size_t>()));
203 if (local_index == d_i)
205 return values::internal::update_real_part(d,
values::abs(dr));
209 using R = std::decay_t<decltype(values::real(std::declval<Scalar>()))>;
210 const Scalar cf_cir {2 * numbers::pi_v<R> / (max - min)};
211 const Scalar mid {R{max + min} * R{0.5}};
223 Scalar x2 = values::internal::update_real_part(x,
values::signbit(dr) ? -xp : xp);
224 Scalar y2 = values::internal::update_real_part(y,
values::signbit(dr) ? -yp : yp);
226 if constexpr (values::complex<Scalar>)
return values::atan2(y2, x2) / cf_cir + mid;
231 const Scalar cf_inc {numbers::pi_v<R> / (up - down)};
232 const Scalar horiz {R{up + down} * R{0.5}};
235 Scalar z2 {values::internal::update_real_part(z,
values::signbit(dr) ? -zp : zp)};
237 if constexpr (values::complex<Scalar>)
240 return theta / cf_inc + horiz;
246 auto theta = (r == 0 or r < z2 or z2 < -r) ? R{0} :
values::asin(z2/r);
247 return theta / cf_inc + horiz;
258 template<
typename Scalar>
259 static constexpr
auto 260 inclination_wrap_impl(
const Scalar& a)
262 using Ret = std::tuple<std::decay_t<std::decay_t<decltype(values::real(a))>>,
bool>;
264 using R = std::decay_t<decltype(ap)>;
265 if (ap >= down and ap <= up)
267 return Ret { ap,
false };
271 constexpr R period = 2 * (up - down);
273 R ar = fmod(ap - R{down}, period);
274 R ar2 = ar < 0 ? ar + period : ar;
275 bool b = ar2 > up - down;
276 return Ret { R{down} + (b ? period - ar2 : ar2), b };
281 template<
typename Scalar>
282 static constexpr std::decay_t<Scalar>
283 azimuth_wrap_impl(
bool reflect_azimuth, Scalar&& a)
285 using R = std::decay_t<decltype(values::real(std::declval<decltype(a)>()))>;
286 constexpr R period {max - min};
287 constexpr R half_period {(max - min) / R{2}};
290 if (ap >= min and ap < max)
292 return values::internal::update_real_part(std::forward<decltype(a)>(a), ap);;
297 auto ar = fmod(ap - R{min}, period);
298 if (ar < 0)
return values::internal::update_real_part(std::forward<decltype(a)>(a), R{min} + ar + period);
299 else return values::internal::update_real_part(std::forward<decltype(a)>(a), R{min} + ar);
312 #ifdef __cpp_concepts 314 get_wrapped_component(
const T& t,
const auto& g,
const values::index auto& local_index)
317 template<
typename Getter,
typename L, std::enable_if_t<values::index<L> and
318 values::value<
typename std::invoke_result<const Getter&, std::
size_t>::type>,
int> = 0>
319 static constexpr
auto 330 return values::internal::update_real_part(d,
values::abs(dp));
334 const bool b = std::get<1>(inclination_wrap_impl(g(i_i)));
340 auto new_i = std::get<0>(inclination_wrap_impl(i));
341 return values::internal::update_real_part(i,
values::signbit(dp) ? -new_i : new_i);
356 #ifdef __cpp_concepts 357 static constexpr
void 358 set_wrapped_component(
const T& t,
const auto& s,
const auto& g,
const values::value auto& x,
const values::index auto& local_index)
359 requires requires(std::size_t i){ s(x, i); s(g(i), i); }
361 template<
typename Setter,
typename Getter,
typename X,
typename L, std::enable_if_t<values::value<X> and values::index<L> and
362 std::is_invocable<const Setter&, const X&, std::
size_t>::value and
363 std::is_invocable<const Setter&,
typename std::invoke_result<const Getter&, std::
size_t>::type, std::
size_t>::value,
int> = 0>
364 static constexpr
void 373 s(values::internal::update_real_part(x,
values::abs(dp)), d_i);
376 auto azimuth_i = a_i;
377 auto inclination = i_i;
378 s(azimuth_wrap_impl(
true, g(azimuth_i)), azimuth_i);
379 s(-g(inclination), inclination);
385 s(azimuth_wrap_impl(
false, x), a_i);
390 const auto [ip, b] = inclination_wrap_impl(x);
391 s(values::internal::update_real_part(x, ip), i_i);
392 const auto azimuth_i = a_i;
393 s(azimuth_wrap_impl(b, g(azimuth_i)), azimuth_i);
408 template<
typename Min,
typename Max,
typename Down,
typename Up>
410 :
detail::SphericalBase<coordinates::Spherical<coordinates::Distance, coordinates::Angle<Min, Max>, coordinates::Inclination<Down, Up>>, Min, Max, Down, Up, 0, 1, 2>
418 template<
typename Down,
typename Up,
typename Min,
typename Max>
420 :
detail::SphericalBase<coordinates::Spherical<coordinates::Distance, coordinates::Inclination<Down, Up>, coordinates::Angle<Min, Max>>, Min, Max, Down, Up, 0, 2, 1>
428 template<
typename Min,
typename Max,
typename Down,
typename Up>
430 :
detail::SphericalBase<coordinates::Spherical<coordinates::Angle<Min, Max>, coordinates::Distance, coordinates::Inclination<Down, Up>>, Min, Max, Down, Up, 1, 0, 2>
438 template<
typename Down,
typename Up,
typename Min,
typename Max>
440 :
detail::SphericalBase<coordinates::Spherical<coordinates::Inclination<Down, Up>, coordinates::Distance, coordinates::Angle<Min, Max>>, Min, Max, Down, Up, 1, 2, 0>
448 template<
typename Min,
typename Max,
typename Down,
typename Up>
450 :
detail::SphericalBase<coordinates::Spherical<coordinates::Angle<Min, Max>, coordinates::Inclination<Down, Up>, coordinates::Distance>, Min, Max, Down, Up, 2, 0, 1>
458 template<
typename Down,
typename Up,
typename Min,
typename Max>
460 :
detail::SphericalBase<coordinates::Spherical<coordinates::Inclination<Down, Up>, coordinates::Angle<Min, Max>, coordinates::Distance>, Min, Max, Down, Up, 2, 1, 0>
466 #endif //OPENKALMAN_SPHERICAL_HPP Definition for get_hash_code.
Definition of the Distance class.
Definition: basics.hpp:41
A positive or negative real number φ representing an inclination or declination from the horizon...
Definition: Inclination.hpp:55
static constexpr auto to_euclidean_component(const T &t, const Getter &g, const L &euclidean_local_index)
Maps an element to coordinates in Euclidean space.
Definition: Spherical.hpp:148
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
static constexpr auto get_wrapped_component(const T &t, const Getter &g, const L &local_index)
Perform modular wrapping of spherical coordinates.
Definition: Spherical.hpp:320
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
Definitions relating to the availability of c++ language features.
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: Spherical.hpp:196
constexpr auto sqrt(const Arg &arg)
A constexpr alternative to std::sqrt.
Definition: sqrt.hpp:46
constexpr auto atan2(const Y &y_arg, const X &x_arg)
Constexpr alternative to the std::atan2 function.
Definition: atan2.hpp:46
A coordinates::descriptor reflecting spherical coordinates.
Definition: Spherical.hpp:66
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
Definition: Spherical.hpp:88
Traits for coordinates::pattern objects.
Definition: coordinate_descriptor_traits.hpp:41
constexpr auto abs(const Arg &arg)
A constexpr alternative to std::abs.
Definition: abs.hpp:38
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: Spherical.hpp:365
constexpr bool index
T is an index value.
Definition: index.hpp:56
Definition of the Inclination class and related limits.
Definition for values::number.
An angle or any other simple modular value.
Definition: Angle.hpp:62
Definition for values::real.
constexpr auto asin(const Arg &arg)
Constexpr alternative to the std::asin function.
Definition: asin.hpp:44
Definition of the Angle class and related limits.