vector.ts 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. import type { GlobalPoint, LocalPoint, Vector } from "./types";
  2. /**
  3. * Create a vector from the x and y coordiante elements.
  4. *
  5. * @param x The X aspect of the vector
  6. * @param y T Y aspect of the vector
  7. * @returns The constructed vector with X and Y as the coordinates
  8. */
  9. export function vector(
  10. x: number,
  11. y: number,
  12. originX: number = 0,
  13. originY: number = 0,
  14. ): Vector {
  15. return [x - originX, y - originY] as Vector;
  16. }
  17. /**
  18. * Turn a point into a vector with the origin point.
  19. *
  20. * @param p The point to turn into a vector
  21. * @param origin The origin point in a given coordiante system
  22. * @returns The created vector from the point and the origin
  23. */
  24. export function vectorFromPoint<Point extends GlobalPoint | LocalPoint>(
  25. p: Point,
  26. origin: Point = [0, 0] as Point,
  27. ): Vector {
  28. return vector(p[0] - origin[0], p[1] - origin[1]);
  29. }
  30. /**
  31. * Cross product is a binary operation on two vectors in 2D space.
  32. * It results in a vector that is perpendicular to both vectors.
  33. *
  34. * @param a One of the vectors to use for the directed area calculation
  35. * @param b The other vector to use for the directed area calculation
  36. * @returns The directed area value for the two vectos
  37. */
  38. export function vectorCross(a: Vector, b: Vector): number {
  39. return a[0] * b[1] - b[0] * a[1];
  40. }
  41. /**
  42. * Dot product is defined as the sum of the products of the
  43. * two vectors.
  44. *
  45. * @param a One of the vectors for which the sum of products is calculated
  46. * @param b The other vector for which the sum of products is calculated
  47. * @returns The sum of products of the two vectors
  48. */
  49. export function vectorDot(a: Vector, b: Vector) {
  50. return a[0] * b[0] + a[1] * b[1];
  51. }
  52. /**
  53. * Determines if the value has the shape of a Vector.
  54. *
  55. * @param v The value to test
  56. * @returns TRUE if the value has the shape and components of a Vectors
  57. */
  58. export function isVector(v: unknown): v is Vector {
  59. return (
  60. Array.isArray(v) &&
  61. v.length === 2 &&
  62. typeof v[0] === "number" &&
  63. !isNaN(v[0]) &&
  64. typeof v[1] === "number" &&
  65. !isNaN(v[1])
  66. );
  67. }
  68. /**
  69. * Add two vectors by adding their coordinates.
  70. *
  71. * @param a One of the vectors to add
  72. * @param b The other vector to add
  73. * @returns The sum vector of the two provided vectors
  74. */
  75. export function vectorAdd(a: Readonly<Vector>, b: Readonly<Vector>): Vector {
  76. return [a[0] + b[0], a[1] + b[1]] as Vector;
  77. }
  78. /**
  79. * Add two vectors by adding their coordinates.
  80. *
  81. * @param start One of the vectors to add
  82. * @param end The other vector to add
  83. * @returns The sum vector of the two provided vectors
  84. */
  85. export function vectorSubtract(
  86. start: Readonly<Vector>,
  87. end: Readonly<Vector>,
  88. ): Vector {
  89. return [start[0] - end[0], start[1] - end[1]] as Vector;
  90. }
  91. /**
  92. * Scale vector by a scalar.
  93. *
  94. * @param v The vector to scale
  95. * @param scalar The scalar to multiply the vector components with
  96. * @returns The new scaled vector
  97. */
  98. export function vectorScale(v: Vector, scalar: number): Vector {
  99. return vector(v[0] * scalar, v[1] * scalar);
  100. }
  101. /**
  102. * Calculates the sqare magnitude of a vector. Use this if you compare
  103. * magnitudes as it saves you an SQRT.
  104. *
  105. * @param v The vector to measure
  106. * @returns The scalar squared magnitude of the vector
  107. */
  108. export function vectorMagnitudeSq(v: Vector) {
  109. return v[0] * v[0] + v[1] * v[1];
  110. }
  111. /**
  112. * Calculates the magnitude of a vector.
  113. *
  114. * @param v The vector to measure
  115. * @returns The scalar magnitude of the vector
  116. */
  117. export function vectorMagnitude(v: Vector) {
  118. return Math.sqrt(vectorMagnitudeSq(v));
  119. }
  120. /**
  121. * Normalize the vector (i.e. make the vector magnitue equal 1).
  122. *
  123. * @param v The vector to normalize
  124. * @returns The new normalized vector
  125. */
  126. export const vectorNormalize = (v: Vector): Vector => {
  127. const m = vectorMagnitude(v);
  128. return vector(v[0] / m, v[1] / m);
  129. };
  130. /**
  131. * Project the first vector onto the second vector
  132. */
  133. export const vectorProjection = (a: Vector, b: Vector) => {
  134. return vectorScale(b, vectorDot(a, b) / vectorDot(b, b));
  135. };