classes/vector.js

  1. /**
  2. * Created by Alex Bol on 2/19/2017.
  3. */
  4. "use strict";
  5. module.exports = function(Flatten) {
  6. /**
  7. * Class representing a vector
  8. * @type {Vector}
  9. */
  10. Flatten.Vector = class Vector {
  11. /**
  12. * Vector may be constructed by two points, or by two float numbers,
  13. * or by array of two numbers
  14. * @param {Point} ps - start point
  15. * @param {Point} pe - end point
  16. */
  17. constructor(...args) {
  18. /**
  19. * x-coordinate of a vector (float number)
  20. * @type {number}
  21. */
  22. this.x = 0;
  23. /**
  24. * y-coordinate of a vector (float number)
  25. * @type {number}
  26. */
  27. this.y = 0;
  28. /* return zero vector */
  29. if (args.length === 0) {
  30. return;
  31. }
  32. if (args.length === 1 && args[0] instanceof Array && args[0].length === 2) {
  33. let arr = args[0];
  34. if (typeof(arr[0]) == "number" && typeof(arr[1]) == "number") {
  35. this.x = arr[0];
  36. this.y = arr[1];
  37. return;
  38. }
  39. }
  40. if (args.length === 1 && args[0] instanceof Object && args[0].name === "vector") {
  41. let {x, y} = args[0];
  42. this.x = x;
  43. this.y = y;
  44. return;
  45. }
  46. if (args.length === 2) {
  47. let a1 = args[0];
  48. let a2 = args[1];
  49. if (typeof(a1) == "number" && typeof(a2) == "number") {
  50. this.x = a1;
  51. this.y = a2;
  52. return;
  53. }
  54. if (a1 instanceof Flatten.Point && a2 instanceof Flatten.Point) {
  55. this.x = a2.x - a1.x;
  56. this.y = a2.y - a1.y;
  57. return;
  58. }
  59. }
  60. throw Flatten.Errors.ILLEGAL_PARAMETERS;
  61. }
  62. /**
  63. * Method clone returns new instance of Vector
  64. * @returns {Vector}
  65. */
  66. clone() {
  67. return new Vector(this.x, this.y);
  68. }
  69. /**
  70. * Slope of the vector in radians from 0 to 2PI
  71. * @returns {number}
  72. */
  73. get slope() {
  74. let angle = Math.atan2(this.y, this.x);
  75. if (angle<0) angle = 2*Math.PI + angle;
  76. return angle;
  77. }
  78. /**
  79. * Length of vector
  80. * @returns {number}
  81. */
  82. get length() {
  83. return Math.sqrt(this.dot(this));
  84. }
  85. /**
  86. * Returns true if vectors are equal up to [DP_TOL]{@link http://localhost:63342/flatten-js/docs/global.html#DP_TOL}
  87. * tolerance
  88. * @param {Vector} v
  89. * @returns {boolean}
  90. */
  91. equalTo(v) {
  92. return Flatten.Utils.EQ(this.x, v.x) && Flatten.Utils.EQ(this.y, v.y);
  93. }
  94. /**
  95. * Returns new vector multiplied by scalar
  96. * @param {number} scalar
  97. * @returns {Vector}
  98. */
  99. multiply(scalar) {
  100. return ( new Vector(scalar * this.x, scalar * this.y) );
  101. }
  102. /**
  103. * Returns scalar product (dot product) of two vectors <br/>
  104. * <code>dot_product = (this * v)</code>
  105. * @param {Vector} v Other vector
  106. * @returns {number}
  107. */
  108. dot(v) {
  109. return ( this.x * v.x + this.y * v.y );
  110. }
  111. /**
  112. * Returns vector product (cross product) of two vectors <br/>
  113. * <code>cross_product = (this x v)</code>
  114. * @param {Vector} v Other vector
  115. * @returns {number}
  116. */
  117. cross(v) {
  118. return ( this.x * v.y - this.y * v.x );
  119. }
  120. /**
  121. * Returns unit vector.<br/>
  122. * Throw error if given vector has zero length
  123. * @returns {Vector}
  124. */
  125. normalize() {
  126. if (!Flatten.Utils.EQ_0(this.length)) {
  127. return ( new Vector(this.x / this.length, this.y / this.length) );
  128. }
  129. throw Flatten.Errors.ZERO_DIVISION;
  130. }
  131. /**
  132. * Returns new vector rotated by given angle,
  133. * positive angle defines rotation in counter clockwise direction,
  134. * negative - in clockwise direction
  135. * @param {number} angle - Angle in radians
  136. * @returns {Vector}
  137. */
  138. rotate(angle) {
  139. let point = new Flatten.Point(this.x, this.y);
  140. let rpoint = point.rotate(angle);
  141. return new Flatten.Vector(rpoint.x, rpoint.y);
  142. }
  143. /**
  144. * Returns vector rotated 90 degrees counter clockwise
  145. * @returns {Vector}
  146. */
  147. rotate90CCW() {
  148. return new Flatten.Vector(-this.y, this.x);
  149. };
  150. /**
  151. * Returns vector rotated 90 degrees clockwise
  152. * @returns {Vector}
  153. */
  154. rotate90CW() {
  155. return new Flatten.Vector(this.y, -this.x);
  156. };
  157. /**
  158. * Return inverted vector
  159. * @returns {Vector}
  160. */
  161. invert() {
  162. return new Flatten.Vector(-this.x, -this.y);
  163. }
  164. /**
  165. * Return result of addition of other vector to this vector as a new vector
  166. * @param {Vector} v Other vector
  167. * @returns {Vector}
  168. */
  169. add(v) {
  170. return new Flatten.Vector(this.x + v.x, this.y + v.y);
  171. }
  172. /**
  173. * Return result of subtraction of other vector from current vector as a new vector
  174. * @param {Vector} v Another vector
  175. * @returns {Vector}
  176. */
  177. subtract(v) {
  178. return new Flatten.Vector(this.x - v.x, this.y - v.y);
  179. }
  180. /**
  181. * Return angle between this vector and other vector. <br/>
  182. * Angle is measured from 0 to 2*PI in the counter clockwise direction
  183. * from current vector to other.
  184. * @param {Vector} v Another vector
  185. * @returns {number}
  186. */
  187. angleTo(v) {
  188. let norm1 = this.normalize();
  189. let norm2 = v.normalize();
  190. let angle = Math.atan2(norm1.cross(norm2), norm1.dot(norm2));
  191. if (angle<0) angle += 2*Math.PI;
  192. return angle;
  193. }
  194. /**
  195. * Return vector projection of the current vector on another vector
  196. * @param {Vector} v Another vector
  197. * @returns {Vector}
  198. */
  199. projectionOn(v){
  200. let n = v.normalize();
  201. let d = this.dot(n);
  202. return n.multiply(d);
  203. }
  204. /**
  205. * This method returns an object that defines how data will be
  206. * serialized when called JSON.stringify() method
  207. * @returns {Object}
  208. */
  209. toJSON() {
  210. return Object.assign({},this,{name:"vector"});
  211. }
  212. };
  213. /**
  214. * Function to create vector equivalent to "new" constructor
  215. * @param args
  216. */
  217. Flatten.vector = (...args) => new Flatten.Vector(...args);
  218. };