UNPKG

@mlightcad/geometry-engine

Version:

The geometry-engine package provides comprehensive geometric entities, mathematical operations, and transformations for 2D and 3D space. This package mimics AutoCAD ObjectARX's AcGe (Geometry) classes and provides the mathematical foundation for CAD opera

1,682 lines 422 kB
import { AcCmErrors as Me } from "@mlightcad/common"; const $t = [ "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0a", "0b", "0c", "0d", "0e", "0f", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1a", "1b", "1c", "1d", "1e", "1f", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2a", "2b", "2c", "2d", "2e", "2f", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "3a", "3b", "3c", "3d", "3e", "3f", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "4a", "4b", "4c", "4d", "4e", "4f", "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5a", "5b", "5c", "5d", "5e", "5f", "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6a", "6b", "6c", "6d", "6e", "6f", "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7a", "7b", "7c", "7d", "7e", "7f", "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8a", "8b", "8c", "8d", "8e", "8f", "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9a", "9b", "9c", "9d", "9e", "9f", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "aa", "ab", "ac", "ad", "ae", "af", "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8", "b9", "ba", "bb", "bc", "bd", "be", "bf", "c0", "c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9", "ca", "cb", "cc", "cd", "ce", "cf", "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "da", "db", "dc", "dd", "de", "df", "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9", "ea", "eb", "ec", "ed", "ee", "ef", "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "fa", "fb", "fc", "fd", "fe", "ff" ]; let Ur = 1234567; const Kr = Math.PI / 180, jr = 180 / Math.PI; function xi() { const E = Math.random() * 4294967295 | 0, e = Math.random() * 4294967295 | 0, i = Math.random() * 4294967295 | 0, a = Math.random() * 4294967295 | 0; return ($t[E & 255] + $t[E >> 8 & 255] + $t[E >> 16 & 255] + $t[E >> 24 & 255] + "-" + $t[e & 255] + $t[e >> 8 & 255] + "-" + $t[e >> 16 & 15 | 64] + $t[e >> 24 & 255] + "-" + $t[i & 63 | 128] + $t[i >> 8 & 255] + "-" + $t[i >> 16 & 255] + $t[i >> 24 & 255] + $t[a & 255] + $t[a >> 8 & 255] + $t[a >> 16 & 255] + $t[a >> 24 & 255]).toLowerCase(); } function Ze(E, e, i) { return Math.max(e, Math.min(i, E)); } function Xr(E, e) { return (E % e + e) % e; } function Mi(E, e, i, a, l) { return a + (E - e) * (l - a) / (i - e); } function Pi(E, e, i) { return E !== e ? (i - E) / (e - E) : 0; } function Wr(E, e, i) { return (1 - i) * E + i * e; } function Ai(E, e, i, a) { return Wr(E, e, 1 - Math.exp(-i * a)); } function zi(E, e = 1) { return e - Math.abs(Xr(E, e * 2) - e); } function Si(E, e, i) { return E <= e ? 0 : E >= i ? 1 : (E = (E - e) / (i - e), E * E * (3 - 2 * E)); } function Ci(E, e, i) { return E <= e ? 0 : E >= i ? 1 : (E = (E - e) / (i - e), E * E * E * (E * (E * 6 - 15) + 10)); } function ki(E, e) { return E + Math.floor(Math.random() * (e - E + 1)); } function Ii(E, e) { return E + Math.random() * (e - E); } function Ni(E) { return E * (0.5 - Math.random()); } function Ei(E) { E !== void 0 && (Ur = E); let e = Ur += 1831565813; return e = Math.imul(e ^ e >>> 15, e | 1), e ^= e + Math.imul(e ^ e >>> 7, e | 61), ((e ^ e >>> 14) >>> 0) / 4294967296; } function Bi(E) { return E * Kr; } function Li(E) { return E * jr; } function Ti(E) { return (E & E - 1) === 0 && E !== 0; } function Ui(E) { return Math.pow(2, Math.ceil(Math.log(E) / Math.LN2)); } function Ri(E) { return Math.pow(2, Math.floor(Math.log(E) / Math.LN2)); } function $n(E) { const e = Math.PI * 2; return (E % e + e) % e; } function Vi(E, e, i) { return E > e && E < i || E > i && E < e; } function Di(E, e, i, a = !1) { return E = $n(E), e = $n(e), i = $n(i), a ? e > i ? E <= e && E >= i : E <= e || E >= i : e < i ? E >= e && E <= i : E >= e || E <= i; } function Zr(E) { return E = Math.abs(E), E < 1 ? 0 : Math.ceil(Math.log10(Math.abs(E) + 1)); } function Fi(E, e = 1e-7) { const i = Zr(E); return Math.max(Math.pow(10, i) * e, e); } const Ct = { DEG2RAD: Kr, RAD2DEG: jr, generateUUID: xi, clamp: Ze, euclideanModulo: Xr, mapLinear: Mi, inverseLerp: Pi, lerp: Wr, damp: Ai, pingpong: zi, smoothstep: Si, smootherstep: Ci, randInt: ki, randFloat: Ii, randFloatSpread: Ni, seededRandom: Ei, degToRad: Bi, radToDeg: Li, isPowerOfTwo: Ti, ceilPowerOfTwo: Ui, floorPowerOfTwo: Ri, normalizeAngle: $n, isBetween: Vi, isBetweenAngle: Di, intPartLength: Zr, relativeEps: Fi }, Fn = class Fn { /** * Construct one vector by two numbers */ constructor(e, i) { this.x = 0, this.y = 0; const a = +(e !== void 0) + +(i !== void 0); if (a !== 0) { if (a === 1 && e instanceof Array) { this.x = e[0], this.y = e[1]; return; } if (a === 1) { const { x: l, y: _ } = e; this.x = l, this.y = _; return; } if (a === 2) { this.x = e, this.y = i; return; } throw Me.ILLEGAL_PARAMETERS; } } /** * Alias for x. */ get width() { return this.x; } set width(e) { this.x = e; } /** * Alias for y. */ get height() { return this.y; } set height(e) { this.y = e; } /** * Sets the x and y components of this vector. * @param x Input x component of this vector * @param y Input y component of this vector * @returns Return this vector */ set(e, i) { return this.x = e, this.y = i, this; } /** * Set the x and y values of this vector both equal to scalar. * @param scalar Input one scalar value * @returns Return this vector */ setScalar(e) { return this.x = e, this.y = e, this; } /** * Replace this vector's x value with x. * @param x Input new value of x component of this vector * @returns Return this vector */ setX(e) { return this.x = e, this; } /** * Replace this vector's y value with y. * @param y Input new value of y component of this vector * @returns Return this vector */ setY(e) { return this.y = e, this; } /** * If index equals 0 set x to value. * If index equals 1 set y to value * @param index 0 or 1. * @param value Input one number * @returns Return this vector */ setComponent(e, i) { switch (e) { case 0: this.x = i; break; case 1: this.y = i; break; default: throw new Error("index is out of range: " + e); } return this; } /** * If index equals 0 returns the x value. * If index equals 1 returns the y value. * @param index 0 or 1. * @returns Return this matrix */ getComponent(e) { switch (e) { case 0: return this.x; case 1: return this.y; default: throw new Error("index is out of range: " + e); } } /** * Return a new 2d vector with the same x and y values as this one. * @returns Return the cloned vector */ clone() { return new Fn(this.x, this.y); } /** * Copy the values of the passed vector's x and y properties to this vector. * @param v Input one 2d vector * @returns Return this vector */ copy(e) { return this.x = e.x, this.y = e.y, this; } /** * Add v to this vector. * @param v Input one 2d vector * @returns Return this vector */ add(e) { return this.x += e.x, this.y += e.y, this; } /** * Add the scalar value s to this vector's x and y values. * @param s Input one scalar value * @returns Return this vector */ addScalar(e) { return this.x += e, this.y += e, this; } /** * Set this vector to a + b. * @param a Input one 2d vector * @param b Input one 2d vector * @returns Return this vector */ addVectors(e, i) { return this.x = e.x + i.x, this.y = e.y + i.y, this; } /** * Add the multiple of v and s to this vector. * @param v Input one 2d vector * @param s Input one scalar value * @returns Return this vector */ addScaledVector(e, i) { return this.x += e.x * i, this.y += e.y * i, this; } /** * Subtract v from this vector. * @param v Input one 2d vector * @returns Return this vector */ sub(e) { return this.x -= e.x, this.y -= e.y, this; } /** * Subtract s from this vector's x and y components. * @param s Input one scalar value * @returns Return this vector */ subScalar(e) { return this.x -= e, this.y -= e, this; } /** * Sets this vector to a - b. * @param a Input one 2d vector * @param b Input one 2d vector * @returns Return this vector */ subVectors(e, i) { return this.x = e.x - i.x, this.y = e.y - i.y, this; } /** * Multiply this vector by v. * @param v Input one 2d vector * @returns Return this vector */ multiply(e) { return this.x *= e.x, this.y *= e.y, this; } /** * Multiply this vector by scalar s. * @param scalar Input one scalar value * @returns Return this vector */ multiplyScalar(e) { return this.x *= e, this.y *= e, this; } /** * Divide this vector by v. * @param v Input one 2d vector * @returns Return this vector */ divide(e) { return this.x /= e.x, this.y /= e.y, this; } /** * Divide this vector by scalar s. * @param scalar Input one scalar value * @returns Return this vector */ divideScalar(e) { return this.multiplyScalar(1 / e); } /** * Multiply this vector (with an implicit 1 as the 3rd component) by m. * @param m Input one 3x3 matrix * @returns Return this vector */ applyMatrix2d(e) { const i = this.x, a = this.y, l = e.elements; return this.x = l[0] * i + l[3] * a + l[6], this.y = l[1] * i + l[4] * a + l[7], this; } /** * If this vector's x or y value is greater than v's x or y value, replace that value with the * corresponding min value. * @param v Input one 2d vector * @returns Return this vector */ min(e) { return this.x = Math.min(this.x, e.x), this.y = Math.min(this.y, e.y), this; } /** * If this vector's x or y value is less than v's x or y value, replace that value with the * corresponding max value. * @param v Input one 2d vector * @returns Return this vector */ max(e) { return this.x = Math.max(this.x, e.x), this.y = Math.max(this.y, e.y), this; } /** * If this vector's x or y value is greater than the max vector's x or y value, it is replaced * by the corresponding value. * If this vector's x or y value is less than the min vector's x or y value, it is replaced by * the corresponding value. * @param min Input the minimum x and y values * @param max Input the maximum x and y values in the desired range * @returns */ clamp(e, i) { return this.x = Math.max(e.x, Math.min(i.x, this.x)), this.y = Math.max(e.y, Math.min(i.y, this.y)), this; } /** * If this vector's x or y values are greater than the max value, they are replaced by the max value. * If this vector's x or y values are less than the min value, they are replaced by the min value. * @param minVal Input the minimum value the components will be clamped to * @param maxVal Input the maximum value the length will be clamped to * @returns Return this vector */ clampScalar(e, i) { return this.x = Math.max(e, Math.min(i, this.x)), this.y = Math.max(e, Math.min(i, this.y)), this; } /** * If this vector's length is greater than the max value, it is replaced by the max value. * If this vector's length is less than the min value, it is replaced by the min value. * @param min Input the minimum value the length will be clamped to * @param max Input the maximum value the length will be clamped to * @returns Return this vector */ clampLength(e, i) { const a = this.length(); return this.divideScalar(a || 1).multiplyScalar( Math.max(e, Math.min(i, a)) ); } /** * The components of this vector are rounded down to the nearest integer value. * @returns Return this vector */ floor() { return this.x = Math.floor(this.x), this.y = Math.floor(this.y), this; } /** * The x and y components of this vector are rounded up to the nearest integer value. * @returns Return this vector */ ceil() { return this.x = Math.ceil(this.x), this.y = Math.ceil(this.y), this; } /** * The components of this vector are rounded to the nearest integer value. * @returns Return this vector */ round() { return this.x = Math.round(this.x), this.y = Math.round(this.y), this; } /** * The components of this vector are rounded towards zero (up if negative, down if positive) to * an integer value. * @returns Return this vector */ roundToZero() { return this.x = Math.trunc(this.x), this.y = Math.trunc(this.y), this; } /** * Invert this vector - i.e. sets x = -x and y = -y. * @returns Return this vector */ negate() { return this.x = -this.x, this.y = -this.y, this; } /** * Calculate the dot product of this vector and v. * @param v Input one 2d vector * @returns Return the dot product of this vector and v. */ dot(e) { return this.x * e.x + this.y * e.y; } /** * Calculate the cross product of this vector and v. Note that a 'cross-product' in 2D is not * well-defined. This function computes a geometric cross-product often used in 2D graphics. * @param v Input one 2d vector * @returns Return the cross product of this vector and v. */ cross(e) { return this.x * e.y - this.y * e.x; } /** * Compute the square of the Euclidean length (straight-line length) from (0, 0) to (x, y). * If you are comparing the lengths of vectors, you should compare the length squared instead * as it is slightly more efficient to calculate. * @returns Return the square of the Euclidean length (straight-line length) from (0, 0) to (x, y) */ lengthSq() { return this.x * this.x + this.y * this.y; } /** * Compute the Euclidean length (straight-line length) from (0, 0) to (x, y). * @returns Return the Euclidean length (straight-line length) from (0, 0) to (x, y). */ length() { return Math.sqrt(this.x * this.x + this.y * this.y); } /** * Compute the Manhattan length of this vector. * @returns Return the Manhattan length of this vector。 */ manhattanLength() { return Math.abs(this.x) + Math.abs(this.y); } /** * Converts this vector to a unit vector - that is, sets it equal to a vector with the same * direction as this one, but length 1. * @returns Return this vector */ normalize() { return this.divideScalar(this.length() || 1); } /** * Compute the angle in radians of this vector with respect to the positive x-axis. * @returns Return the angle in radians of this vector with respect to the positive x-axis. */ angle() { return Math.atan2(-this.y, -this.x) + Math.PI; } /** * Return the angle between this vector and vector v in radians. * @param v Input one 2d vector * @returns Return the angle between this vector and vector v in radians. */ angleTo(e) { const i = Math.sqrt(this.lengthSq() * e.lengthSq()); if (i === 0) return Math.PI / 2; const a = this.dot(e) / i; return Math.acos(Math.max(-1, Math.min(1, a))); } /** * Compute the distance from this vector to v. * @param v Input one 2d vector * @returns Return the distance from this vector to v. */ distanceTo(e) { return Math.sqrt(this.distanceToSquared(e)); } /** * Compute the squared distance from this vector to v. If you are just comparing the distance with * another distance, you should compare the distance squared instead as it is slightly more efficient * to calculate. * @param v Input one 2d vector * @returns Return the squared distance from this vector to v. */ distanceToSquared(e) { const i = this.x - e.x, a = this.y - e.y; return i * i + a * a; } /** * Compute the Manhattan distance from this vector to v. * @param v Input one 2d vector * @returns Return the Manhattan distance from this vector to v. */ manhattanDistanceTo(e) { return Math.abs(this.x - e.x) + Math.abs(this.y - e.y); } /** * Sets this vector to a vector with the same direction as this one, but length l. * @param len Input one sclar value * @returns Return this vector */ setLength(e) { return this.normalize().multiplyScalar(e); } /** * Linearly interpolates between this vector and v, where alpha is the percent distance along the * line - alpha = 0 will be this vector, and alpha = 1 will be v. * @param v Input 2d vector to interpolate towards. * @param alpha Input interpolation factor, typically in the closed interval [0, 1]. * @returns Return this vector */ lerp(e, i) { return this.x += (e.x - this.x) * i, this.y += (e.y - this.y) * i, this; } /** * Sets this vector to be the vector linearly interpolated between v1 and v2 where alpha is the * percent distance along the line connecting the two vectors - alpha = 0 will be v1, and * alpha = 1 will be v2. * @param v1 Input the starting vector. * @param v2 Input vector to interpolate towards. * @param alpha Input interpolation factor, typically in the closed interval [0, 1]. * @returns */ lerpVectors(e, i, a) { return this.x = e.x + (i.x - e.x) * a, this.y = e.y + (i.y - e.y) * a, this; } /** * Return true if the components of this vector and v are strictly equal; false otherwise. * @param v Input one 2d vector to compare * @returns Return true if the components of this vector and v are strictly equal; false otherwise. */ equals(e) { return e.x === this.x && e.y === this.y; } /** * Set this vector's x value to be array[ offset ] and y value to be array[ offset + 1 ]. * @param array Input the source array. * @param offset Input (optional) offset into the array. Default is 0. * @returns Return this vector */ fromArray(e, i = 0) { return this.x = e[i], this.y = e[i + 1], this; } /** * Return an array [x, y], or copies x and y into the provided array. * @param array Input (optional) array to store this vector to. If this is not provided, a new array will be created. * @param offset Input (optional) optional offset into the array. * @returns Return an array [x, y], or copies x and y into the provided array. */ toArray(e = [], i = 0) { return e[i] = this.x, e[i + 1] = this.y, e; } // fromBufferAttribute(attribute, index) { // this.x = attribute.getX(index) // this.y = attribute.getY(index) // return this // } /** * Rotate this vector around center by angle radians. * @param center Input the point around which to rotate. * @param angle Input the angle to rotate, in radians. * @returns Return this vector */ rotateAround(e, i) { const a = Math.cos(i), l = Math.sin(i), _ = this.x - e.x, g = this.y - e.y; return this.x = _ * a - g * l + e.x, this.y = _ * l + g * a + e.y, this; } /** * Set each component of this vector to a pseudo-random value between 0 and 1, excluding 1. * @returns Return this vector */ random() { return this.x = Math.random(), this.y = Math.random(), this; } relativeEps(e = 1e-7) { return Math.min( Ct.relativeEps(this.x, e), Ct.relativeEps(this.y, e) ); } *[Symbol.iterator]() { yield this.x, yield this.y; } }; Fn.EMPTY = Object.freeze(new Fn(0, 0)); let Vt = Fn; const On = class On { /** * Create a 3x3 matrix with the given arguments in row-major order. If no arguments are provided, * the constructor initializes the Matrix3 to the 3x3 identity matrix. * @param n11 Input element in the first row and the first column * @param n12 Input element in the first row and the second column * @param n13 Input element in the first row and the third column * @param n21 Input element in the second row and the first column * @param n22 Input element in the second row and the second column * @param n23 Input element in the second row and the third column * @param n31 Input element in the third row and the first column * @param n32 Input element in the third row and the second column * @param n33 Input element in the third row and the third column */ constructor(e, i, a, l, _, g, p, x, f) { this.elements = [1, 0, 0, 0, 1, 0, 0, 0, 1], e != null && i != null && a != null && l != null && _ != null && g != null && p != null && x != null && f != null && this.set(e, i, a, l, _, g, p, x, f); } /** * Set the 3x3 matrix values to the given row-major sequence of values. * * @param n11 Input element in the first row and the first column * @param n12 Input element in the first row and the second column * @param n13 Input element in the first row and the third column * @param n21 Input element in the second row and the first column * @param n22 Input element in the second row and the second column * @param n23 Input element in the second row and the third column * @param n31 Input element in the third row and the first column * @param n32 Input element in the third row and the second column * @param n33 Input element in the third row and the third column * @returns Return this matrix */ set(e, i, a, l, _, g, p, x, f) { const A = this.elements; return A[0] = e, A[1] = l, A[2] = p, A[3] = i, A[4] = _, A[5] = x, A[6] = a, A[7] = g, A[8] = f, this; } /** * Reset this matrix to the 3x3 identity matrix: * @returns Return this matrix */ identity() { return this.set(1, 0, 0, 0, 1, 0, 0, 0, 1), this; } /** * Copy the elements of matrix m into this matrix. * @param m Input one matrix copied from * @returns Return this matrix */ copy(e) { const i = this.elements, a = e.elements; return i[0] = a[0], i[1] = a[1], i[2] = a[2], i[3] = a[3], i[4] = a[4], i[5] = a[5], i[6] = a[6], i[7] = a[7], i[8] = a[8], this; } /** * Extracts the basis of this matrix into the three axis vectors provided * @param xAxis Input X axis vector * @param yAxis Input Y axis vector * @param zAxis Input Z axis vector * @returns Return this matrix */ extractBasis(e, i, a) { return e.setFromMatrix3Column(this, 0), i.setFromMatrix3Column(this, 1), a.setFromMatrix3Column(this, 2), this; } /** * Set this matrix to the upper 3x3 matrix of the Matrix4 m. * @param m Input one 4x4 matrix * @returns Return this matrix */ setFromMatrix4(e) { const i = e.elements; return this.set(i[0], i[4], i[8], i[1], i[5], i[9], i[2], i[6], i[10]), this; } /** * Post-multiplies this matrix by m. * @param m Input one 3x3 matrix * @returns Return this matrix */ multiply(e) { return this.multiplyMatrices(this, e); } /** * Pre-multiplies this matrix by m. * @param m Input one 3x3 matrix * @returns Return this matrix */ premultiply(e) { return this.multiplyMatrices(e, this); } /** * Set this matrix to a x b. * @param a Input one 3x3 matrix * @param b Input one 3x3 matrix * @returns Return this matrix */ multiplyMatrices(e, i) { const a = e.elements, l = i.elements, _ = this.elements, g = a[0], p = a[3], x = a[6], f = a[1], A = a[4], y = a[7], I = a[2], C = a[5], U = a[8], q = l[0], Z = l[3], j = l[6], yt = l[1], Mt = l[4], ft = l[7], Y = l[2], ut = l[5], ht = l[8]; return _[0] = g * q + p * yt + x * Y, _[3] = g * Z + p * Mt + x * ut, _[6] = g * j + p * ft + x * ht, _[1] = f * q + A * yt + y * Y, _[4] = f * Z + A * Mt + y * ut, _[7] = f * j + A * ft + y * ht, _[2] = I * q + C * yt + U * Y, _[5] = I * Z + C * Mt + U * ut, _[8] = I * j + C * ft + U * ht, this; } /** * Multiply every component of the matrix by the scalar value s. * @param s Input one scalar value * @returns Return this matrix */ multiplyScalar(e) { const i = this.elements; return i[0] *= e, i[3] *= e, i[6] *= e, i[1] *= e, i[4] *= e, i[7] *= e, i[2] *= e, i[5] *= e, i[8] *= e, this; } /** * Compute and return the determinant of this matrix. * @returns Return the determinant of this matrix */ determinant() { const e = this.elements, i = e[0], a = e[1], l = e[2], _ = e[3], g = e[4], p = e[5], x = e[6], f = e[7], A = e[8]; return i * g * A - i * p * f - a * _ * A + a * p * x + l * _ * f - l * g * x; } /** * Invert this matrix, using the analytic method. You can not invert with a determinant of zero. * If you attempt this, the method produces a zero matrix instead. * @returns Return this matrix */ invert() { const e = this.elements, i = e[0], a = e[1], l = e[2], _ = e[3], g = e[4], p = e[5], x = e[6], f = e[7], A = e[8], y = A * g - p * f, I = p * x - A * _, C = f * _ - g * x, U = i * y + a * I + l * C; if (U === 0) return this.set(0, 0, 0, 0, 0, 0, 0, 0, 0); const q = 1 / U; return e[0] = y * q, e[1] = (l * f - A * a) * q, e[2] = (p * a - l * g) * q, e[3] = I * q, e[4] = (A * i - l * x) * q, e[5] = (l * _ - p * i) * q, e[6] = C * q, e[7] = (a * x - f * i) * q, e[8] = (g * i - a * _) * q, this; } /** * Transpose this matrix in place. * @returns Return this matrix */ transpose() { let e; const i = this.elements; return e = i[1], i[1] = i[3], i[3] = e, e = i[2], i[2] = i[6], i[6] = e, e = i[5], i[5] = i[7], i[7] = e, this; } /** * Sets this matrix as the upper left 3x3 of the normal matrix of the passed matrix4. The normal * matrix is the inverse transpose of the matrix m. * @param matrix4 Input one 4x4 matrix * @returns Return this matrix */ getNormalMatrix(e) { return this.setFromMatrix4(e).invert().transpose(); } /** * Set this matrix as the upper left 3x3 of the normal matrix of the passed matrix4. The normal * matrix is the inverse transpose of the matrix m. * @param r Input one 4x4 matrix * @returns Return this matrix */ transposeIntoArray(e) { const i = this.elements; return e.elements[0] = i[0], e.elements[1] = i[3], e.elements[2] = i[6], e.elements[3] = i[1], e.elements[4] = i[4], e.elements[5] = i[7], e.elements[6] = i[2], e.elements[7] = i[5], e.elements[8] = i[8], this; } /** * Set the UV transform matrix from offset, repeat, rotation, and center. * @param tx Input offset x * @param ty Input offset y * @param sx Input repeat x * @param sy Input repeat y * @param rotation Input rotation, in radians. Positive values rotate counterclockwise * @param cx Input center x of rotation * @param cy Input center y of rotation * @returns Return this matrix */ setUvTransform(e, i, a, l, _, g, p) { const x = Math.cos(_), f = Math.sin(_); return this.set( a * x, a * f, -a * (x * g + f * p) + g + e, -l * f, l * x, -l * (-f * g + x * p) + p + i, 0, 0, 1 ), this; } /** * Scale this matrix with the given scalar values. * @param sx Input one scalar value * @param sy Input one scalar value * @returns Return this matrix */ scale(e, i) { return this.premultiply(dr.makeScale(e, i)), this; } /** * Rotate this matrix by the given angle (in radians). * @param theta Input one angle in radians * @returns Return this matrix */ rotate(e) { return this.premultiply(dr.makeRotation(-e)), this; } /** * Translate this matrix by the given scalar values. * @param tx Input one scalar value * @param ty Input one scalar value * @returns Return this matrix */ translate(e, i) { return this.premultiply(dr.makeTranslation(e, i)), this; } /** * Set this matrix as a 2D translation transform: * @param x Input one 2d vector or one number * @param y Input one number * @returns Return this matrix */ makeTranslation(e, i) { return e instanceof Vt ? this.set(1, 0, e.x, 0, 1, e.y, 0, 0, 1) : this.set(1, 0, e, 0, 1, i, 0, 0, 1), this; } /** * Set this matrix as a 2D rotational transformation by theta radians * @param theta Input rotation angle in radians. Positive values rotate counterclockwise. * @returns Return this matrix */ makeRotation(e) { const i = Math.cos(e), a = Math.sin(e); return this.set(i, -a, 0, a, i, 0, 0, 0, 1), this; } /** * Set this matrix as a 2D scale transform * @param x Input the amount to scale in the X axis. * @param y Input the amount to scale in the Y axis. * @returns Return this matrix */ makeScale(e, i) { return this.set(e, 0, 0, 0, i, 0, 0, 0, 1), this; } /** * Return true if this matrix and m are equal. * @param matrix Input one matrix to compare * @returns Return true if this matrix and m are equal. */ equals(e) { const i = this.elements, a = e.elements; for (let l = 0; l < 9; l++) if (i[l] !== a[l]) return !1; return !0; } /** * Set the elements of this matrix based on an array in column-major format. * @param array Input the array to read the elements from. * @param offset Input (optional) index of first element in the array. Default is 0. * @returns Return this matrix */ fromArray(e, i = 0) { for (let a = 0; a < 9; a++) this.elements[a] = e[a + i]; return this; } /** * Write the elements of this matrix to an array in column-major format. * @param array Input (optional) array to store the resulting vector in. If not given a new array will be created. * @param offset Input (optional) offset in the array at which to put the result. * @returns Return this matrix */ toArray(e = [], i = 0) { const a = this.elements; return e[i] = a[0], e[i + 1] = a[1], e[i + 2] = a[2], e[i + 3] = a[3], e[i + 4] = a[4], e[i + 5] = a[5], e[i + 6] = a[6], e[i + 7] = a[7], e[i + 8] = a[8], e; } /** * Creates a new 3x3 matrix and with identical elements to this one. * @returns Return the cloned matrix */ clone() { return new On().fromArray(this.elements); } }; On.IDENTITY = Object.freeze(new On()); let Kn = On; const dr = /* @__PURE__ */ new Kn(), fn = 1e-6, Rt = 2 * Math.PI, ns = { x: 0, y: 0 }, Yr = { x: 0, y: 0, z: 0 }; class Hr { /** * Create tolerance class with default tolerance values */ constructor() { this.equalPointTol = fn, this.equalVectorTol = fn; } /** * Return true if two points are equal with the specified tolerance. * @param p1 Input the first 2d point * @param p2 Input the second 2d point * @returns Return true if two poitns are equal with the specified tolerance. */ equalPoint2d(e, i) { return new Vt(e).sub(i).length() < this.equalPointTol; } /** * Return true if two points are equal with the specified tolerance. * @param p1 Input the first 2d point * @param p2 Input the second 2d point * @returns Return true if two poitns are equal with the specified tolerance. */ equalPoint3d(e, i) { return new H(e).sub(i).length() < this.equalPointTol; } /** * Return true if the value is equal to zero with the specified tolerance. */ static equalToZero(e, i = fn) { return e < i && e > -i; } /** * Return true if two values are equal with the sepcified tolerance. * * @param value1 Input the first value * @param value2 Input the second value * @param tol Input the tolerance value * @returns Return true if two values are equal with the sepcified tolerance */ static equal(e, i, a = fn) { return Math.abs(e - i) < a; } /** * Return true if the first argument are greater than the second argument with the sepcified * tolerance. * * @param value1 Input the first value * @param value2 Input the second value * @param tol Input the tolerance value * @returns Return true if the first argument are greater than the second argument with the * sepcified tolerance. */ static great(e, i, a = fn) { return e - i > a; } /** * Return true if the first argument less than the second argument with the specified tolerance * value * * @param value1 Input the first value * @param value2 Input the second value * @param tol Input the tolerance value * @returns Return *true* if the first argument less than the second argument with the specified * tolerance value */ static less(e, i, a = fn) { return e - i < a; } } const Qr = new Hr(); function Jr(E, e, i = !1) { const a = E.x, l = E.y; let _ = !1; const g = e.length; for (let p = 0, x = g - 1; p < g; x = p++) { const f = e[p].x, A = e[p].y, y = e[x].x, I = e[x].y; let C = A > l != I > l; i && (C = A >= l != I >= l), C && a < (y - f) * (l - A) / (I - A) + f && (_ = !_); } return _; } function Oi(E, e) { if (E.length === 0 || e.length === 0) return !1; const i = new Pe().setFromPoints(E), a = new Pe().setFromPoints(e); if (!i.intersectsBox(a)) return !1; for (let l = 0; l < E.length; ) { if (Jr(E[l], e, !0)) return !0; l < E.length - 1 && Qr.equalPoint2d(E[l + 1], E[l]) && ++l, ++l; } return !1; } const qi = { isPointInPolygon: Jr, isPolygonIntersect: Oi }; function Gi(E, e) { const i = [], a = e - 1, l = E; for (let _ = 0; _ <= l; _++) i.push(0); for (let _ = 1; _ <= a - l; _++) i.push(_); for (let _ = 0; _ <= l; _++) i.push(a - l + 1); return i; } function Ki(E, e) { const i = e.length - 1, a = E, l = [0]; let _ = 0; for (let p = 1; p <= i; p++) { const x = e[p][0] - e[p - 1][0], f = e[p][1] - e[p - 1][1], A = e[p][2] - e[p - 1][2], y = Math.sqrt(x * x + f * f + A * A); _ += y, l.push(_); } const g = []; for (let p = 0; p <= a; p++) g.push(0); for (let p = 1; p <= i - a; p++) { const x = l[p] / _; g.push(x * (i - a + 1)); } for (let p = 0; p <= a; p++) g.push(i - a + 1); return g; } function ji(E, e) { const i = e.length - 1, a = E, l = [0]; let _ = 0; for (let p = 1; p <= i; p++) { const x = e[p][0] - e[p - 1][0], f = e[p][1] - e[p - 1][1], A = e[p][2] - e[p - 1][2], y = Math.sqrt(x * x + f * f + A * A), I = Math.sqrt(y); _ += I, l.push(_); } const g = []; for (let p = 0; p <= a; p++) g.push(0); for (let p = 1; p <= i - a; p++) { const x = l[p] / _; g.push(x * (i - a + 1)); } for (let p = 0; p <= a; p++) g.push(i - a + 1); return g; } function yr(E, e, i, a) { if (e === 0) return i >= a[E] && i < a[E + 1] ? 1 : 0; const l = a[E + e] - a[E], _ = a[E + e + 1] - a[E + 1], g = l > 1e-10 ? (i - a[E]) / l : 0, p = _ > 1e-10 ? (a[E + e + 1] - i) / _ : 0; return g * yr(E, e - 1, i, a) + p * yr(E + 1, e - 1, i, a); } function tr(E, e, i, a, l) { const _ = a.length - 1, g = e; if (E = Math.max(i[g], Math.min(i[_ + 1], E)), Math.abs(E - i[_ + 1]) < 1e-8) return [...a[_]]; if (Math.abs(E - i[g]) < 1e-8) return [...a[0]]; const p = [0, 0, 0]; let x = 0; for (let f = 0; f <= _; f++) { const A = yr(f, g, E, i), y = l[f] * A; p[0] += a[f][0] * y, p[1] += a[f][1] * y, p[2] += a[f][2] * y, x += y; } if (x < 1e-10) { const f = i[i.length - g - 1]; if (Math.abs(E - f) < 1e-8) return [...a[_]]; if (Math.abs(E - i[g]) < 1e-8) return [...a[0]]; } return x > 1e-10 && (p[0] /= x, p[1] /= x, p[2] /= x), p; } function Xi(E, e, i, a) { const l = E, _ = e[l], g = e[e.length - l - 1]; let p = 0; const x = 1e3, f = (g - _) / x; let A = tr( _, E, e, i, a ); for (let q = 1; q <= x; q++) { const Z = _ + q * f, j = tr(Z, E, e, i, a), yt = j[0] - A[0], Mt = j[1] - A[1], ft = j[2] - A[2]; p += Math.sqrt(yt * yt + Mt * Mt + ft * ft), A = j; } const y = tr( g, E, e, i, a ), I = y[0] - A[0], C = y[1] - A[1], U = y[2] - A[2]; return p += Math.sqrt(I * I + C * C + U * U), p; } function rs(E) { return E.map((e) => [...e]); } class ir { /** * Create one instance of this class * @param x Input x coordinate * @param y Input y coordinate * @param z Input z coordinate * @param w Input w coordinate */ constructor(e = 0, i = 0, a = 0, l = 1) { this._x = e, this._y = i, this._z = a, this._w = l; } /** * This SLERP implementation assumes the quaternion data are managed in flat arrays. * @param dst Input the output array * @param dstOffset Input an offset into the output array * @param src0 Input the source array of the starting quaternion. * @param srcOffset0 Input an offset into the array src0. * @param src1 Input the source array of the target quaternion. * @param srcOffset1 Input an offset into the array src1. * @param t Input normalized interpolation factor (between 0 and 1). */ static slerpFlat(e, i, a, l, _, g, p) { let x = a[l + 0], f = a[l + 1], A = a[l + 2], y = a[l + 3]; const I = _[g + 0], C = _[g + 1], U = _[g + 2], q = _[g + 3]; if (p === 0) { e[i + 0] = x, e[i + 1] = f, e[i + 2] = A, e[i + 3] = y; return; } if (p === 1) { e[i + 0] = I, e[i + 1] = C, e[i + 2] = U, e[i + 3] = q; return; } if (y !== q || x !== I || f !== C || A !== U) { let Z = 1 - p; const j = x * I + f * C + A * U + y * q, yt = j >= 0 ? 1 : -1, Mt = 1 - j * j; if (Mt > Number.EPSILON) { const Y = Math.sqrt(Mt), ut = Math.atan2(Y, j * yt); Z = Math.sin(Z * ut) / Y, p = Math.sin(p * ut) / Y; } const ft = p * yt; if (x = x * Z + I * ft, f = f * Z + C * ft, A = A * Z + U * ft, y = y * Z + q * ft, Z === 1 - p) { const Y = 1 / Math.sqrt(x * x + f * f + A * A + y * y); x *= Y, f *= Y, A *= Y, y *= Y; } } e[i] = x, e[i + 1] = f, e[i + 2] = A, e[i + 3] = y; } /** * This multiplication implementation assumes the quaternion data are managed in flat arrays. * @param dst Input the output array. * @param dstOffset Input an offset into the output array. * @param src0 Input the source array of the starting quaternion. * @param srcOffset0 Input an offset into the array src0. * @param src1 Input the source array of the target quaternion. * @param srcOffset1 Input an offset into the array src1. * @returns Return an array */ static multiplyQuaternionsFlat(e, i, a, l, _, g) { const p = a[l], x = a[l + 1], f = a[l + 2], A = a[l + 3], y = _[g], I = _[g + 1], C = _[g + 2], U = _[g + 3]; return e[i] = p * U + A * y + x * C - f * I, e[i + 1] = x * U + A * I + f * y - p * C, e[i + 2] = f * U + A * C + p * I - x * y, e[i + 3] = A * U - p * y - x * I - f * C, e; } /** * X cooridinate */ get x() { return this._x; } set x(e) { this._x = e, this._onChangeCallback(); } /** * Y cooridinate */ get y() { return this._y; } set y(e) { this._y = e, this._onChangeCallback(); } /** * Z cooridinate */ get z() { return this._z; } set z(e) { this._z = e, this._onChangeCallback(); } /** * W cooridinate */ get w() { return this._w; } set w(e) { this._w = e, this._onChangeCallback(); } /** * Set x, y, z, w properties of this quaternion. * @param x Input x coordinate * @param y Input y coordinate * @param z Input z coordinate * @param w Input w coordinate * @returns Return this quaternion */ set(e, i, a, l) { return this._x = e, this._y = i, this._z = a, this._w = l, this._onChangeCallback(), this; } /** * Create a new quaternion with identical x, y, z and w properties to this one. * @returns Return cloned instance */ clone() { return new ir(this._x, this._y, this._z, this._w); } /** * Copy the x, y, z and w properties of q into this quaternion. * @param quaternion Input the quaternion copied from * @returns Return this quaternion */ copy(e) { return this._x = e.x, this._y = e.y, this._z = e.z, this._w = e.w, this._onChangeCallback(), this; } /** * Sets this quaternion from the rotation specified by euler angle. * @param euler Input one euler angle * @param update Input one flag whether to trigger change callback function * @returns Return this quaternion */ setFromEuler(e, i = !0) { const a = e.x, l = e.y, _ = e.z, g = e.order, p = Math.cos, x = Math.sin, f = p(a / 2), A = p(l / 2), y = p(_ / 2), I = x(a / 2), C = x(l / 2), U = x(_ / 2); switch (g) { case "XYZ": this._x = I * A * y + f * C * U, this._y = f * C * y - I * A * U, this._z = f * A * U + I * C * y, this._w = f * A * y - I * C * U; break; case "YXZ": this._x = I * A * y + f * C * U, this._y = f * C * y - I * A * U, this._z = f * A * U - I * C * y, this._w = f * A * y + I * C * U; break; case "ZXY": this._x = I * A * y - f * C * U, this._y = f * C * y + I * A * U, this._z = f * A * U + I * C * y, this._w = f * A * y - I * C * U; break; case "ZYX": this._x = I * A * y - f * C * U, this._y = f * C * y + I * A * U, this._z = f * A * U - I * C * y, this._w = f * A * y + I * C * U; break; case "YZX": this._x = I * A * y + f * C * U, this._y = f * C * y + I * A * U, this._z = f * A * U - I * C * y, this._w = f * A * y - I * C * U; break; case "XZY": this._x = I * A * y - f * C * U, this._y = f * C * y - I * A * U, this._z = f * A * U + I * C * y, this._w = f * A * y + I * C * U; break; default: console.warn( "THREE.Quaternion: .setFromEuler() encountered an unknown order: " + g ); } return i === !0 && this._onChangeCallback(), this; } /** * Set this quaternion from rotation specified by axis and angle. Axis is assumed to be normalized, * angle is in radians. * @param axis Input one normalized axis * @param angle Input one angle in radians * @returns Return this quaternion */ setFromAxisAngle(e, i) { const a = i / 2, l = Math.sin(a); return this._x = e.x * l, this._y = e.y * l, this._z = e.z * l, this._w = Math.cos(a), this._onChangeCallback(), this; } /** * Set this quaternion from rotation component of the specified matrix. * @param m Input a Matrix4 of which the upper 3x3 of matrix is a pure rotation matrix (i.e. unscaled). * @returns Return this quaternion */ setFromRotationMatrix(e) { const i = e.elements, a = i[0], l = i[4], _ = i[8], g = i[1], p = i[5], x = i[9], f = i[2], A = i[6], y = i[10], I = a + p + y; if (I > 0) { const C = 0.5 / Math.sqrt(I + 1); this._w = 0.25 / C, this._x = (A - x) * C, this._y = (_ - f) * C, this._z = (g - l) * C; } else if (a > p && a > y) { const C = 2 * Math.sqrt(1 + a - p - y); this._w = (A - x) / C, this._x = 0.25 * C, this._y = (l + g) / C, this._z = (_ + f) / C; } else if (p > y) { const C = 2 * Math.sqrt(1 + p - a - y); this._w = (_ - f) / C, this._x = (l + g) / C, this._y = 0.25 * C, this._z = (x + A) / C; } else { const C = 2 * Math.sqrt(1 + y - a - p); this._w = (g - l) / C, this._x = (_ + f) / C, this._y = (x + A) / C, this._z = 0.25 * C; } return this._onChangeCallback(), this; } /** * Set this quaternion to the rotation required to rotate direction vector vFrom to direction vector vTo. * @param vFrom Input one normalized direction vector * @param vTo Input one normalized direction vector * @returns Return this quaternion */ setFromUnitVectors(e, i) { let a = e.dot(i) + 1; return a < Number.EPSILON ? (a = 0, Math.abs(e.x) > Math.abs(e.z) ? (this._x = -e.y, this._y = e.x, this._z = 0, this._w = a) : (this._x = 0, this._y = -e.z, this._z = e.y, this._w = a)) : (this._x = e.y * i.z - e.z * i.y, this._y = e.z * i.x - e.x * i.z, this._z = e.x * i.y - e.y * i.x, this._w = a), this.normalize(); } /** * Return the angle between this quaternion and quaternion q in radians. * @param q Input one quaternion * @returns Return the angle between this quaternion and quaternion q in radians. */ angleTo(e) { return 2 * Math.acos(Math.abs(Ze(this.dot(e), -1, 1))); } /** * Rotate this quaternion by a given angular step to the defined quaternion q. The method ensures * that the final quaternion will not overshoot q. * @param q Input the target quaternion. * @param step Input the angular step in radians. * @returns Return this quaternion */ rotateTowards(e, i) { const a = this.angleTo(e); if (a === 0) return this; const l = Math.min(1, i / a); return this.slerp(e, l), this; } /** * Set this quaternion to the identity quaternion; that is, to the quaternion that represents * "no rotation". * @returns Return this quaternion. */ identity() { return this.set(0, 0, 0, 1); } /** * Invert this quaternion - calculates the conjugate. The quaternion is assumed to have unit length. * @returns Return this quaternion. */ invert() { return this.conjugate(); } /** * Return the rotational conjugate of this quaternion. The conjugate of a quaternion represents the * same rotation in the opposite direction about the rotational axis. * @returns Return this quaternion */ conjugate() { return this._x *= -1, this._y *= -1, this._z *= -1, this._onChangeCallback(), this; } /** * Calculate the dot product of quaternions v and this one. * @param v Input one quaternion * @returns Return the dot product of quaternions v and this one */ dot(e) { return this._x * e._x + this._y * e._y + this._z * e._z + this._w * e._w; } /** * Compute the squared Euclidean length (straight-line length) of this quaternion, considered as a * 4 dimensional vector. This can be useful if you are comparing the lengths of two quaternions, as * this is a slightly more efficient calculation than length(). * @returns Return the squared Euclidean length (straight-line length) of this quaternion */ lengthSq() { return this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w; } /** * Compute the Euclidean length (straight-line length) of this quaternion, considered as a 4 dimensional * vector. * @returns Return the Euclidean length (straight-line length) of this quaternion. */ length() { return Math.sqrt( this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w ); } /** * Normalize this quaternion - that is, calculated the quaternion that performs the same rotation as * this one, but has length equal to 1. * @returns Return this quaternion */ normalize() { let e = this.length(); return e === 0 ? (this._x = 0, this._y = 0, this._z = 0, this._w = 1) : (e = 1 / e, this._x = this._x * e, this._y = this._y * e, this._z = this._z * e, this._w = this._w * e), this._onChangeCallback(), this; } /** * Multiply this quaternion by q. * @param q Input one quaternion to multiply * @returns Return this quaternion */ multiply(e) { return this.multiplyQuaternions(this, e); } /** * Pre-multiply this quaternion by q. * @param q Input one quaternion * @returns Return this quaternion */ premultiply(e) { return this.multiplyQuaternions(e, this); } /** * Sets this quaternion to a x b. * @param a Input one quaternion * @param b Input one quaternion * @returns Return this quaternion */ multiplyQuaternions(e, i) { const a = e._x, l = e._y, _ = e._z, g = e._w, p = i._x, x = i._y, f = i._z, A = i._w; return this._x = a * A + g * p + l * f - _ * x, this._y = l * A + g * x + _ * p - a * f, this._z = _ * A + g * f + a * x - l * p, this._w = g * A - a * p - l * x - _ * f, this._onChangeCallback(), this; } /** * Handles the spherical linear interpolation between quaternions. t represents the amount of rotation * between this quaternion (where t is 0) and qb (where t is 1). * @param qb Input the other quaternion rotation * @param t Input interpolation factor in the closed interval [0, 1]. * @returns Return this quaternion */ slerp(e, i) { if (i === 0) return this; if (i === 1) return this.copy(e); const a = this._x, l = this._y, _ = this._z, g = this._w; let p = g * e._w + a * e._x + l * e._y + _ * e._z; if (p < 0 ? (this._w = -e._w, this._x = -e._x, this._y = -e._y, this._z = -e._z, p = -p) : this.copy(e), p >= 1) return this._w = g, this._x = a, this._y = l, this._z = _, this; const x = 1 - p * p; if (x <= Number.EPSILON) { const C = 1 - i; return this._w = C * g + i * this._w, this._x = C * a + i * this._x, this._y = C * l + i * this._y, this._z = C * _ + i * this._z, this.normalize(), this; } const f = Math.sqrt(x), A = Math.atan2(f, p), y = Math.sin((1 - i) * A) / f, I = Math.sin(i * A) / f; return this._w = g * y + this._w * I, this._x = a * y + this._x * I, this._y = l * y + this._y * I, this._z = _ * y + this._z * I, this._onChangeCallback(), this; } /** * Perform a spherical linear interpolation between the given quaternions and stores the result in * this quaternion. * @param qa Input one quaternion rotation * @param qb Input the other quaternion rotation * @param t Input interpolation factor in the closed interval [0, 1]. * @returns Return this quaternion */ slerpQuaternions(e, i, a) { return this.copy(e).slerp(i, a); } /** * Set this quaternion to a uniformly ra