UNPKG

typescript-cubic-spline

Version:
129 lines (128 loc) 4.01 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var Spline = /** @class */ (function () { function Spline(xs, ys) { this.xs = xs; this.ys = ys; this.ks = this.getNaturalKs(new Float64Array(this.xs.length)); } Spline.prototype.getNaturalKs = function (ks) { var n = this.xs.length - 1; var A = zerosMat(n + 1, n + 2); for (var i = 1; i < n; i++ // rows ) { A[i][i - 1] = 1 / (this.xs[i] - this.xs[i - 1]); A[i][i] = 2 * (1 / (this.xs[i] - this.xs[i - 1]) + 1 / (this.xs[i + 1] - this.xs[i])); A[i][i + 1] = 1 / (this.xs[i + 1] - this.xs[i]); A[i][n + 1] = 3 * ((this.ys[i] - this.ys[i - 1]) / ((this.xs[i] - this.xs[i - 1]) * (this.xs[i] - this.xs[i - 1])) + (this.ys[i + 1] - this.ys[i]) / ((this.xs[i + 1] - this.xs[i]) * (this.xs[i + 1] - this.xs[i]))); } A[0][0] = 2 / (this.xs[1] - this.xs[0]); A[0][1] = 1 / (this.xs[1] - this.xs[0]); A[0][n + 1] = (3 * (this.ys[1] - this.ys[0])) / ((this.xs[1] - this.xs[0]) * (this.xs[1] - this.xs[0])); A[n][n - 1] = 1 / (this.xs[n] - this.xs[n - 1]); A[n][n] = 2 / (this.xs[n] - this.xs[n - 1]); A[n][n + 1] = (3 * (this.ys[n] - this.ys[n - 1])) / ((this.xs[n] - this.xs[n - 1]) * (this.xs[n] - this.xs[n - 1])); return solve(A, ks); }; /** * inspired by https://stackoverflow.com/a/40850313/4417327 */ Spline.prototype.getIndexBefore = function (target) { var low = 0; var high = this.xs.length; var mid = 0; while (low < high) { mid = Math.floor((low + high) / 2); if (this.xs[mid] < target && mid !== low) { low = mid; } else if (this.xs[mid] >= target && mid !== high) { high = mid; } else { high = low; } } return low + 1; }; Spline.prototype.at = function (x) { var i = this.getIndexBefore(x); var t = (x - this.xs[i - 1]) / (this.xs[i] - this.xs[i - 1]); var a = this.ks[i - 1] * (this.xs[i] - this.xs[i - 1]) - (this.ys[i] - this.ys[i - 1]); var b = -this.ks[i] * (this.xs[i] - this.xs[i - 1]) + (this.ys[i] - this.ys[i - 1]); var q = (1 - t) * this.ys[i - 1] + t * this.ys[i] + t * (1 - t) * (a * (1 - t) + b * t); return q; }; return Spline; }()); function solve(A, ks) { var m = A.length; var h = 0; var k = 0; while (h < m && k <= m) { var i_max = 0; var max = -Infinity; for (var i = h; i < m; i++) { var v_1 = Math.abs(A[i][k]); if (v_1 > max) { i_max = i; max = v_1; } } if (A[i_max][k] === 0) { k++; } else { swapRows(A, h, i_max); for (var i = h + 1; i < m; i++) { var f = A[i][k] / A[h][k]; A[i][k] = 0; for (var j = k + 1; j <= m; j++) A[i][j] -= A[h][j] * f; } h++; k++; } } for (var i = m - 1; i >= 0; i-- // rows = columns ) { var v = 0; if (A[i][i]) { v = A[i][m] / A[i][i]; } ks[i] = v; for (var j = i - 1; j >= 0; j-- // rows ) { A[j][m] -= A[j][i] * v; A[j][i] = 0; } } return ks; } function zerosMat(r, c) { var A = []; for (var i = 0; i < r; i++) A.push(new Float64Array(c)); return A; } function swapRows(m, k, l) { var p = m[k]; m[k] = m[l]; m[l] = p; } exports.default = Spline;