diff --git a/src/core/main.js b/src/core/main.js
index 4ce9d91c55..969c3a2ba1 100644
--- a/src/core/main.js
+++ b/src/core/main.js
@@ -50,7 +50,7 @@ class p5 {
constructor(sketch, node) {
// Apply addon defined decorations
if(p5.decorations.size > 0){
- decorateClass(p5, p5.decorations);
+ decorateClass(p5, p5.decorations, 'p5');
p5.decorations.clear();
}
diff --git a/src/math/index.js b/src/math/index.js
index 2acb397b21..8e08dd88bd 100644
--- a/src/math/index.js
+++ b/src/math/index.js
@@ -4,6 +4,7 @@ import random from './random.js';
import trigonometry from './trigonometry.js';
import math from './math.js';
import vector from './p5.Vector.js';
+import vectorValidation from './patch-vector.js';
export default function(p5){
p5.registerAddon(calculation);
@@ -12,4 +13,5 @@ export default function(p5){
p5.registerAddon(trigonometry);
p5.registerAddon(math);
p5.registerAddon(vector);
+ p5.registerAddon(vectorValidation);
}
diff --git a/src/math/math.js b/src/math/math.js
index 9e513a7c36..0cfbb593bb 100644
--- a/src/math/math.js
+++ b/src/math/math.js
@@ -38,7 +38,7 @@ function math(p5, fn) {
* p5.Vector class.
*
* @method createVector
- * @param {...Number} x Zero or more numbers, representing each component of the vector.
+ * @param {...Number} x List of numbers representing each component of the vector.
* @return {p5.Vector} new p5.Vector object.
*
* @example
@@ -92,21 +92,8 @@ function math(p5, fn) {
* point(pos);
* }
*/
- fn.createVector = function (x, y, z) {
- if (arguments.length === 0) {
- p5._friendlyError(
- 'In 1.x, createVector() was a shortcut for createVector(0, 0, 0). In 2.x, p5.js has vectors of any dimension, so you must provide your desired number of zeros. Use createVector(0, 0) for a 2D vector and createVector(0, 0, 0) for a 3D vector.'
- );
- }
- if (this instanceof p5) {
- return new p5.Vector(
- this._fromRadians.bind(this),
- this._toRadians.bind(this),
- ...arguments
- );
- } else {
- return new p5.Vector(x, y, z);
- }
+ fn.createVector = function (...args) {
+ return new p5.Vector(...args);
};
/**
diff --git a/src/math/p5.Vector.js b/src/math/p5.Vector.js
index 1f3df37f8a..32cf84a98b 100644
--- a/src/math/p5.Vector.js
+++ b/src/math/p5.Vector.js
@@ -5,85 +5,81 @@
import * as constants from '../core/constants';
-/// HELPERS FOR REMAINDER METHOD
-const calculateRemainder2D = function (xComponent, yComponent) {
- if (xComponent !== 0) {
- this.x = this.x % xComponent;
- }
- if (yComponent !== 0) {
- this.y = this.y % yComponent;
- }
- return this;
+/**
+ * This function is used by binary vector operations to prioritize shorter vectors,
+ * and to emit a warning when lengths do not match.
+ */
+const prioritizeSmallerDimension = function(currentVectorDimension, args) {
+ return Math.min(currentVectorDimension, args.length);
+
+ //if (args.length !== currentVectorDimension && args.length !== 1) {
+ // TODO how to suppress for valid solo arguments?
+ // p5._friendlyError(
+ // `Operating on two vectors of different sizes, the smaller dimension is used. In this operation, both vector will be treated as ${minDimension}D vectors, and any additional values of the longer vector will be ignored.`, 'p5.Vector'
+ //);
+ //}
+ //return minDimension;
};
-const calculateRemainder3D = function (xComponent, yComponent, zComponent) {
- if (xComponent !== 0) {
- this.x = this.x % xComponent;
- }
- if (yComponent !== 0) {
- this.y = this.y % yComponent;
- }
- if (zComponent !== 0) {
- this.z = this.z % zComponent;
- }
- return this;
-};
class Vector {
+ /**
+ * The values of an N-dimensional vector.
+ *
+ * This array of numbers that represents the vector.
+ * Each number in the array corresponds to a different component of the vector,
+ * like its position in different directions (e.g., x, y, z).
+ *
+ * You can update the values of the entire vector to a new set of values.
+ * You need to provide an array of numbers, where each number represents a component
+ * of the vector (e.g., x, y, z). The length of the array will become the number of
+ * dimensions of the vector.
+ *
+ * You can add (`add()`), multiply (`mult()`), divide (`div()`), and subtract (`sub()`)
+ * vectors from each other, and calculate remainder (`rem()`). Only use these functions
+ * on vectors when they are the same size: for example, both 2D, or both 3D.
+ * When an operation uses two vectors of different sizes, the smaller dimension will be
+ * used, any additional values of the longer vector will be ignored.
+ *
+ * You can multiply, divide, or calculate remainder of a vector with a single number. Then,
+ * the same operation will be done on each element of the vector.
+ *
+ * @type {Array} The array of values representing the vector.
+ * @throws Will throw an error if provided no arguments, or if the arguments
+ * are not all finity numbers
+ */
+ values = [];
+
// This is how it comes in with createVector()
// This check if the first argument is a function
constructor(...args) {
- let values = args; // .map(arg => arg || 0);
+
+ if (args.length === 0) {
+ p5._friendlyError(
+ 'Requires valid arguments.', 'p5.Vector'
+ );
+ }
+
if (typeof args[0] === 'function') {
this.isPInst = true;
this._fromRadians = args[0];
this._toRadians = args[1];
- values = args.slice(2); // .map(arg => arg || 0);
+ args = args.slice(2);
}
- let dimensions = values.length; // TODO: make default 3 if no arguments
- if (dimensions === 0) {
- this.dimensions = 2;
- this._values = [0, 0, 0];
+
+ this.values = [];
+ if(Array.isArray(args) && !args.every(v => typeof v === 'number' && Number.isFinite(v))){
+ p5._friendlyError(
+ 'Arguments contain non-finite numbers',
+ target.name
+ );
} else {
- this.dimensions = dimensions;
- this._values = values;
+ this.values = args;
}
}
- /**
- * Gets the values of the N-dimensional vector.
- *
- * This method returns an array of numbers that represent the vector.
- * Each number in the array corresponds to a different component of the vector,
- * like its position in different directions (e.g., x, y, z).
- *
- * @returns {Array} The array of values representing the vector.
- */
- get values() {
- return this._values;
- }
-
- /**
- * Sets the values of the vector.
- *
- * This method allows you to update the entire vector with a new set of values.
- * You need to provide an array of numbers, where each number represents a component
- * of the vector (e.g., x, y, z). The length of the array should match the number of
- * dimensions of the vector. If the array is shorter, the missing components will be
- * set to 0. If the array is longer, the extra values will be ignored.
- *
- * @param {Array} newValues - An array of numbers representing the new values for the vector.
- *
- */
- set values(newValues) {
- let dimensions = newValues.length;
- if (dimensions === 0) {
- this.dimensions = 2;
- this._values = [0, 0, 0];
- } else {
- this.dimensions = dimensions;
- this._values = newValues.slice();
- }
+ get dimensions(){
+ return this.values.length;
}
/**
@@ -96,7 +92,7 @@ class Vector {
* @returns {Number} The x component of the vector. Returns 0 if the value is not defined.
*/
get x() {
- return this._values[0] || 0;
+ return this.values[0] || 0;
}
/**
@@ -117,8 +113,8 @@ class Vector {
* get a value from a position that doesn't exist in the vector.
*/
getValue(index) {
- if (index < this._values.length) {
- return this._values[index];
+ if (index < this.values.length) {
+ return this.values[index];
} else {
p5._friendlyError(
'The index parameter is trying to set a value outside the bounds of the vector',
@@ -142,8 +138,8 @@ class Vector {
* @throws Will throw an error if the index is outside the bounds of the vector, meaning if you try to set a value at a position that doesn't exist in the vector.
*/
setValue(index, value) {
- if (index < this._values.length) {
- this._values[index] = value;
+ if (index < this.values.length) {
+ this.values[index] = value;
} else {
p5._friendlyError(
'The index parameter is trying to set a value outside the bounds of the vector',
@@ -162,7 +158,7 @@ class Vector {
* @returns {Number} The y component of the vector. Returns 0 if the value is not defined.
*/
get y() {
- return this._values[1] || 0;
+ return this.values[1] || 0;
}
/**
@@ -175,7 +171,7 @@ class Vector {
* @returns {Number} The z component of the vector. Returns 0 if the value is not defined.
*/
get z() {
- return this._values[2] || 0;
+ return this.values[2] || 0;
}
/**
@@ -188,7 +184,7 @@ class Vector {
* @returns {Number} The w component of the vector. Returns 0 if the value is not defined.
*/
get w() {
- return this._values[3] || 0;
+ return this.values[3] || 0;
}
/**
@@ -201,8 +197,8 @@ class Vector {
* @param {Number} xVal - The new value for the x component.
*/
set x(xVal) {
- if (this._values.length > 1) {
- this._values[0] = xVal;
+ if (this.values.length > 1) {
+ this.values[0] = xVal;
}
}
@@ -216,8 +212,8 @@ class Vector {
* @param {Number} yVal - The new value for the y component.
*/
set y(yVal) {
- if (this._values.length > 1) {
- this._values[1] = yVal;
+ if (this.values.length > 1) {
+ this.values[1] = yVal;
}
}
@@ -231,8 +227,8 @@ class Vector {
* @param {Number} zVal - The new value for the z component.
*/
set z(zVal) {
- if (this._values.length > 2) {
- this._values[2] = zVal;
+ if (this.values.length > 2) {
+ this.values[2] = zVal;
}
}
@@ -246,8 +242,8 @@ class Vector {
* @param {Number} wVal - The new value for the w component.
*/
set w(wVal) {
- if (this._values.length > 3) {
- this._values[3] = wVal;
+ if (this.values.length > 3) {
+ this.values[3] = wVal;
}
}
@@ -269,7 +265,7 @@ class Vector {
* }
*/
toString() {
- return `vector[${this._values.join(', ')}]`;
+ return `vector[${this.values.join(', ')}]`;
}
/**
@@ -327,13 +323,12 @@ class Vector {
*/
set(...args) {
if (args[0] instanceof Vector) {
- this._values = args[0].values.slice();
+ this.values = args[0].values.slice();
} else if (Array.isArray(args[0])) {
- this._values = args[0].map(arg => arg || 0);
+ this.values = args[0].map(arg => arg || 0);
} else {
- this._values = args.map(arg => arg || 0);
+ this.values = args.map(arg => arg || 0);
}
- this.dimensions = this._values.length;
return this;
}
@@ -363,12 +358,14 @@ class Vector {
*/
copy() {
if (this.isPInst) {
- return new Vector(this._fromRadians, this._toRadians, ...this._values);
+ return new Vector(this._fromRadians, this._toRadians, ...this.values);
} else {
- return new Vector(...this._values);
+ return new Vector(...this.values);
}
}
+
+
/**
* Adds to a vector's components.
*
@@ -376,8 +373,11 @@ class Vector {
* another p5.Vector object, as in `v.add(v2)`, or
* an array of numbers, as in `v.add([1, 2, 3])`.
*
- * If a value isn't provided for a component, it won't change. For
- * example, `v.add(4, 5)` adds 4 to `v.x`, 5 to `v.y`, and 0 to `v.z`.
+ * Add vectors only when they are the same size: both 2D, or both 3D.
+ * When two vectors of different sizes are added, the smaller dimension will be
+ * used, any additional values of the longer vector will be ignored.
+ * For example, adding `[1, 2, 3]` and `[4, 5]` will result in `[5, 7]`.
+ *
* Calling `add()` with no arguments, as in `v.add()`, has no effect.
*
* This method supports N-dimensional vectors.
@@ -494,17 +494,18 @@ class Vector {
* @chainable
*/
add(...args) {
- if (args[0] instanceof Vector) {
- args = args[0].values;
- } else if (Array.isArray(args[0])) {
- args = args[0];
- }
- args.forEach((value, index) => {
- this._values[index] = (this._values[index] || 0) + (value || 0);
- });
+ const minDimension = prioritizeSmallerDimension(this.dimensions, args);
+
+ this.values = this.values.reduce((acc, v, i) => {
+ if(i < minDimension) acc[i] = this.values[i] + Number(args[i]);
+ return acc;
+ }, new Array(minDimension));
+
return this;
}
+
+
/**
* Performs modulo (remainder) division with a vector's `x`, `y`, and `z`
* components.
@@ -514,10 +515,14 @@ class Vector {
* an array of numbers, as in `v.rem([1, 2, 3])`.
*
* If only one value is provided, as in `v.rem(2)`, then all the components
- * will be set to their values modulo 2. If two values are provided, as in
- * `v.rem(2, 3)`, then `v.z` won't change. Calling `rem()` with no
+ * will be set to their values modulo 2. Calling `rem()` with no
* arguments, as in `v.rem()`, has no effect.
*
+ * Modulo vectors only when they are the same size: both 2D, or both 3D.
+ * When two vectors of different sizes are used, the smaller dimension will be
+ * used, any additional values of the longer vector will be ignored.
+ * For example, taking `[3, 6, 9]` modulo `[2, 4]` will result in `[1, 2]`.
+ *
* The static version of `rem()`, as in `p5.Vector.rem(v2, v1)`, returns a
* new p5.Vector object and doesn't change the
* originals.
@@ -612,59 +617,14 @@ class Vector {
* @param {p5.Vector | Number[]} value divisor vector.
* @chainable
*/
- rem(x, y, z) {
- if (x instanceof Vector) {
- if ([x.x, x.y, x.z].every(Number.isFinite)) {
- const xComponent = parseFloat(x.x);
- const yComponent = parseFloat(x.y);
- const zComponent = parseFloat(x.z);
- return calculateRemainder3D.call(
- this,
- xComponent,
- yComponent,
- zComponent
- );
- }
- } else if (Array.isArray(x)) {
- if (x.every(element => Number.isFinite(element))) {
- if (x.length === 2) {
- return calculateRemainder2D.call(this, x[0], x[1]);
- }
- if (x.length === 3) {
- return calculateRemainder3D.call(this, x[0], x[1], x[2]);
- }
- }
- } else if (arguments.length === 1) {
- if (Number.isFinite(arguments[0]) && arguments[0] !== 0) {
- this.x = this.x % arguments[0];
- this.y = this.y % arguments[0];
- this.z = this.z % arguments[0];
- return this;
- }
- } else if (arguments.length === 2) {
- const vectorComponents = [...arguments];
- if (vectorComponents.every(element => Number.isFinite(element))) {
- if (vectorComponents.length === 2) {
- return calculateRemainder2D.call(
- this,
- vectorComponents[0],
- vectorComponents[1]
- );
- }
- }
- } else if (arguments.length === 3) {
- const vectorComponents = [...arguments];
- if (vectorComponents.every(element => Number.isFinite(element))) {
- if (vectorComponents.length === 3) {
- return calculateRemainder3D.call(
- this,
- vectorComponents[0],
- vectorComponents[1],
- vectorComponents[2]
- );
- }
- }
- }
+ rem(...args) {
+ const minDimension = prioritizeSmallerDimension(this.dimensions, args);
+
+ this.values = Array.from({ length: minDimension }, (_, i) => {
+ return (args[i] > 0) ? this.values[i] % args[i] : this.values[i];
+ });
+
+ return this;
}
/**
@@ -674,10 +634,13 @@ class Vector {
* p5.Vector object, as in `v.sub(v2)`, or an array
* of numbers, as in `v.sub([1, 2, 3])`.
*
- * If a value isn't provided for a component, it won't change. For
- * example, `v.sub(4, 5)` subtracts 4 from `v.x`, 5 from `v.y`, and 0 from `v.z`.
* Calling `sub()` with no arguments, as in `v.sub()`, has no effect.
*
+ * Subtract vectors only when they are the same size: both 2D, or both 3D.
+ * When two vectors of different sizes are used, the smaller dimension will be
+ * used, any additional values of the longer vector will be ignored.
+ * For example, subtracting `[1, 2]` from `[3, 5, 7]` will result in `[2, 3]`.
+ *
* The static version of `sub()`, as in `p5.Vector.sub(v2, v1)`, returns a new
* p5.Vector object and doesn't change the
* originals.
@@ -787,19 +750,13 @@ class Vector {
* @chainable
*/
sub(...args) {
- if (args[0] instanceof Vector) {
- args[0].values.forEach((value, index) => {
- this._values[index] -= value || 0;
- });
- } else if (Array.isArray(args[0])) {
- args[0].forEach((value, index) => {
- this._values[index] -= value || 0;
- });
- } else {
- args.forEach((value, index) => {
- this._values[index] -= value || 0;
- });
- }
+ const minDimension = prioritizeSmallerDimension(this.dimensions, args);
+
+ this.values = this.values.reduce((acc, v, i) => {
+ if(i < minDimension) acc[i] = this.values[i] - args[i];
+ return acc;
+ }, new Array(minDimension));
+
return this;
}
@@ -811,11 +768,14 @@ class Vector {
* of numbers, as in `v.mult([1, 2, 3])`.
*
* If only one value is provided, as in `v.mult(2)`, then all the components
- * will be multiplied by 2. If a value isn't provided for a component, it
- * won't change. For example, `v.mult(4, 5)` multiplies `v.x` by, `v.y` by 5,
- * and `v.z` by 1. Calling `mult()` with no arguments, as in `v.mult()`, has
+ * will be multiplied by 2. Calling `mult()` with no arguments, as in `v.mult()`, has
* no effect.
*
+ * Multiply vectors only when they are the same size: both 2D, or both 3D.
+ * When two vectors of different sizes are multiplied, the smaller dimension will be
+ * used, any additional values of the longer vector will be ignored.
+ * For example, multiplying `[1, 2, 3]` by `[4, 5]` will result in `[4, 10]`.
+ *
* The static version of `mult()`, as in `p5.Vector.mult(v, 2)`, returns a new
* p5.Vector object and doesn't change the
* originals.
@@ -978,43 +938,51 @@ class Vector {
* @chainable
*/
mult(...args) {
- if (args.length === 1 && args[0] instanceof Vector) {
- const v = args[0];
- const maxLen = Math.min(this._values.length, v.values.length);
- for (let i = 0; i < maxLen; i++) {
- if (Number.isFinite(v.values[i]) && typeof v.values[i] === 'number') {
- this._values[i] *= v.values[i];
- } else {
- console.warn(
- 'p5.Vector.prototype.mult:',
- 'v contains components that are either undefined or not finite numbers'
- );
- return this;
- }
- }
- } else if (args.length === 1 && Array.isArray(args[0])) {
- const arr = args[0];
- const maxLen = Math.min(this._values.length, arr.length);
- for (let i = 0; i < maxLen; i++) {
- if (Number.isFinite(arr[i]) && typeof arr[i] === 'number') {
- this._values[i] *= arr[i];
- } else {
- console.warn(
- 'p5.Vector.prototype.mult:',
- 'arr contains elements that are either undefined or not finite numbers'
- );
- return this;
- }
- }
- } else if (
- args.length === 1 &&
- typeof args[0] === 'number' &&
- Number.isFinite(args[0])
- ) {
- for (let i = 0; i < this._values.length; i++) {
- this._values[i] *= args[0];
- }
- }
+ const minDimension = prioritizeSmallerDimension(this.dimensions, args);
+
+ this.values = this.values.reduce((acc, v, i) => {
+ if(i < minDimension) acc[i] = this.values[i] * args[i];
+ return acc;
+ }, new Array(minDimension));
+
+ // if (args.length === 1 && args[0] instanceof Vector) {
+ // const v = args[0];
+ // const maxLen = Math.min(this.values.length, v.values.length);
+ // for (let i = 0; i < maxLen; i++) {
+ // if (Number.isFinite(v.values[i]) && typeof v.values[i] === 'number') {
+ // if(!this.values[i]) this.values[i] = 0;
+ // this.values[i] *= v.values[i];
+ // } else {
+ // console.warn(
+ // 'p5.Vector.prototype.mult:',
+ // 'v contains components that are either undefined or not finite numbers'
+ // );
+ // return this;
+ // }
+ // }
+ // } else if (args.length === 1 && Array.isArray(args[0])) {
+ // const arr = args[0];
+ // const maxLen = Math.min(this.values.length, arr.length);
+ // for (let i = 0; i < maxLen; i++) {
+ // if (Number.isFinite(arr[i]) && typeof arr[i] === 'number') {
+ // this.values[i] *= arr[i];
+ // } else {
+ // console.warn(
+ // 'p5.Vector.prototype.mult:',
+ // 'arr contains elements that are either undefined or not finite numbers'
+ // );
+ // return this;
+ // }
+ // }
+ // } else if (
+ // args.length === 1 &&
+ // typeof args[0] === 'number' &&
+ // Number.isFinite(args[0])
+ // ) {
+ // for (let i = 0; i < this.values.length; i++) {
+ // this.values[i] *= args[0];
+ // }
+ // }
return this;
}
@@ -1026,11 +994,14 @@ class Vector {
* of numbers, as in `v.div([1, 2, 3])`.
*
* If only one value is provided, as in `v.div(2)`, then all the components
- * will be divided by 2. If a value isn't provided for a component, it
- * won't change. For example, `v.div(4, 5)` divides `v.x` by, `v.y` by 5,
- * and `v.z` by 1. Calling `div()` with no arguments, as in `v.div()`, has
+ * will be divided by 2. Calling `div()` with no arguments, as in `v.div()`, has
* no effect.
*
+ * Divide vectors only when they are the same size: both 2D, or both 3D.
+ * When two vectors of different sizes are divided, the smaller dimension will be
+ * used, any additional values of the longer vector will be ignored.
+ * For example, dividing `[8, 12, 21]` by `[2, 3]` will result in `[4, 4]`.
+ *
* The static version of `div()`, as in `p5.Vector.div(v, 2)`, returns a new
* p5.Vector object and doesn't change the
* originals.
@@ -1194,57 +1165,20 @@ class Vector {
* @chainable
*/
div(...args) {
- if (args.length === 0) return this;
- if (args.length === 1 && args[0] instanceof Vector) {
- const v = args[0];
- if (
- v._values.every(
- val => Number.isFinite(val) && typeof val === 'number'
- )
- ) {
- if (v._values.some(val => val === 0)) {
- console.warn('p5.Vector.prototype.div:', 'divide by 0');
- return this;
- }
- this._values = this._values.map((val, i) => val / v._values[i]);
- } else {
- console.warn(
- 'p5.Vector.prototype.div:',
- 'vector contains components that are either undefined or not finite numbers'
- );
- }
- return this;
- }
+ const minDimension = prioritizeSmallerDimension(this.dimensions, args);
- if (args.length === 1 && Array.isArray(args[0])) {
- const arr = args[0];
- if (arr.every(val => Number.isFinite(val) && typeof val === 'number')) {
- if (arr.some(val => val === 0)) {
- console.warn('p5.Vector.prototype.div:', 'divide by 0');
- return this;
- }
- this._values = this._values.map((val, i) => val / arr[i]);
- } else {
- console.warn(
- 'p5.Vector.prototype.div:',
- 'array contains components that are either undefined or not finite numbers'
- );
- }
- return this;
- }
-
- if (args.every(val => Number.isFinite(val) && typeof val === 'number')) {
- if (args.some(val => val === 0)) {
- console.warn('p5.Vector.prototype.div:', 'divide by 0');
- return this;
- }
- this._values = this._values.map((val, i) => val / args[0]);
- } else {
+ if(!args.every(v => typeof v === 'number' && v !== 0)){
console.warn(
- 'p5.Vector.prototype.div:',
- 'arguments contain components that are either undefined or not finite numbers'
+ 'p5.Vector.prototype.div',
+ 'Arguments contain components that are 0'
);
- }
+ return this;
+ };
+
+ this.values = this.values.reduce((acc, v, i) => {
+ if(i < minDimension) acc[i] = this.values[i] / args[i];
+ return acc;
+ }, new Array(minDimension));
return this;
}
@@ -1297,7 +1231,8 @@ class Vector {
* // Create a p5.Vector object.
* let p = createVector(30, 40);
*
- * // Draw a line from the origin.
+ * // Draw a line from th
+ * e origin.
* line(0, 0, p.x, p.y);
*
* // Style the text.
@@ -1312,7 +1247,7 @@ class Vector {
* }
*/
magSq() {
- return this._values.reduce(
+ return this.values.reduce(
(sum, component) => sum + component * component,
0
);
@@ -1416,9 +1351,9 @@ class Vector {
*/
dot(...args) {
if (args[0] instanceof Vector) {
- return this.dot(...args[0]._values);
+ return this.dot(...args[0].values);
}
- return this._values.reduce((sum, component, index) => {
+ return this.values.reduce((sum, component, index) => {
return sum + component * (args[index] || 0);
}, 0);
}
@@ -2823,15 +2758,15 @@ class Vector {
equals(...args) {
let values;
if (args[0] instanceof Vector) {
- values = args[0]._values;
+ values = args[0].values;
} else if (Array.isArray(args[0])) {
values = args[0];
} else {
values = args;
}
- for (let i = 0; i < this._values.length; i++) {
- if (this._values[i] !== (values[i] || 0)) {
+ for (let i = 0; i < this.values.length; i++) {
+ if (this.values[i] !== (values[i] || 0)) {
return false;
}
}
@@ -2851,8 +2786,8 @@ class Vector {
* @chainable
*/
clampToZero() {
- for (let i = 0; i < this._values.length; i++) {
- this._values[i] = this._clampToZero(this._values[i]);
+ for (let i = 0; i < this.values.length; i++) {
+ this.values[i] = this._clampToZero(this.values[i]);
}
return this;
}
diff --git a/src/math/patch-vector.js b/src/math/patch-vector.js
new file mode 100644
index 0000000000..8216c822e0
--- /dev/null
+++ b/src/math/patch-vector.js
@@ -0,0 +1,73 @@
+import { Vector } from './p5.Vector.js';
+
+/**
+ * @private
+ * @internal
+ */
+export function _defaultEmptyVector(target){
+ return function(...args){
+ if(args.length === 0){
+ p5._friendlyError(
+ 'In 1.x, createVector() was a shortcut for createVector(0, 0, 0). In 2.x, p5.js has vectors of any dimension, so you must provide your desired number of zeros. Use createVector(0, 0) for a 2D vector and createVector(0, 0, 0) for a 3D vector.',
+ 'p5.createVector'
+ );
+ return target.call(this, 0, 0, 0);
+ }else{
+ if (Array.isArray(args[0])) {
+ args = args[0];
+ }
+ return target.call(this, ...args);
+ }
+ };
+}
+
+
+/**
+ * @private
+ * @internal
+ */
+export function _validatedVectorOperation(expectsSoloNumberArgument){
+ return function(target){
+ return function(...args){
+ if (args.length === 0) {
+ // No arguments? No action
+ return this;
+ } else if (args[0] instanceof Vector) {
+ // First argument is a vector? Make it an array
+ args = args[0].values;
+ } else if (Array.isArray(args[0])) {
+ // First argument is an array? Great, keep it!
+ args = args[0];
+ } else if (expectsSoloNumberArgument && args.length === 1){
+ // Special case for a solo numeric arguments only applies sometimes
+ args = new Array(3).fill(args[0]);
+ }
+
+ if(Array.isArray(args) && !args.every(v => typeof v === 'number' && Number.isFinite(v))){
+ p5._friendlyError(
+ 'Arguments contain non-finite numbers',
+ target.name
+ );
+ return this;
+ };
+
+ return target.call(this, ...args);
+ };
+ };
+}
+
+/**
+ * Each of the following decorators validates the data on vector operations.
+ * These ensure that the arguments are consistently formatted, and that
+ * pre-conditions are met.
+ */
+export default function vectorValidation(p5, fn, lifecycles){
+
+ p5.registerDecorator('p5.prototype.createVector', _defaultEmptyVector);
+ p5.registerDecorator('p5.Vector.prototype.mult', _validatedVectorOperation(true));
+ p5.registerDecorator('p5.Vector.prototype.rem', _validatedVectorOperation(true));
+ p5.registerDecorator('p5.Vector.prototype.div', _validatedVectorOperation(true));
+ p5.registerDecorator('p5.Vector.prototype.add', _validatedVectorOperation(false));
+ p5.registerDecorator('p5.Vector.prototype.sub', _validatedVectorOperation(false));
+
+}
diff --git a/src/webgl/interaction.js b/src/webgl/interaction.js
index ef5beb665a..dd09abed1e 100644
--- a/src/webgl/interaction.js
+++ b/src/webgl/interaction.js
@@ -370,8 +370,11 @@ function interaction(p5, fn){
// accelerate rotate velocity
this._renderer.rotateVelocity.add(
deltaTheta * rotateAccelerationFactor,
- deltaPhi * rotateAccelerationFactor
+ deltaPhi * rotateAccelerationFactor,
+ 0
);
+
+ //console.log("added");
}
if (this._renderer.rotateVelocity.magSq() > 0.000001) {
// if freeRotation is true, the camera always rotates freely in the direction the pointer moves
@@ -390,8 +393,10 @@ function interaction(p5, fn){
}
// damping
this._renderer.rotateVelocity.mult(damping);
+ //console.log("multiplied", damping, this._renderer.rotateVelocity);
+
} else {
- this._renderer.rotateVelocity.set(0, 0);
+ this._renderer.rotateVelocity.set(0, 0, 0);
}
// move process
diff --git a/src/webgl/loading.js b/src/webgl/loading.js
index 23fe61b123..9ddf9101c9 100755
--- a/src/webgl/loading.js
+++ b/src/webgl/loading.js
@@ -615,7 +615,7 @@ function loading(p5, fn){
model.uvs.push(loadedVerts.vt.at(vertParts[1]) ?
loadedVerts.vt.at(vertParts[1]).slice() : [0, 0]);
model.vertexNormals.push(loadedVerts.vn.at(vertParts[2]) ?
- loadedVerts.vn.at(vertParts[2]).copy() : new Vector());
+ loadedVerts.vn.at(vertParts[2]).copy() : new Vector(0, 0, 0));
usedVerts[vertString][currentMaterial] = vertIndex;
face.push(vertIndex);
diff --git a/src/webgl/p5.Camera.js b/src/webgl/p5.Camera.js
index 5dcca97a20..b4dbece928 100644
--- a/src/webgl/p5.Camera.js
+++ b/src/webgl/p5.Camera.js
@@ -1601,10 +1601,10 @@ class Camera {
const up1 = rotMat1.row(1);
// prepare new vectors.
- const newFront = new Vector();
- const newUp = new Vector();
- const newEye = new Vector();
- const newCenter = new Vector();
+ const newFront = new Vector(0, 0, 0);
+ const newUp = new Vector(0, 0, 0);
+ const newEye = new Vector(0, 0, 0);
+ const newCenter = new Vector(0, 0, 0);
// Create the inverse matrix of mat0 by transposing mat0,
// and multiply it to mat1 from the right.
diff --git a/src/webgl/p5.Geometry.js b/src/webgl/p5.Geometry.js
index dad4c860f4..5da0ddbb10 100644
--- a/src/webgl/p5.Geometry.js
+++ b/src/webgl/p5.Geometry.js
@@ -1205,7 +1205,7 @@ class Geometry {
// initialize the vertexNormals array with empty vectors
vertexNormals.length = 0;
for (iv = 0; iv < vertices.length; ++iv) {
- vertexNormals.push(new Vector());
+ vertexNormals.push(new Vector(0, 0, 0));
}
// loop through all the faces adding its normal to the normal
diff --git a/test/bench/vectors.bench.js b/test/bench/vectors.bench.js
new file mode 100644
index 0000000000..952c428509
--- /dev/null
+++ b/test/bench/vectors.bench.js
@@ -0,0 +1,120 @@
+import { Vector } from '../../src/math/p5.Vector.js';
+
+import { bench, describe } from "vitest";
+
+
+describe("vector operations", () => {
+
+ bench(
+ "mult 5",
+ () => {
+ const nLimited = 5;
+ // TODO try just operating on det. values based on i and j
+ // without re-creation
+
+ for (let i = 0; i < nLimited; i++) {
+ for (let j = 0; j < nLimited; j++) {
+ const tmp = arr[i].mult(arr[j]);
+ }
+ }
+ }
+ );
+
+ bench(
+ "mult 10",
+ () => {
+ const nLimited = 10;
+ const arr = setupVectors();
+
+ for (let i = 0; i < nLimited; i++) {
+ for (let j = 0; j < nLimited; j++) {
+ const tmp = arr[i].mult(arr[j]);
+ }
+ }
+ }
+ );
+
+ bench(
+ "mult 20",
+ () => {
+ const nLimited = 20;
+ const arr = setupVectors();
+
+ for (let i = 0; i < nLimited; i++) {
+ for (let j = 0; j < nLimited; j++) {
+ const tmp = arr[i].mult(arr[j]);
+ }
+ }
+ }
+ );
+ bench(
+ "mult 100",
+ () => {
+ const nLimited = 100;
+ const arr = setupVectors();
+
+ for (let i = 0; i < nLimited; i++) {
+ for (let j = 0; j < nLimited; j++) {
+ const tmp = arr[i].mult(arr[j]);
+ }
+ }
+ }
+ );
+
+
+
+ bench(
+ "add 5",
+ () => {
+ const nLimited = 5;
+ const arr = setupVectors();
+
+ for (let i = 0; i < nLimited; i++) {
+ for (let j = 0; j < nLimited; j++) {
+ const tmp = arr[i].add(arr[j]);
+ }
+ }
+ }
+ );
+
+ bench(
+ "add 10",
+ () => {
+ const nLimited = 10;
+ const arr = setupVectors();
+
+ for (let i = 0; i < nLimited; i++) {
+ for (let j = 0; j < nLimited; j++) {
+ const tmp = arr[i].add(arr[j]);
+ }
+ }
+ });
+
+ bench(
+ "add 20",
+ () => {
+ const nLimited = 20;
+ const arr = setupVectors();
+
+ for (let i = 0; i < nLimited; i++) {
+ for (let j = 0; j < nLimited; j++) {
+ const tmp = arr[i].add(arr[j]);
+ }
+ }
+ }
+ );
+ bench(
+ "add 100",
+ () => {
+ const nLimited = 100;
+ const arr = setupVectors();
+
+ for (let i = 0; i < nLimited; i++) {
+ for (let j = 0; j < nLimited; j++) {
+ const tmp = arr[i].add(arr[j]);
+ }
+ }
+ },
+ );
+
+});
diff --git a/test/unit/math/p5.Vector.js b/test/unit/math/p5.Vector.js
index 4028ee2dba..d0fe08bce5 100644
--- a/test/unit/math/p5.Vector.js
+++ b/test/unit/math/p5.Vector.js
@@ -1,24 +1,47 @@
-import vector from '../../../src/math/p5.Vector.js';
+import { Vector } from '../../../src/math/p5.Vector.js';
+import { default as math } from '../../../src/math/math.js';
+import { _defaultEmptyVector, _validatedVectorOperation } from '../../../src/math/patch-vector.js';
import { vi } from 'vitest';
+
suite('p5.Vector', function () {
var v;
- const mockP5 = {
- _validateParameters: vi.fn()
- };
+ const mockP5 = {};
const mockP5Prototype = {};
- beforeEach(async function () {
- vector(mockP5, mockP5Prototype);
+ beforeAll(async function () {
+ // Makes createVector available
+ mockP5.Vector = Vector;
+ math(mockP5, mockP5Prototype);
+
+ // Ensures all decorators are used by unit tests
+ mockP5Prototype.createVector = _defaultEmptyVector(
+ mockP5Prototype.createVector
+ );
+
+ // The following mocks simulate the validation decorator
+ Vector.prototype.add = _validatedVectorOperation(false)(Vector.prototype.add);
+ Vector.prototype.sub = _validatedVectorOperation(false)(Vector.prototype.sub);
+ Vector.prototype.mult = _validatedVectorOperation(true)(Vector.prototype.mult);
+ Vector.prototype.rem = _validatedVectorOperation(true)(Vector.prototype.rem);
+ Vector.prototype.div = _validatedVectorOperation(true)(Vector.prototype.div);
+
+ globalThis.FESCalled = false;
+ globalThis.p5 = {
+ _friendlyError: function(msg, func) {
+ globalThis.FESCalled = true;
+ console.warn(msg);
+ }
+ };
});
afterEach(function () {});
suite.todo('p5.prototype.setHeading() RADIANS', function () {
beforeEach(function () {
- mockP5Prototype.angleMode(mockP5.RADIANS);
- v = mockP5Prototype.createVector(1, 1);
+ mockP5Prototype.angleMode(RADIANS);
+ v = new Vector(1, 1);
v.setHeading(1);
});
test('should have heading() value of 1 (RADIANS)', function () {
@@ -28,7 +51,7 @@ suite('p5.Vector', function () {
suite.todo('p5.prototype.setHeading() DEGREES', function () {
beforeEach(function () {
- mockP5Prototype.angleMode(mockP5.DEGREES);
+ mockP5Prototype.angleMode(DEGREES);
v = mockP5Prototype.createVector(1, 1);
v.setHeading(1);
});
@@ -44,7 +67,7 @@ suite('p5.Vector', function () {
v = mockP5Prototype.createVector();
});
test('should create instance of p5.Vector', function () {
- assert.instanceOf(v, mockP5.Vector);
+ assert.instanceOf(v, Vector);
});
test('should have x, y, z be initialized to 0', function () {
@@ -69,6 +92,32 @@ suite('p5.Vector', function () {
assert.equal(v.z, 3);
});
+ test('should have values be initialized to 1,2,3', function () {
+ assert.deepEqual(v.values, [1, 2, 3]);
+ });
+
+ test('should have dimensions initialized to 3', function () {
+ assert.equal(v.dimensions, 3);
+ });
+ });
+
+
+ suite.todo('p5.prototype.createVector()', function () {
+ beforeEach(function () {
+ v = mockP5Prototype.createVector();
+ });
+
+ test('should have x, y, z be initialized to 0,0,0', function () {
+ console.log(typeof mockP5Prototype.createVector);
+ assert.equal(v.x, 0);
+ assert.equal(v.y, 0);
+ assert.equal(v.z, 0);
+ });
+
+ test('should have values be initialized to 0,0,0', function () {
+ assert.deepEqual(v.values, [0,0,0]);
+ });
+
test('should have dimensions initialized to 3', function () {
assert.equal(v.dimensions, 3);
});
@@ -76,10 +125,10 @@ suite('p5.Vector', function () {
suite('new p5.Vector()', function () {
beforeEach(function () {
- v = new mockP5.Vector();
+ v = new Vector();
});
test('should set constant to DEGREES', function () {
- assert.instanceOf(v, mockP5.Vector);
+ assert.instanceOf(v, Vector);
});
test('should have x, y, z be initialized to 0', function () {
@@ -91,7 +140,7 @@ suite('p5.Vector', function () {
suite('new p5.Vector(1, 2, 3)', function () {
beforeEach(function () {
- v = new mockP5.Vector(1, 2, 3);
+ v = new Vector(1, 2, 3);
});
test('should have x, y, z be initialized to 1,2,3', function () {
@@ -101,9 +150,9 @@ suite('p5.Vector', function () {
});
});
- suite('new p5.Vector(1,2,undefined)', function () {
+ suite('new p5.Vector(1,2)', function () {
beforeEach(function () {
- v = new mockP5.Vector(1, 2, undefined);
+ v = new Vector(1, 2);
});
test('should have x, y, z be initialized to 1,2,0', function () {
@@ -116,13 +165,13 @@ suite('p5.Vector', function () {
suite('rotate', function () {
suite('p5.Vector.prototype.rotate() [INSTANCE]', function () {
test('should return the same object', function () {
- v = new mockP5.Vector(0, 1);
+ v = new Vector(0, 1);
expect(v.rotate(Math.PI)).to.eql(v);
});
suite.todo('radians', function () {
beforeEach(function () {
- mockP5Prototype.angleMode(mockP5.RADIANS);
+ mockP5Prototype.angleMode(RADIANS);
});
test('should rotate the vector [0, 1, 0] by pi radians to [0, -1, 0]', function () {
@@ -152,7 +201,7 @@ suite('p5.Vector', function () {
suite.todo('degrees', function () {
beforeEach(function () {
- mockP5Prototype.angleMode(mockP5.DEGREES);
+ mockP5Prototype.angleMode(DEGREES);
});
test('should rotate the vector [0, 1, 0] by 180 degrees to [0, -1, 0]', function () {
@@ -175,12 +224,12 @@ suite('p5.Vector', function () {
suite.todo('p5.Vector.rotate() [CLASS]', function () {
beforeEach(function () {
- mockP5Prototype.angleMode(mockP5.RADIANS);
+ mockP5Prototype.angleMode(RADIANS);
});
test('should not change the original object', function () {
v = mockP5Prototype.createVector(1, 0, 0);
- mockP5.Vector.rotate(v, Math.PI / 2);
+ Vector.rotate(v, Math.PI / 2);
expect(v.x).to.equal(1);
expect(v.y).to.equal(0);
expect(v.z).to.equal(0);
@@ -188,7 +237,7 @@ suite('p5.Vector', function () {
test('should rotate the vector [0, 1, 0] by pi radians to [0, -1, 0]', function () {
v = mockP5Prototype.createVector(0, 1, 0);
- const v1 = mockP5.Vector.rotate(v, Math.PI);
+ const v1 = Vector.rotate(v, Math.PI);
expect(v1.x).to.be.closeTo(0, 0.01);
expect(v1.y).to.be.closeTo(-1, 0.01);
expect(v1.z).to.be.closeTo(0, 0.01);
@@ -196,7 +245,7 @@ suite('p5.Vector', function () {
test('should rotate the vector [1, 0, 0] by -pi/2 radians to [0, -1, 0]', function () {
v = mockP5Prototype.createVector(1, 0, 0);
- const v1 = mockP5.Vector.rotate(v, -Math.PI / 2);
+ const v1 = Vector.rotate(v, -Math.PI / 2);
expect(v1.x).to.be.closeTo(0, 0.01);
expect(v1.y).to.be.closeTo(-1, 0.01);
expect(v1.z).to.be.closeTo(0, 0.01);
@@ -207,8 +256,8 @@ suite('p5.Vector', function () {
suite('angleBetween', function () {
let v1, v2;
beforeEach(function () {
- v1 = new mockP5.Vector(1, 0, 0);
- v2 = new mockP5.Vector(2, 2, 0);
+ v1 = new Vector(1, 0, 0);
+ v2 = new Vector(2, 2, 0);
});
suite('p5.Vector.prototype.angleBetween() [INSTANCE]', function () {
@@ -218,60 +267,60 @@ suite('p5.Vector', function () {
});
test('should not trip on rounding issues in 2D space', function () {
- v1 = new mockP5.Vector(-11, -20);
- v2 = new mockP5.Vector(-5.5, -10);
- const v3 = new mockP5.Vector(5.5, 10);
+ v1 = new Vector(-11, -20);
+ v2 = new Vector(-5.5, -10);
+ const v3 = new Vector(5.5, 10);
expect(v1.angleBetween(v2)).to.be.closeTo(0, 0.00001);
expect(v1.angleBetween(v3)).to.be.closeTo(Math.PI, 0.00001);
});
test('should not trip on rounding issues in 3D space', function () {
- v1 = new mockP5.Vector(1, 1.1, 1.2);
- v2 = new mockP5.Vector(2, 2.2, 2.4);
+ v1 = new Vector(1, 1.1, 1.2);
+ v2 = new Vector(2, 2.2, 2.4);
expect(v1.angleBetween(v2)).to.be.closeTo(0, 0.00001);
});
test('should return NaN for zero vector', function () {
- v1 = new mockP5.Vector(0, 0, 0);
- v2 = new mockP5.Vector(2, 3, 4);
+ v1 = new Vector(0, 0, 0);
+ v2 = new Vector(2, 3, 4);
expect(v1.angleBetween(v2)).to.be.NaN;
expect(v2.angleBetween(v1)).to.be.NaN;
});
test.todo('between [1,0,0] and [1,0,0] should be 0 degrees', function () {
- mockP5Prototype.angleMode(mockP5.DEGREES);
- v1 = new mockP5.Vector(1, 0, 0);
- v2 = new mockP5.Vector(1, 0, 0);
+ mockP5Prototype.angleMode(DEGREES);
+ v1 = new Vector(1, 0, 0);
+ v2 = new Vector(1, 0, 0);
expect(v1.angleBetween(v2)).to.equal(0);
});
test.todo(
'between [0,3,0] and [0,-3,0] should be 180 degrees',
function () {
- mockP5Prototype.angleMode(mockP5.DEGREES);
- v1 = new mockP5.Vector(0, 3, 0);
- v2 = new mockP5.Vector(0, -3, 0);
+ mockP5Prototype.angleMode(DEGREES);
+ v1 = new Vector(0, 3, 0);
+ v2 = new Vector(0, -3, 0);
expect(v1.angleBetween(v2)).to.be.closeTo(180, 0.01);
}
);
test('between [1,0,0] and [2,2,0] should be 1/4 PI radians', function () {
- v1 = new mockP5.Vector(1, 0, 0);
- v2 = new mockP5.Vector(2, 2, 0);
+ v1 = new Vector(1, 0, 0);
+ v2 = new Vector(2, 2, 0);
expect(v1.angleBetween(v2)).to.be.closeTo(Math.PI / 4, 0.01);
expect(v2.angleBetween(v1)).to.be.closeTo((-1 * Math.PI) / 4, 0.01);
});
test('between [2,0,0] and [-2,0,0] should be PI radians', function () {
- v1 = new mockP5.Vector(2, 0, 0);
- v2 = new mockP5.Vector(-2, 0, 0);
+ v1 = new Vector(2, 0, 0);
+ v2 = new Vector(-2, 0, 0);
expect(v1.angleBetween(v2)).to.be.closeTo(Math.PI, 0.01);
});
test('between [2,0,0] and [-2,-2,0] should be -3/4 PI radians ', function () {
- v1 = new mockP5.Vector(2, 0, 0);
- v2 = new mockP5.Vector(-2, -2, 0);
+ v1 = new Vector(2, 0, 0);
+ v2 = new Vector(-2, -2, 0);
expect(v1.angleBetween(v2)).to.be.closeTo(
-1 * (Math.PI / 2 + Math.PI / 4),
0.01
@@ -279,8 +328,8 @@ suite('p5.Vector', function () {
});
test('between [-2,-2,0] and [2,0,0] should be 3/4 PI radians', function () {
- v1 = new mockP5.Vector(-2, -2, 0);
- v2 = new mockP5.Vector(2, 0, 0);
+ v1 = new Vector(-2, -2, 0);
+ v2 = new Vector(2, 0, 0);
expect(v1.angleBetween(v2)).to.be.closeTo(
Math.PI / 2 + Math.PI / 4,
0.01
@@ -288,40 +337,40 @@ suite('p5.Vector', function () {
});
test('For the same vectors, the angle between them should always be 0.', function () {
- v1 = new mockP5.Vector(288, 814);
- v2 = new mockP5.Vector(288, 814);
+ v1 = new Vector(288, 814);
+ v2 = new Vector(288, 814);
expect(v1.angleBetween(v2)).to.equal(0);
});
test('The angle between vectors pointing in opposite is always PI.', function () {
- v1 = new mockP5.Vector(219, 560);
- v2 = new mockP5.Vector(-219, -560);
+ v1 = new Vector(219, 560);
+ v2 = new Vector(-219, -560);
expect(v1.angleBetween(v2)).to.be.closeTo(Math.PI, 0.0000001);
});
});
suite('p5.Vector.angleBetween() [CLASS]', function () {
test('should return NaN for zero vector', function () {
- v1 = new mockP5.Vector(0, 0, 0);
- v2 = new mockP5.Vector(2, 3, 4);
- expect(mockP5.Vector.angleBetween(v1, v2)).to.be.NaN;
- expect(mockP5.Vector.angleBetween(v2, v1)).to.be.NaN;
+ v1 = new Vector(0, 0, 0);
+ v2 = new Vector(2, 3, 4);
+ expect(Vector.angleBetween(v1, v2)).to.be.NaN;
+ expect(Vector.angleBetween(v2, v1)).to.be.NaN;
});
test.todo(
'between [1,0,0] and [0,-1,0] should be -90 degrees',
function () {
- mockP5Prototype.angleMode(mockP5.DEGREES);
- v1 = new mockP5.Vector(1, 0, 0);
- v2 = new mockP5.Vector(0, -1, 0);
- expect(mockP5.Vector.angleBetween(v1, v2)).to.be.closeTo(-90, 0.01);
+ mockP5Prototype.angleMode(DEGREES);
+ v1 = new Vector(1, 0, 0);
+ v2 = new Vector(0, -1, 0);
+ expect(Vector.angleBetween(v1, v2)).to.be.closeTo(-90, 0.01);
}
);
test('between [0,3,0] and [0,-3,0] should be PI radians', function () {
- v1 = new mockP5.Vector(0, 3, 0);
- v2 = new mockP5.Vector(0, -3, 0);
- expect(mockP5.Vector.angleBetween(v1, v2)).to.be.closeTo(Math.PI, 0.01);
+ v1 = new Vector(0, 3, 0);
+ v2 = new Vector(0, -3, 0);
+ expect(Vector.angleBetween(v1, v2)).to.be.closeTo(Math.PI, 0.01);
});
});
});
@@ -329,7 +378,7 @@ suite('p5.Vector', function () {
suite('set()', function () {
suite('with p5.Vector', function () {
test("should have x, y, z be initialized to the vector's x, y, z", function () {
- v.set(new mockP5.Vector(2, 5, 6));
+ v.set(new Vector(2, 5, 6));
expect(v.x).to.eql(2);
expect(v.y).to.eql(5);
expect(v.z).to.eql(6);
@@ -364,7 +413,7 @@ suite('p5.Vector', function () {
suite('copy', function () {
beforeEach(function () {
- v = new mockP5.Vector(2, 3, 4);
+ v = new Vector(2, 3, 4);
});
suite('p5.Vector.prototype.copy() [INSTANCE]', function () {
@@ -383,12 +432,12 @@ suite('p5.Vector', function () {
suite('p5.Vector.copy() [CLASS]', function () {
test('should not return the same instance', function () {
- var newObject = mockP5.Vector.copy(v);
+ var newObject = Vector.copy(v);
expect(newObject).to.not.equal(v);
});
test("should return the passed object's x, y, z", function () {
- var newObject = mockP5.Vector.copy(v);
+ var newObject = Vector.copy(v);
expect(newObject.x).to.eql(2);
expect(newObject.y).to.eql(3);
expect(newObject.z).to.eql(4);
@@ -398,12 +447,12 @@ suite('p5.Vector', function () {
suite('add()', function () {
beforeEach(function () {
- v = new mockP5.Vector();
+ v = new Vector(0, 0, 0);
});
suite('with p5.Vector', function () {
test('should add x, y, z from the vector argument', function () {
- v.add(new mockP5.Vector(1, 5, 6));
+ v.add(new Vector(1, 5, 6));
expect(v.x).to.eql(1);
expect(v.y).to.eql(5);
expect(v.z).to.eql(6);
@@ -457,9 +506,9 @@ suite('p5.Vector', function () {
suite('p5.Vector.add(v1, v2)', function () {
var v1, v2, res;
beforeEach(function () {
- v1 = new mockP5.Vector(2, 0, 3);
- v2 = new mockP5.Vector(0, 1, 3);
- res = mockP5.Vector.add(v1, v2);
+ v1 = new Vector(2, 0, 3);
+ v2 = new Vector(0, 1, 3);
+ res = Vector.add(v1, v2);
});
test('should return neither v1 nor v2', function () {
@@ -477,7 +526,7 @@ suite('p5.Vector', function () {
suite('rem()', function () {
beforeEach(function () {
- v = new mockP5.Vector(3, 4, 5);
+ v = new Vector(3, 4, 5);
});
test('should give same vector if nothing passed as parameter', function () {
@@ -495,10 +544,12 @@ suite('p5.Vector', function () {
});
test('should give correct output if passed two numeric value', function () {
+ expect(v.dimensions).to.eql(3);
v.rem(2, 3);
expect(v.x).to.eql(1);
expect(v.y).to.eql(1);
- expect(v.z).to.eql(5);
+ expect(v.z).to.eql(0);
+ expect(v.dimensions).to.eql(2);
});
test('should give correct output if passed three numeric value', function () {
@@ -510,28 +561,28 @@ suite('p5.Vector', function () {
suite('with p5.Vector', function () {
test('should return correct output if only one component is non-zero', function () {
- v.rem(new mockP5.Vector(0, 0, 4));
+ v.rem(new Vector(0, 0, 4));
expect(v.x).to.eql(3);
expect(v.y).to.eql(4);
expect(v.z).to.eql(1);
});
test('should return correct output if x component is zero', () => {
- v.rem(new mockP5.Vector(0, 3, 4));
+ v.rem(new Vector(0, 3, 4));
expect(v.x).to.eql(3);
expect(v.y).to.eql(1);
expect(v.z).to.eql(1);
});
test('should return correct output if all components are non-zero', () => {
- v.rem(new mockP5.Vector(2, 3, 4));
+ v.rem(new Vector(2, 3, 4));
expect(v.x).to.eql(1);
expect(v.y).to.eql(1);
expect(v.z).to.eql(1);
});
test('should return same vector if all components are zero', () => {
- v.rem(new mockP5.Vector(0, 0, 0));
+ v.rem(new Vector(0, 0, 0));
expect(v.x).to.eql(3);
expect(v.y).to.eql(4);
expect(v.z).to.eql(5);
@@ -541,10 +592,10 @@ suite('p5.Vector', function () {
suite('with negative vectors', function () {
let v;
beforeEach(function () {
- v = new mockP5.Vector(-15, -5, -2);
+ v = new Vector(-15, -5, -2);
});
test('should return correct output', () => {
- v.rem(new mockP5.Vector(2, 3, 3));
+ v.rem(new Vector(2, 3, 3));
expect(v.x).to.eql(-1);
expect(v.y).to.eql(-2);
expect(v.z).to.eql(-2);
@@ -562,14 +613,16 @@ suite('p5.Vector', function () {
v.rem([2, 3]);
expect(v.x).to.eql(1);
expect(v.y).to.eql(1);
- expect(v.z).to.eql(5);
+ expect(v.z).to.eql(0);
+ expect(v.dimensions).to.eql(2);
});
test('should return correct output if x,y components are zero for 2D vector', () => {
v.rem([0, 0]);
expect(v.x).to.eql(3);
expect(v.y).to.eql(4);
- expect(v.z).to.eql(5);
+ expect(v.z).to.eql(0);
+ expect(v.dimensions).to.eql(2);
});
test('should return same vector if any vector component is non-finite number', () => {
@@ -583,9 +636,9 @@ suite('p5.Vector', function () {
suite('p5.Vector.rem(v1,v2)', function () {
let v1, v2, res;
beforeEach(function () {
- v1 = new mockP5.Vector(2, 3, 4);
- v2 = new mockP5.Vector(1, 2, 3);
- res = mockP5.Vector.rem(v1, v2);
+ v1 = new Vector(2, 3, 4);
+ v2 = new Vector(1, 2, 3);
+ res = Vector.rem(v1, v2);
});
test('should return neither v1 nor v2', function () {
@@ -605,14 +658,11 @@ suite('p5.Vector', function () {
beforeEach(function () {
v.x = 0;
v.y = 0;
- v.z = 0;
});
suite('with p5.Vector', function () {
test('should sub x, y, z from the vector argument', function () {
- v.sub(new mockP5.Vector(2, 5, 6));
- expect(v.x).to.eql(-2);
- expect(v.y).to.eql(-5);
- expect(v.z).to.eql(-6);
+ v.sub(new Vector(2, 5));
+ assert.deepEqual(v.values, [-2, -5]);
});
});
@@ -626,11 +676,9 @@ suite('p5.Vector', function () {
});
});
- test("should subtract from the array's 0,1,2 index", function () {
+ test("should subtract from the array's 0, 1, 2 index", function () {
v.sub([2, 5, 6]);
- expect(v.x).to.eql(-2);
- expect(v.y).to.eql(-5);
- expect(v.z).to.eql(-6);
+ expect(v.values).to.eql([-2, -5]);
});
});
@@ -645,19 +693,19 @@ suite('p5.Vector', function () {
suite('sub(2,3,4)', function () {
test('should subtract the x, y, z components', function () {
- v.sub(5, 5, 5);
+ v.sub(5, 5);
expect(v.x).to.eql(-5);
expect(v.y).to.eql(-5);
- expect(v.z).to.eql(-5);
+ //expect(v.z).to.eql(-5);
});
});
suite('p5.Vector.sub(v1, v2)', function () {
var v1, v2, res;
beforeEach(function () {
- v1 = new mockP5.Vector(2, 0, 3);
- v2 = new mockP5.Vector(0, 1, 3);
- res = mockP5.Vector.sub(v1, v2);
+ v1 = new Vector(2, 0, 3);
+ v2 = new Vector(0, 1, 3);
+ res = Vector.sub(v1, v2);
});
test('should return neither v1 nor v2', function () {
@@ -675,7 +723,7 @@ suite('p5.Vector', function () {
suite('mult()', function () {
beforeEach(function () {
- v = new mockP5.Vector(1, 1, 1);
+ v = new Vector(1, 1, 1);
});
test('should return the same object', function () {
@@ -705,11 +753,20 @@ suite('p5.Vector', function () {
});
});
+ suite('with arglist', function () {
+ test('multiply the x, y, z with the scalar', function () {
+ v.mult(2, 3, 4);
+ expect(v.x).to.eql(2);
+ expect(v.y).to.eql(3);
+ expect(v.z).to.eql(4);
+ });
+ });
+
suite('v0.mult(v1)', function () {
var v0, v1;
beforeEach(function () {
- v0 = new mockP5.Vector(1, 2, 3);
- v1 = new mockP5.Vector(2, 3, 4);
+ v0 = new Vector(1, 2, 3);
+ v1 = new Vector(2, 3, 4);
v0.mult(v1);
});
@@ -723,7 +780,7 @@ suite('p5.Vector', function () {
suite('v0.mult(arr)', function () {
var v0, arr;
beforeEach(function () {
- v0 = new mockP5.Vector(1, 2, 3);
+ v0 = new Vector(1, 2, 3);
arr = [2, 3, 4];
v0.mult(arr);
});
@@ -738,8 +795,8 @@ suite('p5.Vector', function () {
suite('p5.Vector.mult(v, n)', function () {
var v, res;
beforeEach(function () {
- v = new mockP5.Vector(1, 2, 3);
- res = mockP5.Vector.mult(v, 4);
+ v = new Vector(1, 2, 3);
+ res = Vector.mult(v, 4);
});
test('should return a new p5.Vector', function () {
@@ -756,9 +813,9 @@ suite('p5.Vector', function () {
suite('p5.Vector.mult(v, v', function () {
var v0, v1, res;
beforeEach(function () {
- v0 = new mockP5.Vector(1, 2, 3);
- v1 = new mockP5.Vector(2, 3, 4);
- res = mockP5.Vector.mult(v0, v1);
+ v0 = new Vector(1, 2, 3);
+ v1 = new Vector(2, 3, 4);
+ res = Vector.mult(v0, v1);
});
test('should return new vector from component wise multiplication', function () {
@@ -768,12 +825,12 @@ suite('p5.Vector', function () {
});
});
- suite('p5.Vector.mult(v, arr', function () {
+ suite('p5.Vector.mult(v, arr)', function () {
var v0, arr, res;
beforeEach(function () {
- v0 = new mockP5.Vector(1, 2, 3);
+ v0 = new Vector(1, 2, 3);
arr = [2, 3, 4];
- res = mockP5.Vector.mult(v0, arr);
+ res = Vector.mult(v0, arr);
});
test('should return new vector from component wise multiplication with an array', function () {
@@ -786,7 +843,7 @@ suite('p5.Vector', function () {
suite('div()', function () {
beforeEach(function () {
- v = new mockP5.Vector(1, 1, 1);
+ v = new Vector(1, 1, 1);
});
test('should return the same object', function () {
@@ -823,11 +880,20 @@ suite('p5.Vector', function () {
});
});
+ suite('with arglist', function () {
+ test('divide the x, y, z with the scalar', function () {
+ v.div(2, 3, 4);
+ expect(v.x).to.be.closeTo(0.5, 0.01);
+ expect(v.y).to.be.closeTo(0.333, 0.01);
+ expect(v.z).to.be.closeTo(0.25, 0.01);
+ });
+ });
+
suite('p5.Vector.div(v, n)', function () {
var v, res;
beforeEach(function () {
- v = new mockP5.Vector(1, 1, 1);
- res = mockP5.Vector.div(v, 4);
+ v = new Vector(1, 1, 1);
+ res = Vector.div(v, 4);
});
test('should not be undefined', function () {
@@ -848,10 +914,10 @@ suite('p5.Vector', function () {
suite('v0.div(v1)', function () {
var v0, v1, v2, v3;
beforeEach(function () {
- v0 = new mockP5.Vector(2, 6, 9);
- v1 = new mockP5.Vector(2, 2, 3);
- v2 = new mockP5.Vector(1, 1, 1);
- v3 = new mockP5.Vector(0, 0, 0);
+ v0 = new Vector(2, 6, 9);
+ v1 = new Vector(2, 2, 3);
+ v2 = new Vector(1, 1, 1);
+ v3 = new Vector(0, 0, 0);
v0.div(v1);
});
@@ -870,8 +936,8 @@ suite('p5.Vector', function () {
});
test('should work on 2D vectors', function () {
- const v = new mockP5.Vector(1, 1);
- const divisor = new mockP5.Vector(2, 2);
+ const v = new Vector(1, 1);
+ const divisor = new Vector(2, 2);
v.div(divisor);
expect(v.x).to.eql(0.5);
expect(v.y).to.eql(0.5);
@@ -879,8 +945,8 @@ suite('p5.Vector', function () {
});
test('should work when the dividend has 0', function () {
- const v = new mockP5.Vector(1, 0);
- const divisor = new mockP5.Vector(2, 2);
+ const v = new Vector(1, 0);
+ const divisor = new Vector(2, 2);
v.div(divisor);
expect(v.x).to.eql(0.5);
expect(v.y).to.eql(0);
@@ -888,8 +954,8 @@ suite('p5.Vector', function () {
});
test('should do nothing when the divisor has 0', function () {
- const v = new mockP5.Vector(1, 1);
- const divisor = new mockP5.Vector(0, 2);
+ const v = new Vector(1, 1);
+ const divisor = new Vector(0, 2);
v.div(divisor);
expect(v.x).to.eql(1);
expect(v.y).to.eql(1);
@@ -900,8 +966,8 @@ suite('p5.Vector', function () {
suite('v0.div(arr)', function () {
var v0, v1, arr;
beforeEach(function () {
- v0 = new mockP5.Vector(2, 6, 9);
- v1 = new mockP5.Vector(1, 1, 1);
+ v0 = new Vector(2, 6, 9);
+ v1 = new Vector(1, 1, 1);
arr = [2, 2, 3];
v0.div(arr);
});
@@ -923,9 +989,9 @@ suite('p5.Vector', function () {
suite('p5.Vector.div(v, v', function () {
var v0, v1, res;
beforeEach(function () {
- v0 = new mockP5.Vector(2, 6, 9);
- v1 = new mockP5.Vector(2, 2, 3);
- res = mockP5.Vector.div(v0, v1);
+ v0 = new Vector(2, 6, 9);
+ v1 = new Vector(2, 2, 3);
+ res = Vector.div(v0, v1);
});
test('should return new vector from component wise division', function () {
@@ -938,9 +1004,9 @@ suite('p5.Vector', function () {
suite('p5.Vector.div(v, arr', function () {
var v0, arr, res;
beforeEach(function () {
- v0 = new mockP5.Vector(2, 6, 9);
+ v0 = new Vector(2, 6, 9);
arr = [2, 2, 3];
- res = mockP5.Vector.div(v0, arr);
+ res = Vector.div(v0, arr);
});
test('should return new vector from component wise division with an array', function () {
@@ -951,6 +1017,56 @@ suite('p5.Vector', function () {
});
});
+
+ suite('smaller dimension', function () {
+ let v1, v2, v3;
+ beforeEach(function () {
+ v1 = new Vector(1);
+ v2 = new Vector(2, 3);
+ v3 = new Vector(4, 5, 6);
+ });
+
+ test('should be prioritized in add()', function () {
+ assert.deepEqual(v1.add(v2).values, [3]);
+ expect(v1.add(v2).dimensions).to.eql(1);
+
+ assert.deepEqual(v3.add(v2).values, [6, 8]);
+ expect(v3.add(v2).dimensions).to.eql(2);
+ });
+
+ test('should be prioritized in sub()', function () {
+ assert.deepEqual(v1.sub(v2).values, [-1]);
+ expect(v1.sub(v2).dimensions).to.eql(1);
+
+ assert.deepEqual(v3.sub(v2).values, [2, 2]);
+ expect(v3.sub(v2).dimensions).to.eql(2);
+ });
+
+ test('should be prioritized in mult()', function () {
+ assert.deepEqual(v1.mult(v2).values, [2]);
+ expect(v1.mult(v2).dimensions).to.eql(1);
+
+ assert.deepEqual(v3.mult(v2).values, [8, 15]);
+ expect(v3.mult(v2).dimensions).to.eql(2);
+ });
+
+ test('should be prioritized in div()', function () {
+ assert.deepEqual(v1.div(v2).values, [1/2]);
+ expect(v1.div(v2).dimensions).to.eql(1);
+
+ assert.deepEqual(v3.div(v2).values, [2, 5/3]);
+ expect(v3.div(v2).dimensions).to.eql(2);
+ });
+
+ test('should be prioritized in rem()', function () {
+ assert.deepEqual(v1.rem(v2).values, [1]);
+ expect(v1.rem(v2).dimensions).to.eql(1);
+
+ assert.deepEqual(v3.rem(v2).values, [0, 2]);
+ expect(v3.rem(v2).dimensions).to.eql(2);
+ });
+ });
+
suite('dot', function () {
beforeEach(function () {
v.x = 1;
@@ -959,12 +1075,12 @@ suite('p5.Vector', function () {
});
test('should return a number', function () {
- expect(typeof v.dot(new mockP5.Vector()) === 'number').to.eql(true);
+ expect(typeof v.dot(new Vector()) === 'number').to.eql(true);
});
suite('with p5.Vector', function () {
test('should be the dot product of the vector', function () {
- expect(v.dot(new mockP5.Vector(2, 2))).to.eql(4);
+ expect(v.dot(new Vector(2, 2))).to.eql(4);
});
});
@@ -981,9 +1097,9 @@ suite('p5.Vector', function () {
suite('p5.Vector.dot(v, n)', function () {
var v1, v2, res;
beforeEach(function () {
- v1 = new mockP5.Vector(1, 1, 1);
- v2 = new mockP5.Vector(2, 3, 4);
- res = mockP5.Vector.dot(v1, v2);
+ v1 = new Vector(1, 1, 1);
+ v2 = new Vector(2, 3, 4);
+ res = Vector.dot(v1, v2);
});
test('should return a number', function () {
@@ -1005,12 +1121,12 @@ suite('p5.Vector', function () {
});
test('should return a new product', function () {
- expect(v.cross(new mockP5.Vector())).to.not.eql(v);
+ expect(v.cross(new Vector())).to.not.eql(v);
});
suite('with p5.Vector', function () {
test('should cross x, y, z from the vector argument', function () {
- res = v.cross(new mockP5.Vector(2, 5, 6));
+ res = v.cross(new Vector(2, 5, 6));
expect(res.x).to.eql(1); //this.y * v.z - this.z * v.y
expect(res.y).to.eql(-4); //this.z * v.x - this.x * v.z
expect(res.z).to.eql(3); //this.x * v.y - this.y * v.x
@@ -1020,9 +1136,9 @@ suite('p5.Vector', function () {
suite('p5.Vector.cross(v1, v2)', function () {
var v1, v2, res;
beforeEach(function () {
- v1 = new mockP5.Vector(3, 6, 9);
- v2 = new mockP5.Vector(1, 1, 1);
- res = mockP5.Vector.cross(v1, v2);
+ v1 = new Vector(3, 6, 9);
+ v2 = new Vector(1, 1, 1);
+ res = Vector.cross(v1, v2);
});
test('should not be undefined', function () {
@@ -1045,9 +1161,9 @@ suite('p5.Vector', function () {
suite('dist', function () {
var b, c;
beforeEach(function () {
- v = new mockP5.Vector(0, 0, 1);
- b = new mockP5.Vector(0, 0, 5);
- c = new mockP5.Vector(3, 4, 1);
+ v = new Vector(0, 0, 1);
+ b = new Vector(0, 0, 5);
+ c = new Vector(3, 4, 1);
});
test('should return a number', function () {
@@ -1070,23 +1186,23 @@ suite('p5.Vector', function () {
suite('p5.Vector.dist(v1, v2)', function () {
var v1, v2;
beforeEach(function () {
- v1 = new mockP5.Vector(0, 0, 0);
- v2 = new mockP5.Vector(0, 3, 4);
+ v1 = new Vector(0, 0, 0);
+ v2 = new Vector(0, 3, 4);
});
test('should return a number', function () {
- expect(typeof mockP5.Vector.dist(v1, v2) === 'number').to.eql(true);
+ expect(typeof Vector.dist(v1, v2) === 'number').to.eql(true);
});
test('should be commutative', function () {
- expect(mockP5.Vector.dist(v1, v2)).to.eql(mockP5.Vector.dist(v2, v1));
+ expect(Vector.dist(v1, v2)).to.eql(Vector.dist(v2, v1));
});
});
suite('normalize', function () {
suite('p5.Vector.prototype.normalize() [INSTANCE]', function () {
beforeEach(function () {
- v = new mockP5.Vector(1, 1, 1);
+ v = new Vector(1, 1, 1);
});
test('should return the same object', function () {
@@ -1117,8 +1233,8 @@ suite('p5.Vector', function () {
suite('p5.Vector.normalize(v) [CLASS]', function () {
var res;
beforeEach(function () {
- v = new mockP5.Vector(1, 0, 0);
- res = mockP5.Vector.normalize(v);
+ v = new Vector(1, 0, 0);
+ res = Vector.normalize(v);
});
test('should not be undefined', function () {
@@ -1139,7 +1255,7 @@ suite('p5.Vector', function () {
v.x = 2;
v.y = 2;
v.z = 1;
- res = mockP5.Vector.normalize(v);
+ res = Vector.normalize(v);
expect(res.x).to.be.closeTo(0.6666, 0.01);
expect(res.y).to.be.closeTo(0.6666, 0.01);
expect(res.z).to.be.closeTo(0.3333, 0.01);
@@ -1151,7 +1267,7 @@ suite('p5.Vector', function () {
let v;
beforeEach(function () {
- v = new mockP5.Vector(5, 5, 5);
+ v = new Vector(5, 5, 5);
});
suite('p5.Vector.prototype.limit() [INSTANCE]', function () {
@@ -1180,12 +1296,12 @@ suite('p5.Vector', function () {
suite('p5.Vector.limit() [CLASS]', function () {
test('should not return the same object', function () {
- expect(mockP5.Vector.limit(v)).to.not.equal(v);
+ expect(Vector.limit(v)).to.not.equal(v);
});
suite('with a vector larger than the limit', function () {
test('should limit the vector', function () {
- const res = mockP5.Vector.limit(v, 1);
+ const res = Vector.limit(v, 1);
expect(res.x).to.be.closeTo(0.5773, 0.01);
expect(res.y).to.be.closeTo(0.5773, 0.01);
expect(res.z).to.be.closeTo(0.5773, 0.01);
@@ -1194,7 +1310,7 @@ suite('p5.Vector', function () {
suite('with a vector smaller than the limit', function () {
test('should not limit the vector', function () {
- const res = mockP5.Vector.limit(v, 8.67);
+ const res = Vector.limit(v, 8.67);
expect(res.x).to.eql(5);
expect(res.y).to.eql(5);
expect(res.z).to.eql(5);
@@ -1203,8 +1319,8 @@ suite('p5.Vector', function () {
suite('when given a target vector', function () {
test('should store limited vector in the target', function () {
- const target = new mockP5.Vector(0, 0, 0);
- mockP5.Vector.limit(v, 1, target);
+ const target = new Vector(0, 0, 0);
+ Vector.limit(v, 1, target);
expect(target.x).to.be.closeTo(0.5773, 0.01);
expect(target.y).to.be.closeTo(0.5773, 0.01);
expect(target.z).to.be.closeTo(0.5773, 0.01);
@@ -1217,7 +1333,7 @@ suite('p5.Vector', function () {
let v;
beforeEach(function () {
- v = new mockP5.Vector(1, 0, 0);
+ v = new Vector(1, 0, 0);
});
suite('p5.Vector.setMag() [INSTANCE]', function () {
@@ -1245,11 +1361,11 @@ suite('p5.Vector', function () {
suite('p5.Vector.prototype.setMag() [CLASS]', function () {
test('should not return the same object', function () {
- expect(mockP5.Vector.setMag(v, 2)).to.not.equal(v);
+ expect(Vector.setMag(v, 2)).to.not.equal(v);
});
test('should set the magnitude of the vector', function () {
- const res = mockP5.Vector.setMag(v, 4);
+ const res = Vector.setMag(v, 4);
expect(res.x).to.eql(4);
expect(res.y).to.eql(0);
expect(res.z).to.eql(0);
@@ -1259,7 +1375,7 @@ suite('p5.Vector', function () {
v.x = 2;
v.y = 3;
v.z = -6;
- const res = mockP5.Vector.setMag(v, 14);
+ const res = Vector.setMag(v, 14);
expect(res.x).to.eql(4);
expect(res.y).to.eql(6);
expect(res.z).to.eql(-12);
@@ -1267,8 +1383,8 @@ suite('p5.Vector', function () {
suite('when given a target vector', function () {
test('should set the magnitude on the target', function () {
- const target = new mockP5.Vector(0, 1, 0);
- const res = mockP5.Vector.setMag(v, 4, target);
+ const target = new Vector(0, 1, 0);
+ const res = Vector.setMag(v, 4, target);
expect(target).to.equal(res);
expect(target.x).to.eql(4);
expect(target.y).to.eql(0);
@@ -1280,7 +1396,7 @@ suite('p5.Vector', function () {
suite('heading', function () {
beforeEach(function () {
- v = new mockP5.Vector();
+ v = new Vector(0,0,0);
});
suite('p5.Vector.prototype.heading() [INSTANCE]', function () {
@@ -1311,7 +1427,7 @@ suite('p5.Vector', function () {
suite.todo('with `angleMode(DEGREES)`', function () {
beforeEach(function () {
- mockP5Prototype.angleMode(mockP5.DEGREES);
+ mockP5Prototype.angleMode(DEGREES);
});
test('heading for vector pointing right is 0', function () {
@@ -1339,28 +1455,28 @@ suite('p5.Vector', function () {
suite('p5.Vector.heading() [CLASS]', function () {
test('should return a number', function () {
- expect(typeof mockP5.Vector.heading(v) === 'number').to.eql(true);
+ expect(typeof Vector.heading(v) === 'number').to.eql(true);
});
test('heading for vector pointing right is 0', function () {
v.x = 1;
v.y = 0;
v.z = 0;
- expect(mockP5.Vector.heading(v)).to.be.closeTo(0, 0.01);
+ expect(Vector.heading(v)).to.be.closeTo(0, 0.01);
});
test('heading for vector pointing down is PI/2', function () {
v.x = 0;
v.y = 1;
v.z = 0;
- expect(mockP5.Vector.heading(v)).to.be.closeTo(Math.PI / 2, 0.01);
+ expect(Vector.heading(v)).to.be.closeTo(Math.PI / 2, 0.01);
});
test('heading for vector pointing left is PI', function () {
v.x = -1;
v.y = 0;
v.z = 0;
- expect(mockP5.Vector.heading(v)).to.be.closeTo(Math.PI, 0.01);
+ expect(Vector.heading(v)).to.be.closeTo(Math.PI, 0.01);
});
});
});
@@ -1370,14 +1486,13 @@ suite('p5.Vector', function () {
expect(v.lerp()).to.eql(v);
});
- // PEND: ADD BACK IN
- // suite('with p5.Vector', function() {
- // test('should call lerp with 4 arguments', function() {
- // spyOn(v, 'lerp').andCallThrough();
- // v.lerp(new p5.Vector(1,2,3), 1);
- // expect(v.lerp).toHaveBeenCalledWith(1, 2, 3, 1);
- // });
- // });
+ suite('with p5.Vector', function() {
+ test('should call lerp with 4 arguments', function() {
+ vi.spyOn(v, 'lerp');
+ v.lerp(new Vector(1,2,3), 1);
+ expect(v.lerp).toHaveBeenCalledWith(1, 2, 3, 1);
+ });
+ });
suite('with x, y, z, amt', function () {
beforeEach(function () {
@@ -1416,9 +1531,9 @@ suite('p5.Vector', function () {
suite('p5.Vector.lerp(v1, v2, amt)', function () {
var res, v1, v2;
beforeEach(function () {
- v1 = new mockP5.Vector(0, 0, 0);
- v2 = new mockP5.Vector(2, 2, 2);
- res = mockP5.Vector.lerp(v1, v2, 0.5);
+ v1 = new Vector(0, 0, 0);
+ v2 = new Vector(2, 2, 2);
+ res = Vector.lerp(v1, v2, 0.5);
});
test('should not be undefined', function () {
@@ -1426,7 +1541,7 @@ suite('p5.Vector', function () {
});
test('should be a p5.Vector', function () {
- expect(res).to.be.an.instanceof(mockP5.Vector);
+ expect(res).to.be.an.instanceof(Vector);
});
test('should return neither v1 nor v2', function () {
@@ -1445,7 +1560,7 @@ suite('p5.Vector', function () {
var w;
beforeEach(function () {
v.set(1, 2, 3);
- w = new mockP5.Vector(4, 6, 8);
+ w = new Vector(4, 6, 8);
});
test('if amt is 0, returns original vector', function () {
@@ -1496,9 +1611,9 @@ suite('p5.Vector', function () {
suite('p5.Vector.slerp(v1, v2, amt)', function () {
var res, v1, v2;
beforeEach(function () {
- v1 = new mockP5.Vector(1, 0, 0);
- v2 = new mockP5.Vector(0, 0, 1);
- res = mockP5.Vector.slerp(v1, v2, 1 / 3);
+ v1 = new Vector(1, 0, 0);
+ v2 = new Vector(0, 0, 1);
+ res = Vector.slerp(v1, v2, 1 / 3);
});
test('should not be undefined', function () {
@@ -1506,7 +1621,7 @@ suite('p5.Vector', function () {
});
test('should be a p5.Vector', function () {
- expect(res).to.be.an.instanceof(mockP5.Vector);
+ expect(res).to.be.an.instanceof(Vector);
});
test('should return neither v1 nor v2', function () {
@@ -1521,14 +1636,14 @@ suite('p5.Vector', function () {
});
test('Make sure the interpolation in -1/3 is correct', function () {
- mockP5.Vector.slerp(v1, v2, -1 / 3, res);
+ Vector.slerp(v1, v2, -1 / 3, res);
expect(res.x).to.be.closeTo(Math.cos(-Math.PI / 6), 0.00001);
expect(res.y).to.be.closeTo(0, 0.00001);
expect(res.z).to.be.closeTo(Math.sin(-Math.PI / 6), 0.00001);
});
test('Make sure the interpolation in 5/3 is correct', function () {
- mockP5.Vector.slerp(v1, v2, 5 / 3, res);
+ Vector.slerp(v1, v2, 5 / 3, res);
expect(res.x).to.be.closeTo(Math.cos((5 * Math.PI) / 6), 0.00001);
expect(res.y).to.be.closeTo(0, 0.00001);
expect(res.z).to.be.closeTo(Math.sin((5 * Math.PI) / 6), 0.00001);
@@ -1539,7 +1654,7 @@ suite('p5.Vector', function () {
var res, angle;
beforeEach(function () {
angle = Math.PI / 2;
- res = mockP5.Vector.fromAngle(angle);
+ res = Vector.fromAngle(angle);
});
test('should be a p5.Vector with values (0,1)', function () {
@@ -1551,7 +1666,7 @@ suite('p5.Vector', function () {
suite('p5.Vector.random2D()', function () {
var res;
beforeEach(function () {
- res = mockP5.Vector.random2D();
+ res = Vector.random2D();
});
test('should be a unit p5.Vector', function () {
@@ -1562,7 +1677,7 @@ suite('p5.Vector', function () {
suite('p5.Vector.random3D()', function () {
var res;
beforeEach(function () {
- res = mockP5.Vector.random3D();
+ res = Vector.random3D();
});
test('should be a unit p5.Vector', function () {
expect(res.mag()).to.be.closeTo(1, 0.01);
@@ -1571,7 +1686,7 @@ suite('p5.Vector', function () {
suite('array', function () {
beforeEach(function () {
- v = new mockP5.Vector(1, 23, 4);
+ v = new Vector(1, 23, 4);
});
suite('p5.Vector.prototype.array() [INSTANCE]', function () {
@@ -1586,11 +1701,11 @@ suite('p5.Vector', function () {
suite('p5.Vector.array() [CLASS]', function () {
test('should return an array', function () {
- expect(mockP5.Vector.array(v)).to.be.instanceof(Array);
+ expect(Vector.array(v)).to.be.instanceof(Array);
});
test('should return an with the x y and z components', function () {
- expect(mockP5.Vector.array(v)).to.eql([1, 23, 4]);
+ expect(Vector.array(v)).to.eql([1, 23, 4]);
});
});
});
@@ -1609,31 +1724,31 @@ suite('p5.Vector', function () {
incoming_x = 1;
incoming_y = 1;
incoming_z = 1;
- original_incoming = new mockP5.Vector(
+ original_incoming = new Vector(
incoming_x,
incoming_y,
incoming_z
);
- x_normal = new mockP5.Vector(3, 0, 0);
- y_normal = new mockP5.Vector(0, 3, 0);
- z_normal = new mockP5.Vector(0, 0, 3);
+ x_normal = new Vector(3, 0, 0);
+ y_normal = new Vector(0, 3, 0);
+ z_normal = new Vector(0, 0, 3);
- x_bounce_incoming = new mockP5.Vector(
+ x_bounce_incoming = new Vector(
incoming_x,
incoming_y,
incoming_z
);
x_bounce_outgoing = x_bounce_incoming.reflect(x_normal);
- y_bounce_incoming = new mockP5.Vector(
+ y_bounce_incoming = new Vector(
incoming_x,
incoming_y,
incoming_z
);
y_bounce_outgoing = y_bounce_incoming.reflect(y_normal);
- z_bounce_incoming = new mockP5.Vector(
+ z_bounce_incoming = new Vector(
incoming_x,
incoming_y,
incoming_z
@@ -1642,9 +1757,9 @@ suite('p5.Vector', function () {
});
test('should return a p5.Vector', function () {
- expect(x_bounce_incoming).to.be.an.instanceof(mockP5.Vector);
- expect(y_bounce_incoming).to.be.an.instanceof(mockP5.Vector);
- expect(z_bounce_incoming).to.be.an.instanceof(mockP5.Vector);
+ expect(x_bounce_incoming).to.be.an.instanceof(Vector);
+ expect(y_bounce_incoming).to.be.an.instanceof(Vector);
+ expect(z_bounce_incoming).to.be.an.instanceof(Vector);
});
test('should update this', function () {
@@ -1720,47 +1835,47 @@ suite('p5.Vector', function () {
incoming_x = 1;
incoming_y = 1;
incoming_z = 1;
- original_incoming = new mockP5.Vector(
+ original_incoming = new Vector(
incoming_x,
incoming_y,
incoming_z
);
- x_target = new mockP5.Vector();
- y_target = new mockP5.Vector();
- z_target = new mockP5.Vector();
+ x_target = new Vector(0, 0, 0);
+ y_target = new Vector(0, 0, 0);
+ z_target = new Vector(0, 0, 0);
- x_normal = new mockP5.Vector(3, 0, 0);
- y_normal = new mockP5.Vector(0, 3, 0);
- z_normal = new mockP5.Vector(0, 0, 3);
+ x_normal = new Vector(3, 0, 0);
+ y_normal = new Vector(0, 3, 0);
+ z_normal = new Vector(0, 0, 3);
- x_bounce_incoming = new mockP5.Vector(
+ x_bounce_incoming = new Vector(
incoming_x,
incoming_y,
incoming_z
);
- x_bounce_outgoing = mockP5.Vector.reflect(
+ x_bounce_outgoing = Vector.reflect(
x_bounce_incoming,
x_normal,
x_target
);
- y_bounce_incoming = new mockP5.Vector(
+ y_bounce_incoming = new Vector(
incoming_x,
incoming_y,
incoming_z
);
- y_bounce_outgoing = mockP5.Vector.reflect(
+ y_bounce_outgoing = Vector.reflect(
y_bounce_incoming,
y_normal,
y_target
);
- z_bounce_incoming = new mockP5.Vector(
+ z_bounce_incoming = new Vector(
incoming_x,
incoming_y,
incoming_z
);
- z_bounce_outgoing = mockP5.Vector.reflect(
+ z_bounce_outgoing = Vector.reflect(
z_bounce_incoming,
z_normal,
z_target
@@ -1768,9 +1883,9 @@ suite('p5.Vector', function () {
});
test('should return a p5.Vector', function () {
- expect(x_bounce_incoming).to.be.an.instanceof(mockP5.Vector);
- expect(y_bounce_incoming).to.be.an.instanceof(mockP5.Vector);
- expect(z_bounce_incoming).to.be.an.instanceof(mockP5.Vector);
+ expect(x_bounce_incoming).to.be.an.instanceof(Vector);
+ expect(y_bounce_incoming).to.be.an.instanceof(Vector);
+ expect(z_bounce_incoming).to.be.an.instanceof(Vector);
});
test('should not update this', function () {
@@ -1846,8 +1961,8 @@ suite('p5.Vector', function () {
let v1;
beforeEach(function () {
- v0 = new mockP5.Vector(0, 0, 0);
- v1 = new mockP5.Vector(1, 2, 3);
+ v0 = new Vector(0, 0, 0);
+ v1 = new Vector(1, 2, 3);
});
suite('p5.Vector.prototype.mag() [INSTANCE]', function () {
@@ -1859,8 +1974,8 @@ suite('p5.Vector', function () {
suite('p5.Vector.mag() [CLASS]', function () {
test('should return the magnitude of the vector', function () {
- expect(mockP5.Vector.mag(v0)).to.eql(0);
- expect(mockP5.Vector.mag(v1)).to.eql(MAG);
+ expect(Vector.mag(v0)).to.eql(0);
+ expect(Vector.mag(v1)).to.eql(MAG);
});
});
});
@@ -1872,8 +1987,8 @@ suite('p5.Vector', function () {
let v1;
beforeEach(function () {
- v0 = new mockP5.Vector(0, 0, 0);
- v1 = new mockP5.Vector(1, 2, 3);
+ v0 = new Vector(0, 0, 0);
+ v1 = new Vector(1, 2, 3);
});
suite('p5.Vector.prototype.magSq() [INSTANCE]', function () {
@@ -1885,8 +2000,8 @@ suite('p5.Vector', function () {
suite('p5.Vector.magSq() [CLASS]', function () {
test('should return the magnitude of the vector', function () {
- expect(mockP5.Vector.magSq(v0)).to.eql(0);
- expect(mockP5.Vector.magSq(v1)).to.eql(MAG);
+ expect(Vector.magSq(v0)).to.eql(0);
+ expect(Vector.magSq(v1)).to.eql(MAG);
});
});
});
@@ -1894,8 +2009,8 @@ suite('p5.Vector', function () {
suite('equals', function () {
suite('p5.Vector.prototype.equals() [INSTANCE]', function () {
test('should return false for parameters inequal to the vector', function () {
- const v1 = new mockP5.Vector(0, -1, 1);
- const v2 = new mockP5.Vector(1, 2, 3);
+ const v1 = new Vector(0, -1, 1);
+ const v2 = new Vector(1, 2, 3);
const a2 = [1, 2, 3];
expect(v1.equals(v2)).to.be.false;
expect(v1.equals(a2)).to.be.false;
@@ -1903,88 +2018,89 @@ suite('p5.Vector', function () {
});
test('should return true for equal vectors', function () {
- const v1 = new mockP5.Vector(0, -1, 1);
- const v2 = new mockP5.Vector(0, -1, 1);
+ const v1 = new Vector(0, -1, 1);
+ const v2 = new Vector(0, -1, 1);
expect(v1.equals(v2)).to.be.true;
});
test('should return true for arrays equal to the vector', function () {
- const v1 = new mockP5.Vector(0, -1, 1);
+ const v1 = new Vector(0, -1, 1);
const a1 = [0, -1, 1];
expect(v1.equals(a1)).to.be.true;
});
test('should return true for arguments equal to the vector', function () {
- const v1 = new mockP5.Vector(0, -1, 1);
+ const v1 = new Vector(0, -1, 1);
expect(v1.equals(0, -1, 1)).to.be.true;
});
});
suite('p5.Vector.equals() [CLASS]', function () {
test('should return false for inequal parameters', function () {
- const v1 = new mockP5.Vector(0, -1, 1);
- const v2 = new mockP5.Vector(1, 2, 3);
+ const v1 = new Vector(0, -1, 1);
+ const v2 = new Vector(1, 2, 3);
const a2 = [1, 2, 3];
- expect(mockP5.Vector.equals(v1, v2)).to.be.false;
- expect(mockP5.Vector.equals(v1, a2)).to.be.false;
- expect(mockP5.Vector.equals(a2, v1)).to.be.false;
+ expect(Vector.equals(v1, v2)).to.be.false;
+ expect(Vector.equals(v1, a2)).to.be.false;
+ expect(Vector.equals(a2, v1)).to.be.false;
});
test('should return true for equal vectors', function () {
- const v1 = new mockP5.Vector(0, -1, 1);
- const v2 = new mockP5.Vector(0, -1, 1);
- expect(mockP5.Vector.equals(v1, v2)).to.be.true;
+ const v1 = new Vector(0, -1, 1);
+ const v2 = new Vector(0, -1, 1);
+ expect(Vector.equals(v1, v2)).to.be.true;
});
test('should return true for equal vectors and arrays', function () {
- const v1 = new mockP5.Vector(0, -1, 1);
+ const v1 = new Vector(0, -1, 1);
const a1 = [0, -1, 1];
- expect(mockP5.Vector.equals(v1, a1)).to.be.true;
- expect(mockP5.Vector.equals(a1, v1)).to.be.true;
+ expect(Vector.equals(v1, a1)).to.be.true;
+ expect(Vector.equals(a1, v1)).to.be.true;
});
test('should return true for equal arrays', function () {
const a1 = [0, -1, 1];
const a2 = [0, -1, 1];
- expect(mockP5.Vector.equals(a1, a2)).to.be.true;
+ expect(Vector.equals(a1, a2)).to.be.true;
});
});
});
suite('set values', function () {
beforeEach(function () {
- v = new mockP5.Vector();
+ v = new Vector();
});
- test('should set values to [0,0,0] if values array is empty', function () {
+ test('should NOT set values to [0,0,0] if values array is empty', function () {
v.values = [];
assert.equal(v.x, 0);
assert.equal(v.y, 0);
assert.equal(v.z, 0);
- assert.equal(v.dimensions, 2);
+ assert.equal(v.dimensions, 0);
});
});
suite('get value', function () {
test('should return element in range of a non empty vector', function () {
- let vect = new mockP5.Vector(1, 2, 3, 4);
+ let vect = new Vector(1, 2, 3, 4);
assert.equal(vect.getValue(0), 1);
assert.equal(vect.getValue(1), 2);
assert.equal(vect.getValue(2), 3);
assert.equal(vect.getValue(3), 4);
});
- test.fails(
- 'should throw friendly error if attempting to get element outside lenght',
+ test('should throw friendly error if attempting to get element outside length',
function () {
- let vect = new mockP5.Vector(1, 2, 3, 4);
- assert.equal(vect.getValue(5), 1);
+ let vect = new Vector(1, 2, 3, 4);
+ globalThis.FESCalled = false;
+ assert.equal(vect.getValue(5), undefined);
+ assert.equal(globalThis.FESCalled, true);
}
);
});
suite('set value', function () {
test('should set value of element in range', function () {
- let vect = new mockP5.Vector(1, 2, 3, 4);
+ let vect = new Vector(1, 2, 3, 4);
vect.setValue(0, 7);
assert.equal(vect.getValue(0), 7);
assert.equal(vect.getValue(1), 2);
@@ -1992,30 +2108,31 @@ suite('p5.Vector', function () {
assert.equal(vect.getValue(3), 4);
});
- test.fails(
- 'should throw friendly error if attempting to set element outside lenght',
+ test('should throw friendly error if attempting to set element outside lenght',
function () {
- let vect = new mockP5.Vector(1, 2, 3, 4);
+ let vect = new Vector(1, 2, 3, 4);
+ globalThis.FESCalled = false;
vect.setValue(100, 7);
+ assert.equal(globalThis.FESCalled, true);
}
);
});
describe('get w', () => {
it('should return the w component of the vector', () => {
- v = new mockP5.Vector(1, 2, 3, 4);
+ v = new Vector(1, 2, 3, 4);
expect(v.w).toBe(4);
});
it('should return 0 if w component is not set', () => {
- v = new mockP5.Vector(1, 2, 3);
+ v = new Vector(1, 2, 3);
expect(v.w).toBe(0);
});
});
describe('set w', () => {
it('should set 4th dimension of vector to w value if it exists', () => {
- v = new mockP5.Vector(1, 2, 3, 4);
+ v = new Vector(1, 2, 3, 4);
v.w = 7;
expect(v.x).toBe(1);
expect(v.y).toBe(2);
@@ -2024,24 +2141,22 @@ suite('p5.Vector', function () {
});
it('should throw error if trying to set w if vector dimensions is less than 4', () => {
- v = new mockP5.Vector(1, 2);
+ v = new Vector(1, 2);
v.w = 5;
- console.log(v);
- console.log(v.w);
expect(v.w).toBe(0); //TODO: Check this, maybe this should fail
});
});
describe('vector to string', () => {
it('should return the string version of a vector', () => {
- v = new mockP5.Vector(1, 2, 3, 4);
+ v = new Vector(1, 2, 3, 4);
expect(v.toString()).toBe('vector[1, 2, 3, 4]');
});
});
describe('set heading', () => {
it('should rotate a 2D vector by specified angle without changing magnitude', () => {
- v = new mockP5.Vector(0, 2);
+ v = new Vector(0, 2);
const mag = v.mag();
expect(v.setHeading(2 * Math.PI).mag()).toBe(mag);
expect(v.x).toBe(2);
@@ -2051,23 +2166,23 @@ suite('p5.Vector', function () {
describe('clamp to zero', () => {
it('should clamp values cloze to zero to zero, with Number.epsilon value', () => {
- v = new mockP5.Vector(0, 1, 0.5, 0.1, 0.0000000000000001);
+ v = new Vector(0, 1, 0.5, 0.1, 0.0000000000000001);
expect(v.clampToZero().values).toEqual([0, 1, 0.5, 0.1, 0]);
});
});
suite('p5.Vector.fromAngles()', function () {
- it('should create a v3ctor froma pair of ISO spherical angles', () => {
- let vect = mockP5.Vector.fromAngles(0, 0);
+ it('should create a vector froma pair of ISO spherical angles', () => {
+ let vect = Vector.fromAngles(0, 0);
expect(vect.values).toEqual([0, -1, 0]);
});
});
suite('p5.Vector.rotate()', function () {
it('should rotate the vector (only 2D vectors) by the given angle; magnitude remains the same.', () => {
- v = new mockP5.Vector(0, 1, 2);
- let target = new mockP5.Vector();
- mockP5.Vector.rotate(v, 1 * Math.PI, target);
+ v = new Vector(0, 1, 2);
+ let target = new Vector();
+ Vector.rotate(v, 1 * Math.PI, target);
expect(target.values).toEqual([
-4.10759023698152e-16, -2.23606797749979, 2
]);
diff --git a/test/unit/webgl/p5.Shader.js b/test/unit/webgl/p5.Shader.js
index bdfb0e5476..6ad679d39b 100644
--- a/test/unit/webgl/p5.Shader.js
+++ b/test/unit/webgl/p5.Shader.js
@@ -2242,7 +2242,9 @@ test('returns numbers for builtin globals outside hooks and a strandNode when ca
}, { myp5 });
} catch (e) { /* expected */ }
- assert.isAbove(mockUserError.mock.calls.length, 0, 'FES.userError should have been called');
+
+
+ assert.isAbove(mockUserError.mock.calls.length, 0, 'FES.userError should have been called, btw: '+globalThis.FESCalled);
const errMsg = mockUserError.mock.calls[0][1];
assert.include(errMsg, 'float3');
assert.include(errMsg, 'float4');