forked from: 曲線補間
cubicCurveTo() は FlashPlayer11以降
/**
* Copyright tsu_droid ( http://wonderfl.net/user/tsu_droid )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/4IoG
*/
// from http://wonderfl.net/c/tfuX
package {
import flash.display.*;
import flash.events.*;
import flash.geom.*;
import com.bit101.components.*;
public class WonderflMain3_02 extends MovieClip{
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_02(){
init();
}
public 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(evt:Event):void {
var check:CheckBox = evt.target as CheckBox;
}
private function tangentialSlider_change(evt:Event):void {
_tangentialLineRetio = Number(evt.target.value);
_tangentialLineLabel.text = "TangentialLineRetio(for CubicBezierCurve) : " + _tangentialLineRetio;
_click(null);
}
private function randomSlider_change(evt:Event):void {
_random = int(evt.target.value);
_randomLabel.text = "Random : " + _random;
_click(null);
}
private function slider_change(evt:Event):void {
_segment = int(evt.target.value);
_segmentLabel.text = "Segments : " + _segment;
_click(null);
}
private function enterFrame(evt:Event):void {
_pointList.length = Math.min(_pointList.length, 50);
graphics.clear();
_pointList.unshift(new Point(mouseX, mouseY));
draw();
}
private function _click(evt:MouseEvent):void {
_pointList.length = 0;
graphics.clear();
var nn:int = _segment;
for (var ii:int = 0; ii < nn; ii++){
var pt:Point = new Point();
pt.x = (ii / (nn - 1)) * (449 - _random) + _random * Math.random() + 16 * 0.5;
pt.y = (ii / (nn - 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.*;
import flash.geom.*;
class Line {
private var _graphics:Graphics;
public function Line(graphics:Graphics) {
_graphics = graphics;
}
public function draw(pointList:Array/*Point*/):void {
var ii:int;
var nn:int = pointList.length;
if (nn > 1){
var mm:int = nn;
_graphics.lineStyle(0, 0x888888, 0.3);
_graphics.moveTo(pointList[0].x, pointList[0].y);
for (ii = 0; ii < mm; ii++) {
_graphics.lineTo(pointList[ii].x, pointList[ii].y);
}
}
_graphics.lineStyle(0, 0x000000, 0.5);
for (ii = 0; ii < nn; ii++) {
_graphics.drawCircle(pointList[ii].x, pointList[ii].y, 2);
}
}
}
// 2次ベジェ曲線(内接)
class InscribedCurve {
private var _graphics:Graphics;
public function InscribedCurve(graphics:Graphics) {
_graphics = graphics;
}
public function draw(pointList:Array/*Point*/):void{
var nn:int = pointList.length;
if (nn > 2) {
var mm:int = nn - 2;
for (var ii:int = 0; ii < mm; ii++) {
drawCurve(pointList[ii], pointList[ii + 1], pointList[ii + 2], ii == 0, ii == (mm - 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 nn:int = pointList.length;
if (nn > 3) {
var mm:int = nn - 3;
for (var ii:int = 0; ii < mm; ii++) {
drawLine(pointList[ii], pointList[ii + 1], pointList[ii + 2], pointList[ii + 3], ii == 0, ii == (mm - 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 nn:int = pointList.length;
if (nn > 3) {
var mm:int = nn - 3;
for (var ii:int = 0; ii < mm; ii++) {
drawLine(pointList[ii], pointList[ii + 1], pointList[ii + 2], pointList[ii + 3], ii == 0, ii == (mm - 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(aa:Point, bb:Point):Number {
return Math.acos((aa.x * bb.x + aa.y * bb.y) / (Math.sqrt(aa.x * aa.x + aa.y * aa.y) * Math.sqrt(bb.x * bb.x + bb.y * bb.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;
}
}