Angle.cs 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. /*
  2. * -----------------------------------------------------------------------------
  3. * Original code from SlimMath project. http://code.google.com/p/slimmath/
  4. * Greetings to SlimDX Group. Original code published with the following license:
  5. * -----------------------------------------------------------------------------
  6. *
  7. * Copyright (c) 2007-2010 SlimDX Group
  8. *
  9. * Permission is hereby granted, free of charge, to any person obtaining a copy
  10. * of this software and associated documentation files (the "Software"), to deal
  11. * in the Software without restriction, including without limitation the rights
  12. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  13. * copies of the Software, and to permit persons to whom the Software is
  14. * furnished to do so, subject to the following conditions:
  15. *
  16. * The above copyright notice and this permission notice shall be included in
  17. * all copies or substantial portions of the Software.
  18. *
  19. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  20. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  22. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  23. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  24. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  25. * THE SOFTWARE.
  26. */
  27. using System;
  28. using System.Diagnostics;
  29. using System.Runtime.Serialization;
  30. using Microsoft.Xna.Framework;
  31. namespace MonoGame.Extended
  32. {
  33. public enum AngleType : byte
  34. {
  35. Radian = 0,
  36. Degree,
  37. Revolution, //or Turn / cycle
  38. Gradian // or Gon
  39. }
  40. [DataContract]
  41. [DebuggerDisplay("{ToString(),nq}")]
  42. public struct Angle : IComparable<Angle>, IEquatable<Angle>
  43. {
  44. private const float _tau = (float) (Math.PI*2.0);
  45. private const float _tauInv = (float) (0.5/Math.PI);
  46. private const float _degreeRadian = (float) (Math.PI/180.0);
  47. private const float _radianDegree = (float) (180.0/Math.PI);
  48. private const float _gradianRadian = (float) (Math.PI/200.0);
  49. private const float _radianGradian = (float) (200.0/Math.PI);
  50. [DataMember]
  51. public float Radians { get; set; }
  52. public float Degrees
  53. {
  54. get => Radians*_radianDegree;
  55. set => Radians = value*_degreeRadian;
  56. }
  57. public float Gradians
  58. {
  59. get => Radians*_radianGradian;
  60. set => Radians = value*_gradianRadian;
  61. }
  62. public float Revolutions
  63. {
  64. get => Radians*_tauInv;
  65. set => Radians = value*_tau;
  66. }
  67. public Angle(float value, AngleType angleType = AngleType.Radian)
  68. {
  69. switch (angleType)
  70. {
  71. default:
  72. Radians = 0f;
  73. break;
  74. case AngleType.Radian:
  75. Radians = value;
  76. break;
  77. case AngleType.Degree:
  78. Radians = value*_degreeRadian;
  79. break;
  80. case AngleType.Revolution:
  81. Radians = value*_tau;
  82. break;
  83. case AngleType.Gradian:
  84. Radians = value*_gradianRadian;
  85. break;
  86. }
  87. }
  88. public float GetValue(AngleType angleType)
  89. {
  90. switch (angleType)
  91. {
  92. default:
  93. return 0f;
  94. case AngleType.Radian:
  95. return Radians;
  96. case AngleType.Degree:
  97. return Degrees;
  98. case AngleType.Revolution:
  99. return Revolutions;
  100. case AngleType.Gradian:
  101. return Gradians;
  102. }
  103. }
  104. public void Wrap()
  105. {
  106. var angle = Radians%_tau;
  107. if (angle <= Math.PI) angle += _tau;
  108. if (angle > Math.PI) angle -= _tau;
  109. Radians = angle;
  110. }
  111. public void WrapPositive()
  112. {
  113. Radians %= _tau;
  114. if (Radians < 0d) Radians += _tau;
  115. Radians = Radians;
  116. }
  117. public static Angle FromVector(Vector2 vector)
  118. {
  119. return new Angle((float) Math.Atan2(-vector.Y, vector.X));
  120. }
  121. public Vector2 ToUnitVector() => ToVector(1);
  122. public Vector2 ToVector(float length)
  123. {
  124. return new Vector2(length*(float) Math.Cos(Radians), -length*(float) Math.Sin(Radians));
  125. }
  126. public static bool IsBetween(Angle value, Angle min, Angle end)
  127. {
  128. return end < min
  129. ? (value >= min) || (value <= end)
  130. : (value >= min) && (value <= end);
  131. }
  132. public int CompareTo(Angle other)
  133. {
  134. WrapPositive();
  135. other.WrapPositive();
  136. return Radians.CompareTo(other.Radians);
  137. }
  138. public bool Equals(Angle other)
  139. {
  140. WrapPositive();
  141. other.WrapPositive();
  142. return Radians.Equals(other.Radians);
  143. }
  144. public override bool Equals(object obj)
  145. {
  146. if (ReferenceEquals(null, obj)) return false;
  147. return obj is Angle a && Equals(a);
  148. }
  149. public override int GetHashCode()
  150. {
  151. // ReSharper disable once NonReadonlyMemberInGetHashCode
  152. return Radians.GetHashCode();
  153. }
  154. public static implicit operator float(Angle angle)
  155. {
  156. return angle.Radians;
  157. }
  158. public static explicit operator Angle(float angle)
  159. {
  160. return new Angle(angle);
  161. }
  162. public static Angle operator -(Angle angle)
  163. {
  164. return new Angle(-angle.Radians);
  165. }
  166. public static bool operator ==(Angle a, Angle b)
  167. {
  168. return a.Equals(b);
  169. }
  170. public static bool operator !=(Angle a, Angle b)
  171. {
  172. return !a.Equals(b);
  173. }
  174. public static Angle operator -(Angle left, Angle right)
  175. {
  176. return new Angle(left.Radians - right.Radians);
  177. }
  178. public static Angle operator *(Angle left, float right)
  179. {
  180. return new Angle(left.Radians*right);
  181. }
  182. public static Angle operator *(float left, Angle right)
  183. {
  184. return new Angle(right.Radians*left);
  185. }
  186. public static Angle operator +(Angle left, Angle right)
  187. {
  188. return new Angle(left.Radians + right.Radians);
  189. }
  190. public override string ToString()
  191. {
  192. return $"{Radians} Radians";
  193. }
  194. }
  195. }