Source: utils/datastructures/CircularIntervalSet.js

"use strict";
/**
 * @classdesc A circular interval set.
 *
 * @author   Ikaros Kappler
 * @date     2020-10-02
 * @modified 2020-10-18 Ported to Typescript from vanilla JS.
 * @modified 2020-10-22 Added the removeAt funcion.
 * @version  1.0.1
 * @name CircularIntervalSet
 **/
Object.defineProperty(exports, "__esModule", { value: true });
var CircularIntervalSet = /** @class */ (function () {
    /**
     * Create a new CircularIntervalSet with the given lower and upperBound (start and end).
     *
     * The intervals inside lower and upper bound will initially be added to this set (full range).
     *
     * @param {number} start
     * @param {number} end
     * @method clear
     * @memberof CircularIntervalSet
     **/
    function CircularIntervalSet(start, end) {
        this.start = start;
        this.end = end;
        this.intervals = [[start, end]];
    }
    ;
    /**
     * Clear this set (will be empty after this operation).
     *
     * @method clear
     * @instance
     * @memberof CircularIntervalSet
     * @return {void}
     **/
    CircularIntervalSet.prototype.clear = function () {
        this.intervals = [];
    };
    ;
    /**
     * Remove the interval at given index.
     *
     * @param {number} index
     * @method removeAt
     * @instance
     * @memberof CircularIntervalSet
     * @return {void}
     **/
    // Todo: remove? (not in use any more?)
    CircularIntervalSet.prototype.removeAt = function (index) {
        if (index < 0 || index >= this.intervals.length)
            return;
        this.intervals.splice(index, 1);
    };
    ;
    /**
     * Intersect all sub intervalls with the given range (must be inside bounds).
     *
     * @param {number} start
     * @param {number} end
     * @method intersect
     * @instance
     * @memberof CircularIntervalSet
     * @return {void}
     **/
    CircularIntervalSet.prototype.intersect = function (start, end) {
        for (var i = 0; i < this.intervals.length;) {
            if (start <= end) {
                if ((this.intervals[i][0] >= end || this.intervals[i][1] <= start)) {
                    // Current interval is fully outside range.
                    // REMOVE
                    this.intervals.splice(i, 1);
                }
                else if (this.intervals[i][0] >= start && this.intervals[i][1] <= end) {
                    // Current interval is fully inside.
                    // KEEP
                    i++;
                }
                else if (this.intervals[i][0] <= start && this.intervals[i][1] >= end) {
                    // Desired range lies inside current interval.
                    // CUT OFF LEFT AND RIGHT.
                    this.intervals.splice(i, 1, [start, end]);
                    i++;
                }
                else if (this.intervals[i][0] <= start && this.intervals[i][1] < end) {
                    // Right end is inside range.
                    // CUT OFF LEFT.
                    this.intervals[i][0] = start;
                    i++;
                }
                else if (this.intervals[i][0] > start && this.intervals[i][1] >= end) {
                    // LEFT end is inside range.
                    // CUT OFF RIGHT.
                    this.intervals[i][1] = end;
                    i++;
                }
                else {
                    // NOOP
                    i++;
                }
            }
            else {
                // start > end
                if (this.intervals[i][0] >= end && this.intervals[i][1] <= start) {
                    // Current interval is fully outside range.
                    // REMOVE
                    this.intervals.splice(i, 1);
                }
                else if (this.intervals[i][0] >= start) {
                    // Full inside (right range).
                    // Keep.
                    i++;
                }
                else if (this.intervals[i][1] <= end) {
                    // Full inside (left range).
                    // Keep.
                    i++;
                }
                else if (this.intervals[i][0] >= end && this.intervals[i][1] > start) {
                    // Right part inside.
                    // Cut off left part.
                    this.intervals.splice(i, 1, [start, this.intervals[i][1]]);
                    i++;
                }
                else if (this.intervals[i][0] <= end && this.intervals[i][1] < start) {
                    // Left part inside.
                    // Cut off right part.
                    this.intervals.splice(i, 1, [this.intervals[i][0], end]);
                    i++;
                }
                else if (this.intervals[i][0] <= end && this.intervals[i][1] >= start) {
                    // Start and end inside, inner part is not.
                    // Cut into two.
                    this.intervals.splice(i, 1, [this.intervals[i][0], end], [start, this.intervals[i][1]]);
                    i += 2;
                }
                else {
                    // NOOP
                    i++;
                }
            }
        }
    };
    ;
    /**
     * Convert this set to a human readable string.
     *
     * @method toString
     * @instance
     * @memberof CircularIntervalSet
     * @return {string}
     **/
    CircularIntervalSet.prototype.toString = function () {
        return JSON.stringify(this.intervals);
    };
    ;
    return CircularIntervalSet;
}());
exports.CircularIntervalSet = CircularIntervalSet;
//# sourceMappingURL=CircularIntervalSet.js.map