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

ラグランジュ補間法

式は
http://www.sist.ac.jp/~suganuma/kougi/other_lecture/SE/num/num.htm#7.1
のJava版を移植させていただきました。

あとは扱いやすいようにクラス化した感じです。
点が多いと酷いことになるので注意。

赤い玉はドラッグできます。
Get Adobe Flash player
by Hiiragi 10 Mar 2011
    Embed
/**
 * Copyright Hiiragi ( http://wonderfl.net/user/Hiiragi )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/cTzd
 */

package
{
    import flash.display.Sprite;
    import flash.display.Graphics;
    import flash.geom.Point;
    import flash.events.Event;
    
    /**
     * ラグランジュ補間法
     * @author Hiiragi
     * 
     * 式は
     * http://www.sist.ac.jp/~suganuma/kougi/other_lecture/SE/num/num.htm#7.1
     * のJava版を移植させていただきました。
     * 
     * あとは扱いやすいようにクラス化した感じです。
     * 点が多いと酷いことになるので注意。
     * 
     * 赤い玉はドラッグできます。
     */
    [SWF(width="465", height="465", frameRate="30", backgroundColor="0xFFFFFF")]
    public class Main extends Sprite
    {
        private var _dragPoints:Vector.<DragPoint>;
        
        public function Main()
        {
            
            _dragPoints = new Vector.<DragPoint>();
            
            _dragPoints.push(this.addChild(new DragPoint(50, 200)) as DragPoint);
            _dragPoints.push(this.addChild(new DragPoint(100, 100)) as DragPoint);
            _dragPoints.push(this.addChild(new DragPoint(200, 300)) as DragPoint);
            _dragPoints.push(this.addChild(new DragPoint(400, 50)) as DragPoint);
            _dragPoints.push(this.addChild(new DragPoint(440, 200)) as DragPoint);
            
            this.addEventListener(Event.ENTER_FRAME, onEnterFrameHandler);
        }
        
        private function onEnterFrameHandler(e:Event):void
        {
            var points:Vector.<Point> = new Vector.<Point>();
            var i:int;
            var len:int = _dragPoints.length;
            
            for (i = 0; i < len; i++)
            {
                points.push(_dragPoints[i].getPoint());
            }
            
            
            
            var vec:Vector.<Point> = MathEx.lagrangePolynomial(points, 30);
            len = vec.length;
            
            var g:Graphics = this.graphics;
            g.clear();
            g.lineStyle(1);
            g.moveTo(vec[0].x, vec[0].y);
            
            for (i = 1; i < len; i++)
            {
                g.lineTo(vec[i].x, vec[i].y);
            }
        }
    }
}

import flash.display.Sprite;
import flash.display.Graphics;
import flash.events.MouseEvent;


class DragPoint extends Sprite
{

    public function DragPoint(positionX:Number = 0, positionY:Number = 0):void
    {
        this.x = positionX;
        this.y = positionY;
        
        var g:Graphics = this.graphics;
        g.beginFill(0xFF0000, 0.5);
        g.drawCircle(0, 0, 8);
        g.endFill();
        
        this.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDownHandler);
        this.addEventListener(MouseEvent.MOUSE_UP, onMouseUpHandler);
    }
    
    private function onMouseDownHandler(e:MouseEvent):void
    {
        this.startDrag();
    }
    
    private function onMouseUpHandler(e:MouseEvent):void
    {
        this.stopDrag();
    }
    
    
    public function getPoint():Point
    {
        return new Point(this.x, this.y);
    }
}


import flash.geom.Point;

class MathEx extends Object
{
    
    public static function lagrangePolynomial(points:Vector.<Point>, splitCount:uint):Vector.<Point>
    {
        points.sort(xNumericAscending);
        
        var len:int = points.length - 1;
        var len2:int;
        
        var currentX:Number = points[0].x;
        var diffX:Number;
        
        var returnVec:Vector.<Point> = new Vector.<Point>();
        
        for (var i:int = 0; i < len; i++)
        {
            diffX = (points[i + 1].x - points[i].x) / splitCount;
            for (var j:int = 0; j < splitCount; j++)
            {
                var point:Point = new Point(currentX, lagrangePolynomialBase(points, currentX));
                returnVec.push(point);
                currentX += diffX;
            }
        }
        returnVec.push(points[points.length - 1]);
        
        return returnVec;
    }
    
    
    private static function lagrangePolynomialBase(points:Vector.<Point>, currentX:Number):Number
    {
        var s1:Number;
        var s2:Number;
        var y1:Number = 0.0;
        var i1:int;
        var i2:int;
        var n:int = points.length - 1;

        for (i1 = 0; i1 <= n; i1++)
        {
            s1 = 1.0;
            s2 = 1.0;
            
            for (i2 = 0; i2 <= n; i2++)
            {
                if (i2 != i1)
                {
                    s1 *= (currentX - points[i2].x);
                    s2 *= (points[i1].x - points[i2].x);
                }
            }
            
            y1 += points[i1].y * s1 / s2;
        }
        return y1;
    }
    
    public static function xNumericAscending(a1:Point, a2:Point):Number
    {
        if (a1.x > a2.x)
        {
            return 1;
        }
        else if (a1.x < a2.x)
        {
            return -1;
        }
        
        return 0;
    }
}