3次のベジェ曲線
ベジェ曲線
マウスドラッグで制御点を移動
カーソルキー左右でパラメータtを移動
カーソルキー上下で「分離」「連結」「2次」のタイプの切り替え
参考:Wikipedia:ベジェ曲線
http://ja.wikipedia.org/wiki/%E3%83%99%E3%82%B8%E3%82%A7%E6%9B%B2%E7%B7%9A
// ベジェ曲線
// マウスドラッグで制御点を移動
// カーソルキー左右でパラメータtを移動
// カーソルキー上下で「分離」「連結」「2次」のタイプの切り替え
//
// 参考:Wikipedia:ベジェ曲線
// http://ja.wikipedia.org/wiki/%E3%83%99%E3%82%B8%E3%82%A7%E6%9B%B2%E7%B7%9A
//
package {
import flash.display.Sprite;
import flash.events.*;
[SWF(width="465", height="465", backgroundColor="0xFFFFFF", frameRate="60")]
public class FlashTest extends Sprite {
public function FlashTest() {
Main = this;
initialize();
stage.addEventListener(Event.ENTER_FRAME,update);
stage.addEventListener(KeyboardEvent.KEY_UP, keyCheckUp);
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyCheckDown);
stage.addEventListener(MouseEvent.MOUSE_UP, MouseCheckUp);
stage.addEventListener(MouseEvent.MOUSE_DOWN, MouseCheckDown);
}
}
}
import flash.display.Sprite;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.ui.Keyboard;
import flash.text.TextField;
import flash.geom.*;
var Main:Sprite;
var SCREEN_W:Number = 465;
var SCREEN_H:Number = 465;
var Text:TextField
var T:Number = 0.5;
var Mode:int = 0;
var Pnt:Vector.<ControlPoint> = new Vector.<ControlPoint>;
var Bezier2Ary:Vector.<Bezier2> = new Vector.<Bezier2>;
var Bezier3Ary:Vector.<Bezier3> = new Vector.<Bezier3>;
function initialize():void{
Text = new TextField();
Text.text = "----";
Text.autoSize = "left";
Main.addChild(Text);
graphicClear();
Pnt[0] = new ControlPoint( new Point(SCREEN_W/2-150, SCREEN_H/2) );
Pnt[1] = new ControlPoint( new Point(SCREEN_W/2-100, SCREEN_H/2-100) );
Pnt[2] = new ControlPoint( new Point(SCREEN_W/2+0, SCREEN_H/2-100) );
Pnt[3] = new ControlPoint( new Point(SCREEN_W/2+100, SCREEN_H/2) );
Pnt[4] = new ControlPoint( new Point(SCREEN_W/2+100, SCREEN_H/2+100) );
Pnt[5] = new ControlPoint( new Point(SCREEN_W/2+0, SCREEN_H/2+200) );
Pnt[6] = new ControlPoint( new Point(SCREEN_W/2-100, SCREEN_H/2+200) );
Bezier2Ary[0] = new Bezier2( Pnt[0], Pnt[1], Pnt[2] );
Bezier2Ary[1] = new Bezier2( Pnt[2], Pnt[3], Pnt[4] );
Bezier2Ary[2] = new Bezier2( Pnt[4], Pnt[5], Pnt[6] );
Bezier3Ary[0] = new Bezier3( Pnt[0], Pnt[1], Pnt[2], Pnt[3] );
Bezier3Ary[1] = new Bezier3( Pnt[3], Pnt[4], Pnt[5], Pnt[6] );
}
function update(e :Event):void{
graphicClear();
if( KeyData & KEY_LEFT ) T -= 0.01;
if( KeyData & KEY_RIGHT ) T += 0.01;
if( T < 0.0 ) T = 0.0;
if( T > 1.0 ) T = 1.0;
if( KeyData & KEY_UP_TRG ) Mode++;
if( KeyData & KEY_DOWN_TRG ) Mode--;
if( Mode > 3 ) Mode = 0;
if( Mode < 0 ) Mode = 3;
var i:int;
switch( Mode ){
case 0:
{
Text.text = "3次のベジェ曲線 t=" + Math.round( T*100 ) / 100;
Bezier3Ary[0].drawGuideLine( T );
Bezier3Ary[0].draw();
Bezier3Ary[0].drawPoint( T );
for( i=4; i<7; i++ ) Pnt[i].setEnable(false);
break;
}
case 1:
Text.text = "3次のベジェ曲線(分離) t=" + Math.round( T*100 ) / 100;
Bezier3Ary[0].drawGuideLine( T );
Bezier3Ary[0].draw();
Bezier3Ary[0].drawPoint( T );
Bezier3Ary[1].drawGuideLine( T );
Bezier3Ary[1].draw();
Bezier3Ary[1].drawPoint( T );
for( i=4; i<7; i++ ) Pnt[i].setEnable(true);
break;
case 2:
Text.text = "3次のベジェ曲線(連結) t=" + Math.round( T*100 ) / 100;
Bezier3Ary[0].drawGuideLine( T );
Bezier3Ary[0].draw();
Bezier3Ary[0].drawPoint( T );
Bezier3Ary[1].drawGuideLine( T );
Bezier3Ary[1].draw();
Bezier3Ary[1].drawPoint( T );
Pnt[4].setEnable(false);
Pnt[4].Sp.x = Pnt[3].Sp.x + Pnt[3].Sp.x - Pnt[2].Sp.x;
Pnt[4].Sp.y = Pnt[3].Sp.y + Pnt[3].Sp.y - Pnt[2].Sp.y;
break;
case 3:
Text.text = "2次のベジェ曲線 t=" + Math.round( T*100 ) / 100;
for each( var b2:Bezier2 in Bezier2Ary ){
b2.drawGuideLine( T );
b2.draw();
b2.drawPoint( T );
}
for( i=4; i<7; i++ ) Pnt[i].setEnable(true);
break;
case 4:
Mode = 0;
break;
}
updateKey();
}
class Bezier2{
public var Cp:Vector.<ControlPoint> = new Vector.<ControlPoint>;
public var DivNum:int = 60;
public var p4:Point=new Point(), p5:Point=new Point(), p6:Point=new Point();
public function Bezier2( p0:ControlPoint, p1:ControlPoint, p2:ControlPoint ){
Cp[0] = p0; Cp[1] = p1; Cp[2] = p2;;
}
public function draw():void{
var t:Number = 0;
var tAdd:Number = 1.0 / DivNum;
var pp:Point=new Point();
pp.x = Cp[0].Sp.x, pp.y = Cp[0].Sp.y;
for( var lp:int=0; lp<DivNum; lp++,t+=tAdd ){
getPosition( t );
drawLine( pp.x, pp.y, p6.x, p6.y, 1.0, 0x0000ff );
pp.x = p6.x;
pp.y = p6.y;
}
}
public function drawGuideLine( t:Number ):void{
for( var i:int=0; i<2; i++ ){
drawLine( Cp[i].Sp.x, Cp[i].Sp.y, Cp[i+1].Sp.x, Cp[i+1].Sp.y, 1.0, 0x00ff00 );
}
getPosition( t );
drawLine( p4.x, p4.y, p5.x, p5.y, 1.0, 0xf08000 );
drawLine( p5.x, p5.y, p6.x, p6.y, 1.0, 0xf08000 );
drawCircle( p4.x, p4.y, 0.5, 0x000000 );
drawCircle( p5.x, p5.y, 0.5, 0x000000 );
}
public function drawPoint( t:Number ):void{
getPosition( t );
drawCircle( p6.x, p6.y, 2.5, 0xff0000 );
}
public function getPosition( t:Number ):void{
p4.x = Cp[0].Sp.x + (Cp[1].Sp.x - Cp[0].Sp.x) * t;
p4.y = Cp[0].Sp.y + (Cp[1].Sp.y - Cp[0].Sp.y) * t;
p5.x = Cp[1].Sp.x + (Cp[2].Sp.x - Cp[1].Sp.x) * t;
p5.y = Cp[1].Sp.y + (Cp[2].Sp.y - Cp[1].Sp.y) * t;
p6.x = p4.x + (p5.x - p4.x) * t;
p6.y = p4.y + (p5.y - p4.y) * t;
}
}
class Bezier3{
public var Pnt:Vector.<ControlPoint> = new Vector.<ControlPoint>;
public var DivNum:int = 60;
public var p4_x:Number, p4_y:Number, p5_x:Number, p5_y:Number, p6_x:Number, p6_y:Number;
public var p7_x:Number, p7_y:Number, p8_x:Number, p8_y:Number, p9_x:Number, p9_y:Number;
public function Bezier3( p0:ControlPoint, p1:ControlPoint, p2:ControlPoint, p3:ControlPoint ){
Pnt[0] = p0; Pnt[1] = p1; Pnt[2] = p2; Pnt[3] = p3;
}
public function draw():void{
var t:Number = 0;
var tAdd:Number = 1.0 / DivNum;
var sp:Point = getPosition( 0.0 ), ep:Point;
for( var lp:int=tAdd; lp<DivNum; lp++,t+=tAdd ){
ep = getPosition( t );
drawLine( sp.x, sp.y, ep.x, ep.y, 1.0, 0x0000ff );
sp = ep;
}
}
public function drawGuideLine( t:Number ):void{
for( var i:int=0; i<3; i++ ){
drawLine( Pnt[i].Sp.x, Pnt[i].Sp.y, Pnt[i+1].Sp.x, Pnt[i+1].Sp.y, 1.0, 0x00ff00 );
}
getPosition( t );
drawLine( p4_x, p4_y, p5_x, p5_y, 1.0, 0xf08000 );
drawLine( p5_x, p5_y, p6_x, p6_y, 1.0, 0xf08000 );
drawLine( p7_x, p7_y, p8_x, p8_y, 1.0, 0xc0c000 );
drawCircle( p4_x, p4_y, 0.5, 0x000000 );
drawCircle( p5_x, p5_y, 0.5, 0x000000 );
drawCircle( p6_x, p6_y, 0.5, 0x000000 );
drawCircle( p7_x, p7_y, 0.5, 0x000000 );
drawCircle( p8_x, p8_y, 0.5, 0x000000 );
}
public function drawPoint( t:Number ):void{
getPosition( t );
drawCircle( p9_x, p9_y, 2.5, 0xff0000 );
}
public function getPosition( t:Number ):Point{
p4_x = Pnt[0].Sp.x + (Pnt[1].Sp.x - Pnt[0].Sp.x) * t;
p4_y = Pnt[0].Sp.y + (Pnt[1].Sp.y - Pnt[0].Sp.y) * t;
p5_x = Pnt[1].Sp.x + (Pnt[2].Sp.x - Pnt[1].Sp.x) * t;
p5_y = Pnt[1].Sp.y + (Pnt[2].Sp.y - Pnt[1].Sp.y) * t;
p6_x = Pnt[2].Sp.x + (Pnt[3].Sp.x - Pnt[2].Sp.x) * t;
p6_y = Pnt[2].Sp.y + (Pnt[3].Sp.y - Pnt[2].Sp.y) * t;
p7_x = p4_x + (p5_x - p4_x) * t;
p7_y = p4_y + (p5_y - p4_y) * t;
p8_x = p5_x + (p6_x - p5_x) * t;
p8_y = p5_y + (p6_y - p5_y) * t;
p9_x = p7_x + (p8_x - p7_x) * t;
p9_y = p7_y + (p8_y - p7_y) * t;
return new Point( p9_x, p9_y );
}
}
class ControlPoint{
public var Sp:Sprite;
public var isEnable:Boolean = false;
public var Pos:Point;
public function ControlPoint( p:Point ){
Sp=new Sprite();
Pos = p;
Sp.x = Pos.x;
Sp.y = Pos.y;
setEnable( true );
Main.stage.addChild(Sp);
Sp.addEventListener(MouseEvent.MOUSE_UP, function (event:MouseEvent):void{ Sp.stopDrag(); });
Sp.addEventListener(MouseEvent.MOUSE_DOWN, function (event:MouseEvent):void{ if( isEnable ) Sp.startDrag(); });
}
public function setEnable( flg:Boolean ):void{
if( flg == true && isEnable == false ){
Sp.graphics.clear();
Sp.graphics.lineStyle(1.4,0x000000);
Sp.graphics.beginFill(0xe0d000,1);
Sp.graphics.drawCircle(0,0,8.0);
Sp.graphics.endFill();
}else if( flg == false && isEnable == true ){
Sp.graphics.clear();
}
isEnable = flg;
}
}
function graphicClear():void{
Main.graphics.clear();
Main.graphics.lineStyle(1.2,0xb0b040);
Main.graphics.moveTo( SCREEN_W/2, 0 );
Main.graphics.lineTo( SCREEN_W/2, SCREEN_H );
Main.graphics.moveTo( 0, SCREEN_H/2 );
Main.graphics.lineTo( SCREEN_W, SCREEN_H/2 );
}
function drawLine( sx:Number, sy:Number, ex:Number, ey:Number, size:Number, col:int ):void{
Main.graphics.lineStyle(size,col);
Main.graphics.moveTo( sx, sy );
Main.graphics.lineTo( ex, ey );
}
function drawCircle( x:Number, y:Number, size:Number, col:int ):void{
Main.graphics.lineStyle(1.0,0x000000);
Main.graphics.beginFill( col, 1 );
Main.graphics.drawCircle( x, y, size );
Main.graphics.endFill();
}
var KEY_UP:int = 0x01;
var KEY_DOWN:int = 0x02;
var KEY_LEFT:int = 0x04;
var KEY_RIGHT:int = 0x08;
var KEY_UP_TRG:int = 0x10;
var KEY_DOWN_TRG:int = 0x20;
var KEY_LEFT_TRG:int = 0x40;
var KEY_RIGHT_TRG:int = 0x80;
var KeyData:int;
function keyCheckDown(event:KeyboardEvent):void {
switch (event.keyCode){
case Keyboard.UP: KeyData |= KEY_UP|KEY_UP_TRG; break;
case Keyboard.DOWN: KeyData |= KEY_DOWN|KEY_DOWN_TRG; break;
case Keyboard.LEFT: KeyData |= KEY_LEFT|KEY_LEFT_TRG; break;
case Keyboard.RIGHT: KeyData |= KEY_RIGHT|KEY_RIGHT_TRG; break;
}
}
function keyCheckUp(event:KeyboardEvent):void {
switch (event.keyCode){
case Keyboard.UP: KeyData &= ~KEY_UP; break;
case Keyboard.DOWN: KeyData &= ~KEY_DOWN; break;
case Keyboard.LEFT: KeyData &= ~KEY_LEFT; break;
case Keyboard.RIGHT: KeyData &= ~KEY_RIGHT; break;
}
}
function updateKey():void{
KeyData &= ~(KEY_UP_TRG|KEY_DOWN_TRG|KEY_LEFT_TRG|KEY_RIGHT_TRG);
}
var MOUSE_LEFT:int = 0x01;
var MOUSE_LEFT_TRG:int = 0x02;
var MouseData:int;
function MouseCheckDown(event:MouseEvent):void{
MouseData |= MOUSE_LEFT;
MouseData |= MOUSE_LEFT_TRG;
}
function MouseCheckUp(event:MouseEvent):void{
MouseData &= ~MOUSE_LEFT;
}
function MouseUpdate():void{
MouseData &= ~MOUSE_LEFT_TRG;
}