C曲線 (Levy C curve)
C曲線(Levy c curve)を描く
@author H.Horiuchi
/**
* Copyright Horiuchi_H ( http://wonderfl.net/user/Horiuchi_H )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/tmnw
*/
package
{
import flash.display.Graphics;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Point;
import flash.text.AntiAliasType;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormat;
[SWF(width = 465, height = 465, frameRate = 30, backgroundColor = "#000000")]
/**
* C曲線(Levy c curve)を描く
* @author H.Horiuchi
*/
public class Main extends Sprite
{
private var counter_:int = 10;
private var counterField_:TextField = new TextField();
private var cachePoints_:Vector.<Vector.<Point>> = new Vector.<Vector.<Point>>();
public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
var width:int = this.stage.stageWidth;
var height:int = this.stage.stageHeight;
// 初期値だけ設定しておく
var level0:Vector.<Point> = new Vector.<Point>();
level0.push(new Point(width / 4, height * 2 / 3), new Point(width * 3 / 4, height * 2 / 3));
cachePoints_.push(level0);
configureCounterField();
this.addChild(counterField_);
// ClickでLevelを+1、Shiftを押してると-1
this.stage.addEventListener(MouseEvent.CLICK, function(event:MouseEvent):void {
counter_ += (event.shiftKey)? -1: 1;
refresh();
});
// Wheelでも Levelを上下
this.stage.addEventListener(MouseEvent.MOUSE_WHEEL, function(event:MouseEvent):void {
counter_ += (event.delta > 0)? -1: 1;
refresh();
});
refresh();
}
private function configureCounterField():void
{
counterField_.x = 0;
counterField_.y = 465 - 60;
counterField_.antiAliasType = AntiAliasType.ADVANCED;
counterField_.autoSize = TextFieldAutoSize.CENTER;
var format:TextFormat = new TextFormat();
format.color = 0xCCCCCC;
format.size = 36;
counterField_.defaultTextFormat = format;
}
private function refresh():void
{
if (counter_ < 0) {
counter_ = 0;
}
drawCCurve(counter_);
counterField_.text = counter_.toString();
}
private function drawCCurve(level:int):void
{
var g:Graphics = this.graphics;
g.clear();
g.lineStyle(1, 0xFFFFFF);
// まだ座標計算してなかった時に計算する
if (cachePoints_.length <= level) {
createCCurve(level);
}
var points:Vector.<Point> = cachePoints_[level];
g.moveTo(points[0].x, points[0].y);
for (var index:int = 1; index < points.length; index++) {
g.lineTo(points[index].x, points[index].y);
}
}
private function createCCurve(level:int):void
{
if (cachePoints_.length < level) {
createCCurve(level - 1);
}
var points:Vector.<Point> = new Vector.<Point>();
var prevPoints:Vector.<Point> = cachePoints_[level - 1];
points.push(prevPoints[0]);
for (var index:int = 1; index < prevPoints.length; index++) {
var start:Point = prevPoints[index - 1];
var end:Point = prevPoints[index];
var distance:Number = Point.distance(start, end) / 2 * Math.SQRT2;
var angle:Number = Math.atan2(end.y - start.y, end.x - start.x);
var addPoint:Point = new Point(
distance * Math.cos(angle-Math.PI / 4) + start.x,
distance * Math.sin(angle-Math.PI / 4) + start.y
);
points.push(addPoint);
points.push(end);
}
cachePoints_.push(points);
}
}
}