Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

192 rindas
5.4 KiB

  1. use std::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
  2. use std::f64::consts::PI;
  3. use auto_ops::impl_op_ex;
  4. #[cfg(feature = "serde")]
  5. use serde::{Deserialize, Serialize};
  6. pub use super::numeric::{Float, Numeric};
  7. /* Angle */
  8. #[derive(Debug, Clone, Copy)]
  9. #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
  10. pub enum Angle<T> {
  11. Deg(T),
  12. Rad(T),
  13. }
  14. impl<T> Angle<T>
  15. where
  16. T: Numeric,
  17. {
  18. pub fn into_inner(self) -> T {
  19. match self {
  20. Self::Deg(v) => v,
  21. Self::Rad(v) => v,
  22. }
  23. }
  24. pub fn into_deg(self) -> Self {
  25. match self {
  26. Self::Deg(v) => Self::Deg(v),
  27. Self::Rad(v) => Self::Rad(T::to_degrees(v)),
  28. }
  29. }
  30. pub fn into_rad(self) -> Self {
  31. match self {
  32. Self::Deg(v) => Self::Deg(T::to_radians(v)),
  33. Self::Rad(v) => Self::Rad(v),
  34. }
  35. }
  36. pub fn abs(self) -> Self {
  37. match self {
  38. Self::Deg(value) => Self::Deg(value.abs()),
  39. Self::Rad(value) => Self::Rad(value.abs()),
  40. }
  41. }
  42. fn _neg(self) -> Self {
  43. match self {
  44. Self::Deg(value) => Self::Deg(-value),
  45. Self::Rad(value) => Self::Rad(-value),
  46. }
  47. }
  48. fn _add(self, other: &Self) -> Self {
  49. match self {
  50. Self::Deg(value) => Self::Deg(value + other.into_deg().into_inner()),
  51. Self::Rad(value) => Self::Rad(value + other.into_rad().into_inner()),
  52. }
  53. }
  54. fn _mul(self, other: T) -> Self {
  55. match self {
  56. Self::Deg(value) => Self::Deg(value * other),
  57. Self::Rad(value) => Self::Rad(value * other),
  58. }
  59. }
  60. }
  61. impl<T> Angle<T>
  62. where
  63. T: Float,
  64. {
  65. pub fn sin(self) -> T {
  66. T::sin(self.into_rad().into_inner())
  67. }
  68. pub fn cos(self) -> T {
  69. T::cos(self.into_rad().into_inner())
  70. }
  71. /// Normalizes the angle to (-pi, pi] / (-180.0, 180.0]
  72. pub fn normalize(self) -> Self {
  73. match self {
  74. Self::Deg(value) => Self::Deg(normalize(value, T::new(-180.0), T::new(180.0))),
  75. Self::Rad(value) => Self::Rad(normalize(value, T::new(-PI), T::new(PI))),
  76. }
  77. }
  78. }
  79. impl_op_ex!(*|a: &f32, b: &Angle<f32>| -> Angle<f32> { b._mul(*a) });
  80. impl_op_ex!(- <T: Numeric> |a: &Angle<T>| -> Angle<T> { a._neg() });
  81. impl_op_ex!(+ <T: Numeric> |a: &Angle<T>, b: &Angle<T>| -> Angle<T> { a._add(b) });
  82. impl_op_ex!(- <T: Numeric> |a: &Angle<T>, b: &Angle<T>| -> Angle<T> { a._add(&b._neg()) });
  83. impl_op_ex!(* <T: Numeric> |a: &Angle<T>, b: &T| -> Angle<T> { a._mul(*b) });
  84. impl_op_ex!(/ <T: Numeric> |a: &Angle<T>, b: &T| -> Angle<T> { a._mul(T::one() / *b) });
  85. impl_op_ex!(+= <T: Numeric> |a: &mut Angle<T>, b: &Angle<T>| { *a = a._add(b); });
  86. impl_op_ex!(-= <T: Numeric> |a: &mut Angle<T>, b: &Angle<T>| { *a = a._add(&b._neg()); });
  87. impl<T> Default for Angle<T>
  88. where
  89. T: Numeric,
  90. {
  91. fn default() -> Self {
  92. Self::Deg(T::zero())
  93. }
  94. }
  95. impl<T, S> PartialEq<Angle<S>> for Angle<T>
  96. where
  97. T: Numeric + PartialEq<S>,
  98. S: Numeric,
  99. {
  100. fn eq(&self, other: &Angle<S>) -> bool {
  101. match self {
  102. Self::Deg(v) => v.eq(&other.into_deg().into_inner()),
  103. Self::Rad(v) => v.eq(&other.into_rad().into_inner()),
  104. }
  105. }
  106. }
  107. impl<T> Eq for Angle<T> where T: Numeric + Eq {}
  108. impl<T, S> PartialOrd<Angle<S>> for Angle<T>
  109. where
  110. T: Numeric + PartialOrd<S>,
  111. S: Numeric,
  112. {
  113. fn partial_cmp(&self, other: &Angle<S>) -> Option<Ordering> {
  114. match self {
  115. Self::Deg(v) => v.partial_cmp(&other.into_deg().into_inner()),
  116. Self::Rad(v) => v.partial_cmp(&other.into_rad().into_inner()),
  117. }
  118. }
  119. }
  120. impl<T> Ord for Angle<T>
  121. where
  122. T: Ord + Numeric,
  123. {
  124. fn cmp(&self, other: &Self) -> Ordering {
  125. match self {
  126. Self::Deg(v) => v.cmp(&other.into_deg().into_inner()),
  127. Self::Rad(v) => v.cmp(&other.into_rad().into_inner()),
  128. }
  129. }
  130. }
  131. fn normalize<T>(value: T, min: T, max: T) -> T
  132. where
  133. T: Float,
  134. {
  135. let range = max - min;
  136. let value = value - min;
  137. let f = (value / range).floor();
  138. value + min - f * range
  139. }
  140. #[cfg(test)]
  141. mod tests {
  142. use super::*;
  143. #[test]
  144. fn normalize() {
  145. assert_eq!(Angle::Deg(-180.0), Angle::Deg(540.0).normalize());
  146. assert_eq!(Angle::Deg(-180.0), Angle::Deg(180.0).normalize());
  147. assert_eq!(Angle::Deg(-180.0), Angle::Deg(-180.0).normalize());
  148. assert_eq!(Angle::Deg(-180.0), Angle::Deg(-540.0).normalize());
  149. assert_eq!(Angle::Deg(0.0), Angle::Deg(720.0).normalize());
  150. assert_eq!(Angle::Deg(0.0), Angle::Deg(360.0).normalize());
  151. assert_eq!(Angle::Deg(0.0), Angle::Deg(-360.0).normalize());
  152. assert_eq!(Angle::Deg(0.0), Angle::Deg(-720.0).normalize());
  153. assert_eq!(Angle::Deg(90.0), Angle::Deg(-630.0).normalize());
  154. assert_eq!(Angle::Deg(90.0), Angle::Deg(-270.0).normalize());
  155. assert_eq!(Angle::Deg(90.0), Angle::Deg(90.0).normalize());
  156. assert_eq!(Angle::Deg(90.0), Angle::Deg(450.0).normalize());
  157. assert_eq!(Angle::Deg(90.0), Angle::Deg(810.0).normalize());
  158. assert_eq!(Angle::Deg(-90.0), Angle::Deg(-810.0).normalize());
  159. assert_eq!(Angle::Deg(-90.0), Angle::Deg(-450.0).normalize());
  160. assert_eq!(Angle::Deg(-90.0), Angle::Deg(-90.0).normalize());
  161. assert_eq!(Angle::Deg(-90.0), Angle::Deg(270.0).normalize());
  162. assert_eq!(Angle::Deg(-90.0), Angle::Deg(630.0).normalize());
  163. }
  164. }