UNPKG

@turbox3d/math

Version:

Large-scale graphics application math library

335 lines 11.5 kB
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; } }]); }();