ベジェ曲線を書いてみた。

curveToのように2つの点と1つでコントロールポイントで描くのではなく、イラストレイターみたいに1つの点と1つのコントロールポイントで描く方が扱いやすい。

 
 

そこで早速調べてみた。
http://ja.wikipedia.org/wiki/%E3%83%99%E3%82%B8%E3%82%A7%E6%9B%B2%E7%B7%9A
各点をn分割して、さらにその点をn分割していくようです。
なるほど。
早速、書いてみました。
  

 
[sourcecode language=”as3″]
package{
import com.bit101.components.*;
import flash.display.Graphics;
import flash.display.Shape;
import flash.display.Sprite;
import flash.display.MovieClip;
import flash.display.StageScaleMode;
import flash.display.StageAlign
import flash.events.Event;
import flash.events.MouseEvent;
public class FlashTest extends Sprite{
private var partitions:uint=30;
//
private var points:Sprite;
private var g:Graphics;
private var P0:MovieClip;
private var P1:MovieClip;
private var P2:MovieClip;
private var P3:MovieClip;
private var lines:Shape;
//
private var slider:HSlider;
private var sliderlabel:Label;
private var dragPoint:MovieClip;
//
private var mvx:Number;
private var mvy:Number;
private var preX:Number;
private var preY:Number;
public function FlashTest():void{
stage.align=StageAlign.TOP_LEFT;
stage.scaleMode=StageScaleMode.NO_SCALE;
slider = new HSlider(this, 3, 25);
slider.addEventListener(Event.CHANGE, sliderChange);
slider.value=partitions;
sliderlabel= new Label(this, 3, 35);
sliderlabel.text = String(partitions);
var btn:PushButton=new PushButton(this,3,3,"lines",btnClick);
//
points=new Sprite();
addChild(points);
P0=setPoints(0);
P1=setPoints(1);
P2=setPoints(2);
P3=setPoints(3);
//
lines=new Shape();
addChild(lines);
//
drowLines();
preX=mouseX;
preY=mouseY;
addEventListener(Event.ENTER_FRAME,ent);
}
private function btnClick(evt:Event):void{
lines.visible=!lines.visible;
}
private function sliderChange(evt:Event):void {
partitions=slider.value;
sliderlabel.text = String(slider.value);
}
private function ent(evt:Event):void{

mvx=mouseX-preX;
mvy=mouseY-preY;
drowLines();
preX=mouseX;
preY=mouseY;
}
private function drowLines():void{
var i:uint;
var lines_g:Graphics=lines.graphics;
lines_g.clear();
var g:Graphics=points.graphics;
g.clear();
g.lineStyle(1,0x00FF00);
g.moveTo(P0.x,P0.y);
g.lineTo(P1.x,P1.y);
g.endFill();
g.lineStyle(1,0x00FF00,0.3);
g.moveTo(P1.x,P1.y);
g.lineTo(P2.x,P2.y);
g.endFill();
g.lineStyle(1,0x00FF00);
g.moveTo(P2.x,P2.y);
g.lineTo(P3.x,P3.y);
g.endFill();
g.lineStyle(2,0x0000FF);
g.moveTo(P0.x,P0.y);
for(i=1;i<partitions;i++){
var cnt:Number=i/partitions;
var P4x:Number=P1.x*cnt+P0.x*(1-cnt);
var P4y:Number=P1.y*cnt+P0.y*(1-cnt);
var P5x:Number=P2.x*cnt+P1.x*(1-cnt);
var P5y:Number=P2.y*cnt+P1.y*(1-cnt);
var P6x:Number=P3.x*cnt+P2.x*(1-cnt);
var P6y:Number=P3.y*cnt+P2.y*(1-cnt);
lines_g.lineStyle(1,0xFF0000,0.1);
lines_g.moveTo(P4x,P4y);
lines_g.lineTo(P5x,P5y);
lines_g.lineTo(P6x,P6y);
var P7x:Number=P5x*cnt+P4x*(1-cnt);
var P7y:Number=P5y*cnt+P4y*(1-cnt);
var P8x:Number=P6x*cnt+P5x*(1-cnt);
var P8y:Number=P6y*cnt+P5y*(1-cnt);
lines_g.lineStyle(1,0xAAAA00,0.3);
lines_g.moveTo(P7x,P7y);
lines_g.lineTo(P8x,P8y);
var P9x:Number=P8x*cnt+P7x*(1-cnt);
var P9y:Number=P8y*cnt+P7y*(1-cnt);
g.lineTo(P9x,P9y);
}
g.lineTo(P3.x,P3.y);
}
private function setPoints(n:uint):MovieClip{
var mc:MovieClip=new MovieClip()
g=mc.graphics;
g.beginFill(0xCCCCCC);
g.drawCircle(0,0,5)
g.endFill();
points.addChild(mc);
//
mc.buttonMode=true;
//
mc.addEventListener(MouseEvent.MOUSE_DOWN,pointPress);
//
mc.x=stage.stageWidth*Math.random();
mc.y=stage.stageHeight*Math.random();
//
mc.flag=true;
var theta:Number=Math.PI*2*Math.random();
var v:Number=50+50*Math.random();
mc.vx=v*Math.cos(theta);
mc.vy=v*Math.sin(theta);
mc.addEventListener(Event.ENTER_FRAME,pointMove);
return mc;
}
//
private function pointMove(evt:Event):void{
var mc:MovieClip=evt.currentTarget as MovieClip
if(mc.flag){
mc.vx*=0.98;
mc.vy*=0.98;
mc.x+=mc.vx;
mc.y+=mc.vy;
if(mc.x<0){
mc.x=0;
mc.vx*=-1
}else if(mc.x>stage.stageWidth){
mc.x=stage.stageWidth
mc.vx*=-1
}
if(mc.y<0){
mc.y=0;
mc.vy*=-1
}else if(mc.y>stage.stageHeight){
mc.y=stage.stageHeight
mc.vy*=-1
}
}
}
private function pointPress(evt:Event):void{
dragPoint=evt.currentTarget as MovieClip;
dragPoint.flag=false;
dragPoint.startDrag();
stage.addEventListener(MouseEvent.MOUSE_UP,pointUp)
}
private function pointUp(evt:Event):void{
dragPoint.flag=true;
dragPoint.vx=mvx;
dragPoint.vy=mvy;
dragPoint.stopDrag();
stage.removeEventListener(MouseEvent.MOUSE_UP,pointUp)
}
}
}
[/sourcecode]

左上のlinesボタンで、補助線を消すことができます。
その下のスライダーで、分割数を変えることができます。
分割数を少なくすると、どのように描いているのかわかりやすいと思います。
あと計算順番が重要でした。

終点から点対称の位置に次の線のコントロールポイントを打てば、スムーズで連続的な曲線が引けそうです。

1 Comment

Comments are closed.