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; } /** * 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; } /** * 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); } /** * 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); } /** * 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)); } } /** * 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} elts The elements to sort and reduce * @return {Array} 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)); } /** * 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; } } module.exports = MathUtil;