-
-
Notifications
You must be signed in to change notification settings - Fork 23
/
Copy pathmath.js
163 lines (149 loc) · 4.33 KB
/
math.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
/**
* @module Math
*/
/**
* Constrain a number between two limits.
* @param {Number} value - Any number
* @param {Number} min - Minimal limit for the value
* @param {Number} max - Maximal limit for the value
* @return {Number}
* @example
* constrain(999, 0, 50); // => 50
* constrain(-999, 0, 50); // => 0
*/
const constrain = (value, min, max) => Math.min(Math.max(value, min), max);
/**
* Determine if two number can considered equals accounting for JS precision.
* @param {Number} number1 - Any number
* @param {Number} number2 - Any number
* @param {Number} [epsilon=Number.EPSILON] - Maximum difference to consider two number equal.
* @return {Boolean}
* @example
* equals(0.1 + 0.2, 0.3); // => true
*/
const equals = (number1, number2, epsilon = Number.EPSILON) => Math.abs(number1 - number2) < epsilon;
/**
* Return a random number between limits
* @param {Number} [min=1] - Lower limit, or upper limit if max is omitted
* @param {Number} [max] - Upper limit, can be omitted
* @return {Number}
* @example
* random(); // => 0.5918807307648482
* random(10); // => 4.4856764978326735
* random(100, 200); // => 134.57047268453047
*/
const random = (min = 1, max) => {
let from = min;
let to = max;
if (max === undefined) {
from = 0;
to = min;
}
return (Math.random() * (to - from)) + from;
};
/**
* Truncate a number to its integer part.
* @param {Number} value - Any number
* @return {Number}
* @example
* truncate(12.3); // => 12
* truncate(-4.9); // => -4
*/
// eslint-disable-next-line no-bitwise
const truncate = value => value << 0;
/**
* Full rotation on radian circle
* @type {Number}
*/
const radianCircle = Math.PI * 2;
/**
* Full rotation on degree circle
* @type {Number}
*/
const degreeCircle = 360;
/**
* Golden ratio number
* @type {Number}
*/
const phi = (Math.sqrt(5) + 1) / 2;
/**
* Return modulo with the same sign as the divisor (Floored division)
* @param {Number} value - Dividend
* @param {Number} divisor - Divisor
* @return {Number}
* @example
* modulo(10, 3); // => 1
* modulo(10, -3); // => -2
*/
const modulo = (value, divisor) => {
const remainder = value % divisor;
return !value || Math.sign(value) === Math.sign(divisor) ? remainder : remainder + divisor;
};
/**
* Returns an array of evenly distributed value across a range
* @param {Number} nbValue - Number of value to generate
* @param {Number} [min=0] - Starting value of the range
* @param {Number} [max=1] - Ending value of the range
* @return {Array<Number>}
* @example
* distribute(10); // => Number[10] evenly distributed across [0, 1]
* distribute(5, 10, 20); // => Number[5] evenly distributed across [10, 20]
*/
const distribute = (nbValue, min = 0, max = 1) => {
const start = random(min, max);
const diff = max - min;
return [...new Array(nbValue)].map((_, i) => min + modulo(start + (i * phi * diff), diff));
};
/**
* Add up all values passed as argument
* @param {...Number} values - Any set of number
* @return {Number}
* @example
* sum(1, 2, 3); // => 6
*/
const sum = (...values) => values.reduce((acc, value) => acc + value, 0);
/**
* Return the average of all values
* @param {...Number} values - Any set of number
* @return {Number}
* @example
* sum(1, 2, 3); // => 2
*/
const average = (...values) => sum(...values) / values.length;
/**
* Return the equivalent of a value from a scale to another
* @param {Number} value - Value to use
* @param {Number} fromMin - Start of the origin scale
* @param {Number} fromMax - End of the origin scale
* @param {Number} [toMin=0] - Start of the target scale
* @param {Number} [toMax=1] - End of the target scale
* @return {Number}
* @example
* map(5, 0, 10, 100, 200); // => 150
*/
const map = (value, fromMin, fromMax, toMin = 0, toMax = 1) => (
((value - fromMin) / (fromMax - fromMin)) * (toMax - toMin) + toMin
);
/**
* Linear extrapolation computation, useful when doing animation
* @param {Number} from - Starting value
* @param {Number} to - Ending value
* @param {Number} ratio - Extrapolation ratio, 0 is the starting value and 1 the ending value
* @return {Number}
*/
const lerp = (from, to, ratio) => from + ((to - from) * ratio);
export {
constrain,
equals,
random,
truncate,
radianCircle,
degreeCircle,
phi,
modulo,
distribute,
sum,
average,
map,
lerp,
};