Forked from: Horiuchi_H's ドラゴン曲線(Dragon curve) diff:22 コッホ曲線(Koch curve) コッホ曲線(Koch curve)を描く @author H.Horiuchi Horiuchi_H forked:0favorite:0lines:110license : MIT License modified : 2009-11-25 18:32:55 Embed Tweet // forked from Horiuchi_H's ドラゴン曲線(Dragon curve) // forked from Horiuchi_H's C曲線 (Levy C curve) 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")] /** * コッホ曲線(Koch curve)を描く * @author H.Horiuchi */ public class KochCurve extends Sprite { private var counter_:int = 5; private var counterField_:TextField = new TextField(); private var cachePoints_:Vector.<Vector.<Point>> = new Vector.<Vector.<Point>>(); public function KochCurve():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 / 8, height * 2 / 3), new Point(width * 7 / 8, 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; } drawCurve(counter_); counterField_.text = counter_.toString(); } private function drawCurve(level:int):void { var g:Graphics = this.graphics; g.clear(); g.lineStyle(1, 0xFFFFFF); // まだ座標計算してなかった時に計算する if (cachePoints_.length <= level) { createCurve(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 createCurve(level:int):void { if (cachePoints_.length < level) { createCurve(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) / 3; var angle:Number = Math.atan2(end.y - start.y, end.x - start.x); var theta:Number = angle - Math.PI / 3; var p1:Point = new Point( distance * Math.cos(angle) + start.x, distance * Math.sin(angle) + start.y ); var p2:Point = new Point( distance * Math.cos(theta) + p1.x, distance * Math.sin(theta) + p1.y ); var p3:Point = new Point( 2 * distance * Math.cos(angle) + start.x, 2 * distance * Math.sin(angle) + start.y ); points.push(p1); points.push(p2); points.push(p3); points.push(end); } cachePoints_.push(points); } } } Code Fullscreen Preview Fullscreen curve fractal Point height width shiftKey MouseEvent.ADDED_TO_STAGE MouseEvent.MOUSE_WHEEL delta Vector stage Math.cos graphics MouseEvent addEventListener Point.distance TextFormat toString removeEventListener push Math.sin Math.atan2