package { import flash.display.Sprite; import flash.display.Shape; import flash.events.Event; import flash.geom.*; import flash.display.StageAlign; import flash.display.StageScaleMode; import com.bit101.components.*; [SWF(backgroundColor="0xffffff", width="750", height="650", frameRate="30")] public class Koch1 extends Sprite { private var pathData:Vector. = new Vector.(); private var commands:Vector. = new Vector.(); private var pts:Vector. = new Vector.(5); private var dummy:Shape; private var len:Number; private var iter:int; public function Koch1() { stage.align = StageAlign.TOP_LEFT; stage.scaleMode = StageScaleMode.NO_SCALE; init(); } private function init():void { //set initial size of line len = 500; iter = 3; //create new Sprite to use localToGlobal() dummy = new Shape(); addChild(dummy); //define rule ... _/\_ pts = Vector.([ new Point(0,0), new Point(len,0), new Point(len + Math.cos(Math.PI*60/180)*len,Math.sin(Math.PI*60/180)*len), new Point(2*len,0), new Point(3*len,0) ]); //add seed points //pathData.push(0,0,len,0); pathData.push(stage.stageWidth/2-len/2,stage.stageHeight/2+len/3, stage.stageWidth/2+len/2,stage.stageHeight/2+len/3, stage.stageWidth/2-len/2 + Math.cos(60*Math.PI/180)*len, stage.stageHeight/2+len/3 - Math.sin(60*Math.PI/180)*len, stage.stageWidth/2-len/2,stage.stageHeight/2+len/3); commands.push(1); drawFractal(); //depth control var iter_lbl:Label = new Label(this, 450, 15, "iterations:"); var iter_val:Label = new Label(this, 600, 15, ""+iter); var iter_sldr:HSlider = new HSlider(this, 500, 20, function(e:Event):void { iter = Math.ceil(e.target.value); iter_val.text = ""+iter; }); iter_sldr.setSliderParams(1,7,iter); //add redraw button var btn:PushButton = new PushButton(this, 620, 15, "redraw", function(e:Event):void { redraw(); }); } private function redraw():void { pathData = new Vector.(); commands = new Vector.(); //add seed points //pathData.push(0,0,len,0); pathData.push(stage.stageWidth/2-len/2,stage.stageHeight/2+len/3, stage.stageWidth/2+len/2,stage.stageHeight/2+len/3, stage.stageWidth/2-len/2 + Math.cos(60*Math.PI/180)*len, stage.stageHeight/2+len/3 - Math.sin(60*Math.PI/180)*len, stage.stageWidth/2-len/2,stage.stageHeight/2+len/3); commands.push(1); drawFractal(); } private function drawFractal():void { graphics.clear(); graphics.beginFill(0x00000); graphics.lineStyle(0); //we must interpolate new points between each two points in pathData //work on a copy of the pathData - keeps same length //whereas interpolated points are injected into pathData for(var i:int = 1; i <= iter; i++){ var pathDataCopy:Vector. = pathData.slice(0); var nmpts:Number = pathDataCopy.length; var ptIndex:Number = 0;//used to keep track of next point to interpolate //start on first point, take every pair after that for(var p:int = 0; p < nmpts-2; p+=2){ //reset the dummy's transforms dummy.transform.matrix = new Matrix(); //position dummy at first point dummy.x = pathDataCopy[p]; dummy.y = pathDataCopy[p+1]; dummy.scaleX = dummy.scaleY = 1/Math.pow(3,i); dummy.rotation = 180*Math.atan2(pathDataCopy[p+3]-dummy.y,pathDataCopy[p+2]-dummy.x)/Math.PI; //for each point in the rule... //calculate absolute points var absVts:Vector. = new Vector.(10); for(var pt:int = 0; pt < pts.length; pt++){ var apt:Point = dummy.localToGlobal(pts[pt]); absVts[pt*2] = apt.x; absVts[pt*2+1] = apt.y; } //splice into pathData pathData.splice(ptIndex,4,absVts[0],absVts[1],absVts[2],absVts[3],absVts[4],absVts[5],absVts[6],absVts[7],absVts[8],absVts[9]); ptIndex += 8; } } for(var c:int = 1; c < pathData.length/2; c++){ commands.push(2); } //draw! //trace("drawPath(["+commands+"],["+pathData+"])"); //trace("drawPath(["+commands.length+"],["+pathData.length/2+"])"); graphics.drawPath(commands,pathData); } } }