Skip to content

Instantly share code, notes, and snippets.

@skhokhlov
Created December 15, 2016 18:03
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save skhokhlov/66aa6254f930f98b2c917abaf63eecb9 to your computer and use it in GitHub Desktop.
Save skhokhlov/66aa6254f930f98b2c917abaf63eecb9 to your computer and use it in GitHub Desktop.
'use strict';
const X = [0.1, 0.5, 0.9, 1.3, 1.7];
const Y = [-2.3026, -0.69315, -0.10536, 0.26236, 0.53063];
const x = 0.8;
// const n = 3;
// var splines = new Array(X.length).fill({a:null,b:null,c:null,d:null,x:null});
var splines = [];
for (let i =0; i < X.length; i++){
splines.push({a:null,b:null,c:null,d:null,x:null});
}
function BuildSpline(x, y) {
// var splines = new Array(X.length).fill({a:null,b:null,c:null,d:null,x:null});
const n = x.length;
for (let i = 0; i<n; i++){
splines[i].x = x[i];
splines[i].a = y[i];
}
splines[0].c = splines[n-1].c = 0;
// Решение СЛАУ относительно коэффициентов сплайнов c[i] методом прогонки для трехдиагональных матриц
// Вычисление прогоночных коэффициентов - прямой ход метода прогонки
var alpha = new Array(n - 1).fill(0);
var beta = new Array(n - 1).fill(0);
for (var i = 1; i < n - 1; ++i) {
var hi = x[i] - x[i - 1];
var hi1 = x[i + 1] - x[i];
var A = hi;
var C = 2.0 * (hi + hi1);
var B = hi1;
var F = 6.0 * ((y[i + 1] - y[i]) / hi1 - (y[i] - y[i - 1]) / hi);
var z = (A * alpha[i - 1] + C);
alpha[i] = -B / z;
beta[i] = (F - A * beta[i - 1]) / z;
}
// Нахождение решения - обратный ход метода прогонки
for (var i = n - 2; i > 0; --i) {
splines[i].c = alpha[i] * splines[i + 1].c + beta[i];
}
// По известным коэффициентам c[i] находим значения b[i] и d[i]
for (var i = n - 1; i > 0; --i){
var hi = x[i] - x[i - 1];
splines[i].d = (splines[i].c - splines[i - 1].c) / hi;
splines[i].b = hi * (2.0 * splines[i].c + splines[i - 1].c) / 6.0 + (y[i] - y[i - 1]) / hi;
}
}
function Interpolate(x) {
if (splines == null)
{
return NaN; // Если сплайны ещё не построены - возвращаем NaN
}
const n = splines.length;
var s = {a:null,b:null,c:null,d:null,x:null};
if (x <= splines[0].x) // Если x меньше точки сетки x[0] - пользуемся первым эл-тов массива
{
s = splines[0];
}
else if (x >= splines[n - 1].x) // Если x больше точки сетки x[n - 1] - пользуемся последним эл-том массива
{
s = splines[n - 1];
}
else // Иначе x лежит между граничными точками сетки - производим бинарный поиск нужного эл-та массива
{
var i = 0;
var j = n - 1;
while (i + 1 < j)
{
var k = i + (j - i) / 2;
if (x <= splines[k].x)
{
j = k;
}
else
{
i = k;
}
}
s = splines[j];
}
var dx = x - s.x;
// Вычисляем значение сплайна в заданной точке по схеме Горнера (в принципе, "умный" компилятор применил бы схему Горнера сам, но ведь не все так умны, как кажутся)
return s.a + (s.b + (s.c / 2.0 + s.d * dx / 6.0) * dx) * dx;
}
BuildSpline(X,Y);
console.log(splines);
console.log(Interpolate(0.8));
@vlad1m1r0v
Copy link

Сергей, низкий вам поклон.

@rifttech
Copy link

Получается для splines[0] коффиценты splines[0].b и splines[0].d всегда null ?

     // По известным коэффициентам c[i] находим значения b[i] и d[i]
        for (var i = n - 1; i > 0; --i){
            var hi = x[i] - x[i - 1];
            splines[i].d = (splines[i].c - splines[i - 1].c) / hi;
            splines[i].b = hi * (2.0 * splines[i].c + splines[i - 1].c) / 6.0 + (y[i] - y[i - 1]) / hi;
        }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment