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

曲線補間

/**
 * Copyright umhr ( http://wonderfl.net/user/umhr )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/tfuX
 */

package  
{
    import com.bit101.components.CheckBox;
    import com.bit101.components.Label;
    import com.bit101.components.Slider;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.geom.Point;
    /**
     * ...
     * @author umhr
     */
    public class WonderflMain3 extends Sprite
    {
        [SWF(width = 465, height = 465, backgroundColor = 0xFFFFFF, frameRate = 30)]
        
        private var _pointList:Array/*Point*/ = [];
        private var _checkBoxList:Array/*CheckBox*/ = [];
        private var _circumscribedCurve:CircumscribedCurve;
        private var _inscribedCurve:InscribedCurve;
        private var _cubicCurve:CubicBezierCurve;
        private var _line:Line;
        private var _segmentLabel:Label;
        private var _randomLabel:Label;
        private var _tangentialLineLabel:Label;
        private var _segment:int = 5;
        private var _random:Number = 200;
        private var _tangentialLineRetio:Number = 0.33;
        public function WonderflMain3() 
        {
            init();
        }
        
        private function init():void 
        {
            
            _circumscribedCurve = new CircumscribedCurve(graphics);
            _inscribedCurve = new InscribedCurve(graphics);
            _cubicCurve = new CubicBezierCurve(graphics);
            _line = new Line(graphics);
            
            var segmentSlider:Slider = new Slider("horizontal", this, 230, 20, slider_change);
            segmentSlider.width = 220;
            segmentSlider.setSliderParams(4, 30, _segment);
            
            var randomSlider:Slider = new Slider("horizontal", this, 230, 55, randomSlider_change);
            randomSlider.width = 220;
            randomSlider.setSliderParams(0, 400, _random);
            
            var tangentialSlider:Slider = new Slider("horizontal", this, 230, 90, tangentialSlider_change);
            tangentialSlider.width = 220;
            tangentialSlider.setSliderParams(0, 2, _tangentialLineRetio);
            
            _segmentLabel = new Label(this, 230, 30, "Segments : " + _segment);
            _randomLabel = new Label(this, 230, 65, "Random : " + _random);
            _tangentialLineLabel = new Label(this, 230, 100, "TangentialLineRetio(for CubicBezierCurve) : " + _tangentialLineRetio);
            
            _checkBoxList[0] = new CheckBox(this, 25, 355, "Line", checkBox_click);
            _checkBoxList[0].selected = true;
            (_checkBoxList[0].getChildAt(2) as Label).textField.textColor = 0x888888;
            _checkBoxList[1] = new CheckBox(this, 25, 380, "QuadraticBezierCurve(Circumscribed)", checkBox_click);
            _checkBoxList[1].selected = true;
            (_checkBoxList[1].getChildAt(2) as Label).textField.textColor = 0xFF0000;
            _checkBoxList[2] = new CheckBox(this, 25, 405, "QuadraticBezierCurve(Inscribed)", checkBox_click);            
            _checkBoxList[2].selected = true;
            (_checkBoxList[2].getChildAt(2) as Label).textField.textColor = 0x0000FF;
            _checkBoxList[3] = new CheckBox(this, 25, 430, "CubicBezierCurve", checkBox_click);            
            _checkBoxList[3].selected = true;
            (_checkBoxList[3].getChildAt(2) as Label).textField.textColor = 0x00FF00;
            
            click(null);
            stage.addEventListener(MouseEvent.CLICK, click);
            //addEventListener(Event.ENTER_FRAME, enterFrame);
        }
        private function checkBox_click(e:Event):void 
        {
            var check:CheckBox = e.target as CheckBox;
        }
        
        private function tangentialSlider_change(e:Event):void 
        {
            _tangentialLineRetio = Number(e.target.value);
            _tangentialLineLabel.text = "TangentialLineRetio(for CubicBezierCurve) : " + _tangentialLineRetio;
            click(null);
        }
        
        private function randomSlider_change(e:Event):void 
        {
            _random = int(e.target.value);
            _randomLabel.text = "Random : " + _random;
            click(null);
        }
        
        private function slider_change(e:Event):void 
        {
            _segment = int(e.target.value);
            _segmentLabel.text = "Segments : " + _segment;
            click(null);
        }
        
        private function enterFrame(e:Event):void 
        {
            _pointList.length = Math.min(_pointList.length, 50);
            graphics.clear();
            _pointList.unshift(new Point(mouseX, mouseY));
            draw();
        }
        
        private function click(e:MouseEvent):void 
        {
            _pointList.length = 0;
            graphics.clear();
            
            var n:int = _segment;
            for (var i:int = 0; i < n; i++) 
            {
                var pt:Point = new Point();
                pt.x = (i / (n - 1)) * (449 - _random) + _random * Math.random() + 16 * 0.5;
                pt.y = (i / (n - 1)) * (449 - _random) + _random * Math.random() + 16 * 0.5;
                _pointList.unshift(pt);
            }
            
            draw();
        }
        private function draw():void {
            if(_checkBoxList[0].selected){
                _line.draw(_pointList);
            }
            if(_checkBoxList[1].selected){
                _circumscribedCurve.draw(_pointList);
            }
            if(_checkBoxList[2].selected){
                _inscribedCurve.draw(_pointList);
            }
            if(_checkBoxList[3].selected){
                _cubicCurve.draw(_pointList, _tangentialLineRetio);
            }
            
        }
    }

}
import flash.display.Graphics;
import flash.geom.Point;


