Vector.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451
  1. #pragma once
  2. #include <cmath>
  3. #include "Helpers.h"
  4. /**
  5. * @class Vector
  6. * @brief Represents a 2D vector and provides various operations on it.
  7. *
  8. * This class represents a 2D vector with `x` and `y` components. It provides
  9. * various operators and functions to perform operations on vectors such as
  10. * addition, subtraction, multiplication, division, normalization, rotation, etc.
  11. */
  12. struct Vector {
  13. float x;
  14. float y;
  15. Vector &operator=(const Vector &other) {
  16. if (this != &other) {
  17. x = other.x;
  18. y = other.y;
  19. }
  20. return *this;
  21. }
  22. Vector(const Vector &other) : x(other.x), y(other.y) {}
  23. Vector(float _x, float _y) : x(_x), y(_y) {}
  24. Vector() : x(0), y(0) {}
  25. /**
  26. * @brief Represents the addition of two vectors.
  27. *
  28. * @param other The vector to add with.
  29. * @return The sum of the two vectors.
  30. */
  31. Vector operator+(Vector const &other) {
  32. return Vector({x + other.x, y + other.y});
  33. }
  34. /**
  35. * @brief Represents the addition of a constant float to a vector.
  36. *
  37. * This function overloads the '+' operator to allow the addition of a constant float value to a vector.
  38. *
  39. * @param other The constant float value to add.
  40. * @return A new vector that is the sum of the original vector and the constant float value.
  41. */
  42. Vector operator+(float const &other) {
  43. return Vector({x + other, y + other});
  44. }
  45. /**
  46. * @brief Adds a vector to the current vector.
  47. *
  48. * This operator overloads the '+=' operator to allow adding another vector to the current vector.
  49. *
  50. * @param other The vector to be added to the current vector.
  51. * @return A reference to the modified current vector.
  52. */
  53. Vector &operator+=(Vector const &other) {
  54. x += other.x;
  55. y += other.y;
  56. return *this;
  57. }
  58. /**
  59. * @brief Represents the subtraction of two vectors.
  60. *
  61. * This operator overloads the '-' operator to subtract one vector from another.
  62. *
  63. * @param other The vector to subtract with.
  64. * @return The result of subtracting the two vectors.
  65. */
  66. Vector operator-(Vector const &other) const{
  67. return Vector{x - other.x, y - other.y};
  68. }
  69. /**
  70. * @brief Subtract another vector from the current vector.
  71. *
  72. * This operator overloads the '-=' operator to subtract another vector from the current vector.
  73. *
  74. * @param other The vector to subtract.
  75. * @return A reference to the modified current vector.
  76. */
  77. Vector &operator-=(Vector const &other) {
  78. x -= other.x;
  79. y -= other.y;
  80. return *this;
  81. }
  82. /**
  83. * @brief Represents the multiplication of two vectors.
  84. *
  85. * This operator overloads the '*' operator to multiply two vectors element-wise.
  86. *
  87. * @param other The vector to multiply with.
  88. * @return The result of multiplying the two vectors element-wise.
  89. */
  90. Vector operator*(Vector const &other) {
  91. return Vector{x * other.x, y * other.y};
  92. }
  93. /**
  94. * @brief Multiplies the vector with a constant float value.
  95. *
  96. * This operator overloads the '*' operator to allow the multiplication of the
  97. * vector with a constant float value. The result is a new vector with each
  98. * component of the original vector multiplied by the constant float value.
  99. *
  100. * @param other The constant float value to multiply with.
  101. * @return A new vector that is the result of multiplying the original vector
  102. * with the constant float value.
  103. */
  104. Vector operator*(float other) {
  105. return Vector{x * other, y * other};
  106. }
  107. /**
  108. * @brief Multiplies the vector with another vector element-wise.
  109. *
  110. * This operator overloads the "*=" operator to multiply the vector with another vector
  111. * element-wise. Each component of the current vector is multiplied by the corresponding
  112. * component of the other vector.
  113. *
  114. * @param other The vector to multiply with.
  115. * @return A reference to the modified current vector.
  116. */
  117. Vector &operator*=(Vector const &other) {
  118. x *= other.x;
  119. y *= other.y;
  120. return *this;
  121. }
  122. /**
  123. * @brief Multiplies the vector by a constant float value in place.
  124. *
  125. * This operator overloads the "*=" operator to multiply each component of the vector by a constant float value.
  126. *
  127. * @param other The constant float value to multiply the vector by.
  128. * @return A reference to the modified vector.
  129. */
  130. Vector &operator*=(float other) {
  131. x *= other;
  132. y *= other;
  133. return *this;
  134. }
  135. /**
  136. * @brief Represents the division of two vectors.
  137. *
  138. * This operator overloads the '/' operator to divide one vector by another element-wise.
  139. *
  140. * @param other The vector to divide by.
  141. * @return The result of dividing the two vectors element-wise.
  142. */
  143. Vector operator/(Vector const &other) {
  144. return Vector{x / other.x, y / other.y};
  145. }
  146. /**
  147. * @brief Divides the vector by another vector element-wise.
  148. *
  149. * This operator overloads the '/=' operator to divide the vector by another vector
  150. * element-wise. Each component of the current vector is divided by the corresponding
  151. * component of the other vector.
  152. *
  153. * @param other The vector to divide by.
  154. * @return A reference to the modified current vector.
  155. */
  156. Vector &operator/=(Vector const &other) {
  157. x /= other.x;
  158. y /= other.y;
  159. return *this;
  160. }
  161. /**
  162. * @brief Divides the vector by a constant float value.
  163. *
  164. * This operator overloads the '/' operator to divide each component of the vector
  165. * by a constant float value. The result is a new vector with each component of the
  166. * original vector divided by the constant float value.
  167. *
  168. * @param other The constant float value to divide the vector by.
  169. * @return A new vector that is the result of dividing the original vector by the
  170. * constant float value.
  171. */
  172. Vector operator/(float other) {
  173. return Vector{x / other, y / other};
  174. }
  175. /**
  176. * @brief Divides the vector by a constant float value in place.
  177. *
  178. * This operator overloads the '/=' operator to divide each component of the vector
  179. * by a constant float value. The result is a new vector with each component of the
  180. * original vector divided by the constant float value.
  181. *
  182. * @param other The constant float value to divide the vector by.
  183. * @return A reference to the modified vector.
  184. */
  185. Vector &operator/=(float other) {
  186. x /= other;
  187. y /= other;
  188. return *this;
  189. }
  190. /**
  191. * @brief Calculates the magnitude of the vector.
  192. *
  193. * The magnitude of a 2D vector is the length of the vector computed using the Euclidean distance formula.
  194. * The magnitude is computed as the square root of the sum of the squares of the vector's x and y components.
  195. *
  196. * @return The magnitude of the vector.
  197. */
  198. float magnitude() {
  199. return sqrtf(x * x + y * y);
  200. }
  201. /**
  202. * @brief Calculates the distance between the current vector and another vector.
  203. *
  204. * This function calculates the distance between the current vector and another vector by subtracting the two vectors and then calculating the magnitude of the resulting vector.
  205. *
  206. * @param other The vector to calculate the distance from.
  207. * @return The distance between the two vectors.
  208. */
  209. float distance(Vector const &other) {
  210. Vector v = *this - other;
  211. return v.magnitude();
  212. }
  213. /**
  214. * @brief Normalizes the vector.
  215. *
  216. * This function normalizes the vector by dividing its components by its magnitude.
  217. * If the magnitude is zero, the vector is set to (0,0).
  218. *
  219. * @return void
  220. */
  221. void normalize() {
  222. float m = magnitude();
  223. if (m == 0) {
  224. x = 0;
  225. y = 0;
  226. }else{
  227. x = x / m;
  228. y = y / m;
  229. }
  230. }
  231. /**
  232. * @brief Returns a new vector that is the normalized version of the current vector.
  233. *
  234. * This function normalizes the vector by dividing its components by its magnitude.
  235. * If the magnitude is zero, the vector is set to (0,0).
  236. *
  237. * @return The normalized vector.
  238. */
  239. Vector normalized() {
  240. float m = magnitude();
  241. if (m == 0) return {0, 0};
  242. return {x / m, y / m};
  243. }
  244. /**
  245. * @brief Returns the inverse of the vector.
  246. *
  247. * The inverse of a vector is a new vector with the negated values of its `x` and `y` components.
  248. *
  249. * @return The inverse of the vector.
  250. */
  251. Vector inverse() {
  252. return {-x, -y};
  253. }
  254. /**
  255. * @brief Calculates the dot product of the current vector and another vector.
  256. *
  257. * The dot product is a scalar value that represents the projection of one vector onto another.
  258. *
  259. * The dot product of two vectors A and B can be calculated using the formula:
  260. * dot(A, B) = A.x * B.x + A.y * B.y
  261. *
  262. * @param b The vector to calculate the dot product with.
  263. * @return The dot product of the two vectors.
  264. */
  265. float dot(Vector const &b) {
  266. return x * b.x + y * b.y;
  267. }
  268. /**
  269. * @brief Rotates the vector by the specified angle in degrees.
  270. *
  271. * This function rotates the vector by the specified angle in degrees.
  272. * The rotation is performed using the cosine and sine functions, and the result is stored in the x and y components of the vector.
  273. *
  274. * @param deg The angle to rotate the vector by in degrees.
  275. * @return void
  276. */
  277. void rotate(float deg) {
  278. float tx = x;
  279. float ty = y;
  280. x = (float) (cos(deg) * tx - sin(deg) * ty);
  281. y = (float) (sin(deg) * tx + cos(deg) * ty);
  282. }
  283. /**
  284. * @brief Rounds the x and y components of the vector to the nearest integer.
  285. *
  286. * This function rounds the x and y components of the vector to the nearest integer by using the round function
  287. * from the cmath library. The result is stored back into the x and y
  288. * components of the vector.
  289. *
  290. * @return void
  291. */
  292. void rounded() {
  293. x = (float) round(x);
  294. y = (float) round(y);
  295. }
  296. /**
  297. * @brief Calculates and returns a 2D vector that is rotated by the specified angle in degrees.
  298. *
  299. * This function takes a floating-point value representing an angle in degrees and returns a new 2D vector that is rotated by
  300. * that angle. The rotation is performed in the counter-clockwise direction.
  301. *
  302. * @param deg The angle to rotate the vector by in degrees.
  303. * @return The rotated 2D vector.
  304. *
  305. * @note This function assumes that the input angle is in degrees, not radians. If the input angle is in radians, it needs to be
  306. * converted to degrees before being passed to this function.
  307. *
  308. * @note The returned vector is a new instance and does not modify the original vector.
  309. *
  310. * @warning This function assumes that the vector is represented using floating-point values. If the vector uses integer values,
  311. * the return type and calculations should be adjusted accordingly.
  312. *
  313. * @see https://en.wikipedia.org/wiki/Rotation_matrix for more information on rotation matrices.
  314. *
  315. * @sa rotate(float deg) to rotate the vector in-place.
  316. *
  317. * Example usage:
  318. * @code
  319. * Vector v1(2, 3);
  320. * Vector v2 = v1.rotated(45.0f);
  321. * // v2 = { -0.707, 3.536 }
  322. * @endcode
  323. */
  324. Vector rotated(float deg) {
  325. return {
  326. (float) (cos(deg) * x - sin(deg) * y),
  327. (float) (sin(deg) * x + cos(deg) * y)
  328. };
  329. }
  330. /**
  331. * @brief Calculates the cross product between two vectors.
  332. *
  333. * This method calculates the cross product between the current vector and the
  334. * specified vector, and returns the result. The cross product is calculated
  335. * using the formula: cross product = (x1 * y2) - (y1 * x2).
  336. *
  337. * @param other The vector to calculate the cross product with.
  338. * @return The cross product between the two vectors.
  339. */
  340. float cross(Vector const &other) {
  341. return x * other.x - y * other.y;
  342. }
  343. /**
  344. * @brief Calculates the perpendicular vector.
  345. *
  346. * This function calculates the perpendicular vector of the current vector.
  347. *
  348. * @return The perpendicular vector.
  349. */
  350. Vector perpendicular() {
  351. return {-y, x};
  352. }
  353. /**
  354. * @brief Projects a vector onto a line segment defined by two points.
  355. *
  356. * Given a line segment defined by two points lineA and lineB, this function calculates the projection of the current vector onto that line segment.
  357. * It returns the projected vector point and also sets the success flag to indicate whether the projection was successful or not.
  358. *
  359. * @param lineA The first point defining the line segment.
  360. * @param lineB The second point defining the line segment.
  361. * @param success A pointer to a boolean value that will be set to true if the projection is successful, and false otherwise.
  362. *
  363. * @return The projected vector point if the projection is successful, otherwise an empty vector.
  364. */
  365. Vector project(Vector const &lineA, Vector const &lineB, bool *success) {
  366. Vector AB = lineB - lineA;
  367. Vector AC = *this - lineA;
  368. float k = AC.dot(AB) / AB.dot(AB);
  369. if (k < 0 || k > 1) {
  370. *success = false;
  371. return {};
  372. }
  373. *success = true;
  374. return {
  375. k * AB.x + lineA.x,
  376. k * AB.y + lineA.y
  377. };
  378. }
  379. /**
  380. * @brief Linearly interpolates between two vectors.
  381. *
  382. * This function performs linear interpolation between two vectors using the given time value.
  383. * It is assumed that the start and end vectors have the same dimension.
  384. *
  385. * @param start The start vector.
  386. * @param end The end vector.
  387. * @param time The interpolation time value between 0 and 1.
  388. * @return The interpolated vector.
  389. */
  390. static Vector Lerp(Vector const &start, Vector const &end, float time) {
  391. return {
  392. lerp(start.x, end.x, time),
  393. lerp(start.y, end.y, time)
  394. };
  395. }
  396. /**
  397. * @brief Calculate the quadratic Bezier interpolation between three vectors.
  398. *
  399. * This function calculates the position of a point along a quadratic Bezier curve, given three control points
  400. * and a time value.
  401. *
  402. * @param start The start point of the curve.
  403. * @param control The control point of the curve, which affects the shape of the curve.
  404. * @param end The end point of the curve.
  405. * @param time The time value parameter that specifies the position along the curve.
  406. * @return The interpolated vector position.
  407. *
  408. * @see Vector::Lerp()
  409. */
  410. static Vector Quadratic(Vector const &start, Vector const &control, Vector const &end, float time) {
  411. Vector a = Vector::Lerp(start, control, time);
  412. Vector b = Vector::Lerp(control, end, time);
  413. return Vector::Lerp(a, b, time);
  414. }
  415. };