@turbox3d/math
Version:
Large-scale graphics application math library
335 lines • 11.5 kB
JavaScript
import _classCallCheck from "@babel/runtime/helpers/esm/classCallCheck";
import _createClass from "@babel/runtime/helpers/esm/createClass";
function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
import { MathUtils } from '../MathUtils';
import { Tolerance } from './Tolerance';
export var Interval = /*#__PURE__*/function () {
/**
* constructor
* @param start
* @param end
*/
function Interval(start, end) {
_classCallCheck(this, Interval);
this._start = start;
this._end = end;
}
/**
* Get interval's start
*/
return _createClass(Interval, [{
key: "start",
get: function get() {
return this._start;
}
/**
* Get interval's end
*/
}, {
key: "end",
get: function get() {
return this._end;
}
/**
* Returns true if this interval is equal to another within specified tolerance.
* @param other
* @param numericTolerance
* @return
*/
}, {
key: "isEqual",
value: function isEqual(other, numTol) {
var tolerance = numTol || Tolerance.global.numTol;
return MathUtils.isEqual(this._start, other.start, tolerance) && MathUtils.isEqual(this._end, other.end, tolerance);
}
/**
* Get the middle number
* @return
*/
}, {
key: "middle",
get: function get() {
return 0.5 * (this._start + this._end);
}
/**
* Get the cloned object of this Interval.
*/
}, {
key: "clone",
value: function clone() {
return new Interval(this._start, this._end);
}
/**
* Get interval's length
* @return
*/
}, {
key: "length",
get: function get() {
return Math.abs(this._end - this._start);
}
/**
* interval string
* @return
*/
}, {
key: "toString",
value: function toString() {
return "Interval{start: ".concat(this._start, ", end: ").concat(this._end, "}");
}
/**
* Indicates whether the Interval is Valid
* @return
*/
}, {
key: "isValid",
value: function isValid() {
return !Number.isNaN(this._start) && !Number.isNaN(this._end);
}
/**
* interval mul by number
* @param alpha
* @returns
*/
}, {
key: "mul",
value: function mul(alpha) {
return new Interval(this._start * alpha, this._end * alpha);
}
/**
* interval add by number
* @param alpha
* @returns
*/
}, {
key: "add",
value: function add(interval) {
if (!interval) {
return new Interval(this._start, this._end);
}
return new Interval(this._start + interval.start, this._end + interval.end);
}
}, {
key: "addByNumber",
value: function addByNumber(alpha) {
return new Interval(this._start + alpha, this._end + alpha);
}
/**
* interval sub by Interval
* @param interval
* @returns
*/
}, {
key: "sub",
value: function sub(interval) {
if (!interval) {
return new Interval(this._start, this._end);
}
return new Interval(this._start - interval.start, this._end - interval.end);
}
/**
* Interval interpolate
* @param alpha
* @returns
*/
}, {
key: "interpolate",
value: function interpolate(alpha) {
return (1 - alpha) * this._start + alpha * this._end;
}
/**
* Interval expand
* @param length
* @returns
*/
}, {
key: "expand",
value: function expand(length) {
return new Interval(this._start - length, this._end + length);
}
/**
* Indicates whether the given value is included in this interval.
* @param {number} point
* @param {boolean} includeEnds - Indicates whether to check the ends.
* @param {number} [tolerance] - Tolerance to check on the ends.
* @returns {boolean}
*/
}, {
key: "contains",
value: function contains(point, includeEnds) {
var tolerance = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : Tolerance.global.distTol;
if (includeEnds) {
return point <= this._end + tolerance && point >= this._start - tolerance;
}
return point < this._end - tolerance && point > this._start + tolerance;
}
/**
* Indicates whether the given interval is included in this interval.
* @param {Interval} interval
* @param {boolean} includeEnds - Indicates whether to check the ends.
* @param {number} [tolerance] - Tolerance to check on the ends.
* @returns {boolean}
*/
}, {
key: "containsInterval",
value: function containsInterval(interval, includeEnds) {
var tolerance = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : Tolerance.global.distTol;
if (includeEnds) {
return interval._start >= this._start - tolerance && interval._end <= this._end + tolerance;
}
return interval._start > this._start + tolerance && interval._end < this._end - tolerance;
}
/**
* Indicates whether the given interval is intersected with this interval.
* @param {Interval} interval
* @param {boolean} includeEnds - Indicates whether to check the ends.
* @param {number} [tolerance] - Intersection tolerance.
* @returns {boolean}
*/
}, {
key: "intersects",
value: function intersects(interval, includeEnds) {
var tolerance = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : Tolerance.global.distTol;
if (includeEnds) {
return !(this._start > interval._end + tolerance || this._end < interval._start - tolerance);
}
return !(this._start >= interval._end - tolerance || this._end <= interval._start + tolerance);
}
/**
* Indicates whether the given interval is intersected with this interval.
* @param {Interval} interval
* @param {boolean} includeEnds - Indicates whether to check the ends.
* @param {number} [tolerance] - Intersection tolerance.
* @returns {boolean}
*/
}, {
key: "intersected",
value: function intersected(interval, includeEnds) {
var tolerance = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : Tolerance.global.distTol;
if (includeEnds) {
return !(this._start > interval._end + tolerance || this._end < interval._start - tolerance);
}
return !(this._start >= interval._end - tolerance || this._end <= interval._start + tolerance);
}
/**
* Get the intersect part with interval. If the intervals are not intersectant, we will return an invalid interval
* @param interval
* @returns {Interval} | null
*/
}, {
key: "intersection",
value: function intersection(interval) {
if (!interval || !this.intersected(interval, true)) {
return Interval.invalid();
}
return new Interval(Math.max(interval.start, this.start), Math.min(interval.end, this.end));
}
/**
* Combine with interval. If the intervals are not intersectant, we will return an invalid interval
* @param interval
* @returns
*/
}, {
key: "includeInterval",
value: function includeInterval(interval) {
if (!interval || !this.intersected(interval, true)) {
return Interval.invalid();
}
return new Interval(Math.min(interval.start, this.start), Math.max(interval.end, this.end));
}
}], [{
key: "invalid",
value: function invalid() {
return new Interval(NaN, NaN);
}
/**
* interval mul by number
* @param alpha
* @returns
*/
}, {
key: "mul",
value: function mul(interval, alpha) {
if (!interval) {
return Interval.invalid();
}
return new Interval(interval.start * alpha, interval.end * alpha);
}
/**
* Get the intersect intervals of two list of intervals.
* @param intervals1
* @param intervals2
* @returns List<Interval>
*/
}, {
key: "intersect",
value: function intersect(intervals1, intervals2) {
if (!intervals1 || intervals1.length === 0) {
return [];
}
if (!intervals2 || intervals2.length === 0) {
return [];
}
var sortedIntervals1 = Interval.union(intervals1);
var sortedIntervals2 = Interval.union(intervals2);
var resultIntervals = [];
sortedIntervals1 = sortedIntervals1.sort(function (n1, n2) {
return n1.start - n2.start;
});
sortedIntervals2 = sortedIntervals2.sort(function (n1, n2) {
return n1.start - n2.start;
});
var index1 = 0;
var index2 = 0;
while (index1 < sortedIntervals1.length && index2 < sortedIntervals2.length) {
if (sortedIntervals1[index1].intersected(sortedIntervals2[index2], true)) {
resultIntervals.push(sortedIntervals1[index1].intersection(sortedIntervals2[index2]));
}
if (sortedIntervals1[index1].end < sortedIntervals2[index2].end) {
index1 += 1;
} else {
index2 += 1;
}
}
return resultIntervals;
}
/**
* Combine the intervals.Return the list of intervals after unioned
* @param intervals
* @returns {Interval[]}
*/
}, {
key: "union",
value: function union(intervals) {
if (!intervals || intervals.length === 0) {
return [];
}
var sortedIntervals = intervals.sort(function (n1, n2) {
return n1.start - n2.start;
});
var resultIntervals = [];
var temp = sortedIntervals[0];
var _iterator = _createForOfIteratorHelper(sortedIntervals),
_step;
try {
for (_iterator.s(); !(_step = _iterator.n()).done;) {
var interval = _step.value;
if (!temp.intersected(interval, true)) {
resultIntervals.push(temp);
temp = new Interval(interval.start, interval.end);
} else {
temp = temp.includeInterval(interval);
}
}
} catch (err) {
_iterator.e(err);
} finally {
_iterator.f();
}
resultIntervals.push(temp);
return resultIntervals;
}
}]);
}();