toosoon-utils
Version:
Utility functions & classes
163 lines (162 loc) • 4.9 kB
JavaScript
import { radToSphere } from './geometry';
/**
* Generate a random boolean (true or false)
*
* @param {number} [probability=0.5] Probability to get true
* @returns {boolean} Either `true` or `false`
*/
export function randomBoolean(probability = 0.5) {
return Math.random() < probability;
}
/**
* Generate a random sign (1 or -1)
*
* @param {number} [probability=0.5] Probability to get 1
* @returns {number} Either 1 or -1
*/
export function randomSign(probability = 0.5) {
return randomBoolean(probability) ? 1 : -1;
}
/**
* Generate a random floating-point number within a specified range
*
* @param {number} [min=0] Minimum boundary
* @param {number} [max=1] Maximum boundary
* @param {number} [precision=2] Number of digits after the decimal point
* @returns {number} Generated float
*/
export function randomFloat(min = 0, max = 1, precision = 2) {
return parseFloat(Math.min(min + Math.random() * (max - min), max).toFixed(precision));
}
/**
* Generate a random integer number within a specified range
*
* @param {number} min Minimum boundary
* @param {number} max Maximum boundary
* @returns {number} Generated integer
*/
export function randomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1) + min);
}
/**
* Generate a random hexadecimal color
*
* @returns {string} Generated hexadecimal color
*/
export function randomHexColor() {
return '#' + ('00000' + ((Math.random() * (1 << 24)) | 0).toString(16)).slice(-6);
}
/**
* Pick a random item from a given array
*
* @param {T[]} array Array to pick the item from
* @returns {T|undefined} Random item picked
*/
export function randomItem(array) {
if (array.length === 0)
return undefined;
return array[randomInt(0, array.length - 1)];
}
/**
* Pick a random property value from a given object
*
* @param {object} object Object to pick the property from
* @returns {T|undefined} Random item picked
*/
export function randomObjectProperty(object) {
const keys = Object.keys(object);
const key = randomItem(keys);
if (key && object.hasOwnProperty(key)) {
return object[key];
}
}
/**
* Select a random index from an array of weighted items
*
* @param {number[]} weights Array of weights
* @returns {number} Random index based on weights
*/
export function randomIndex(weights) {
if (weights.length === 0)
return -1;
let totalWeight = 0;
for (let weight of weights) {
totalWeight += weight;
}
if (totalWeight <= 0) {
console.warn('randomIndex()', 'Weights must sum to > 0', totalWeight);
return 0;
}
let weight = Math.random() * totalWeight;
for (let i = 0; i < weights.length; i++) {
if (weight < weights[i])
return i;
weight -= weights[i];
}
return 0;
}
/**
* Generate a random number fitting a Gaussian (normal) distribution
*
* @param {number} [mean=0] Central value
* @param {number} [spread=1] Standard deviation
* @returns {number} Generated number
*/
export function randomGaussian(mean = 0, spread = 1) {
const u = Math.random();
const v = Math.random();
const z = Math.sqrt(-2.0 * Math.log(u)) * Math.cos(2.0 * Math.PI * v);
return mean + z * spread;
}
// *********************
// Geometry
// *********************
/**
* Produce a random 2D point around the perimiter of a unit circle
*
* @param {number} [radius=1] Radius of the circle
* @param {Point} [target] Target point
* @returns {Point} Random 2D point on circle
*/
export function onCircle(radius = 1, target = [0, 0]) {
const angle = Math.random() * 2.0 * Math.PI;
target[0] = radius * Math.cos(angle);
target[1] = radius * Math.sin(angle);
return target;
}
/**
* Produce a random 2D point inside a unit circle
*
* @param {number} [radius=1] Radius of the circle
* @param {Point} [target] Target vector
* @returns {Point} Random 2D point inside circle
*/
export function insideCircle(radius = 1, target = [0, 0]) {
radius *= Math.random();
return onCircle(radius, target);
}
/**
* Produce a random 3D point on the surface of a unit sphere
*
* @param {number} [radius=1] Radius of the sphere
* @param {Point3} [target] Target vector
* @returns {Point3} Random 3D point on sphere
*/
export function onSphere(radius = 1, target = [0, 0, 0]) {
const u = Math.random() * Math.PI * 2;
const v = Math.random() * 2 - 1;
const phi = u;
const theta = Math.acos(v);
return radToSphere(radius, phi, theta, target);
}
/**
* Produce a random 3D point inside a unit sphere
*
* @param {number} [radius=1] Radius of the sphere
* @param {Point3} [target] Target vector
* @returns {Point3} Random 3D point inside sphere
*/
export function insideSphere(radius = 1, target = [0, 0, 0]) {
radius *= Math.random();
return onSphere(radius, target);
}