www.adobeshow.com
标签 Tag : 算法

三次样条插值法AS代码

<Category: ActionScript 2.0, ActionScript 3.0, Adobe, Flash> 发表评论

三次样条插值是在曲线拟合中用到得比较好得算法,根据的是曲线的光滑的必要条件:二阶导连续.
下面是主要的算法代码:

//===============三次样条插值======================================
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代码