1 /////////////////////////////////////////////////////////////////////
4 // Class for representing and manipulating 2D vectors
6 /////////////////////////////////////////////////////////////////////
8 // TODO: Type errors if v not instanceof Vector classes
9 // TODO: Possibly implement in C++
11 function Vector2D(x, y)
13 if (arguments.length == 2)
19 Vector2D.prototype.clone = function()
21 return new Vector2D(this.x, this.y);
24 // Mutating 2D functions
26 // These functions modify the current object,
27 // and always return this object to allow chaining
29 Vector2D.prototype.set = function(x, y)
36 Vector2D.prototype.add = function(v)
43 Vector2D.prototype.sub = function(v)
50 Vector2D.prototype.mult = function(f)
57 Vector2D.prototype.div = function(f)
64 Vector2D.prototype.normalize = function()
66 let magnitude = this.length();
70 return this.div(magnitude);
74 * Rotate a radians anti-clockwise
76 Vector2D.prototype.rotate = function(a)
78 let sin = Math.sin(a);
79 let cos = Math.cos(a);
81 let x = this.x * cos + this.y * sin;
82 let y = this.y * cos - this.x * sin;
90 // Numeric 2D info functions (non-mutating)
92 // These methods serve to get numeric info on the vector, they don't modify the vector
95 * Return the vector that forms a right angle with this one.
97 Vector2D.prototype.perpendicular = function()
99 return new Vector2D(-this.y, this.x);
103 * Computes the scalar product of the two vectors.
104 * Geometrically, this is the product of the length of the two vectors and the cosine of the angle between them.
105 * If the vectors are orthogonal, the product is zero.
107 Vector2D.prototype.dot = function(v)
109 return this.x * v.x + this.y * v.y;
113 * Computes the non-zero coordinate of the cross product of the two vectors.
114 * Geometrically, the cross of the vectors is the 3D vector perpendicular to the two 2D vectors.
115 * This returned length of that vector equals the area of the parallelogram that the vectors span.
117 Vector2D.prototype.cross = function(v)
119 return this.x * v.y - this.y * v.x;
122 Vector2D.prototype.lengthSquared = function()
124 return this.dot(this);
127 Vector2D.prototype.length = function()
129 return Math.sqrt(this.lengthSquared());
133 * Compare this length to the length of v,
134 * @return 0 if the lengths are equal
135 * @return 1 if this is longer than v
136 * @return -1 if this is shorter than v
137 * @return NaN if the vectors aren't comparable
139 Vector2D.prototype.compareLength = function(v)
141 return Math.sign(this.lengthSquared() - v.lengthSquared());
144 Vector2D.prototype.distanceToSquared = function(v)
146 return Math.euclidDistance2DSquared(this.x, this.y, v.x, v.y);
149 Vector2D.prototype.distanceTo = function(v)
151 return Math.euclidDistance2D(this.x, this.y, v.x, v.y);
154 // Static 2D functions
156 // Static functions that return a new vector object.
157 // Note that object creation is slow in JS, so use them only when necessary
159 Vector2D.from3D = function(v)
161 return new Vector2D(v.x, v.z);
164 Vector2D.add = function(v1, v2)
166 return new Vector2D(v1.x + v2.x, v1.y + v2.y);
169 Vector2D.sub = function(v1, v2)
171 return new Vector2D(v1.x - v2.x, v1.y - v2.y);
174 Vector2D.mult = function(v, f)
176 return new Vector2D(v.x * f, v.y * f);
179 Vector2D.div = function(v, f)
181 return new Vector2D(v.x / f, v.y / f);
184 Vector2D.avg = function(vectorList)
186 return Vector2D.sum(vectorList).div(vectorList.length);
189 Vector2D.sum = function(vectorList)
191 var sum = new Vector2D();
192 vectorList.forEach(v => sum.add(v));
196 /////////////////////////////////////////////////////////////////////
199 // Class for representing and manipulating 3D vectors
201 /////////////////////////////////////////////////////////////////////
203 function Vector3D(x, y, z)
205 if (arguments.length == 3)
211 Vector3D.prototype.clone = function()
213 return new Vector3D(this.x, this.y, this.z);
216 // Mutating 3D functions
218 // These functions modify the current object,
219 // and always return this object to allow chaining
221 Vector3D.prototype.set = function(x, y, z)
229 Vector3D.prototype.add = function(v)
237 Vector3D.prototype.sub = function(v)
245 Vector3D.prototype.mult = function(f)
253 Vector3D.prototype.div = function(f)
261 Vector3D.prototype.normalize = function()
263 let magnitude = this.length();
267 return this.div(magnitude);
270 // Numeric 3D info functions (non-mutating)
272 // These methods serve to get numeric info on the vector, they don't modify the vector
274 Vector3D.prototype.dot = function(v)
276 return this.x * v.x + this.y * v.y + this.z * v.z;
280 * Returns a vector perpendicular to the two given vectors.
281 * The length of the returned vector corresponds to the area of the parallelogram with the vectors for sides.
283 Vector3D.prototype.cross = function(v)
286 this.y * v.z - this.z * v.y,
287 this.z * v.x - this.x * v.z,
288 this.x * v.y - this.y * v.x);
291 Vector3D.prototype.lengthSquared = function()
293 return this.dot(this);
296 Vector3D.prototype.length = function()
298 return Math.sqrt(this.lengthSquared());
302 * Compare this length to the length of v,
303 * @return 0 if the lengths are equal
304 * @return 1 if this is longer than v
305 * @return -1 if this is shorter than v
306 * @return NaN if the vectors aren't comparable
308 Vector3D.prototype.compareLength = function(v)
310 return Math.sign(this.lengthSquared() - v.lengthSquared());
313 Vector3D.prototype.distanceToSquared = function(v)
315 return Math.euclidDistance3DSquared(this.x, this.y, this.z, v.x, v.y, v.z);
318 Vector3D.prototype.distanceTo = function(v)
320 return Math.euclidDistance3D(this.x, this.y, this.z, v.x, v.y, v.z);
323 Vector3D.prototype.horizDistanceToSquared = function(v)
325 return Math.euclidDistance2DSquared(this.x, this.z, v.x, v.z);
328 Vector3D.prototype.horizDistanceTo = function(v)
330 return Math.sqrt(this.horizDistanceToSquared(v));
333 // Static 3D functions
335 // Static functions that return a new vector object.
336 // Note that object creation is slow in JS, so use them only when really necessary
338 Vector3D.add = function(v1, v2)
340 return new Vector3D(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z);
343 Vector3D.sub = function(v1, v2)
345 return new Vector3D(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z);
348 Vector3D.mult = function(v, f)
350 return new Vector3D(v.x * f, v.y * f, v.z * f);
353 Vector3D.div = function(v, f)
355 return new Vector3D(v.x / f, v.y / f, v.z / f);
359 // make the prototypes easily accessible to C++
360 const Vector2Dprototype = Vector2D.prototype;
361 const Vector3Dprototype = Vector3D.prototype;