2次ベジェの分割
...
@author Motoki Matsumoto
/**
* Copyright mtok ( http://wonderfl.net/user/mtok )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/jc2x
*/
package
{
import flash.display.GradientType;
import flash.geom.Point;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.display.Graphics;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import com.bit101.components.HSlider;
import com.bit101.components.Label;
/**
* ...
* @author Motoki Matsumoto
*/
public class SpliteBezier extends Sprite
{
private var _bg:Sprite;
private var _canvas:Sprite;
private var _bezier:Bezier;
private var p0:Pointer;
private var p1:Pointer;
private var p2:Pointer;
private var _p:Pointer;
private var _slider1:HSlider;
private var _label1:Label;
private var _slider2:HSlider;
private var _label2:Label;
public function SpliteBezier()
{
addEventListener(Event.ADDED_TO_STAGE, addedToStage);
addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
}
private function mouseDownHandler(e:MouseEvent):void
{
var p:Pointer = e.target as Pointer;
if (p) {
addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
_p = p;
}
}
private function mouseMoveHandler(e:MouseEvent):void
{
if (e.buttonDown) {
_p.x = mouseX;
_p.y = mouseY;
stage.invalidate();
}else {
removeEventListener(e.type, arguments.callee);
}
}
private function renderHandler(e:Event):void
{
redraw();
}
private function addedToStage(e:Event):void
{
removeEventListener(Event.ADDED_TO_STAGE, addedToStage);
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
addChild(_bg = new Sprite());
_bg.graphics.beginFill(0xffffff);
_bg.graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
_bg.graphics.endFill();
addChild(_canvas = new Sprite());
addEventListener(Event.RENDER, renderHandler);
addChild(p0 = new Pointer( 10, 10));
addChild(p1 = new Pointer( 10, 300));
addChild(p2 = new Pointer( 300, 300));
_bezier = new Bezier(p0.getPos(), p1.getPos(), p2.getPos());
buildUI();
stage.invalidate();
}
private function buildUI():void {
_label1 = new Label(this, 10, 400, "0.5");
_label1.autoSize = false;
_label1.setSize(80, 20);
_slider1 = new HSlider(this, _label1.x + 50, 400, function():void {
var v:Number = _slider1.value;
_label1.text = String(round(v));
stage.invalidate();
});
_slider1.setSize(100, 20);
_slider1.setSliderParams(0, 1, 0.5);
_label2 = new Label(this, _slider1.x + _slider1.width + 10, 400, "0.5");
_label2.autoSize = false;
_label2.setSize(80, 20);
_slider2 = new HSlider(this, _label2.x + 50, 400, function():void {
var v:Number = _slider2.value;
_label2.text = String(round(v));
stage.invalidate();
});
_slider2.setSize(100, 20);
_slider2.setSliderParams(0, 1, 0.5);
}
private function round(v:Number):Number {
return Math.round(v * 100)/100;
}
private function redraw():void {
var g:Graphics = _canvas.graphics;
g.clear();
g.lineStyle(1, 0x555555);
_bezier.setVertex(p0.getPos(), p1.getPos(), p2.getPos());
_bezier.draw(g);
g.lineStyle(1,0xff0000);
g.moveTo(p0.x, p0.y);
g.lineTo(p1.x, p1.y);
g.lineTo(p2.x, p2.y);
var v1:Number = _slider1.value;
var v2:Number = _slider2.value;
plotLine(g, v1, 0xffff00);
plotLine(g, v2, 0xff00ff);
plotPoint(g, _bezier.getPos(v1));
plotPoint(g, _bezier.getPos(v2));
var b:Bezier = _bezier.split(v1, v2);
if (b) {
g.lineStyle(4, 0xcc33cc);
b.draw(g);
plotPoint(g, b.p1, 4, 0x0f0fff);
}
}
private function plotLine(g:Graphics, t:Number, color:uint):void {
var pt0:Vertex = new Vertex();
var pt1:Vertex = new Vertex();
g.lineStyle(1, color);
pt0.x = (1 - t) * p0.x + t * p1.x;
pt0.y = (1 - t) * p0.y + t * p1.y;
plotPoint(g, pt0, 2, color);
pt1.x = (1 - t) * p1.x + t * p2.x;
pt1.y = (1 - t) * p1.y + t * p2.y;
plotPoint(g, pt1, 2, color);
_plotLine(g, pt0, pt1);
}
private function _plotLine(g:Graphics, p1:Vertex, p2:Vertex):void {
g.moveTo(p1.x, p1.y);
g.lineTo(p2.x, p2.y);
}
private function plotPoint(g:Graphics, p:Vertex, r:Number = 3, color:uint = 0xcccccc):void {
g.beginFill(color);
g.drawCircle(p.x, p.y, r);
g.endFill();
}
}
}
import flash.display.Sprite;
import flash.display.Graphics;
import flash.geom.Point;
class Bezier {
private var _p0:Vertex;
private var _p1:Vertex;
private var _p2:Vertex;
public function Bezier(p0:Vertex, p1:Vertex, p2:Vertex) {
_p0 = p0;
_p1 = p1;
_p2 = p2;
}
public function draw(g:Graphics):void {
g.moveTo(_p0["x"], _p0["y"]);
g.curveTo(_p1["x"], _p1["y"], _p2["x"], _p2["y"]);
}
public function split(t0:Number, t1:Number):Bezier {
if (t0 == t1) {
return null;
}
var p1:Vertex = getPos(t0);
var p2:Vertex = getPos(t1);
var ctrl:Vertex;
ctrl = _p0.lerp(_p1, t0).lerp(_p1.lerp(_p2,t0), t1);
return new Bezier(p1, ctrl, p2);
}
public function setVertex(p0:Vertex, p1:Vertex, p2:Vertex):void {
_p0 = p0;
_p1 = p1;
_p2 = p2;
}
public function getPos(t:Number):Vertex {
return new Vertex(_getValue(t, "x"), _getValue(t, "y"));
}
public function getX(t:Number):Number{
return _getValue(t, "x");
}
public function getY(t:Number):Number {
return _getValue(t, "y");
}
private function _getValue(t:Number, axis:String):Number {
var _t:Number = 1 - t;
return _t * (_t * _p0[axis] + 2 * t * _p1[axis]) + t * t * _p2[axis];
}
public function get p0():Vertex { return _p0; }
public function set p0(value:Vertex):void
{
_p0 = value;
}
public function get p1():Vertex { return _p1; }
public function set p1(value:Vertex):void
{
_p1 = value;
}
public function get p2():Vertex { return _p2; }
public function set p2(value:Vertex):void
{
_p2 = value;
}
}
class Vertex {
public var x:Number;
public var y:Number;
public function Vertex(x:Number = 0, y:Number = 0) {
this.x = x;
this.y = y;
}
public function lerp(v:Vertex, t:Number):Vertex {
var s:Number = 1 - t;
return new Vertex(s*x + t*v.x, s*y + t*v.y);
}
}
class Pointer extends Sprite{
public function Pointer(x:Number = 0, y:Number = 0 ) {
var g:Graphics = this.graphics;
g.beginFill(0xcccccc);
g.drawCircle(0, 0, 8);
g.endFill();
this.x = x;
this.y = y;
}
public function getPos():Vertex {
return new Vertex(x, y);
}
}