class Line {
    private var _graphics:Graphics;
    public function Line(graphics:Graphics) {
        _graphics = graphics;
    }
    public function draw(pointList:Array/*Point*/):void 
    {
        var i:int;
        var n:int = pointList.length;
        if (n > 1) {
            var m:int = n;
            _graphics.lineStyle(0, 0x888888, 0.3);
            _graphics.moveTo(pointList[0].x, pointList[0].y);
            for (i = 0; i < m; i++) 
            {
                _graphics.lineTo(pointList[i].x, pointList[i].y);
            }
        }
        
        _graphics.lineStyle(0, 0x000000, 0.5);
        for (i = 0; i < n; i++) 
        {
            _graphics.drawCircle(pointList[i].x, pointList[i].y, 2);
        }
    }
}

// 2次ベジェ曲線(内接)
class InscribedCurve {
    private var _graphics:Graphics;
    public function InscribedCurve(graphics:Graphics) {
        _graphics = graphics;
    }
    public function draw(pointList:Array/*Point*/):void 
    {
        var n:int = pointList.length;
        if (n > 2) {
            var m:int = n - 2;
            for (var i:int = 0; i < m; i++) 
            {
                drawCurve(pointList[i], pointList[i + 1], pointList[i + 2], i == 0, i == (m - 1));
            }
        }
    }
    
    private function drawCurve(pt0:Point, pt1:Point, pt2:Point, isIn:Boolean, isOut:Boolean):void 
    {
        var p0:Point = new Point((pt1.x + pt0.x) * 0.5, (pt1.y + pt0.y) * 0.5);
        var p1:Point = new Point((pt1.x + pt2.x) * 0.5, (pt1.y + pt2.y) * 0.5);
        
        _graphics.lineStyle(0, 0x0000FF, 0.5);
        if (isIn) {
            _graphics.moveTo(pt0.x, pt0.y);
            _graphics.lineTo(p0.x, p0.y);
        }
        _graphics.moveTo(p0.x, p0.y);
        _graphics.curveTo(pt1.x, pt1.y, p1.x, p1.y);
        if (isOut) {
            _graphics.lineTo(pt2.x, pt2.y);
        }
    }
}

// 3次ベジェ曲線
class CubicBezierCurve {
    private var _graphics:Graphics;
    private var _tangentialLineLength:Number;
    public function CubicBezierCurve(graphics:Graphics) {
        _graphics = graphics;
    }
    public function draw(pointList:Array/*Point*/, tangentialLineLength:Number):void 
    {
        _tangentialLineLength = tangentialLineLength;
        var n:int = pointList.length;
        if (n > 3) {
            var m:int = n - 3;
            for (var i:int = 0; i < m; i++) 
            {
                drawLine(pointList[i], pointList[i + 1], pointList[i + 2], pointList[i + 3], i == 0, i == (m - 1));
            }
        }
    }
    
