UNPKG

cubic-beziers-through-points

Version:

A function to fit fair (bending energy minimizing) cubic bezier curves through a set of given ordered points in the plane.

1,483 lines (1,428 loc) 115 kB
/******/ // The require scope /******/ var __webpack_require__ = {}; /******/ /************************************************************************/ /******/ /* webpack/runtime/define property getters */ /******/ (() => { /******/ // define getter functions for harmony exports /******/ __webpack_require__.d = (exports, definition) => { /******/ for(var key in definition) { /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); /******/ } /******/ } /******/ }; /******/ })(); /******/ /******/ /* webpack/runtime/hasOwnProperty shorthand */ /******/ (() => { /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) /******/ })(); /******/ /************************************************************************/ var __webpack_exports__ = {}; // EXPORTS __webpack_require__.d(__webpack_exports__, { r: () => (/* reexport */ cubicBeziersThroughPoints), B6: () => (/* reexport */ cubicBeziersThroughPoints_C2), RX: () => (/* reexport */ cubicsAndEnergyThroughPoints), nV: () => (/* reexport */ energyThroughPoints) }); ;// ./node_modules/flo-vector2d/node/affine-transformations/translate/translate.js // From: https://en.wikipedia.org/wiki/Affine_transformation // "If X is the point set of an affine space, then every affine transformation // on X can be represented as the composition of a linear transformation on X // and a translation of X" function translate(a, b) { function f(b) { return [a[0] + b[0], a[1] + b[1]]; } // Curry the function return b === undefined ? f : f(b); } //# sourceMappingURL=translate.js.map ;// ./node_modules/flo-vector2d/node/affine-transformations/linear/reverse.js /** * Returns the given 2-vector reversed (i.e. scaled by -1). * @param p a vector */ function reverse(p) { return [-p[0], -p[1]]; } //# sourceMappingURL=reverse.js.map ;// ./node_modules/flo-vector2d/node/affine-transformations/linear/rotate.js function rotate(sinθ, cosθ, p) { function rotateByθ(p) { return [ p[0] * cosθ - p[1] * sinθ, p[0] * sinθ + p[1] * cosθ ]; } // Curry the function return p === undefined ? rotateByθ : rotateByθ(p); } //# sourceMappingURL=rotate.js.map ;// ./node_modules/flo-vector2d/node/affine-transformations/linear/scale.js /** * Returns a scaled version of the given 2-vector. * @param p a vector * @param c a scale factor */ function scale(p, c) { return [c * p[0], c * p[1]]; } //# sourceMappingURL=scale.js.map ;// ./node_modules/flo-vector2d/node/distance-and-length/len.js /** * Returns the length of the given 2-vector. * @param p a 2d vector */ function len(p) { return Math.sqrt(p[0] * p[0] + p[1] * p[1]); } //# sourceMappingURL=len.js.map ;// ./node_modules/flo-bezier3/node/angles-and-speeds/bezier-by-angles-and-speeds/cubic-to-angles-and-speeds.js const { cos, sin, atan2 } = Math; /** * For the given bernstein cubic bezier curve basis return the angles-and-speeds * basis coefficients, i.e. * * α -> initial tangent angle in degrees * * β -> terminal tangent angle in degrees * * s0 -> inital speed * * s1 -> terminal speed * * L -> distance between initial and final point (cannot be 0) * * rot -> rotation of entire curve * * p -> initial position offset * * @param ps an order 3 (cubic) bezier curve given as an ordered array of its * control point coordinates, e.g. `[[0,0], [1,1], [2,1], [2,0]]` */ function cubicToAnglesAndSpeeds(ps) { // [_x1,_y1],[_x2,_y2],[_x3,_y3] const p = ps[0]; // move ps to origin ps = ps.map(translate(reverse(p))); const [x, y] = [ps[3][0], ps[3][1]]; const rot = atan2(y, x); ps = ps.map(rotate(sin(-rot), cos(-rot))); const L = ps[3][0]; ps = ps.map(p => scale(p, 1 / L)); // TS -> tangent vector at `t === 0` const TS = ps[1]; // TE -> tangent vector at `t === 1` const TE = [1 - ps[2][0], -ps[2][1]]; // const h2 = sqrt(x1**2 + y1**2); const α = atan2(TS[1], TS[0]); const β = atan2(TE[1], TE[0]); const s0 = 3 * len(TS); const s1 = 3 * len(TE); return { α, β, s0, s1, L, rot, p }; } //# sourceMappingURL=cubic-to-angles-and-speeds.js.map ;// ./node_modules/flo-gauss-quadrature/node/index.js // TODO A future improvement can be to use the Gauss–Kronrod rules // to estimate the error and thus choose a number of constants based // on the error. Maybe not. // TODO In future, the constants can be calculated and cached so we can // choose any value for the order. // TODO - to limit rounding error do pairwise addition of terms // TODO order abscissas // TODO - auto calc abscissas and weights (on first call to function only) /** * Numerically integrates the given function using the Gaussian Quadrature * method. * * See https://en.wikipedia.org/wiki/Gaussian_quadrature * See http://pomax.github.io/bezierinfo/#arclength * @param f The univariate function to be integrated * @param interval The integration interval * @param order Can be 2, 4, 8, or 16. Higher values give more accurate results * but is slower - defaults to 16. */ function gaussQuadrature(f, interval, order = 16) { if (interval[0] === interval[1]) { return 0; } const { weights, abscissas } = GAUSS_CONSTANTS[order]; const [a, b] = interval; let result = 0; const m1 = (b - a) / 2; const m2 = (b + a) / 2; for (let i = 0; i <= order - 1; i++) { result += weights[i] * f(m1 * abscissas[i] + m2); } return m1 * result; } // The Gaussian Legendre Quadrature method constants. const GAUSS_CONSTANTS = { 2: { weights: [1, 1], abscissas: [-0.5773502691896257, 0.5773502691896257] }, 4: { weights: [ 0.6521451548625461, 0.6521451548625461, 0.3478548451374538, 0.3478548451374538 ], abscissas: [ -0.3399810435848563, 0.3399810435848563, -0.8611363115940526, 0.8611363115940526 ] }, 8: { weights: [ 0.3626837833783620, 0.3626837833783620, 0.3137066458778873, 0.3137066458778873, 0.2223810344533745, 0.2223810344533745, 0.1012285362903763, 0.1012285362903763 ], abscissas: [ -0.1834346424956498, 0.1834346424956498, -0.5255324099163290, 0.5255324099163290, -0.7966664774136267, 0.7966664774136267, -0.9602898564975363, 0.9602898564975363 ] }, // Taken from http://keisan.casio.com/exec/system/1330940731 16: { weights: [ 0.0271524594117540948518, 0.062253523938647892863, 0.0951585116824927848099, 0.1246289712555338720525, 0.1495959888165767320815, 0.169156519395002538189, 0.182603415044923588867, 0.189450610455068496285, 0.1894506104550684962854, 0.182603415044923588867, 0.1691565193950025381893, 0.149595988816576732081, 0.124628971255533872053, 0.095158511682492784809, 0.062253523938647892863, 0.027152459411754094852 ], abscissas: [ -0.989400934991649932596, -0.944575023073232576078, -0.86563120238783174388, -0.7554044083550030338951, -0.6178762444026437484467, -0.4580167776572273863424, -0.28160355077925891323, -0.0950125098376374401853, 0.0950125098376374401853, 0.28160355077925891323, 0.4580167776572273863424, 0.617876244402643748447, 0.755404408355003033895, 0.8656312023878317438805, 0.944575023073232576078, 0.989400934991649932596 ], }, 64: { weights: [ 0.048690957009139724, 0.048690957009139724, 0.04857546744150343, 0.04857546744150343, 0.048344762234802954, 0.048344762234802954, 0.04799938859645831, 0.04799938859645831, 0.04754016571483031, 0.04754016571483031, 0.04696818281621002, 0.04696818281621002, 0.046284796581314416, 0.046284796581314416, 0.04549162792741814, 0.04549162792741814, 0.044590558163756566, 0.044590558163756566, 0.04358372452932345, 0.04358372452932345, 0.04247351512365359, 0.04247351512365359, 0.04126256324262353, 0.04126256324262353, 0.03995374113272034, 0.03995374113272034, 0.038550153178615626, 0.038550153178615626, 0.03705512854024005, 0.03705512854024005, 0.035472213256882386, 0.035472213256882386, 0.033805161837141606, 0.033805161837141606, 0.03205792835485155, 0.03205792835485155, 0.030234657072402478, 0.030234657072402478, 0.028339672614259483, 0.028339672614259483, 0.02637746971505466, 0.02637746971505466, 0.024352702568710874, 0.024352702568710874, 0.022270173808383253, 0.022270173808383253, 0.02013482315353021, 0.02013482315353021, 0.017951715775697343, 0.017951715775697343, 0.015726030476024718, 0.015726030476024718, 0.013463047896718643, 0.013463047896718643, 0.011168139460131128, 0.011168139460131128, 0.008846759826363947, 0.008846759826363947, 0.006504457968978363, 0.006504457968978363, 0.004147033260562468, 0.004147033260562468, 0.001783280721696433, 0.001783280721696433 ], abscissas: [ -0.024350292663424433, 0.024350292663424433, -0.07299312178779904, 0.07299312178779904, -0.12146281929612056, 0.12146281929612056, -0.16964442042399283, 0.16964442042399283, -0.21742364374000708, 0.21742364374000708, -0.2646871622087674, 0.2646871622087674, -0.31132287199021097, 0.31132287199021097, -0.3572201583376681, 0.3572201583376681, -0.4022701579639916, 0.4022701579639916, -0.4463660172534641, 0.4463660172534641, -0.48940314570705296, 0.48940314570705296, -0.5312794640198946, 0.5312794640198946, -0.571895646202634, 0.571895646202634, -0.6111553551723933, 0.6111553551723933, -0.6489654712546573, 0.6489654712546573, -0.6852363130542333, 0.6852363130542333, -0.7198818501716109, 0.7198818501716109, -0.7528199072605319, 0.7528199072605319, -0.7839723589433414, 0.7839723589433414, -0.8132653151227975, 0.8132653151227975, -0.8406292962525803, 0.8406292962525803, -0.8659993981540928, 0.8659993981540928, -0.8893154459951141, 0.8893154459951141, -0.9105221370785028, 0.9105221370785028, -0.9295691721319396, 0.9295691721319396, -0.9464113748584028, 0.9464113748584028, -0.9610087996520538, 0.9610087996520538, -0.973326827789911, 0.973326827789911, -0.983336253884626, 0.983336253884626, -0.9910133714767443, 0.9910133714767443, -0.9963401167719553, 0.9963401167719553, -0.9993050417357722, 0.9993050417357722 ] } }; //# sourceMappingURL=index.js.map ;// ./node_modules/double-double/node/basic/two-diff.js /** * Returns the exact result of subtracting b from a. * * @param a minuend - a double-double precision floating point number * @param b subtrahend - a double-double precision floating point number */ function twoDiff(a, b) { const x = a - b; const bvirt = a - x; const y = (a - (x + bvirt)) + (bvirt - b); return [y, x]; } //# sourceMappingURL=two-diff.js.map ;// ./node_modules/double-double/node/basic/two-sum.js /** * Returns the exact result of adding two doubles. * * * the resulting array is the reverse of the standard twoSum in the literature. * * Theorem 7 (Knuth): Let a and b be p-bit floating-point numbers. Then the * following algorithm will produce a nonoverlapping expansion x + y such that * a + b = x + y, where x is an approximation to a + b and y is the roundoff * error in the calculation of x. * * See https://people.eecs.berkeley.edu/~jrs/papers/robustr.pdf */ function two_sum_twoSum(a, b) { const x = a + b; const bv = x - a; return [(a - (x - bv)) + (b - bv), x]; } // inlined //const R = a + b; const _ = R - a; const r = (a - (R - _)) + (b - _); return [r,R] //# sourceMappingURL=two-sum.js.map ;// ./node_modules/big-float-ts/node/double-expansion/fast-expansion-sum.js // import { eCompress } from "./e-compress.js"; // We *have* to do the below❗ The assignee is a getter❗ The assigned is a pure function❗ // const compress = eCompress; /** * Returns the result of adding two expansions. * * Theorem 13: Let e = sum_(i=1)^m(e_i) and f = sum_(i=1)^n(f_i) be strongly * nonoverlapping expansions of m and n p-bit components, respectively, where * p >= 4. Suppose that the components of both e and f are sorted in order of * increasing magnitude, except that any of the e_i or f_i may be zero. On a * machine whose arithmetic uses the round-to-even rule, the following algorithm * will produce a strongly nonoverlapping expansion h such that * sum_(i=1)^(m+n)(e_i + f_i) = e + f, where the components of h are also in * order of increasing magnitude, except that any of the h_i may be zero. * * See https://people.eecs.berkeley.edu/~jrs/papers/robustr.pdf */ function fastExpansionSum(e, f) { //const g = merge(e,f); // inlined (above line) const lenE = e.length; const lenF = f.length; let i = 0; let j = 0; const g = []; while (i < lenE && j < lenF) { if (e[i] === 0) { i++; continue; } if (f[j] === 0) { j++; continue; } if (Math.abs(e[i]) <= Math.abs(f[j])) { g.push(e[i]); i++; } else { g.push(f[j]); j++; } } while (i < lenE) { g.push(e[i]); i++; } while (j < lenF) { g.push(f[j]); j++; } if (g.length === 0) { return [0]; } // end inlined const len = g.length; if (len === 1) { return g; } //const h: number[] = new Array(len); const h = []; //const q: number; //[h[0], q] = fastTwoSum(g[1], g[0]); // inlined (above line) const a = g[1]; const b = g[0]; let q = a + b; //h[0] = b - (q - a); const hh = b - (q - a); if (hh !== 0) { h.push(hh); } //let j = 0; j = 0; for (let i = 2; i < len; i++) { //[h[i-1], q] = twoSum(q, g[i]); // inlined (above line) const b = g[i]; const R = q + b; const _ = R - q; //h[i-1] = (q - (R - _)) + (b - _); const hh = (q - (R - _)) + (b - _); if (hh !== 0) { h.push(hh); } q = R; } //h[len-1] = q; //h.push(q); if (q !== 0 || h.length === 0) { h.push(q); } //return compress(h); return h; } /** * Returns the result of merging an expansion e and f into a single expansion, * in order of nondecreasing magnitude (possibly with interspersed zeros). * (This function is zero-eliminating) * * * see [Shewchuk](https://people.eecs.berkeley.edu/~jrs/papers/robustr.pdf) * * @param e a floating point expansion * @param f another floating point expansion */ function merge(e, f) { const lenE = e.length; const lenF = f.length; let i = 0; let j = 0; const merged = []; while (i < lenE && j < lenF) { if (e[i] === 0) { i++; continue; } if (f[j] === 0) { j++; continue; } if (Math.abs(e[i]) <= Math.abs(f[j])) { merged.push(e[i]); i++; } else { merged.push(f[j]); j++; } } while (i < lenE) { merged.push(e[i]); i++; } while (j < lenF) { merged.push(f[j]); j++; } if (merged.length === 0) { return [0]; } return merged; } //# sourceMappingURL=fast-expansion-sum.js.map ;// ./node_modules/big-float-ts/node/double-expansion/e-negative-of.js /** * Returns the negative of the given floating point expansion. * * see [Shewchuk](https://people.eecs.berkeley.edu/~jrs/papers/robustr.pdf) * * @param e a floating point expansion */ function eNegativeOf(e) { const m = e.length; const h = new Array(m); for (let i = 0; i < m; i++) { h[i] = -e[i]; } return h; } //# sourceMappingURL=e-negative-of.js.map ;// ./node_modules/big-float-ts/node/double-expansion/e-diff.js // We *have* to do the below❗ The assignee is a getter❗ The assigned is a pure function❗ const negativeOf = eNegativeOf; const add = fastExpansionSum; /** * Returns the difference between two floating point expansions, i.e. e - f. * * * see [Shewchuk](https://people.eecs.berkeley.edu/~jrs/papers/robustr.pdf) * * @param e a floating point expansion * @param f another floating point expansion */ function eDiff(e, f) { const g = negativeOf(f); return add(e, g); } //# sourceMappingURL=e-diff.js.map ;// ./node_modules/big-float-ts/node/double-expansion/scale-expansion.js const f = 134217729; // 2**27 + 1; // We *have* to do the below❗ The assignee is a getter❗ The assigned is a pure function❗ const tp = (/* unused pure expression or super */ null && (twoProduct)); const ts = (/* unused pure expression or super */ null && (twoSum)); const fts = (/* unused pure expression or super */ null && (fastTwoSum)); const compress = (/* unused pure expression or super */ null && (eCompress)); /** * Returns the result of multiplying an expansion by a double. * * * see [Shewchuk](https://people.eecs.berkeley.edu/~jrs/papers/robustr.pdf) * * Theorem 19 (Shwechuk): Let e = sum_(i=1)^m(e_i) be a nonoverlapping expansion * of m p-bit components, and const b be a p-bit value where p >= 4. Suppose that * the components of e are sorted in order of increasing magnitude, except that * any of the e_i may be zero. Then the following algorithm will produce a * nonoverlapping expansion h such that h = sum_(i=1)^(2m)(h_i) = be, where the * components of h are also in order of increasing magnitude, except that any of * the h_i may be zero. Furthermore, if e is nonadjacent and round-to-even * tiebreaking is used, then h is non-adjacent. * * @param e a double floating point expansion * @param b a double */ function scaleExpansion(e, b) { const m = e.length; //const h: number[] = new Array(2*m); let q_; //[h[0], q] = tp(e[0], b); // inlined (above line) const a = e[0]; let q = a * b; const c = f * a; const ah = c - (c - a); const al = a - ah; const d = f * b; const bh = d - (d - b); const bl = b - bh; const h = []; //h[0] = (al*bl) - ((q - (ah*bh)) - (al*bh) - (ah*bl)); const hh = (al * bl) - ((q - (ah * bh)) - (al * bh) - (ah * bl)); if (hh !== 0) { h.push(hh); } for (let i = 1; i < m; i++) { //const [t, T] = tp(e[i], b); // inlined (above line) const a = e[i]; const T = a * b; const c = f * a; const ah = c - (c - a); const al = a - ah; const d = f * b; const bh = d - (d - b); const bl = b - bh; const t = (al * bl) - ((T - (ah * bh)) - (al * bh) - (ah * bl)); //[h[2*i-1], q_] = ts(q, t); // inlined (above line) const x = q + t; const bv = x - q; //h[2*i-1] = (q - (x - bv)) + (t - bv); //h.push((q - (x - bv)) + (t - bv)); const hh = (q - (x - bv)) + (t - bv); if (hh !== 0) { h.push(hh); } q_ = x; //[h[2*i], q] = fts(T, q_); // inlined (above line) const xx = T + q_; //h[2*i] = q_ - (xx - T); //h.push(q_ - (xx - T)); const hhh = q_ - (xx - T); if (hhh !== 0) { h.push(hhh); } q = xx; } //h[2*m - 1] = q; //h.push(q); if (q !== 0 || h.length === 0) { h.push(q); } //return eCompress(h); return h; } /** * Returns the result of multiplying an expansion by a double. * * * see [Shewchuk](https://people.eecs.berkeley.edu/~jrs/papers/robustr.pdf) * * Theorem 19 (Shwechuk): Let e = sum_(i=1)^m(e_i) be a nonoverlapping expansion * of m p-bit components, and const b be a p-bit value where p >= 4. Suppose that * the components of e are sorted in order of increasing magnitude, except that * any of the e_i may be zero. Then the following algorithm will produce a * nonoverlapping expansion h such that h = sum_(i=1)^(2m)(h_i) = be, where the * components of h are also in order of increasing magnitude, except that any of * the h_i may be zero. Furthermore, if e is nonadjacent and round-to-even * tiebreaking is used, then h is non-adjacent. * * @param e a double floating point expansion * @param b a double */ function scaleExpansion2(b, e) { const m = e.length; //const h: number[] = new Array(2*m); let q_; //[h[0], q] = tp(e[0], b); // inlined (above line) const a = e[0]; let q = a * b; const c = f * a; const ah = c - (c - a); const al = a - ah; const d = f * b; const bh = d - (d - b); const bl = b - bh; const h = []; //h[0] = (al*bl) - ((q - (ah*bh)) - (al*bh) - (ah*bl)); const hh = (al * bl) - ((q - (ah * bh)) - (al * bh) - (ah * bl)); if (hh !== 0) { h.push(hh); } for (let i = 1; i < m; i++) { //const [t, T] = tp(e[i], b); // inlined (above line) const a = e[i]; const T = a * b; const c = f * a; const ah = c - (c - a); const al = a - ah; const d = f * b; const bh = d - (d - b); const bl = b - bh; const t = (al * bl) - ((T - (ah * bh)) - (al * bh) - (ah * bl)); //[h[2*i-1], q_] = ts(q, t); // inlined (above line) const x = q + t; const bv = x - q; //h[2*i-1] = (q - (x - bv)) + (t - bv); //h.push((q - (x - bv)) + (t - bv)); const hh = (q - (x - bv)) + (t - bv); if (hh !== 0) { h.push(hh); } q_ = x; //[h[2*i], q] = fts(T, q_); // inlined (above line) const xx = T + q_; //h[2*i] = q_ - (xx - T); //h.push(q_ - (xx - T)); const hhh = q_ - (xx - T); if (hhh !== 0) { h.push(hhh); } q = xx; } //h[2*m - 1] = q; //h.push(q); if (q !== 0 || h.length === 0) { h.push(q); } //return eCompress(h); return h; } //# sourceMappingURL=scale-expansion.js.map ;// ./node_modules/big-float-ts/node/double-expansion/expansion-product.js // We *have* to do the below❗ The assignee is a getter❗ The assigned is a pure function❗ const multByDouble = scaleExpansion; const expansion_product_add = fastExpansionSum; const expansion_product_compress = (/* unused pure expression or super */ null && (eCompress)); /** * Returns the product of two double floating point expansions. * * * see [Shewchuk](https://people.eecs.berkeley.edu/~jrs/papers/robustr.pdf) * * As per Shewchuk in the above paper: "To find the product of two expansions * e and f, use SCALE-EXPANSION (with zero elimination) to form the expansions * ef_1, ef_2, ..., then sum these using a distillation tree." * * A distillation tree used with fastExpansionSum will give O(k*log k) vs O(k^2) * operations. * * Implemented naively and not as described by Shewchuk (i.e. the algorithm * takes O(k^2) operations). * @param e a double floating point expansion * @param f another double floating point expansion */ function expansionProduct(e, f) { let sum = [0]; for (let i = 0; i < e.length; i++) { sum = expansion_product_add(sum, multByDouble(f, e[i])); } //return compress(sum); return sum; } //# sourceMappingURL=expansion-product.js.map ;// ./node_modules/big-float-ts/node/double-expansion/grow-expansion.js // We *have* to do the below❗ The assignee is a getter❗ The assigned is a pure function❗ const grow_expansion_compress = (/* unused pure expression or super */ null && (eCompress)); /** * Returns the result of adding a double to an expansion. * * Let e be a nonoverlapping expansion of m p-bit components, and let b be a * p-bit value where p >= 3. Suppose that the components e_1, ..., e_m are * sorted in order of *increasing* magnitude, except that any of the ei may be * zero. * Then the following algorithm will produce a nonoverlapping expansion such * that h = sum_i(h_i) = e + b, where the components h_1, ..., h_(m+1) are also * in order of increasing magnitude, except that any of the h_i may be zero. * Furthermore, if e is nonadjacent and round-to-even tiebreaking is used, then * h is nonadjacent. * See https://people.eecs.berkeley.edu/~jrs/papers/robustr.pdf * @param e A floating point expansion * @param b Another floating point expansion */ function growExpansion(e, b) { const m = e.length; let q = b; //const h: number[] = new Array(m+1); const h = []; //let j = 0; for (let i = 0; i < m; i++) { // Note the use of twoSum and not fastTwoSum. //[h[i], q] = ts(q, e[i]); const ee = e[i]; const x = q + ee; const bv = x - q; const hh = (q - (x - bv)) + (ee - bv); if (hh !== 0) { h.push(hh); } q = x; } //h[j] = q; if (q !== 0 || h.length === 0) { h.push(q); } //return compress(h); return h; } //# sourceMappingURL=grow-expansion.js.map ;// ./node_modules/big-float-ts/node/double-expansion/e-sign.js /** * Returns the sign of the given expansion such that a negative value means a * negative sign and a positive value means a positive sign, 0 meaning 0 of * course. * * * see [Shewchuk](https://people.eecs.berkeley.edu/~jrs/papers/robustr.pdf) * * From Shewchuk: "A nonoverlapping expansion is desirable because it is easy to * determine its sign (take the sign of the largest component) ... " * * @param e A floating point expansion with zeroes eliminated. */ function eSign(e) { return e[e.length - 1]; } //# sourceMappingURL=e-sign.js.map ;// ./node_modules/big-float-ts/node/double-expansion/e-compare.js /** * Returns 0 if a === b, a +tive value if a > b or a negative value if a < b. * * * see [Shewchuk](https://people.eecs.berkeley.edu/~jrs/papers/robustr.pdf) * * "The easiest way to compare two expansions is to subtract one from the other, * and test the sign of the result. An expansion’s sign can be easily tested * because of the nonoverlapping property; simply check the sign of the * expansion's most significant nonzero component..." * * @param a a floating point expansion * @param b another floating point expansion */ function eCompare(a, b) { return eSign(eDiff(a, b)); } //# sourceMappingURL=e-compare.js.map ;// ./node_modules/flo-bezier3/node/error-analysis/error-analysis.js const u = Number.EPSILON / 2; const uu = u * u; /** @internal */ function γ(n) { const nu = n * u; return nu / (1 - nu); } /** @internal */ function γγ(n) { const nuu = n * uu; return nuu / (1 - nuu); } γ(1); //=> 1.1102230246251568e-16 γγ(3); //=> 3.697785493223493e-32 //# sourceMappingURL=error-analysis.js.map ;// ./node_modules/flo-bezier3/node/global-properties/classification/is-really-point.js /** * Returns `true` if the given bezier curve has all control points coincident, * `false` otherwise. * * @param ps an order 0,1,2 or 3 bezier curve given as an array of its control * points, e.g. `[[0,0],[1,1],[2,1],[2,0]]` * * @doc */ function isReallyPoint(ps) { const x = ps[0][0]; const y = ps[0][1]; for (let i = 1; i < ps.length; i++) { if (x !== ps[i][0] || y !== ps[i][1]) { return false; } } return true; } //# sourceMappingURL=is-really-point.js.map ;// ./node_modules/big-float-ts/node/basic/two-sum.js /** * Returns the exact result of adding two doubles. * * * the resulting array is the reverse of the standard twoSum in the literature. * * Theorem 7 (Knuth): Let a and b be p-bit floating-point numbers. Then the * following algorithm will produce a nonoverlapping expansion x + y such that * a + b = x + y, where x is an approximation to a + b and y is the roundoff * error in the calculation of x. * * See https://people.eecs.berkeley.edu/~jrs/papers/robustr.pdf */ function basic_two_sum_twoSum(a, b) { const x = a + b; const bv = x - a; return [(a - (x - bv)) + (b - bv), x]; } // inlined //const R = a + b; const _ = R - a; const r = (a - (R - _)) + (b - _); return [r,R] //# sourceMappingURL=two-sum.js.map ;// ./node_modules/flo-bezier3/node/global-properties/classification/is-quad-really-line.js // We *have* to do the below❗ The assignee is a getter❗ The assigned is a pure function❗ const ediff = eDiff; const esign = eSign; const is_quad_really_line_ts = basic_two_sum_twoSum; const { abs } = Math; /** * Returns `true` if the given quadratic bezier curve is really a linear curve * (or a point), i.e. if all control points collinear *and* it can be converted * to an order 1 bezier curve (a line) such that the * same `(x,y)` point is returned for the same `t` value, `false` otherwise. * * * the required condition is met if: `x0 + x2 = 2*x1` and `y0 + y2 = 2*y1` * * **exact**: not susceptible to floating point round-off * * @param ps a quadratic bezier curve given as an array of its control * points, e.g. `[[1,2],[5,6],[7,8]]` * * @doc mdx */ function isQuadReallyLine(ps) { const [[x0, y0], [x1, y1], [x2, y2]] = ps; //if (x0 + x2 === 2*x1) && (y0 + y2 === 2*y1) // Calculate an approximation of the above with error bounds and use it as // a fast filter. const q = x0 + x2; const _q_ = abs(q); // the absolute error bound in q (after multipliciation by `u`) const w = q - 2 * x1; const w_ = _q_ + abs(w); // the absolute error bound in w // if w cannot possibly be zero, i.e. if the error is smaller than the value if (abs(w) - w_ > 0) { // fast filter passed return false; } const r = y0 + y2; const _r_ = abs(r); // the absolute error bound in r (after multipliciation by `u`) const z = r - 2 * y1; const z_ = _r_ + abs(z); // the absolute error bound in w // if the error is smaller than the value if (abs(z) - z_ > 0) { // fast filter passed return false; } // unable to filter - go slow and exact return (esign(ediff(is_quad_really_line_ts(x0, x2), [2 * x1])) === 0 && esign(ediff(is_quad_really_line_ts(y0, y2), [2 * y1])) === 0); } //# sourceMappingURL=is-quad-really-line.js.map ;// ./node_modules/big-float-ts/node/basic/two-product.js const two_product_f = 134217729; // 2**27 + 1; /** * Returns the exact result of multiplying two doubles. * * * the resulting array is the reverse of the standard twoSum in the literature. * * Theorem 18 (Shewchuk): Let a and b be p-bit floating-point numbers, where * p >= 6. Then the following algorithm will produce a nonoverlapping expansion * x + y such that ab = x + y, where x is an approximation to ab and y * represents the roundoff error in the calculation of x. Furthermore, if * round-to-even tiebreaking is used, x and y are non-adjacent. * * See https://people.eecs.berkeley.edu/~jrs/papers/robustr.pdf * @param a A double * @param b Another double */ function two_product_twoProduct(a, b) { const x = a * b; //const [ah, al] = split(a); const c = two_product_f * a; const ah = c - (c - a); const al = a - ah; //const [bh, bl] = split(b); const d = two_product_f * b; const bh = d - (d - b); const bl = b - bh; const y = (al * bl) - ((x - (ah * bh)) - (al * bh) - (ah * bl)); //const err1 = x - (ah * bh); //const err2 = err1 - (al * bh); //const err3 = err2 - (ah * bl); //const y = (al * bl) - err3; return [y, x]; } //# sourceMappingURL=two-product.js.map ;// ./node_modules/flo-bezier3/node/global-properties/classification/is-cubic-really-quad.js // We *have* to do the below❗ The assignee is a getter❗ The assigned is a pure function❗ const is_cubic_really_quad_tp = two_product_twoProduct; const fes = fastExpansionSum; const is_cubic_really_quad_esign = eSign; const is_cubic_really_quad_ediff = eDiff; const is_cubic_really_quad_u = Number.EPSILON / 2; const is_cubic_really_quad_abs = Math.abs; /** * Returns `true` if the given cubic bezier curve is really a quadratic (or * lower order) curve in disguise, i.e. it can be represent by a quadratic * bezier curve, `false` otherwise. * * * **exact**: not susceptible to floating point round-off * * @param ps an order 0,1,2 or 3 bezier curve given as an array of its control * points, e.g. `[[1,2],[3,4],[5,6],[7,8]]` * * @doc mdx */ function isCubicReallyQuad(ps) { const [[x0, y0], [x1, y1], [x2, y2], [x3, y3]] = ps; // The line below is unrolled (uses a toHybridQuadratic condition (points same?)) //if ((x3 + 3*x1) - (x0 + 3*x2) === 0 && // (y3 + 3*y1) - (y0 + 3*y2) === 0) { // Calculate an approximation of the above with error bounds and use it as // a fast filter. const u1 = 3 * x1; const u1_ = is_cubic_really_quad_abs(3 * x1); // the absolute error in u1 const u2 = x3 + u1; const u2_ = u1_ + is_cubic_really_quad_abs(u2); // the absolute error in u2 const v1 = 3 * x2; const v1_ = is_cubic_really_quad_abs(3 * x2); // the absolute error in v1 const v2 = x0 + v1; const v2_ = v1_ + is_cubic_really_quad_abs(v2); // the absolute error in v2 const w = u2 - v2; const w_ = u2_ + v2_ + is_cubic_really_quad_abs(w); // the absolute error in w // if w cannot possibly be zero, i.e. if the error is smaller than the value if (is_cubic_really_quad_abs(w) - is_cubic_really_quad_u * w_ > 0) { // fast filter 1 passed return false; } const q1 = 3 * y1; const q1_ = is_cubic_really_quad_abs(3 * y1); // the absolute error in q1 const q2 = y3 + q1; const q2_ = q1_ + is_cubic_really_quad_abs(q2); // the absolute error in q2 const r1 = 3 * y2; const r1_ = is_cubic_really_quad_abs(3 * y2); // the absolute error in r1 const r2 = y0 + r1; const r2_ = r1_ + is_cubic_really_quad_abs(r2); // the absolute error in r2 const s = q2 - r2; const s_ = q2_ + r2_ + is_cubic_really_quad_abs(s); // the absolute error in s if (is_cubic_really_quad_abs(s) - is_cubic_really_quad_u * s_ > 0) { // fast filter 2 passed return false; } // unable to filter - go slow and exact return (is_cubic_really_quad_esign(is_cubic_really_quad_ediff(fes([x3], is_cubic_really_quad_tp(3, x1)), fes([x0], is_cubic_really_quad_tp(3, x2)))) === 0 && is_cubic_really_quad_esign(is_cubic_really_quad_ediff(fes([y3], is_cubic_really_quad_tp(3, y1)), fes([y0], is_cubic_really_quad_tp(3, y2)))) === 0); } //# sourceMappingURL=is-cubic-really-quad.js.map ;// ./node_modules/big-float-ts/node/double-expansion/e-estimate.js /** * Returns the result of the given floating point expansion rounded to a double * floating point number. * * The result is within 1 ulps of the actual value, e.g. imagine the worst case * situation where we add (in 4dot4) 1111.1000 + 0.000011111111... The result * will be 1111.1000 whereas as the correct result should be 1111.1001 and we * thus lost 1 ulp of accuracy. It does not matter that the expansion contain * several floats since none is overlapping. * * See Shewchuk https://people.eecs.berkeley.edu/~jrs/papers/robustr.pdf * * @param e a floating point expansion */ function eEstimate(e) { let Q = e[0]; for (let i = 1; i < e.length; i++) { Q += e[i]; } return Q; } //# sourceMappingURL=e-estimate.js.map ;// ./node_modules/big-float-ts/node/basic/two-diff.js /** * Returns the exact result of subtracting b from a (as a floating point * expansion). * @param a * @param b */ function two_diff_twoDiff(a, b) { const x = a - b; const bvirt = a - x; const y = (a - (x + bvirt)) + (bvirt - b); return [y, x]; } //# sourceMappingURL=two-diff.js.map ;// ./node_modules/big-float-ts/node/double-expansion/e-compress.js /** * Returns the result of compressing the given floating point expansion. * * * primarily for internal library use * * * see [Shewchuk](https://people.eecs.berkeley.edu/~jrs/papers/robustr.pdf) * * Theorem 23 (Shewchuck): Let e = sum_(i=1)^m(e_i) be a nonoverlapping * expansion of m p-bit components, where m >= 3. Suppose that the components of * e are sorted in order of increasing magnitude, except that any of the e_i may * be zero. Then the following algorithm will produce a nonoverlapping expansion * (nonadjacent if round-to even tiebreaking is used) such that * h = sum_(i=1)^n(h_i) = e, where the components h_i are in order of increasing * magnitude. If h != 0, none of the h_i will be zero. Furthermore, the largest * component h_n approximates h with an error smaller than ulp(h_n). */ function e_compress_eCompress(e) { //return e; const e_ = e.slice(); const m = e_.length; if (m === 1) { return e_; } let Q = e_[m - 1]; let bottom = m; for (let i = m - 2; i >= 0; --i) { const a = Q; const b = e_[i]; Q = a + b; const bv = Q - a; const q = b - bv; if (q) { e_[--bottom] = Q; Q = q; } } let top = 0; for (let i = bottom; i < m; ++i) { const a = e_[i]; const b = Q; Q = a + b; const bv = Q - a; const q = b - bv; if (q) { e_[top++] = q; } } e_[top++] = Q; e_.length = top; return e_; } //# sourceMappingURL=e-compress.js.map ;// ./node_modules/big-float-ts/node/geometric-primitives/orient2d.js const ccwerrboundA = 3.330669073875472e-16; const ccwerrboundB = 2.220446049250315e-16; const ccwerrboundC = 1.109335647967049e-31; const resulterrbound = 3.330669073875471e-16; /** * * Ported from [Shewchuk](http://docs.ros.org/kinetic/api/asr_approx_mvbb/html/Predicates_8cpp_source.html) * * see also https://people.eecs.berkeley.edu/~jrs/papers/robustr.pdf * * * Adaptive exact 2d orientation test. * * * Robust. * * Return a positive value if the points pa, pb, and pc occur in * counterclockwise order; a negative value if they occur in clockwise order; * and zero if they are collinear. The result is also a rough approximation of * twice the signed area of the triangle defined by the three points. * * The result returned is the determinant of a matrix. This determinant is * computed adaptively, in the sense that exact arithmetic is used only to the * degree it is needed to ensure that the returned value has the correct sign. * Hence, orient2d() is usually quite fast, but will run more slowly when the * input points are collinear or nearly so. */ function orient2d(A, B, C) { const detleft = (A[0] - C[0]) * (B[1] - C[1]); const detright = (A[1] - C[1]) * (B[0] - C[0]); const det = detleft - detright; let detsum; if (detleft > 0) { if (detright <= 0) { // Anti-clockwise return det; } else { detsum = detleft + detright; } } else if (detleft < 0) { if (detright >= 0) { // Clockwise return det; } else { detsum = -detleft - detright; } } else { // Anti-clockwise, clockwise or straight return det; } if (Math.abs(det) >= ccwerrboundA * detsum) { // Anti-clockwise or clockwise return det; } return orient2dAdapt(A, B, C, detsum); } function orient2dAdapt(A, B, C, detsum) { const acx = A[0] - C[0]; const bcx = B[0] - C[0]; const acy = A[1] - C[1]; const bcy = B[1] - C[1]; const b = eDiff(two_product_twoProduct(acx, bcy), two_product_twoProduct(acy, bcx)); let det = eEstimate(b); if (Math.abs(det) >= ccwerrboundB * detsum) { // Anti-clockwise or clockwise return det; } const acxtail = two_diff_twoDiff(A[0], C[0])[0]; const bcxtail = two_diff_twoDiff(B[0], C[0])[0]; const acytail = two_diff_twoDiff(A[1], C[1])[0]; const bcytail = two_diff_twoDiff(B[1], C[1])[0]; if (acxtail === 0 && acytail === 0 && bcxtail === 0 && bcytail === 0) { // Straight return det; } const errbound = ccwerrboundC * detsum + resulterrbound * Math.abs(det); det += (acx * bcytail + bcy * acxtail) - (acy * bcxtail + bcx * acytail); if (Math.abs(det) >= errbound) { return det; } const a = eDiff(two_product_twoProduct(acxtail, bcy), two_product_twoProduct(acytail, bcx)); const c = fastExpansionSum(b, a); const d = eDiff(two_product_twoProduct(acx, bcytail), two_product_twoProduct(acy, bcxtail)); const e = fastExpansionSum(c, d); const f = eDiff(two_product_twoProduct(acxtail, bcytail), two_product_twoProduct(acytail, bcxtail)); let D = fastExpansionSum(e, f); D = e_compress_eCompress(D); return D[D.length - 1]; } //# sourceMappingURL=orient2d.js.map ;// ./node_modules/flo-bezier3/node/global-properties/classification/is-collinear.js // We *have* to do the below❗ The assignee is a getter❗ The assigned is a pure function❗ const is_collinear_orient2d = orient2d; /** * Returns `true` if the given bezier curve has all control points collinear, * `false` otherwise. * * * if you need to know whether a given bezier curve can be converted to an * order 1 bezier curve (a line) such that the same `(x,y)` point is returned * for the same `t` value then use e.g. [[isQuadReallyLine]] instead. * * * **exact** not susceptible to floating point round-off * * @param ps an order 0,1,2 or 3 bezier curve given as an array of its control * points, e.g. `[[1,2],[3,4],[5,6],[7,8]]` * * @doc mdx */ function isCollinear(ps) { if (ps.length === 4) { // Cubic bezier return (is_collinear_orient2d(ps[0], ps[1], ps[2]) === 0 && is_collinear_orient2d(ps[1], ps[2], ps[3]) === 0 && // The below check is necessary for if ps[1] === ps[2] is_collinear_orient2d(ps[0], ps[2], ps[3]) === 0); } if (ps.length === 3) { // Quadratic bezier return is_collinear_orient2d(ps[0], ps[1], ps[2]) === 0; } if (ps.length <= 2) { // Line (or point) return true; } throw new Error('The given bezier curve must be of order <= 3.'); } /** * Returns `true` if the given bezier curve has all control points the * same `y` value (possibly self-overlapping), `false` otherwise. * * @param ps An order 0, 1, 2 or 3 bezier curve. * * @doc */ function isHorizontal(ps) { const y = ps[0][1]; for (let i = 1; i < ps.length; i++) { if (ps[i][1] !== y) { return false; } } return true; } /** * Returns `true` if the given bezier curve has all control points the * same `x` value (possibly self-overlapping), `false` otherwise. * * @param ps An order 0, 1, 2 or 3 bezier curve. * * @doc */ function isVertical(ps) { const x = ps[0][0]; for (let i = 1; i < ps.length; i++) { if (ps[i][0] !== x) { return false; } } return true; } //# sourceMappingURL=is-collinear.js.map ;// ./node_modules/flo-bezier3/node/global-properties/classification/is-cubic-really-line.js // We *have* to do the below to improve performance with bundlers❗ The assignee is a getter❗ The assigned is a pure function❗ const sce = scaleExpansion; const is_cubic_really_line_ediff = eDiff; const is_cubic_really_line_ts = basic_two_sum_twoSum; const is_cubic_really_line_esign = eSign; /** * Returns `true` if the given bezier curve has all control points collinear * *and* it can be converted to an order 1 bezier curve (a line) such that the * same `(x,y)` point is returned for the same `t` value, `false` otherwise. * * * **exact**: not susceptible to floating point round-off * * @param ps a cubic bezier curve given as an array of its control * points, e.g. `[[1,2],[3,4],[5,6],[7,8]]` * * @doc mdx */ function isCubicReallyLine(ps) { // note: if cubic is really a quad then // x3 + 3*(x1 - x2) === x0 && // y3 + 3*(y1 - y2) === y0 if (!isCollinear(ps)) { return false; } const [p0, p1, p2, p3] = ps; const [x0, y0] = p0; const [x1, y1] = p1; const [x2, y2] = p2; const [x3, y3] = p3; // convert middle two control points to single quad point // [ // (3*(x1 + x2) - (x0 + x3)) / 4, // (3*(y1 + y2) - (y0 + y3)) / 4 // ] const qx1 = is_cubic_really_line_ediff(sce(is_cubic_really_line_ts(x1 / 4, x2 / 4), 3), is_cubic_really_line_ts(x0 / 4, x3 / 4)); const qy1 = is_cubic_really_line_ediff(sce(is_cubic_really_line_ts(y1 / 4, y2 / 4), 3), is_cubic_really_line_ts(y0 / 4, y3 / 4)); // is quad really line: // if (x0 + x2 === 2*x1) && (y0 + y2 === 2*y1) OR // if ((x0 + x2)/2 === x1) && ((y0 + y2)/2 === y1) return (is_cubic_really_line_esign(is_cubic_really_line_ediff(is_cubic_really_line_ts(x0 / 2, x3 / 2), qx1)) === 0 && is_cubic_really_line_esign(is_cubic_really_line_ediff(is_cubic_really_line_ts(y0 / 2, y3 / 2), qy1)) === 0); } //# sourceMappingURL=is-cubic-really-line.js.map ;// ./node_modules/flo-bezier3/node/to-power-basis/to-power-basis/double/to-power-basis-with-running-error.js const to_power_basis_with_running_error_abs = Math.abs; /** * Returns the power basis representation of a bezier curve of order cubic or * less including a coefficient-wise absolute error bound. * * * intermediate calculations are done in double precision * * the error bound need to be multiplied by `γ(1) === u/(1-u)` * where `u = Number.EPSILON/2` before use * * returns the resulting power basis x and y coordinate polynomials from * highest power to lowest, e.g. if `x(t) = at^2 + bt + c` * and `y(t) = dt^2 + et + f` then the result is returned * as `[[a,b,c],[d,e,f]]` * * @param ps an order 0,1,2 or 3 bezier curve given by an ordered array of its * control points, e.g. `[[0,0],[1,1],[2,1],[2,0]]` * * @doc */ function toPowerBasisWithRunningError(ps) { if (ps.length === 4) { return toPowerBasis3WithRunningError(ps); } if (ps.length === 3) { return toPowerBasis2WithRunningError(ps); } if (ps.length === 2) { return toPowerBasis1WithRunningError(ps); } if (ps.length === 1) { return toPowerBasis0WithRunningError(ps); } throw new Error('The given bezier curve must be of order <= 3.'); } /** @internal */ function toPowerBasis3WithRunningError(ps) { const [[x0, y0], [x1, y1], [x2, y2], [x3, y3]] = ps; // ---------------------------- // xx3 = (x3 - x0) + 3*(x1 - x2) // ---------------------------- const xa = x3 - x0; const _xa_ = to_power_basis_with_running_error_abs(xa); const xb = x1 - x2; const _xb_ = to_power_basis_with_running_error_abs(xb); const xc = 3 * xb; const xc_ = 6 * _xb_; // === 3*_xb_ + 3*abs(xc) const xx3 = xa + xc; const xx3_ = _xa_ + xc_ + to_power_basis_with_running_error_abs(xx3); // ---------------------------- // xx2 = 3*((x2 + x0) - 2*x1) // ---------------------------- const xd = x2 + x0; const _xd_ = to_power_basis_with_running_error_abs(xd); const xe = xd - 2 * x1; const _xe_ = _xd_ + to_power_basis_with_running_error_abs(xe); const xx2 = 3 * xe; const xx2_ = 6 * _xe_; // 3*_xe_ + abs(xx2) // ---------------------------- // xx1 = 3*(x1 - x0) // ---------------------------- const xg = x1 - x0; const _xg_ = to_power_basis_with_running_error_abs(xg); const xx1 = 3 * xg; const xx1_ = 6 * _xg_; // 3*_xg_ + abs(3*xg) // ------------------------------ // yy3 = (y3 - y0) + 3*(y1 - y2) // ------------------------------ const ya = y3 - y0; const _ya_ = to_power_basis_with_running_error_abs(ya); const yb = y1 - y2; const _yb_ = to_power_basis_with_running_error_abs(yb); const yc = 3 * yb; const yc_ = 6 * _yb_; // === 3*_yb_ + 3*abs(yc) const yy3 = ya + yc; const yy3_ = _ya_ + yc_ + to_power_basis_with_running_error_abs(yy3); // ---------------------------- // yy2 = 3*((y2 + y0) - 2*y1) // ---------------------------- const yd = y2 + y0; const _yd_ = to_power_basis_w