prog.hu: Automatikus gyűrű topológia építése

by szbzs2004
http://forum.prog.hu/tudastar/165959/Automatikus+gyuru+topologia+epitese.html
idea by WarmUp

MouseDown (on canvas)
 + add node

MouseDown (on node)
 + drag node
 or
 - delete node (if the Caps Lock key is activated)

Space
 + hide/show nodes
♥0 | Line 134 | Modified 2013-04-18 08:51:39 | MIT License
play

ActionScript3 source code

/**
 * Copyright szbzs2004 ( http://wonderfl.net/user/szbzs2004 )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/korO
 */

// http://forum.prog.hu/tudastar/165959/Automatikus+gyuru+topologia+epitese.html
// idea by WarmUp
package  {

    import flash.display.Graphics;
    import flash.display.Shape;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.KeyboardEvent;
    import flash.events.MouseEvent;
    import flash.geom.Point;
    import flash.ui.Keyboard;

    [SWF (width="465", height="465", frameRate="50", backgroundColor="#000000")]

    public class Ring extends Sprite {

        private var nodes:Vector.<Node>;
        private var nodesVisible:Boolean;
        private var canvas:Sprite;
        private var ring:Shape;
        private var currentNode:Node;
        private var grabPoint:Point;

        public function Ring() {
            nodes = new Vector.<Node>();
            nodesVisible = true;

            canvas = new Sprite();
            canvas.graphics.beginFill(0x000000);
            canvas.graphics.drawRect(0, 0, 465, 465);
            canvas.addEventListener(MouseEvent.MOUSE_DOWN, addNode);
            addChild(canvas);

            ring = new Shape();
            addChild(ring);

            stage.addEventListener(KeyboardEvent.KEY_UP, switchVisibility);
        }

        private function addNode(e:MouseEvent):void {
            var n:Node = new Node(new Point(e.target.mouseX, e.target.mouseY));
            n.addEventListener(MouseEvent.MOUSE_DOWN, grabNode);
            n.buttonMode = true;
            n.visible = nodesVisible;
            addChild(n);
            nodes.push(n);
            drawRing();
        }

        private function removeNode(n:Node):void {
            n.removeEventListener(MouseEvent.MOUSE_DOWN, grabNode);
            n.parent.removeChild(n);
            nodes.splice(nodes.indexOf(n), 1);
        }
        
        private function switchVisibility(e:KeyboardEvent):void {
            if (e.keyCode == Keyboard.SPACE) {
                nodesVisible = !nodesVisible;
                for (var i:uint = 0; i < nodes.length; ++i) 
                    nodes[i].visible = nodesVisible;
            }
        }

        private function grabNode(e:MouseEvent):void {
            currentNode = Node(e.target);
            if (Keyboard.capsLock) {
                removeNode(currentNode);
                currentNode = null;
                drawRing();
            } else {
                grabPoint = new Point(currentNode.mouseX, currentNode.mouseY);
                currentNode.parent.setChildIndex(currentNode, currentNode.parent.numChildren - 1);
                stage.addEventListener(MouseEvent.MOUSE_MOVE, dragNode);
                stage.addEventListener(MouseEvent.MOUSE_UP, releaseNode);
            }
        }

        private function dragNode(e:MouseEvent):void {
            currentNode.x = stage.mouseX - grabPoint.x;
            currentNode.y = stage.mouseY - grabPoint.y;
            drawRing();
            e.updateAfterEvent();
        }

        private function releaseNode(e:MouseEvent):void {
            stage.removeEventListener(MouseEvent.MOUSE_MOVE, dragNode);
            stage.removeEventListener(MouseEvent.MOUSE_UP, releaseNode);
        }

        private function drawRing():void {
            var g:Graphics = ring.graphics;
            g.clear();
            if (nodes.length > 1) {
                var center:Point = new Point(0, 0);
                var i:uint;
                // calculate center
                for (i = 0; i < nodes.length; ++i) {
                    center.x += nodes[i].x;
                    center.y += nodes[i].y;
                }
                center.x /= nodes.length;
                center.y /= nodes.length;
                // calculate fi, r
                for (i = 0; i < nodes.length; ++i)
                    nodes[i].calcFiR(center);
                // sort Nodes
                nodes.sort(
                    function(k1:Node, k2:Node):Number {
                        if (k1.fi == k2.fi)
                            return k1.r - k2.r;
                        else
                            return k1.fi - k2.fi;
                    }
                );
                // draw center
                g.lineStyle(0, 0x808080);
                g.moveTo(center.x - 10, center.y);
                g.lineTo(center.x + 10, center.y);
                g.moveTo(center.x, center.y - 10);
                g.lineTo(center.x, center.y + 10);
                // draw lines
                g.lineStyle(0, 0xffffff);
                g.moveTo(nodes[0].x, nodes[0].y);
                for (i = 1; i < nodes.length; ++i)
                    g.lineTo(nodes[i].x, nodes[i].y); 
                g.lineTo(nodes[0].x, nodes[0].y);
            }
        }
    }
}

import flash.display.Sprite;
import flash.geom.Point;

class Node extends Sprite {

    private static const RADIUS:Number = 5;
    private static const COLOR:uint = 0xff0000;

    private var _fi:Number = 0;
    private var _r:Number = 0;

    public function Node(p:Point) {
        x = p.x;
        y = p.y;
        graphics.beginFill(COLOR);
        graphics.drawCircle(0, 0, RADIUS);
        graphics.endFill();
    }

    public function calcFiR(center:Point):void {
        _r = Point.distance(center, new Point(x, y));
        _fi = Math.atan2(y - center.y, x - center.x);
    }

    public function get fi():Number {
        return _fi;
    }

    public function get r():Number {
        return _r;
    }
}