    private function drawLine(pt0:Point, pt1:Point, pt2:Point, pt3:Point, isIn:Boolean, isOut:Boolean):void 
    {
        var p1:Point = Calc.tangentialLine(pt0, pt1, pt2);
        var p2:Point = Calc.tangentialLine(pt3, pt2, pt1);
        
        var clossPoint:Point = Calc.getClossPoint(pt1, pt2, pt1.add(p1), pt2.add(p2));
        var cpt1:Point = clossPoint.subtract(pt1);
        var cpt2:Point = clossPoint.subtract(pt2);
        
        // 接線
        var length:Number = pt1.subtract(pt2).length * _tangentialLineLength;
        p1.normalize(length);
        p2.normalize(length);
        _graphics.lineStyle(0, 0x66FF66, 0.3);
        _graphics.moveTo(pt1.x, pt1.y);
        _graphics.lineTo(pt1.x + p1.x, pt1.y + p1.y);
        _graphics.lineStyle(0, 0x66FF66, 0.3);
        _graphics.moveTo(pt2.x, pt2.y);
        _graphics.lineTo(pt2.x + p2.x, pt2.y + p2.y);
        
        _graphics.lineStyle(0, 0x00FF00, 0.6);
        _graphics.moveTo(pt1.x, pt1.y);
        _graphics.cubicCurveTo(pt1.x + p1.x, pt1.y + p1.y, pt2.x + p2.x, pt2.y + p2.y, pt2.x, pt2.y);
        
        if(isIn){
            length = pt0.subtract(pt1).length * _tangentialLineLength;
            p1.normalize(length);
            _graphics.lineStyle(0, 0x00FF00, 0.6);
            _graphics.moveTo(pt0.x, pt0.y);
            _graphics.cubicCurveTo(pt0.x + (pt1.x - pt0.x) * _tangentialLineLength, pt0.y + (pt1.y - pt0.y) * _tangentialLineLength, pt1.x - p1.x, pt1.y - p1.y, pt1.x, pt1.y);
            _graphics.lineStyle(0, 0x66FF66, 0.3);
            _graphics.lineTo(pt1.x - p1.x, pt1.y - p1.y);
            _graphics.moveTo(pt0.x, pt0.y);
            _graphics.lineTo(pt0.x + (pt1.x - pt0.x) * _tangentialLineLength, pt0.y + (pt1.y - pt0.y) * _tangentialLineLength);
        }
        if (isOut) {
            length = pt2.subtract(pt3).length * _tangentialLineLength;
            p2.normalize(length);
            _graphics.lineStyle(0, 0x00FF00, 0.6);
            _graphics.moveTo(pt2.x, pt2.y);
            _graphics.cubicCurveTo(pt2.x - p2.x, pt2.y - p2.y, pt3.x + (pt2.x - pt3.x) * _tangentialLineLength, pt3.y + (pt2.y - pt3.y) * _tangentialLineLength, pt3.x, pt3.y);
            _graphics.lineStyle(0, 0x66FF66, 0.3);
            _graphics.lineTo(pt3.x + (pt2.x - pt3.x) * _tangentialLineLength, pt3.y + (pt2.y - pt3.y) * _tangentialLineLength);
            _graphics.moveTo(pt2.x, pt2.y);
            _graphics.lineTo(pt2.x - p2.x, pt2.y - p2.y);
        }
    }
    
    private function drawCurve(pt0:Point, clossPoint:Point, pt1:Point):void 
    {
        _graphics.moveTo(pt0.x, pt0.y);
        _graphics.curveTo(clossPoint.x, clossPoint.y, pt1.x, pt1.y);
    }    
    
    
}

// 2次ベジェ曲線(外接)
class CircumscribedCurve {
    private var _graphics:Graphics;
    public function CircumscribedCurve(graphics:Graphics) {
        _graphics = graphics;
    }
    public function draw(pointList:Array/*Point*/):void 
    {
        var n:int = pointList.length;
        if (n > 3) {
            var m:int = n - 3;
            for (var i:int = 0; i < m; i++) 
            {
                drawLine(pointList[i], pointList[i + 1], pointList[i + 2], pointList[i + 3], i == 0, i == (m - 1));
            }
        }
    }
    
