三次样条插值是在曲线拟合中用到得比较好得算法,根据的是曲线的光滑的必要条件:二阶导连续.
下面是主要的算法代码:
//===============三次样条插值======================================
function Hermite(arr:Array):Array
{
var history_arr:Array = new Array();
history_arr[0] = arr[1];
//trace(arr[1].y)
for (var i = 1; i<arr.length/3-1; i++) {
history_arr[i] = arr[i*3];
}
history_arr.push(arr[arr.length-1]);
var N:Number = history_arr.length;
//trace(N);
var M:Number = 3*N+3;
var H:Number = history_arr[N-1].x/M;
var x:Array = new Array();
var y:Array = new Array();
var f:Array = new Array();
var h:Array = new Array();
var a:Array = new Array();
var b:Array = new Array();
var A:Array = new Array();
var B:Array = new Array();
var m:Array = new Array();
var s:Array = new Array();
var xx:Array = new Array();
var record:Array = new Array();
var tmp:Array = new Array();
for (var i = 0; i<N; i++) {
x[i] = history_arr[i].x;
y[i] = history_arr[i].y;
h[i] = 0;
a[i] = 0;
b[i] = 0;
A[i] = 0;
B[i] = 0;
}
h[0] = x[1]-x[0];
a[0] = 1;
b[0] = 3*(y[1]-y[0])/h[0];
A[0] = -a[0]/2;
B[0] = b[0]/2;
for (var i = 1; i<N-1; i++) {
h[i] = x[i+1]-x[i];
}
for (var i = 1; i<N-1; i++) {
a[i] = h[i-1]/(h[i-1]+h[i]);
b[i] = 3*((1-a[i])*(y[i]-y[i-1])/h[i-1]+a[i]*(y[i+1]-y[i])/h[i]);
}
for (var i = 1; i<N-1; i++) {
A[i] = -a[i]/(2+(1-a[i])*A[i-1]);
B[i] = (b[i]-(1-a[i])*B[i-1])/(2+(1-a[i])*A[i-1]);
}
m[N-1] = (b[N-1]-(1-a[N-1])*B[N-2])/(2+(1-a[N-1])*A[N-2]);
for (var i = N-2; i>=0; i–) {
m[i] = A[i]*m[i+1]+B[i];
}
for (var k = 1; k<=M; k++) {
xx[k] = H*k;
for (var i = 0; i<N-1; i++) {
if (xx[k]>=x[i] && xx[k]<=x[i+1]) {
s[k] = (1+2*(xx[k]-x[i])/(x[i+1]-x[i]))*Math.pow((xx[k]-x[i+1])/(x[i]-x[i+1]), 2)*y[i]+(1+2*(xx[k]-x[i+1])/(x[i]-x[i+1]))*Math.pow((xx[k]-x[i])/(x[i+1]-x[i]), 2)*y[i+1]+(xx[k]-x[i])*Math.pow((xx[k]-x[i+1])/(x[i]-x[i+1]), 2)*m[i]+(xx[k]-x[i+1])*Math.pow((xx[k]-x[i])/(x[i+1]-x[i]), 2)*m[i+1];
record.push({hk:k, hs:s[k]});
}
}
}
for (var i = 0; i<record.length; i++) {
tmp.push({x:record[i].hk*H, y:record[i].hs});
}
for (var i = 0; i<history_arr.length; i++) {
tmp.push({x:history_arr[i].x, y:history_arr[i].y});
}
tmp.sortOn(["x"], [Array.NUMERIC]);
for (var i = 0; i<tmp.length; i++) {
//trace(“tmp["+i+"]:=”+tmp[i].x);
}
return tmp;
}
主要的思想是取一段不光滑曲线的若干个点,根据这些点生成一些插入点,然後根据这个插入点和取出的曲线的点连结起来,这样就能得到一条光滑的曲线了
这个函数我写的是一个单调增的,当然现实的情况不止是单调增这么简单,也有可能单调减或复合型的
本文来自: 三次样条插值法AS代码
