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

SplineCurve

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

package {
    import flash.display.Sprite;
    import flash.display.Graphics;
    import flash.events.Event;
    
    import flash.geom.Point;
    
    [SWF(width = "465", height = "465", frameRate="60")]
    
    
    /**
     * ...
     * @author 
     */
    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() * 5 - 2.5, Math.random() * 5 - 2.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:Array = new Array();
            for ( i = 0; i < pnum; i++ )    array.push( ctrlp[i].pos );
            array = spline.Make( array );
            
            for ( i = 0; i < WIDTH; i++ )
            {
                var y:Number = spline.GetSplineValue( i, array );
                if ( i == 0 )    g.moveTo( i, y );
                else             g.lineTo( i, y );
            }
        }
    }
    
}

import flash.geom.Point;

    class ControlPoint {
        public var pos:Point;
        public var vec:Point;
    }


    /**
     * スプライン曲線を作成するクラス
     * @author 
     */
    class Spline
    {
        private var _z:Array;
                
        public function Spline() 
        {
        }
        
        /**
         * スプライン曲線を作成する
         * @param    p    Point型の制御点の位置を入れてある配列 (未ソートでOK)
         */
        public function Make( p:/*Point*/Array ) : Array
        {
            if ( !CheckControlPointType( p ) )    return p;
            
            var i:int;
            
            //    制御点をソートしる
            var len:int = p.length;            
            var sort:int = 0;
            for ( var a:int = 0; a < len - 1; a++ )
            {
                sort = 1;
                for ( var b:int = len-1; b > a; b-- )
                {
                    var pA:Point = p[b - 1];
                    var pB:Point = p[b];
                            
                    if( pA.x > pB.x )
                    {
                        var tmp:* = p[b];
                        p[b] = p[b - 1];
                        p[b - 1] = tmp;
                        sort = 0;
                    }
                }
                if ( sort != 0 ) break;
            }
            
            //    テーブルを作成する
            var N:int = p.length;
            var h:Array = new Array(N);
            var d:Array = new Array(N);
            _z = new Array(N);
            
            _z[0] = 0; _z[N - 1] = 0;
            for ( i = 0; i < N - 1; i++ )
            {
                h[i] =  p[i + 1].x - p[i].x;
                d[i + 1] =  (p[i + 1].y - p[i].y) / h[i];
            }
            
            _z[1] = d[2] - d[1] - h[0] * _z[0];
            d[1] = 2 * (p[2].x - p[0].x);
            
            var t:Number;
            for ( i = 1; i < N - 2; i++ )
            {
                t = h[i] / d[i];
                _z[i + 1] = d[i + 2] - d[i + 1] - _z[i] * t;
                d[i + 1] = 2 * (p[i + 2].x - p[i].x) - h[i] * t;
            }
            _z[N - 2] -= h[N - 2] * _z[N - 1];
            for ( i = N - 2; i > 0; i-- )
            {
                _z[i] = (_z[i] - h[i] * _z[i + 1]) / d[i];
            }
            
            return    p;
        }
        
        /**
         * 補間値を取得する
         * @param    t
         * @param    p
         * @return
         */
        public function GetSplineValue( t:Number, p:/*Point*/Array ) : Number
        {
            var i:int, j:int, k:int;
            var N:int = p.length;
            var h:Number, d:Number;
            
            i = 0; j = N - 1;
            while ( i < j ) {
                k = (i + j) / 2;
                if ( p[k].x < t )     i = k + 1;
                else                 j = k;
            }
            
            if ( i > 0 ) i--;
            h = p[i + 1].x - p[i].x;
            d = t - p[i].x;
            
            return    (((_z[i + 1] - _z[i]) * d / h + _z[i] * 3) * d
                    + ((p[i + 1].y - p[i].y) / h
                    - (_z[i] * 2 + _z[i + 1]) * h)) * d + p[i].y;
        }
        
        
        /**
         * 制御点のエラーチェック
         * @param    p
         * @return
         */
        private function CheckControlPointType( p:Array ) : Boolean
        {
            try {
                if( p == null )    throw new Error("*** Error Spline.as CheckControlPointType ***");
                var len:int = p.length;
                for ( var i:int = 0; i < len; i++ )
                {
                    if ( !(p[i] is Point) )    throw new Error("*** Error Spline.as CheckControlPointType ***");
                }
            }catch (e:Error)
            {
                trace(e.message);
                return    false;
            }
            return    true;
        }
        
    }