    private function drawLine(pt0:Point, pt1:Point, pt2:Point, pt3:Point, isIn:Boolean, isOut:Boolean):void 
    {
        var p1:Point = Calc.tangentialLine(pt0, pt1, pt2);
        var p2:Point = Calc.tangentialLine(pt3, pt2, pt1);
        
        var clossPoint:Point = Calc.getClossPoint(pt1, pt2, pt1.add(p1), pt2.add(p2));
        var cpt1:Point = clossPoint.subtract(pt1);
        var cpt2:Point = clossPoint.subtract(pt2);
        
        if (p1.add(cpt1).length > p1.subtract(cpt1).length && p2.add(cpt2).length > p2.subtract(cpt2).length) {
            _graphics.lineStyle(0, 0xFF0000, 0.5);
            drawCurve(pt1, clossPoint, pt2);
            _graphics.lineStyle(0, 0xFF6666, 0.2);
            _graphics.moveTo(pt1.x, pt1.y);
            _graphics.lineTo(clossPoint.x, clossPoint.y);
            _graphics.lineTo(pt2.x, pt2.y);
        }else {
            var p1Radian:Number = Calc.angleBetween(p1, pt2.subtract(pt1));
            var p2Radian:Number = Calc.angleBetween(p2, pt1.subtract(pt2));
            var ratio:Number = p2Radian / (p1Radian + p2Radian);
            var radian:Number = (Math.atan2(p1.y, p1.x) + Math.atan2(p2.y, p2.x)) * 0.5;
            var apt:Point = new Point(pt1.x, pt1.y);
            var bpt:Point = new Point(pt1.x + p1.x * 30, pt1.y + p1.y * 30);
            var cpt:Point = new Point((pt1.x * ratio + pt2.x * (1 - ratio)), (pt1.y * ratio + pt2.y * (1 - ratio)));
            var dpt:Point = new Point((pt1.x * ratio + pt2.x * (1 - ratio)) + Math.cos(radian) * 20, (pt1.y * ratio + pt2.y * (1 - ratio)) + Math.sin(radian) * 20);
            
            var ept:Point = new Point(pt2.x, pt2.y);
            var fpt:Point = new Point(pt2.x + p2.x * 30, pt2.y + p2.y * 30);
            
            var c1Point:Point = Calc.getClossPoint(apt, cpt, bpt, dpt);
            var c2Point:Point = Calc.getClossPoint(ept, cpt, fpt, dpt);
            
            _graphics.lineStyle(0, 0xFF0000, 0.5);
            drawCurve(apt, c1Point, cpt);
            drawCurve(cpt, c2Point, ept);
            
            _graphics.lineStyle(0, 0xFF6666, 0.2);
            _graphics.moveTo(apt.x, apt.y);
            _graphics.lineTo(c1Point.x, c1Point.y);
            _graphics.lineTo(c2Point.x, c2Point.y);
            _graphics.lineTo(ept.x, ept.y);
            
        }
        var length:Number;
        var corner:Point;
        if (isIn) {
            length = pt0.subtract(pt1).length * 0.25;
            _graphics.lineStyle(0, 0xFF0000, 0.5);
            corner = new Point(pt1.x - p1.x * length, pt1.y - p1.y * length);
            drawCurve(pt0, corner, pt1);
            
            _graphics.lineStyle(0, 0xFF6666, 0.2);
            _graphics.moveTo(pt0.x, pt0.y);
            _graphics.lineTo(corner.x, corner.y);
            _graphics.lineTo(pt1.x, pt1.y);
        }
        if (isOut) {
            length = pt2.subtract(pt3).length * 0.25;
            _graphics.lineStyle(0, 0xFF0000, 0.5);
            corner = new Point(pt2.x - p2.x * length, pt2.y - p2.y * length)
            drawCurve(pt2, corner, pt3);
            
            _graphics.lineStyle(0, 0xFF6666, 0.2);
            _graphics.moveTo(pt2.x, pt2.y);
            _graphics.lineTo(corner.x, corner.y);
            _graphics.lineTo(pt3.x, pt3.y);
        }
    }
    
    private function drawCurve(pt0:Point, clossPoint:Point, pt1:Point):void 
    {
        _graphics.moveTo(pt0.x, pt0.y);
        _graphics.curveTo(clossPoint.x, clossPoint.y, pt1.x, pt1.y);
    }    
    
}


class Calc {
    public function Calc() {
        
    }
    
    static public function angleBetween(a:Point,b:Point):Number {
        return Math.acos((a.x * b.x + a.y * b.y) / (Math.sqrt(a.x * a.x + a.y * a.y) * Math.sqrt(b.x * b.x + b.y * b.y)));
    }

    // 折れた直線の接線のベクトルを求める
    static public function tangentialLine(point0:Point, point1:Point, point2:Point):Point 
    {
        var pt0:Point = point1.subtract(point0);
        var pt1:Point = point1.subtract(point2);
        
        pt0.normalize(1);
        pt1.normalize(1);
        
        return pt0.subtract(pt1);
    }
    
    // 4点からなる交点
    static public function getClossPoint(pa0:Point, pa1:Point, pb0:Point, pb1:Point):Point {
        var result:Point = new Point();
        var s0:Number = ((pb1.x - pa1.x) * (pa0.y - pa1.y) - (pb1.y - pa1.y) * (pa0.x - pa1.x)) * 0.5;
        var s1:Number = ((pb1.x - pa1.x) * (pa1.y - pb0.y) - (pb1.y - pa1.y) * (pa1.x - pb0.x)) * 0.5;
        result.x = pa0.x + (pb0.x - pa0.x) * (s0 / (s0 + s1));
        result.y = pa0.y + (pb0.y - pa0.y) * (s0 / (s0 + s1));
        return result;
    }
}