Int3.cs 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
  1. using PF;
  2. namespace PF {
  3. /** Holds a coordinate in integers */
  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. /** Precision for the integer coordinates.
  10. * 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).
  11. * This value affects the maximum coordinates for nodes as well as how large the cost values are for moving between two nodes.
  12. * 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.
  13. */
  14. public const int Precision = 1000;
  15. /** #Precision as a float */
  16. public const float FloatPrecision = 1000F;
  17. /** 1 divided by #Precision */
  18. public const float PrecisionFactor = 0.001F;
  19. public static Int3 zero { get { return new Int3(); } }
  20. public Int3 (Vector3 position) {
  21. x = (int)System.Math.Round(position.x*FloatPrecision);
  22. y = (int)System.Math.Round(position.y*FloatPrecision);
  23. z = (int)System.Math.Round(position.z*FloatPrecision);
  24. }
  25. public Int3 (int _x, int _y, int _z) {
  26. x = _x;
  27. y = _y;
  28. z = _z;
  29. }
  30. public static bool operator == (Int3 lhs, Int3 rhs) {
  31. return lhs.x == rhs.x &&
  32. lhs.y == rhs.y &&
  33. lhs.z == rhs.z;
  34. }
  35. public static bool operator != (Int3 lhs, Int3 rhs) {
  36. return lhs.x != rhs.x ||
  37. lhs.y != rhs.y ||
  38. lhs.z != rhs.z;
  39. }
  40. public static explicit operator Int3 (Vector3 ob) {
  41. return new Int3(
  42. (int)System.Math.Round(ob.x*FloatPrecision),
  43. (int)System.Math.Round(ob.y*FloatPrecision),
  44. (int)System.Math.Round(ob.z*FloatPrecision)
  45. );
  46. }
  47. public static explicit operator Vector3 (Int3 ob) {
  48. return new Vector3(ob.x*PrecisionFactor, ob.y*PrecisionFactor, ob.z*PrecisionFactor);
  49. }
  50. #if !SERVER
  51. public static explicit operator Int3 (UnityEngine.Vector3 ob) {
  52. return new Int3(
  53. (int)System.Math.Round(ob.x*FloatPrecision),
  54. (int)System.Math.Round(ob.y*FloatPrecision),
  55. (int)System.Math.Round(ob.z*FloatPrecision)
  56. );
  57. }
  58. public static explicit operator UnityEngine.Vector3 (Int3 ob) {
  59. return new UnityEngine.Vector3(ob.x*PrecisionFactor, ob.y*PrecisionFactor, ob.z*PrecisionFactor);
  60. }
  61. #endif
  62. public static Int3 operator - (Int3 lhs, Int3 rhs) {
  63. lhs.x -= rhs.x;
  64. lhs.y -= rhs.y;
  65. lhs.z -= rhs.z;
  66. return lhs;
  67. }
  68. public static Int3 operator - (Int3 lhs) {
  69. lhs.x = -lhs.x;
  70. lhs.y = -lhs.y;
  71. lhs.z = -lhs.z;
  72. return lhs;
  73. }
  74. public static Int3 operator + (Int3 lhs, Int3 rhs) {
  75. lhs.x += rhs.x;
  76. lhs.y += rhs.y;
  77. lhs.z += rhs.z;
  78. return lhs;
  79. }
  80. public static Int3 operator * (Int3 lhs, int rhs) {
  81. lhs.x *= rhs;
  82. lhs.y *= rhs;
  83. lhs.z *= rhs;
  84. return lhs;
  85. }
  86. public static Int3 operator * (Int3 lhs, float rhs) {
  87. lhs.x = (int)System.Math.Round(lhs.x * rhs);
  88. lhs.y = (int)System.Math.Round(lhs.y * rhs);
  89. lhs.z = (int)System.Math.Round(lhs.z * rhs);
  90. return lhs;
  91. }
  92. public static Int3 operator * (Int3 lhs, double rhs) {
  93. lhs.x = (int)System.Math.Round(lhs.x * rhs);
  94. lhs.y = (int)System.Math.Round(lhs.y * rhs);
  95. lhs.z = (int)System.Math.Round(lhs.z * rhs);
  96. return lhs;
  97. }
  98. public static Int3 operator / (Int3 lhs, float rhs) {
  99. lhs.x = (int)System.Math.Round(lhs.x / rhs);
  100. lhs.y = (int)System.Math.Round(lhs.y / rhs);
  101. lhs.z = (int)System.Math.Round(lhs.z / rhs);
  102. return lhs;
  103. }
  104. public int this[int i] {
  105. get {
  106. return i == 0 ? x : (i == 1 ? y : z);
  107. }
  108. set {
  109. if (i == 0) x = value;
  110. else if (i == 1) y = value;
  111. else z = value;
  112. }
  113. }
  114. /** Angle between the vectors in radians */
  115. public static float Angle (Int3 lhs, Int3 rhs) {
  116. double cos = Dot(lhs, rhs)/ ((double)lhs.magnitude*(double)rhs.magnitude);
  117. cos = cos < -1 ? -1 : (cos > 1 ? 1 : cos);
  118. return (float)System.Math.Acos(cos);
  119. }
  120. public static int Dot (Int3 lhs, Int3 rhs) {
  121. return
  122. lhs.x * rhs.x +
  123. lhs.y * rhs.y +
  124. lhs.z * rhs.z;
  125. }
  126. public static long DotLong (Int3 lhs, Int3 rhs) {
  127. return
  128. (long)lhs.x * (long)rhs.x +
  129. (long)lhs.y * (long)rhs.y +
  130. (long)lhs.z * (long)rhs.z;
  131. }
  132. /** Normal in 2D space (XZ).
  133. * Equivalent to Cross(this, Int3(0,1,0) )
  134. * except that the Y coordinate is left unchanged with this operation.
  135. */
  136. public Int3 Normal2D () {
  137. return new Int3(z, y, -x);
  138. }
  139. /** 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:
  140. * \code Debug.Log ("Distance between 3,4,5 and 6,7,8 is: "+(new Int3(3,4,5) - new Int3(6,7,8)).magnitude); \endcode
  141. */
  142. public float magnitude {
  143. get {
  144. //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)!
  145. double _x = x;
  146. double _y = y;
  147. double _z = z;
  148. return (float)System.Math.Sqrt(_x*_x+_y*_y+_z*_z);
  149. }
  150. }
  151. /** Magnitude used for the cost between two nodes. The default cost between two nodes can be calculated like this:
  152. * \code int cost = (node1.position-node2.position).costMagnitude; \endcode
  153. *
  154. * This is simply the magnitude, rounded to the nearest integer
  155. */
  156. public int costMagnitude {
  157. get {
  158. return (int)System.Math.Round(magnitude);
  159. }
  160. }
  161. /** The magnitude in world units.
  162. * \deprecated This property is deprecated. Use magnitude or cast to a Vector3
  163. */
  164. [System.Obsolete("This property is deprecated. Use magnitude or cast to a Vector3")]
  165. public float worldMagnitude {
  166. get {
  167. double _x = x;
  168. double _y = y;
  169. double _z = z;
  170. return (float)System.Math.Sqrt(_x*_x+_y*_y+_z*_z)*PrecisionFactor;
  171. }
  172. }
  173. /** The squared magnitude of the vector */
  174. public float sqrMagnitude {
  175. get {
  176. double _x = x;
  177. double _y = y;
  178. double _z = z;
  179. return (float)(_x*_x+_y*_y+_z*_z);
  180. }
  181. }
  182. /** The squared magnitude of the vector */
  183. public long sqrMagnitudeLong {
  184. get {
  185. long _x = x;
  186. long _y = y;
  187. long _z = z;
  188. return (_x*_x+_y*_y+_z*_z);
  189. }
  190. }
  191. public static implicit operator string(Int3 obj) {
  192. return obj.ToString();
  193. }
  194. /** Returns a nicely formatted string representing the vector */
  195. public override string ToString () {
  196. return "( "+x+", "+y+", "+z+")";
  197. }
  198. public override bool Equals (System.Object obj) {
  199. if (obj == null) return false;
  200. var rhs = (Int3)obj;
  201. return x == rhs.x &&
  202. y == rhs.y &&
  203. z == rhs.z;
  204. }
  205. #region IEquatable implementation
  206. public bool Equals (Int3 other) {
  207. return x == other.x && y == other.y && z == other.z;
  208. }
  209. #endregion
  210. public override int GetHashCode () {
  211. return x*73856093 ^ y*19349663 ^ z*83492791;
  212. }
  213. }
  214. /** Two Dimensional Integer Coordinate Pair */
  215. public struct Int2 : System.IEquatable<Int2> {
  216. public int x;
  217. public int y;
  218. public Int2 (int x, int y) {
  219. this.x = x;
  220. this.y = y;
  221. }
  222. public long sqrMagnitudeLong {
  223. get {
  224. return (long)x*(long)x+(long)y*(long)y;
  225. }
  226. }
  227. public static Int2 operator + (Int2 a, Int2 b) {
  228. return new Int2(a.x+b.x, a.y+b.y);
  229. }
  230. public static Int2 operator - (Int2 a, Int2 b) {
  231. return new Int2(a.x-b.x, a.y-b.y);
  232. }
  233. public static bool operator == (Int2 a, Int2 b) {
  234. return a.x == b.x && a.y == b.y;
  235. }
  236. public static bool operator != (Int2 a, Int2 b) {
  237. return a.x != b.x || a.y != b.y;
  238. }
  239. /** Dot product of the two coordinates */
  240. public static long DotLong (Int2 a, Int2 b) {
  241. return (long)a.x*(long)b.x + (long)a.y*(long)b.y;
  242. }
  243. public override bool Equals (System.Object o) {
  244. if (o == null) return false;
  245. var rhs = (Int2)o;
  246. return x == rhs.x && y == rhs.y;
  247. }
  248. #region IEquatable implementation
  249. public bool Equals (Int2 other) {
  250. return x == other.x && y == other.y;
  251. }
  252. #endregion
  253. public override int GetHashCode () {
  254. return x*49157+y*98317;
  255. }
  256. /** Matrices for rotation.
  257. * Each group of 4 elements is a 2x2 matrix.
  258. * The XZ position is multiplied by this.
  259. * So
  260. * \code
  261. * //A rotation by 90 degrees clockwise, second matrix in the array
  262. * (5,2) * ((0, 1), (-1, 0)) = (2,-5)
  263. * \endcode
  264. */
  265. private static readonly int[] Rotations = {
  266. 1, 0, //Identity matrix
  267. 0, 1,
  268. 0, 1,
  269. -1, 0,
  270. -1, 0,
  271. 0, -1,
  272. 0, -1,
  273. 1, 0
  274. };
  275. /** Returns a new Int2 rotated 90*r degrees around the origin.
  276. * \deprecated Deprecated becuase it is not used by any part of the A* Pathfinding Project
  277. */
  278. [System.Obsolete("Deprecated becuase it is not used by any part of the A* Pathfinding Project")]
  279. public static Int2 Rotate (Int2 v, int r) {
  280. r = r % 4;
  281. return new Int2(v.x*Rotations[r*4+0] + v.y*Rotations[r*4+1], v.x*Rotations[r*4+2] + v.y*Rotations[r*4+3]);
  282. }
  283. public static Int2 Min (Int2 a, Int2 b) {
  284. return new Int2(System.Math.Min(a.x, b.x), System.Math.Min(a.y, b.y));
  285. }
  286. public static Int2 Max (Int2 a, Int2 b) {
  287. return new Int2(System.Math.Max(a.x, b.x), System.Math.Max(a.y, b.y));
  288. }
  289. public static Int2 FromInt3XZ (Int3 o) {
  290. return new Int2(o.x, o.z);
  291. }
  292. public static Int3 ToInt3XZ (Int2 o) {
  293. return new Int3(o.x, 0, o.y);
  294. }
  295. public override string ToString () {
  296. return "("+x+", " +y+")";
  297. }
  298. }
  299. }