package { import flash.display.Sprite; import flash.geom.Point; import flash.events.Event; import flash.events.MouseEvent; import flash.text.TextField; /* * ベジェ曲線ってどういうふうに計算しているんだろう? * というのを確認したときに、絵で見てみたくなって作ったFlash。 * * 文章はこっち: * http://blog.livedoor.jp/takaaki_bb/archives/51352885.html */ [SWF(width="480", height="360", backgroundColor="#ffffff", frameRate=24)] public class TestBezier2 extends Sprite { private var pA:Point; // 始点のコントロールポイント private var pB:Point; // 始点のコントロールポイント private var pC:Point; // 終点のアンカーポイント private var pD:Point; // 終点のコントロールポイント private var pE:Point; // AB を t : 1 - t に内分する点 private var pF:Point; // BC を t : 1 - t に内分する点 private var pG:Point; // CD を t : 1 - t に内分する点 private var pH:Point; // EF を t : 1 - t に内分する点 private var pI:Point; // FG を t : 1 - t に内分する点 private var pJ:Point; // HI を t : 1 - t に内分する点 private var t:Number; private var curve:Array; // <Point> public function TestBezier2() { pA = new Point( 30, 240); pB = new Point(150, 80); pC = new Point(270, 50); pD = new Point(370, 200); curve = new Array(); t = 0; // いきなり再生されるのもあれなので、クリックされたら動かすようにした var tf:TextField = new TextField(); tf.text = "\n クリックして開始(ベジェ曲線を描きます)"; // ・・・ tf.width = 400; tf.height = 300; tf.selectable = false; addChild(tf); tf.addEventListener(MouseEvent.CLICK, function(e:MouseEvent):void { removeChild(tf); addEventListener(Event.ENTER_FRAME, calcBezier); removeEventListener(MouseEvent.CLICK, arguments.callee); }); } /* * ベジェ曲線の計算をする(現時点の t での座標を求める) */ private function calcBezier(e:Event):void { pE = getDividingPoint(pA, pB, t); pF = getDividingPoint(pB, pC, t); pG = getDividingPoint(pC, pD, t); pH = getDividingPoint(pE, pF, t); pI = getDividingPoint(pF, pG, t); pJ = getDividingPoint(pH, pI, t); curve.push(pJ); // いったん絵を消す graphics.clear(); // 線を引く graphics.lineStyle(1, 0xCCCCFF); graphics.moveTo(pA.x, pA.y); graphics.lineTo(pB.x, pB.y); graphics.lineTo(pC.x, pC.y); graphics.lineTo(pD.x, pD.y); graphics.lineStyle(1, 0xCCFFCC); graphics.moveTo(pE.x, pE.y); graphics.lineTo(pF.x, pF.y); graphics.lineTo(pG.x, pG.y); graphics.lineStyle(1, 0xFFCCCC); graphics.moveTo(pH.x, pH.y); graphics.lineTo(pI.x, pI.y); // 点を打つ graphics.lineStyle(0, 0, 0); graphics.beginFill(0x000000); graphics.drawCircle(pA.x, pA.y, 2); graphics.drawCircle(pB.x, pB.y, 2); graphics.drawCircle(pC.x, pC.y, 2); graphics.drawCircle(pD.x, pD.y, 2); graphics.endFill(); graphics.beginFill(0x0000FF); graphics.drawCircle(pE.x, pE.y, 2); graphics.drawCircle(pF.x, pF.y, 2); graphics.drawCircle(pG.x, pG.y, 2); graphics.endFill(); graphics.beginFill(0x00FF00); graphics.drawCircle(pH.x, pH.y, 2); graphics.drawCircle(pI.x, pI.y, 2); graphics.endFill(); graphics.beginFill(0xFF0000); graphics.drawCircle(pJ.x, pJ.y, 2); graphics.endFill(); // ratio 1.0 までいったら終わり if (t > 1.0) { e.target.removeEventListener(Event.ENTER_FRAME, arguments.callee); e.target.graphics.clear(); graphics.beginFill(0x000000); graphics.drawCircle(pA.x, pA.y, 1); graphics.drawCircle(pB.x, pB.y, 1); graphics.drawCircle(pC.x, pC.y, 1); graphics.drawCircle(pD.x, pD.y, 1); graphics.endFill(); } t += 0.005; // 出来た線を引く graphics.lineStyle(1, 0xFF0000, 1); graphics.moveTo(curve[0].x, curve[0].y); for (var i:int = 1; i < curve.length; i++) { graphics.lineTo(curve[i].x, curve[i].y); } } /* * p1 と p2 を t : 1 - t に内分する点を求める */ private function getDividingPoint(p1:Point, p2:Point, t:Number):Point { return new Point(p1.x + (p2.x - p1.x) * t, p1.y + (p2.y - p1.y) * t); } } } ベジェ曲線のアルゴリズム理解