In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

SplineCurve2

参考書籍
C言語によるアルゴリズム事典
Get Adobe Flash player
by okoi 29 Mar 2011
    Embed
/**
 * Copyright okoi ( http://wonderfl.net/user/okoi )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/itsS
 */

package {
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.geom.Point;
    import flash.display.Graphics;
    
    [SWF(width = "465", height = "465", frameRate="60")]

    /**
     * ...
     * @author okoi
     */
    public class Main extends Sprite 
    {
        public static const WIDTH:int = 465;
        public static const HEIGHT:int = 465;

        private var ctrlp:/*ControlPoint*/Array;
        private var spline:Spline;
        
        public function Main():void 
        {
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init);
        }
        
        private function init(e:Event = null):void 
        {
            removeEventListener(Event.ADDED_TO_STAGE, init);
            // entry point
            ctrlp = new Array();
            for ( var i:int = 0; i < 5; i++ )
            {
                var p:ControlPoint = new ControlPoint();
                p.pos = new Point( Math.random() * WIDTH, Math.random() * HEIGHT );
                p.vec = new Point( Math.random() - 0.5, Math.random() - 0.5 );
                ctrlp.push( p );
            }
            
            spline = new Spline();
            
            addEventListener( Event.ENTER_FRAME, EnterFrameHandler );            
        }
        
        
        private function EnterFrameHandler( e:Event ) : void
        {
            var pnum:int = ctrlp.length;
            var i:int;
            for ( i = 0; i < pnum; i++ )
            {
                ctrlp[i].pos.x += ctrlp[i].vec.x;
                ctrlp[i].pos.y += ctrlp[i].vec.y;
                if ( ctrlp[i].pos.x < 0 )    ctrlp[i].pos.x = WIDTH + ctrlp[i].pos.x;
                else if ( ctrlp[i].pos.x > WIDTH )    ctrlp[i].pos.x = (ctrlp[i].pos.x % WIDTH);
                
                if ( ctrlp[i].pos.y < 0 )    ctrlp[i].pos.y = HEIGHT + ctrlp[i].pos.y;
                else if ( ctrlp[i].pos.y > HEIGHT )    ctrlp[i].pos.y = (ctrlp[i].pos.y % HEIGHT);
            }
            
            var g:Graphics = this.graphics;
            g.clear();
            g.lineStyle(1, 0);
            for ( i = 0; i < pnum; i++ )
            {
                g.drawCircle( ctrlp[i].pos.x, ctrlp[i].pos.y, 3 );
            }
            
            var array:/*Point*/Array = new Array();
            for ( i = 0; i < pnum; i++ )    array.push( ctrlp[i].pos );
            
            //    ソート
            var sort:int = 0;
            for ( var a:int = 0; a < pnum - 1; a++ )
            {
                sort = 1;
                for ( var b:int = pnum-1; b > a; b-- )
                {
                    var pA:Point = array[b - 1];
                    var pB:Point = array[b];
                            
                    if( pA.x > pB.x )
                    {
                        var tmp:* = array[b];
                        array[b] = array[b - 1];
                        array[b - 1] = tmp;
                        sort = 0;
                    }
                }
                if ( sort != 0 ) break;
            }
            spline.Make( array );
            
            var t:Number
            
            for ( t = array[0].x; t <= array[pnum-1].x; t+=0.1 )
            {
                var y:Number = spline.GetSplineValue( t );
                if ( t == array[0].x )    g.moveTo( t, y );
                else             g.lineTo( t, y );
            }
            
            /*
            for ( t = 0; t <= WIDTH; t+=0.1 )
            {
                var y:Number = spline.GetSplineValue( t );
                if ( t == 0 )    g.moveTo( t, y );
                else             g.lineTo( t, y );
            }
            */
        }        
    }
    
}

import flash.geom.Point;

class ControlPoint {
    public var pos:Point;
    public var vec:Point;
}
    
    /**
     * x[0..N] y[0..N] に与えたN+1個の点(xi,yi), x0 < x1 < ... < xN, y0 < y1 < ... < yN を
     * 周期 xN - x0 の周期関数で補間する
     * Makeで求める z:Array は各点での2次導関数の1/6にあたる
     * x = t での補間値は GetSplineValue で求める
     * @author okoi
     */
    class Spline
    {
        private var N:int;
        private var z:Array;
                
        private var x:Array;
        private var y:Array;
                
        public function Make( points:/*Point*/Array ) : void
        {
            var i:int;
            var t:Number;
            
            N = points.length - 1;
            
            z = new Array(N + 1);
            var h:Array = new Array(N + 1);
            var d:Array = new Array(N + 1);
            var w:Array = new Array(N + 1);
            
            x = new Array(N + 1);
            y = new Array(N + 1);
            
            for ( i = 0; i < points.length; i++ )
            {
                x[i] = points[i].x;
                y[i] = points[i].y;
            }
            
            for ( i = 0; i < N; i++ )
            {                                
                h[i] = x[i + 1] - x[i];
                w[i] = (y[i + 1] - y[i]) / h[i];
            }
            w[N] = w[0];
            for ( i = 1; i < N; i++ )
            {
                d[i] = 2 * (x[i + 1] - x[i - 1]);
            }
            d[N] = 2 * (h[N - 1] + h[0]);
            for ( i = 1; i <= N; i++ )
            {
                z[i] = w[i] - w[i - 1];
            }
            w[1] = h[0];
            w[N - 1] = h[N - 1];
            w[N] = d[N];
            for ( i = 2; i < N - 1; i++ )    w[i] = 0;
            for ( i = 1; i < N; i++ )
            {
                t = h[i] / d[i];
                z[i + 1] = z[i + 1] - z[i] * t;
                d[i + 1] = d[i + 1] - h[i] * t;
                w[i + 1] = w[i + 1] - w[i] * t;
            }
            w[0] = w[N];
            z[0] = z[N];
            for ( i = N - 2; i >= 0; i-- )
            {
                t = h[i] / d[i + 1];
                z[i] = z[i] - z[i + 1] * t;
                w[i] = w[i] - w[i + 1] * t;
            }
            
            t = z[0] / w[0];
            z[0] = t;
            z[N] = t;
            for ( i = 1; i < N; i++ )
            {
                z[i] = (z[i] - w[i] * t) / d[i];
            }
        }
        
        public function GetSplineValue( t:Number ) : Number
        {
            var i:int, j:int, k:int;
            var d:Number, h:Number, period:Number;
            
            period = x[N] - x[0];
            while ( t > x[N] ) t -= period;
            while ( t < x[0] ) t += period;
            
            i = 0; j = N;
            while ( i < j ) {
                k = (i + j) / 2;
                if ( x[k] < t ) i = k + 1;
                else             j = k;
            }
            if ( i > 0 ) i--;
            h = x[i + 1] - x[i];
            d = t - x[i];
            
            return    (((z[i + 1] - z[i]) * d / h + z[i] * 3) * d
                    + ((y[i + 1] - y[i]) / h
                    - (z[i] * 2 + z[i + 1]) * h)) * d + y[i];
        }
    }