Utils/Utils.js

/** A utility class containing static methods. */
Lore.Utils = class Utils {
    /**
     * Merges two objects, overriding probierties set in both objects in the first one.
     * 
     * @returns {object} The merged object.
     */
    static extend() {
        let extended = {};
        let deep = false;
        let i = 0;
        let length = arguments.length;

        if (Object.prototype.toString.call(arguments[0]) === '[object Boolean]') {
            deep = arguments[0];
            i++;
        }

        let merge = function (obj) {
            for (let prop in obj) {
                if (Object.prototype.hasOwnProperty.call(obj, prop)) {
                    if (deep && Object.prototype.toString.call(obj[prop]) === '[object Object]') {
                        extended[prop] = Lore.Utils.extend(true, extended[prop], obj[prop]);
                    } else {
                        extended[prop] = obj[prop];
                    }
                }
            }
        };

        for ( ; i < length; i++) {
            let obj = arguments[i];
            merge(obj);
        }

        return extended;
    }

    /**
     * Checks whether or not an array contains a given value.
     * 
     * @param {Array} array An array.
     * @param {object} value An object.
     * @returns {boolean} A boolean whether or not the array contains the value.
     */
    static arrayContains(array, value) {
        for(let i = 0; i < array.length; i++) {
            if(array[i] === value) {
                return true;
            }
        }

        return false;
    }

    /**
     * Concatinate two typed arrays.
     * 
     * @param {TypedArray} arrA A typed array.
     * @param {TypedArray} arrB A typed array.
     * @returns {TypedArray} The concatinated typed array.
     */
    static concatTypedArrays(arrA, arrB) {
        let arrC = new a.constructor(arrA.length + arrB.length);
        
        arrC.set(arrA);
        arrC.set(arrB, arrA.length);

        return arrC;
    };

    /**
     * Get the most significant bit (MSB) of a number.
     * 
     * @param {Number} n A number. 
     * @returns {Number} The most significant bit (0 or 1).
     */
    static msb(n) {
        return (n & 0x80000000) ? 31 : Lore.Utils.msb((n << 1) | 1) - 1;
    }

    /**
     *  An utility method to merge two point distance objects containing arrays of indices and squared distances.
     * 
     * @static
     * @param {object} a An object in the form of { indices: TypedArray, distancesSq: TypedArray }.
     * @param {object} b An object in the form of { indices: TypedArray, distancesSq: TypedArray }.
     * @returns  {object} The object with merged indices and squared distances.
     */
    static mergePointDistances(a, b) {
        let newObj = {};

        newObj.indices = Lore.Utils.concatTypedArrays(a.indices, b.indices);
        newObj.distancesSq = Lore.Utils.concatTypedArrays(a.distancesSq, b.distancesSq);
        
        return newObj;
    }

    /**
     * Checks whether or not the number is an integer.
     * 
     * @param {number} n A number.
     * @returns A boolean whether or not the number is an integer.
     */
    static isInt(n){
        return Number(n) === n && n % 1 === 0;
    }

    /**
     * Checks whether or not the number is a float.
     * 
     * @param {number} n A number.
     * @returns A boolean whether or not the number is a float.
     */
    static isFloat(n){
        return Number(n) === n && n % 1 !== 0;
    }

    /**
     * A helper method enabling JSONP requests to an url.
     * 
     * @param {String} url An url.
     * @param {Function} callback The callback to be called when the data is loaded.
     */
    static jsonp(url, callback) {
        let callbackName = 'jsonp_callback_' + Math.round(100000 * Math.random());
        window[callbackName] = function(response) {
            delete window[callbackName];
            document.body.removeChild(script);
            callback(response);
        };

        let script = document.createElement('script');
        script.src = url + (url.indexOf('?') >= 0 ? '&' : '?') + 'callback=' + callbackName;
        document.body.appendChild(script);
    }
}

Lore.Utils.DEG2RAD = Math.PI / 180.0;