1#ifndef LIBSBX_MATH_ANGLE_HPP_
2#define LIBSBX_MATH_ANGLE_HPP_
8#include <libsbx/math/concepts.hpp>
9#include <libsbx/math/smooth_value.hpp>
13template<
floating_po
int Type>
18 using value_type = Type;
21 inline static constexpr basic_degree max{value_type{360}};
25 template<scalar Other>
26 requires (std::is_convertible_v<Other, Type>)
28 : _value{
static_cast<Type
>(value)} { }
30 template<
floating_po
int Other>
31 requires (std::is_convertible_v<Other, Type>)
33 : _value{
static_cast<Type
>(other._value)} { }
37 template<
floating_po
int Other>
38 requires (std::is_convertible_v<Other, Type>)
40 _value =
static_cast<Type
>(other._value);
45 template<
floating_po
int Other>
46 requires (std::is_convertible_v<Other, Type>)
48 _value +=
static_cast<Type
>(rhs._value);
53 template<
floating_po
int Other>
54 requires (std::is_convertible_v<Other, Type>)
56 _value -=
static_cast<Type
>(rhs._value);
61 template<
floating_po
int Other>
62 requires (std::is_convertible_v<Other, Type>)
64 _value *=
static_cast<Type
>(rhs);
69 template<
floating_po
int Other>
70 requires (std::is_convertible_v<Other, Type>)
72 _value /=
static_cast<Type
>(rhs);
77 constexpr auto value()
const noexcept -> value_type {
81 constexpr operator value_type()
const noexcept {
91template<
floating_po
int Type>
93 return static_cast<basic_degree<Type>::value_type
>(lhs) ==
static_cast<basic_degree<Type>::value_type
>(rhs);
96template<
floating_po
int Type,
floating_po
int Other>
97constexpr auto operator<=>(
const basic_degree<Type>& lhs,
const basic_degree<Other>& rhs)
noexcept -> std::partial_ordering {
98 return static_cast<basic_degree<Type>::value_type
>(lhs) <=>
static_cast<basic_degree<Type>::value_type
>(rhs);
101template<
floating_po
int Type,
floating_po
int Other>
102requires (std::is_convertible_v<Other, Type>)
103constexpr auto operator+(basic_degree<Type> lhs,
const basic_degree<Other>& rhs)
noexcept -> basic_degree<Type> {
107template<
floating_po
int Type,
floating_po
int Other>
108requires (std::is_convertible_v<Other, Type>)
109constexpr auto operator-(basic_degree<Type> lhs,
const basic_degree<Other>& rhs)
noexcept -> basic_degree<Type> {
113template<
floating_po
int Type, std::convertible_to<Type> Other>
114constexpr auto operator*(basic_degree<Type> lhs,
const Other rhs)
noexcept -> basic_degree<Type> {
115 return lhs *=
static_cast<Type
>(rhs);
118template<
floating_po
int Type, std::convertible_to<Type> Other>
119constexpr auto operator/(basic_degree<Type> lhs,
const Other rhs)
noexcept -> basic_degree<Type> {
120 return lhs /=
static_cast<Type
>(rhs);
123template<
floating_po
int Type>
124constexpr auto clamp(
const basic_degree<Type>& value,
const basic_degree<Type>& min,
const basic_degree<Type>& max) ->
const basic_degree<Type>& {
136using degree = basic_degree<std::float_t>;
138template<
floating_po
int Type>
141template<
floating_po
int Type>
147 return base_trait::equal(lhs.value(), rhs.value());
152template<
floating_po
int Type>
157template<
floating_po
int Type>
162 using value_type = Type;
164 inline static constexpr basic_radian min{value_type{0}};
165 inline static constexpr basic_radian max{value_type{2 * std::numbers::pi_v<value_type>}};
169 template<scalar Other>
170 requires (std::is_convertible_v<Other, Type>)
172 : _value{
static_cast<Type
>(value)} { }
174 template<
floating_po
int Other>
175 requires (std::is_convertible_v<Other, Type>)
177 : _value{
static_cast<Type
>(other._value)} { }
181 template<
floating_po
int Other>
182 requires (std::is_convertible_v<Other, Type>)
184 _value =
static_cast<Type
>(other._value);
189 template<
floating_po
int Other>
190 requires (std::is_convertible_v<Other, Type>)
192 _value +=
static_cast<Type
>(rhs._value);
197 template<
floating_po
int Other>
198 requires (std::is_convertible_v<Other, Type>)
200 _value -=
static_cast<Type
>(rhs._value);
205 template<
floating_po
int Other>
206 requires (std::is_convertible_v<Other, Type>)
208 _value *=
static_cast<Type
>(rhs);
213 constexpr auto value()
const noexcept -> value_type {
217 constexpr operator value_type()
const noexcept {
227template<
floating_po
int Type>
229 return static_cast<basic_radian<Type>::value_type
>(lhs) ==
static_cast<basic_radian<Type>::value_type
>(rhs);
232template<
floating_po
int Type,
floating_po
int Other>
233constexpr auto operator<=>(
const basic_radian<Type>& lhs,
const basic_radian<Other>& rhs)
noexcept -> std::partial_ordering {
234 return static_cast<basic_radian<Type>::value_type
>(lhs) <=>
static_cast<basic_radian<Type>::value_type
>(rhs);
237template<
floating_po
int Type,
floating_po
int Other>
238requires (std::is_convertible_v<Other, Type>)
239constexpr auto operator+(basic_radian<Type> lhs,
const basic_radian<Other>& rhs)
noexcept -> basic_radian<Type> {
243template<
floating_po
int Type,
floating_po
int Other>
244requires (std::is_convertible_v<Other, Type>)
245constexpr auto operator-(basic_radian<Type> lhs,
const basic_radian<Other>& rhs)
noexcept -> basic_radian<Type> {
249template<
floating_po
int Type, std::convertible_to<Type> Other>
250requires (std::is_convertible_v<Other, Type>)
251constexpr auto operator*(basic_radian<Type> lhs,
const Other rhs)
noexcept -> basic_radian<Type> {
252 return lhs *=
static_cast<Type
>(rhs);
255template<
floating_po
int Type>
256constexpr auto clamp(
const basic_radian<Type>& value,
const basic_radian<Type>& min,
const basic_radian<Type>& max) ->
const basic_radian<Type>& {
268using radian = basic_radian<std::float_t>;
270template<
floating_po
int Type>
275 using value_type = Type;
278 : _radian{
degree.value() * std::numbers::pi_v<value_type> /
static_cast<value_type
>(180)} {}
283 template<
floating_po
int Other>
284 requires (std::is_convertible_v<Other, Type>)
286 : _radian{other._radian} { }
288 template<
floating_po
int Other>
289 requires (std::is_convertible_v<Other, Type>)
296 template<
floating_po
int Other>
297 requires (std::is_convertible_v<Other, Type>)
302 template<
floating_po
int Other>
303 requires (std::is_convertible_v<Other, Type>)
308 template<
floating_po
int Other>
309 requires (std::is_convertible_v<Other, Type>)
316 template<
floating_po
int Other>
317 requires (std::is_convertible_v<Other, Type>)
322 template<
floating_po
int Other>
323 requires (std::is_convertible_v<Other, Type>)
328 template<
floating_po
int Other>
329 requires (std::is_convertible_v<Other, Type>)
350template<
floating_po
int Type>
352 return lhs.to_radians() == rhs.to_radians();
355template<
floating_po
int Type,
floating_po
int Other>
356constexpr auto operator<=>(
const basic_angle<Type>& lhs,
const basic_angle<Other>& rhs)
noexcept -> std::partial_ordering {
357 return lhs.to_radians() <=> rhs.to_radians();
360template<
floating_po
int LhsType,
floating_po
int RhsType>
361requires (std::is_convertible_v<RhsType, LhsType>)
362constexpr auto operator+(basic_angle<LhsType> lhs,
const basic_angle<RhsType>& rhs)
noexcept -> basic_angle<LhsType> {
366template<
floating_po
int LhsType,
floating_po
int RhsType>
367requires (std::is_convertible_v<RhsType, LhsType>)
368constexpr auto operator+(basic_angle<LhsType> lhs,
const basic_degree<RhsType>& rhs)
noexcept -> basic_angle<LhsType> {
369 return lhs += basic_angle<LhsType>(rhs);
372template<
floating_po
int LhsType,
floating_po
int RhsType>
373requires (std::is_convertible_v<RhsType, LhsType>)
374constexpr auto operator+(basic_angle<LhsType> lhs,
const basic_radian<RhsType>& rhs)
noexcept -> basic_angle<LhsType> {
375 return lhs += basic_angle<LhsType>(rhs);
378template<
floating_po
int LhsType,
floating_po
int RhsType>
379requires (std::is_convertible_v<RhsType, LhsType>)
380constexpr auto operator-(basic_angle<LhsType> lhs,
const basic_angle<RhsType>& rhs)
noexcept -> basic_angle<LhsType> {
384template<
floating_po
int LhsType,
floating_po
int RhsType>
385requires (std::is_convertible_v<RhsType, LhsType>)
386constexpr auto operator-(basic_angle<LhsType> lhs,
const basic_degree<RhsType>& rhs)
noexcept -> basic_angle<LhsType> {
387 return lhs -= basic_angle<LhsType>(rhs);
390template<
floating_po
int LhsType,
floating_po
int RhsType>
391requires (std::is_convertible_v<RhsType, LhsType>)
392constexpr auto operator-(basic_angle<LhsType> lhs,
const basic_radian<RhsType>& rhs)
noexcept -> basic_angle<LhsType> {
393 return lhs -= basic_angle<LhsType>(rhs);
396template<
floating_po
int LhsType,
floating_po
int RhsType>
397requires (std::is_convertible_v<RhsType, LhsType>)
398constexpr auto operator*(basic_angle<LhsType> lhs,
const RhsType rhs)
noexcept -> basic_angle<LhsType> {
402template<
floating_po
int Type>
403constexpr auto clamp(
const basic_angle<Type>& value,
const basic_angle<Type>& min,
const basic_angle<Type>& max) ->
const basic_angle<Type>& {
415using angle = basic_angle<std::float_t>;
417template<
floating_po
int Type>
418constexpr auto to_degrees(
const basic_radian<Type>& radian)
noexcept -> basic_degree<Type> {
419 return basic_angle<Type>{radian}.to_degrees();
422template<
floating_po
int Type>
423constexpr auto to_radians(
const basic_degree<Type>& degree)
noexcept -> basic_radian<Type> {
424 return basic_angle<Type>{degree}.to_radians();
429constexpr auto operator""_deg(
long double value)
noexcept -> degree {
430 return degree{
static_cast<std::float_t
>(value)};
433constexpr auto operator""_deg(
unsigned long long value)
noexcept -> degree {
434 return degree{
static_cast<std::float_t
>(value)};
437constexpr auto operator""_rad(
long double value)
noexcept -> radian {
438 return radian{
static_cast<std::float_t
>(value)};
441constexpr auto operator""_rad(
unsigned long long value)
noexcept -> radian {
442 return radian{
static_cast<std::float_t
>(value)};
Definition: angle.hpp:271
Definition: angle.hpp:158
Definition: traits.hpp:13
Definition: traits.hpp:10
Definition: smooth_value.hpp:25