Int3.cs 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. using UnityEngine;
  2. namespace Pathfinding {
  3. /// <summary>Holds a coordinate in integers</summary>
  4. public struct Int3 : System.IEquatable<Int3> {
  5. public int x;
  6. public int y;
  7. public int z;
  8. //These should be set to the same value (only PrecisionFactor should be 1 divided by Precision)
  9. /// <summary>
  10. /// Precision for the integer coordinates.
  11. /// One world unit is divided into [value] pieces. A value of 1000 would mean millimeter precision, a value of 1 would mean meter precision (assuming 1 world unit = 1 meter).
  12. /// This value affects the maximum coordinates for nodes as well as how large the cost values are for moving between two nodes.
  13. /// A higher value means that you also have to set all penalty values to a higher value to compensate since the normal cost of moving will be higher.
  14. /// </summary>
  15. public const int Precision = 1000;
  16. /// <summary><see cref="Precision"/> as a float</summary>
  17. public const float FloatPrecision = 1000F;
  18. /// <summary>1 divided by <see cref="Precision"/></summary>
  19. public const float PrecisionFactor = 0.001F;
  20. public static Int3 zero { get { return new Int3(); } }
  21. public Int3 (Vector3 position) {
  22. x = (int)System.Math.Round(position.x*FloatPrecision);
  23. y = (int)System.Math.Round(position.y*FloatPrecision);
  24. z = (int)System.Math.Round(position.z*FloatPrecision);
  25. }
  26. public Int3 (int _x, int _y, int _z) {
  27. x = _x;
  28. y = _y;
  29. z = _z;
  30. }
  31. public static bool operator == (Int3 lhs, Int3 rhs) {
  32. return lhs.x == rhs.x &&
  33. lhs.y == rhs.y &&
  34. lhs.z == rhs.z;
  35. }
  36. public static bool operator != (Int3 lhs, Int3 rhs) {
  37. return lhs.x != rhs.x ||
  38. lhs.y != rhs.y ||
  39. lhs.z != rhs.z;
  40. }
  41. public static explicit operator Int3 (Vector3 ob) {
  42. return new Int3(
  43. (int)System.Math.Round(ob.x*FloatPrecision),
  44. (int)System.Math.Round(ob.y*FloatPrecision),
  45. (int)System.Math.Round(ob.z*FloatPrecision)
  46. );
  47. }
  48. public static explicit operator Vector3 (Int3 ob) {
  49. return new Vector3(ob.x*PrecisionFactor, ob.y*PrecisionFactor, ob.z*PrecisionFactor);
  50. }
  51. public static Int3 operator - (Int3 lhs, Int3 rhs) {
  52. lhs.x -= rhs.x;
  53. lhs.y -= rhs.y;
  54. lhs.z -= rhs.z;
  55. return lhs;
  56. }
  57. public static Int3 operator - (Int3 lhs) {
  58. lhs.x = -lhs.x;
  59. lhs.y = -lhs.y;
  60. lhs.z = -lhs.z;
  61. return lhs;
  62. }
  63. public static Int3 operator + (Int3 lhs, Int3 rhs) {
  64. lhs.x += rhs.x;
  65. lhs.y += rhs.y;
  66. lhs.z += rhs.z;
  67. return lhs;
  68. }
  69. public static Int3 operator * (Int3 lhs, int rhs) {
  70. lhs.x *= rhs;
  71. lhs.y *= rhs;
  72. lhs.z *= rhs;
  73. return lhs;
  74. }
  75. public static Int3 operator * (Int3 lhs, float rhs) {
  76. lhs.x = (int)System.Math.Round(lhs.x * rhs);
  77. lhs.y = (int)System.Math.Round(lhs.y * rhs);
  78. lhs.z = (int)System.Math.Round(lhs.z * rhs);
  79. return lhs;
  80. }
  81. public static Int3 operator * (Int3 lhs, double rhs) {
  82. lhs.x = (int)System.Math.Round(lhs.x * rhs);
  83. lhs.y = (int)System.Math.Round(lhs.y * rhs);
  84. lhs.z = (int)System.Math.Round(lhs.z * rhs);
  85. return lhs;
  86. }
  87. public static Int3 operator / (Int3 lhs, float rhs) {
  88. lhs.x = (int)System.Math.Round(lhs.x / rhs);
  89. lhs.y = (int)System.Math.Round(lhs.y / rhs);
  90. lhs.z = (int)System.Math.Round(lhs.z / rhs);
  91. return lhs;
  92. }
  93. public int this[int i] {
  94. get {
  95. return i == 0 ? x : (i == 1 ? y : z);
  96. }
  97. set {
  98. if (i == 0) x = value;
  99. else if (i == 1) y = value;
  100. else z = value;
  101. }
  102. }
  103. /// <summary>Angle between the vectors in radians</summary>
  104. public static float Angle (Int3 lhs, Int3 rhs) {
  105. double cos = Dot(lhs, rhs)/ ((double)lhs.magnitude*(double)rhs.magnitude);
  106. cos = cos < -1 ? -1 : (cos > 1 ? 1 : cos);
  107. return (float)System.Math.Acos(cos);
  108. }
  109. public static int Dot (Int3 lhs, Int3 rhs) {
  110. return
  111. lhs.x * rhs.x +
  112. lhs.y * rhs.y +
  113. lhs.z * rhs.z;
  114. }
  115. public static long DotLong (Int3 lhs, Int3 rhs) {
  116. return
  117. (long)lhs.x * (long)rhs.x +
  118. (long)lhs.y * (long)rhs.y +
  119. (long)lhs.z * (long)rhs.z;
  120. }
  121. /// <summary>
  122. /// Normal in 2D space (XZ).
  123. /// Equivalent to Cross(this, Int3(0,1,0) )
  124. /// except that the Y coordinate is left unchanged with this operation.
  125. /// </summary>
  126. public Int3 Normal2D () {
  127. return new Int3(z, y, -x);
  128. }
  129. /// <summary>
  130. /// Returns the magnitude of the vector. The magnitude is the 'length' of the vector from 0,0,0 to this point. Can be used for distance calculations:
  131. /// <code> Debug.Log ("Distance between 3,4,5 and 6,7,8 is: "+(new Int3(3,4,5) - new Int3(6,7,8)).magnitude); </code>
  132. /// </summary>
  133. public float magnitude {
  134. get {
  135. //It turns out that using doubles is just as fast as using ints with Mathf.Sqrt. And this can also handle larger numbers (possibly with small errors when using huge numbers)!
  136. double _x = x;
  137. double _y = y;
  138. double _z = z;
  139. return (float)System.Math.Sqrt(_x*_x+_y*_y+_z*_z);
  140. }
  141. }
  142. /// <summary>
  143. /// Magnitude used for the cost between two nodes. The default cost between two nodes can be calculated like this:
  144. /// <code> int cost = (node1.position-node2.position).costMagnitude; </code>
  145. ///
  146. /// This is simply the magnitude, rounded to the nearest integer
  147. /// </summary>
  148. public int costMagnitude {
  149. get {
  150. return (int)System.Math.Round(magnitude);
  151. }
  152. }
  153. /// <summary>The squared magnitude of the vector</summary>
  154. public float sqrMagnitude {
  155. get {
  156. double _x = x;
  157. double _y = y;
  158. double _z = z;
  159. return (float)(_x*_x+_y*_y+_z*_z);
  160. }
  161. }
  162. /// <summary>The squared magnitude of the vector</summary>
  163. public long sqrMagnitudeLong {
  164. get {
  165. long _x = x;
  166. long _y = y;
  167. long _z = z;
  168. return (_x*_x+_y*_y+_z*_z);
  169. }
  170. }
  171. public static implicit operator string (Int3 obj) {
  172. return obj.ToString();
  173. }
  174. /// <summary>Returns a nicely formatted string representing the vector</summary>
  175. public override string ToString () {
  176. return "( "+x+", "+y+", "+z+")";
  177. }
  178. public override bool Equals (System.Object obj) {
  179. if (obj == null) return false;
  180. var rhs = (Int3)obj;
  181. return x == rhs.x &&
  182. y == rhs.y &&
  183. z == rhs.z;
  184. }
  185. #region IEquatable implementation
  186. public bool Equals (Int3 other) {
  187. return x == other.x && y == other.y && z == other.z;
  188. }
  189. #endregion
  190. public override int GetHashCode () {
  191. return x*73856093 ^ y*19349669 ^ z*83492791;
  192. }
  193. }
  194. /// <summary>Two Dimensional Integer Coordinate Pair</summary>
  195. public struct Int2 : System.IEquatable<Int2> {
  196. public int x;
  197. public int y;
  198. public Int2 (int x, int y) {
  199. this.x = x;
  200. this.y = y;
  201. }
  202. public long sqrMagnitudeLong {
  203. get {
  204. return (long)x*(long)x+(long)y*(long)y;
  205. }
  206. }
  207. public static Int2 operator - (Int2 lhs) {
  208. lhs.x = -lhs.x;
  209. lhs.y = -lhs.y;
  210. return lhs;
  211. }
  212. public static Int2 operator + (Int2 a, Int2 b) {
  213. return new Int2(a.x+b.x, a.y+b.y);
  214. }
  215. public static Int2 operator - (Int2 a, Int2 b) {
  216. return new Int2(a.x-b.x, a.y-b.y);
  217. }
  218. public static bool operator == (Int2 a, Int2 b) {
  219. return a.x == b.x && a.y == b.y;
  220. }
  221. public static bool operator != (Int2 a, Int2 b) {
  222. return a.x != b.x || a.y != b.y;
  223. }
  224. /// <summary>Dot product of the two coordinates</summary>
  225. public static long DotLong (Int2 a, Int2 b) {
  226. return (long)a.x*(long)b.x + (long)a.y*(long)b.y;
  227. }
  228. public override bool Equals (System.Object o) {
  229. if (o == null) return false;
  230. var rhs = (Int2)o;
  231. return x == rhs.x && y == rhs.y;
  232. }
  233. #region IEquatable implementation
  234. public bool Equals (Int2 other) {
  235. return x == other.x && y == other.y;
  236. }
  237. #endregion
  238. public override int GetHashCode () {
  239. return x*49157+y*98317;
  240. }
  241. public static Int2 Min (Int2 a, Int2 b) {
  242. return new Int2(System.Math.Min(a.x, b.x), System.Math.Min(a.y, b.y));
  243. }
  244. public static Int2 Max (Int2 a, Int2 b) {
  245. return new Int2(System.Math.Max(a.x, b.x), System.Math.Max(a.y, b.y));
  246. }
  247. public static Int2 FromInt3XZ (Int3 o) {
  248. return new Int2(o.x, o.z);
  249. }
  250. public static Int3 ToInt3XZ (Int2 o) {
  251. return new Int3(o.x, 0, o.y);
  252. }
  253. public override string ToString () {
  254. return "("+x+", " +y+")";
  255. }
  256. }
  257. }