2017-04-17 19:42:48 -04:00
|
|
|
class MathUtil {
|
|
|
|
/**
|
|
|
|
* Convert a value from degrees to radians.
|
|
|
|
* @param {!number} deg Value in degrees.
|
|
|
|
* @return {!number} Equivalent value in radians.
|
|
|
|
*/
|
|
|
|
static degToRad (deg) {
|
|
|
|
return deg * Math.PI / 180;
|
|
|
|
}
|
2016-06-29 23:07:23 -04:00
|
|
|
|
2017-04-17 19:42:48 -04:00
|
|
|
/**
|
|
|
|
* Convert a value from radians to degrees.
|
|
|
|
* @param {!number} rad Value in radians.
|
|
|
|
* @return {!number} Equivalent value in degrees.
|
|
|
|
*/
|
|
|
|
static radToDeg (rad) {
|
|
|
|
return rad * 180 / Math.PI;
|
|
|
|
}
|
2016-06-29 23:07:23 -04:00
|
|
|
|
2017-04-17 19:42:48 -04:00
|
|
|
/**
|
|
|
|
* Clamp a number between two limits.
|
|
|
|
* If n < min, return min. If n > max, return max. Else, return n.
|
|
|
|
* @param {!number} n Number to clamp.
|
|
|
|
* @param {!number} min Minimum limit.
|
|
|
|
* @param {!number} max Maximum limit.
|
|
|
|
* @return {!number} Value of n clamped to min and max.
|
|
|
|
*/
|
|
|
|
static clamp (n, min, max) {
|
|
|
|
return Math.min(Math.max(n, min), max);
|
|
|
|
}
|
2016-06-29 23:07:23 -04:00
|
|
|
|
2017-04-17 19:42:48 -04:00
|
|
|
/**
|
|
|
|
* Keep a number between two limits, wrapping "extra" into the range.
|
|
|
|
* e.g., wrapClamp(7, 1, 5) == 2
|
|
|
|
* wrapClamp(0, 1, 5) == 5
|
|
|
|
* wrapClamp(-11, -10, 6) == 6, etc.
|
|
|
|
* @param {!number} n Number to wrap.
|
|
|
|
* @param {!number} min Minimum limit.
|
|
|
|
* @param {!number} max Maximum limit.
|
|
|
|
* @return {!number} Value of n wrapped between min and max.
|
|
|
|
*/
|
|
|
|
static wrapClamp (n, min, max) {
|
|
|
|
const range = (max - min) + 1;
|
|
|
|
return n - (Math.floor((n - min) / range) * range);
|
|
|
|
}
|
2016-06-29 23:07:23 -04:00
|
|
|
|
2017-01-31 19:05:54 -05:00
|
|
|
|
2017-04-17 19:42:48 -04:00
|
|
|
/**
|
|
|
|
* Convert a value from tan function in degrees.
|
|
|
|
* @param {!number} angle in degrees
|
|
|
|
* @return {!number} Correct tan value
|
|
|
|
*/
|
|
|
|
static tan (angle) {
|
|
|
|
angle = angle % 360;
|
|
|
|
switch (angle) {
|
|
|
|
case -270:
|
|
|
|
case 90:
|
|
|
|
return Infinity;
|
|
|
|
case -90:
|
|
|
|
case 270:
|
|
|
|
return -Infinity;
|
|
|
|
default:
|
|
|
|
return parseFloat(Math.tan((Math.PI * angle) / 180).toFixed(10));
|
|
|
|
}
|
2017-01-31 19:05:54 -05:00
|
|
|
}
|
2018-07-24 11:00:48 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Given an array of unique numbers,
|
|
|
|
* returns a reduced array such that each element of the reduced array
|
|
|
|
* represents the position of that element in a sorted version of the
|
|
|
|
* original array.
|
|
|
|
* E.g. [5, 19. 13, 1] => [1, 3, 2, 0]
|
|
|
|
* @param {Array<number>} elts The elements to sort and reduce
|
|
|
|
* @return {Array<number>} The array of reduced orderings
|
|
|
|
*/
|
|
|
|
static reducedSortOrdering (elts) {
|
|
|
|
const sorted = elts.slice(0).sort((a, b) => a - b);
|
|
|
|
return elts.map(e => sorted.indexOf(e));
|
|
|
|
}
|
2019-04-08 17:56:54 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Scales a number from one range to another.
|
|
|
|
* @param {number} i number to be scaled
|
|
|
|
* @param {number} iMin input range minimum
|
|
|
|
* @param {number} iMax input range maximum
|
|
|
|
* @param {number} oMin output range minimum
|
|
|
|
* @param {number} oMax output range maximum
|
|
|
|
* @return {number} scaled number
|
|
|
|
*/
|
|
|
|
static scale (i, iMin, iMax, oMin, oMax) {
|
|
|
|
const p = (i - iMin) / (iMax - iMin);
|
|
|
|
return (p * (oMax - oMin)) + oMin;
|
|
|
|
}
|
2017-04-17 19:42:48 -04:00
|
|
|
}
|
2017-01-31 19:05:54 -05:00
|
|
|
|
2016-06-29 23:07:23 -04:00
|
|
|
module.exports = MathUtil;
|