package { import fl.controls.Button; import fl.controls.CheckBox; import flash.display.GradientType; import flash.display.Sprite; import flash.events.Event; import flash.events.KeyboardEvent; import flash.events.MouseEvent; import flash.geom.Matrix; /** * Bootstraps the Project * @author Chad Nelson */ public class Main extends Sprite { private var voronoi_diagram : VoronoiDiagram = new VoronoiDiagram(); private var delaunay_triangulation : DelaunayTriangulation = new DelaunayTriangulation(); private var mouse_sites : Vector. = new Vector.(); private var step_btn : Button = new Button(); private var bstep_btn : Button = new Button(); private var calc_btn : Button = new Button(); private var clear_btn : Button = new Button(); private var animate_btn : Button = new Button(); private var animating : Boolean = false; private var mode_btn : Button = new Button(); private var mouseMode : Boolean = false; private var bg : Sprite = new Sprite(); private var delaunayCheck : CheckBox = new CheckBox(); private var circlesCheck : CheckBox = new CheckBox(); public function Main():void { addChild(bg); addChild(voronoi_diagram); addChild(delaunay_triangulation); addChild(calc_btn); addChild(clear_btn); addChild(bstep_btn); addChild(step_btn); addChild(mode_btn); addChild(animate_btn); addChild(delaunayCheck); addChild(circlesCheck); var mat : Matrix = new Matrix(); mat.createGradientBox(900, 900, -1.4, 0, 0); bg.graphics.beginGradientFill(GradientType.LINEAR, [0xAAAAAA, 0xFFFFFF], [1, 1], [0x00, 0x99], mat); if (stage) init(); else addEventListener(Event.ADDED_TO_STAGE, init); } private function init(e:Event = null):void { removeEventListener(Event.ADDED_TO_STAGE, init); // entry point calc_btn.width = 60; calc_btn.x = 5; calc_btn.y = stage.stageHeight - 5 - calc_btn.height; calc_btn.label = "Calculate"; clear_btn.width = 40; clear_btn.x = 10 + calc_btn.width; clear_btn.y = stage.stageHeight - 5 - clear_btn.height; clear_btn.label = "Clear"; bstep_btn.width = 70; bstep_btn.x = 15 + calc_btn.width + clear_btn.width; bstep_btn.y = stage.stageHeight - 5 - step_btn.height; bstep_btn.label = "Prev Event"; step_btn.width = 70; step_btn.x = 20 + calc_btn.width + clear_btn.width + bstep_btn.width; step_btn.y = stage.stageHeight - 5 - step_btn.height; step_btn.label = "Next Event"; mode_btn.width = 80; mode_btn.x = 25 + calc_btn.width + clear_btn.width + step_btn.width+ bstep_btn.width; mode_btn.y = stage.stageHeight - 5 - mode_btn.height; mode_btn.label = "Mouse Mode"; animate_btn.width = 60; animate_btn.x = 30 + calc_btn.width + clear_btn.width + step_btn.width + mode_btn.width+ bstep_btn.width; animate_btn.y = stage.stageHeight - 5 - mode_btn.height; animate_btn.label = "Animate"; bg.graphics.drawRect(0, 0, stage.stageWidth * 2, stage.stageHeight * 2); delaunayCheck.label = "Delaunay Triangulation"; delaunayCheck.width = 160; delaunayCheck.selected = true; delaunayCheck.x = 5; delaunayCheck.y = 5; circlesCheck.label = "Circle Events"; circlesCheck.width = 130; circlesCheck.selected = true; circlesCheck.x = 5; circlesCheck.y = 10 + delaunayCheck.height; bg.addEventListener(MouseEvent.CLICK, addPoint); calc_btn.addEventListener(MouseEvent.CLICK, calculate); clear_btn.addEventListener(MouseEvent.CLICK, clear); step_btn.addEventListener(MouseEvent.CLICK, next); mode_btn.addEventListener(MouseEvent.CLICK, toggleMouseMode); animate_btn.addEventListener(MouseEvent.CLICK, toggleAnimation); bstep_btn.addEventListener(MouseEvent.CLICK, prev); // Checkboxes delaunayCheck.addEventListener(MouseEvent.CLICK, redraw); circlesCheck.addEventListener(MouseEvent.CLICK, redraw); stage.addEventListener(KeyboardEvent.KEY_DOWN, debug); FileIO.readInput(parseInput); } private function prev(e:Event):void { var temp : Number = voronoi_diagram.eventsHandled; voronoi_diagram.setSites(mouse_sites); trace(temp); while (voronoi_diagram.eventsHandled < (temp-1)) voronoi_diagram.nextEvent(); delaunay_triangulation.calculate(); redraw(); } private function redraw(e:Event = null):void { voronoi_diagram.draw(true, circlesCheck.selected); if (delaunayCheck.selected) delaunay_triangulation.draw(); else delaunay_triangulation.graphics.clear(); if (voronoi_diagram.events.length == 0) step_btn.enabled = false; else step_btn.enabled = true; if (voronoi_diagram.eventsHandled == 0 ) bstep_btn.enabled = false; else bstep_btn.enabled = true; if (animating) { bstep_btn.enabled = false; step_btn.enabled = false; } } private function debug(e:Event):void { trace("Events"); trace(voronoi_diagram.events[0].y); trace(voronoi_diagram.events[1].y); trace(voronoi_diagram.events[2].y); trace(voronoi_diagram.events[3].y); } private function toggleAnimation(e:Event = null):void { animating = !animating; if (animating) { animate_btn.label = "Pause"; calc_btn.enabled = false; mode_btn.enabled = false; step_btn.enabled = false; if (mouseMode) toggleMouseMode(); if (BeachLine.directrix == Number.POSITIVE_INFINITY) { bl = stage.stageHeight; } else { bl = BeachLine.directrix; } stage.addEventListener(Event.ENTER_FRAME, animateFrame); } else { animate_btn.label = "Animate"; calc_btn.enabled = true; mode_btn.enabled = true; step_btn.enabled = true; stage.removeEventListener(Event.ENTER_FRAME, animateFrame); } } private var bl : Number; private function animateFrame(e:Event):void { bl -= 1; voronoi_diagram.calculate(bl); BeachLine.directrix = bl; delaunay_triangulation.calculate(); redraw(); if (voronoi_diagram.events.length == 0 && bl < 0) toggleAnimation(); } private function toggleMouseMode(e:Event = null):void { mouseMode = !mouseMode; if (mouseMode) { stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMove); } else { stage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMove); voronoi_diagram.setSites(mouse_sites); step_btn.enabled = (voronoi_diagram.events.length != 0); delaunay_triangulation.calculate(); redraw(); } } private function mouseMove(e:Event):void { if (BeachLine.directrix < stage.stageHeight - mouseY) voronoi_diagram.setSites(mouse_sites); voronoi_diagram.calculate(stage.stageHeight - mouseY); BeachLine.directrix = stage.stageHeight - mouseY; delaunay_triangulation.calculate(); redraw(); } private function next(e:Event):void { voronoi_diagram.nextEvent() if (voronoi_diagram.events.length == 0) step_btn.enabled = false; delaunay_triangulation.calculate(); redraw(); } private function addPoint(e:Event):void { mouse_sites.push(new VoronoiSite("" + (mouse_sites.length + 1), mouseX, stage.stageHeight - mouseY)); voronoi_diagram.setSites(mouse_sites); step_btn.enabled = true; delaunay_triangulation.calculate(); redraw(); } private function clear(e:Event):void { mouse_sites = new Vector.(); voronoi_diagram.setSites(mouse_sites); voronoi_diagram.graphics.clear(); delaunay_triangulation.graphics.clear(); step_btn.enabled = false; if (mouseMode) toggleMouseMode(); if (animating) toggleAnimation(); } private function calculate(e:Event = null):void { voronoi_diagram.setSites(mouse_sites); voronoi_diagram.calculate(); delaunay_triangulation.setDiagram(voronoi_diagram); delaunay_triangulation.calculate(); if (mouseMode) toggleMouseMode(); delaunay_triangulation.setDiagram(voronoi_diagram); delaunay_triangulation.calculate(); redraw(); } private function parseInput(e:Event):void { mouse_sites = FileIO.parseInput(e.target.data); trace("Got sites.txt: " + mouse_sites); calculate(); var output : String; output = voronoi_diagram.outputDCEL(); output += delaunay_triangulation.outputDCEL(); FileIO.printOutput(output); } } }