VectorExtensions.cs 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. using System.Collections.Generic;
  2. using System.Linq;
  3. using UnityEngine;
  4. namespace Rokid.UXR.Exentesions
  5. {
  6. /// <summary>
  7. /// Extension methods for Unity's Vector struct
  8. /// </summary>
  9. public static class VectorExtensions
  10. {
  11. public static Vector2 Mul(this Vector2 value, Vector2 scale)
  12. {
  13. return new Vector2(value.x * scale.x, value.y * scale.y);
  14. }
  15. public static Vector2 Div(this Vector2 value, Vector2 scale)
  16. {
  17. return new Vector2(value.x / scale.x, value.y / scale.y);
  18. }
  19. public static Vector3 Mul(this Vector3 value, Vector3 scale)
  20. {
  21. return new Vector3(value.x * scale.x, value.y * scale.y, value.z * scale.z);
  22. }
  23. public static Vector3 Div(this Vector3 value, Vector3 scale)
  24. {
  25. return new Vector3(value.x / scale.x, value.y / scale.y, value.z / scale.z);
  26. }
  27. public static Vector3 RotateAround(this Vector3 point, Vector3 pivot, Quaternion rotation)
  28. {
  29. return rotation * (point - pivot) + pivot;
  30. }
  31. public static Vector3 RotateAround(this Vector3 point, Vector3 pivot, Vector3 eulerAngles)
  32. {
  33. return RotateAround(point, pivot, Quaternion.Euler(eulerAngles));
  34. }
  35. public static Vector3 TransformPoint(this Vector3 point, Vector3 translation, Quaternion rotation, Vector3 lossyScale)
  36. {
  37. return rotation * Vector3.Scale(lossyScale, point) + translation;
  38. }
  39. public static Vector3 InverseTransformPoint(this Vector3 point, Vector3 translation, Quaternion rotation, Vector3 lossyScale)
  40. {
  41. var scaleInv = new Vector3(1 / lossyScale.x, 1 / lossyScale.y, 1 / lossyScale.z);
  42. return Vector3.Scale(scaleInv, (Quaternion.Inverse(rotation) * (point - translation)));
  43. }
  44. public static Vector2 Average(this IEnumerable<Vector2> vectors)
  45. {
  46. float x = 0f;
  47. float y = 0f;
  48. int count = 0;
  49. foreach (var pos in vectors)
  50. {
  51. x += pos.x;
  52. y += pos.y;
  53. count++;
  54. }
  55. return new Vector2(x / count, y / count);
  56. }
  57. public static Vector3 Average(this IEnumerable<Vector3> vectors)
  58. {
  59. float x = 0f;
  60. float y = 0f;
  61. float z = 0f;
  62. int count = 0;
  63. foreach (var pos in vectors)
  64. {
  65. x += pos.x;
  66. y += pos.y;
  67. z += pos.z;
  68. count++;
  69. }
  70. return new Vector3(x / count, y / count, z / count);
  71. }
  72. public static Vector2 Average(this ICollection<Vector2> vectors)
  73. {
  74. int count = vectors.Count;
  75. if (count == 0)
  76. {
  77. return Vector2.zero;
  78. }
  79. float x = 0f;
  80. float y = 0f;
  81. foreach (var pos in vectors)
  82. {
  83. x += pos.x;
  84. y += pos.y;
  85. }
  86. return new Vector2(x / count, y / count);
  87. }
  88. public static Vector3 Average(this ICollection<Vector3> vectors)
  89. {
  90. int count = vectors.Count;
  91. if (count == 0)
  92. {
  93. return Vector3.zero;
  94. }
  95. float x = 0f;
  96. float y = 0f;
  97. float z = 0f;
  98. foreach (var pos in vectors)
  99. {
  100. x += pos.x;
  101. y += pos.y;
  102. z += pos.z;
  103. }
  104. return new Vector3(x / count, y / count, z / count);
  105. }
  106. public static Vector2 Median(this IEnumerable<Vector2> vectors)
  107. {
  108. var enumerable = vectors as Vector2[] ?? vectors.ToArray();
  109. int count = enumerable.Length;
  110. return count == 0 ? Vector2.zero : enumerable.OrderBy(v => v.sqrMagnitude).ElementAt(count / 2);
  111. }
  112. public static Vector3 Median(this IEnumerable<Vector3> vectors)
  113. {
  114. var enumerable = vectors as Vector3[] ?? vectors.ToArray();
  115. int count = enumerable.Length;
  116. return count == 0 ? Vector3.zero : enumerable.OrderBy(v => v.sqrMagnitude).ElementAt(count / 2);
  117. }
  118. public static Vector2 Median(this ICollection<Vector2> vectors)
  119. {
  120. int count = vectors.Count;
  121. return count == 0 ? Vector2.zero : vectors.OrderBy(v => v.sqrMagnitude).ElementAt(count / 2);
  122. }
  123. public static Vector3 Median(this ICollection<Vector3> vectors)
  124. {
  125. int count = vectors.Count;
  126. return count == 0 ? Vector3.zero : vectors.OrderBy(v => v.sqrMagnitude).ElementAt(count / 2);
  127. }
  128. public static bool IsValidVector(this Vector3 vector)
  129. {
  130. return !float.IsNaN(vector.x) && !float.IsNaN(vector.y) && !float.IsNaN(vector.z) &&
  131. !float.IsInfinity(vector.x) && !float.IsInfinity(vector.y) && !float.IsInfinity(vector.z);
  132. }
  133. /// <summary>
  134. /// Determines if the distance between two vectors is within a given tolerance.
  135. /// </summary>
  136. /// <param name="v1">The first vector.</param>
  137. /// <param name="v2">The second vector.</param>
  138. /// <param name="distanceTolerance">The maximum distance that will cause this to return true.</param>
  139. /// <returns>True if the distance between the two vectors is within the tolerance, false otherwise.</returns>
  140. public static bool CloseEnough(Vector3 v1, Vector3 v2, float distanceTolerance)
  141. {
  142. return Mathf.Abs(Vector3.Distance(v1, v2)) < distanceTolerance;
  143. }
  144. /// <summary>
  145. /// Get the relative mapping based on a source Vec3 and a radius for spherical mapping.
  146. /// </summary>
  147. /// <param name="source">The source <see href="https://docs.unity3d.com/ScriptReference/Vector3.html">Vector3</see> to be mapped to sphere</param>
  148. /// <param name="radius">This is a <see cref="float"/> for the radius of the sphere</param>
  149. public static Vector3 SphericalMapping(Vector3 source, float radius)
  150. {
  151. float circ = 2f * Mathf.PI * radius;
  152. float xAngle = (source.x / circ) * 360f;
  153. float yAngle = -(source.y / circ) * 360f;
  154. source.Set(0.0f, 0.0f, radius);
  155. Quaternion rot = Quaternion.Euler(yAngle, xAngle, 0.0f);
  156. source = rot * source;
  157. return source;
  158. }
  159. /// <summary>
  160. /// Get the relative mapping based on a source Vec3 and a radius for cylinder mapping.
  161. /// </summary>
  162. /// <param name="source">The source <see href="https://docs.unity3d.com/ScriptReference/Vector3.html">Vector3</see> to be mapped to cylinder</param>
  163. /// <param name="radius">This is a <see cref="float"/> for the radius of the cylinder</param>
  164. public static Vector3 CylindricalMapping(Vector3 source, float radius)
  165. {
  166. float circ = 2f * Mathf.PI * radius;
  167. float xAngle = (source.x / circ) * 360f;
  168. source.Set(0.0f, source.y, radius);
  169. Quaternion rot = Quaternion.Euler(0.0f, xAngle, 0.0f);
  170. source = rot * source;
  171. return source;
  172. }
  173. /// <summary>
  174. /// Get the relative mapping based on a source Vec3 and a radius for radial mapping.
  175. /// </summary>
  176. /// <param name="source">The source <see href="https://docs.unity3d.com/ScriptReference/Vector3.html">Vector3</see> to be mapped to cylinder</param>
  177. /// <param name="radialRange">The total range of the radial in degrees as a <see cref="float"/></param>
  178. /// <param name="radius">This is a <see cref="float"/> for the radius of the radial</param>
  179. /// <param name="row">The current row as a <see cref="int"/> for the radial calculation</param>
  180. /// <param name="totalRows">The total rows as a <see cref="int"/> for the radial calculation</param>
  181. /// <param name="column">The current column as a <see cref="int"/> for the radial calculation</param>
  182. /// <param name="totalColumns">The total columns as a <see cref="int"/> for the radial calculation</param>
  183. public static Vector3 RadialMapping(Vector3 source, float radialRange, float radius, int row, int totalRows, int column, int totalColumns)
  184. {
  185. float radialCellAngle = radialRange / totalColumns;
  186. source.x = 0f;
  187. source.y = 0f;
  188. source.z = (radius / totalRows) * row;
  189. float yAngle = radialCellAngle * (column - (totalColumns * 0.5f)) + (radialCellAngle * .5f);
  190. Quaternion rot = Quaternion.Euler(0.0f, yAngle, 0.0f);
  191. source = rot * source;
  192. return source;
  193. }
  194. /// <summary>
  195. /// Randomized mapping based on a source Vec3 and a radius for randomization distance.
  196. /// </summary>
  197. /// <param name="source">The source <see href="https://docs.unity3d.com/ScriptReference/Vector3.html">Vector3</see> to be mapped to cylinder</param>
  198. /// <param name="radius">This is a <see cref="float"/> for the radius of the cylinder</param>
  199. public static Vector3 ScatterMapping(Vector3 source, float radius)
  200. {
  201. source.x = UnityEngine.Random.Range(-radius, radius);
  202. source.y = UnityEngine.Random.Range(-radius, radius);
  203. return source;
  204. }
  205. }
  206. }