Arc, forked from: 2D Geometry Test

by aobyrne forked from 2D Geometry Test (diff: 119)
♥0 | Line 226 | Modified 2012-05-20 17:26:35 | MIT License
play

ActionScript3 source code

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

package 
{
    import flash.display.*;
    import flash.events.*;
    import flash.filters.GlowFilter;
    import flash.geom.*;
    import flash.text.*;
    
    public class WonderflGeometryArc extends Sprite 
    {
        private var frameBuffer:BitmapData = new BitmapData(stage.stageWidth, stage.stageHeight, false);
        
        private var red:ControlPoint;
        private var green:ControlPoint;
        private var blue:ControlPoint;
        
        
        private var shape:Shape = new Shape();
        private var g:Graphics = shape.graphics;
        
        public function WonderflGeometryArc():void 
        {
            addChild(new Bitmap(frameBuffer));
            
            var shape:Shape = new Shape();
            addChild(shape);
            
            red = new ControlPoint(this, 60, 340, 0xFF4444);
            green = new ControlPoint(this, 210, 140, 0x44FF44);
            blue = new ControlPoint(this, 300, 280, 0x4444FF);
            
            repaint();
        }
        
        public function repaint():void 
        {
            var v1:Point = sub(green, red);
            var v2:Point = sub(blue, red);
            
            var p3:Point = add(green, v2);
            
            var v1Length:Number = norm(v1);
            var v2Length:Number = norm(v2);
            
            // rendering
            frameBuffer.fillRect(frameBuffer.rect, 0xFFFFFF);
            
            
            drawArrow(red, green, 0x333333);
            drawArrow(red, blue, 0x333333);
            
            var radius:Number = Math.min(80, Math.min(v1Length, v2Length));
                
            var startAngle:Number = getAngle(v1);
            var endAngle:Number = getAngle(v2);
            if (endAngle - startAngle > Math.PI) {
                startAngle += Math.PI * 2;
            }
            if (startAngle - endAngle > Math.PI) {
                endAngle += Math.PI * 2;
            }
            drawArc(red, radius, 0x333333        , startAngle, endAngle);
            drawArc(red, radius * 0.8, 0x333333    , startAngle, endAngle);
            
        }
        
        private function moveTo(p:Point):void
        {
            g.moveTo(p.x, p.y);
        }
        
        private function lineTo(p:Point):void
        {
            g.lineTo(p.x, p.y);
        }
        
        private function drawLine(start:Point, end:Point):void
        {
            moveTo(start);
            lineTo(end);
        }
        
        private function drawArrow(start:Point, end:Point, color:uint):void
        {
            g.clear();
            {
                g.lineStyle(2, color, 1, false, "normal", null, JointStyle.MITER);
                g.moveTo(start.x, start.y);
                g.lineTo(end.x, end.y);
                
                var len:Number = distance(start, end);
                var arrowLen:Number = Math.min(len, 30) / 3;
                var arrowWidth:Number = arrowLen / 3;
                
                if (arrowLen > 0) {
                    var v:Point = sub(end, start);
                    var c:Point = sub(end, cut(v, arrowLen));
                    var l:Point = add(c, cut(normal(v), arrowWidth));
                    var r:Point = add(c, cut(normal(v), -arrowWidth));
                
                    g.beginFill(color);
                    moveTo(end);
                    lineTo(l);
                    lineTo(r);
                    lineTo(end);
                    g.endFill();
                }
            }
            frameBuffer.draw(shape);
        }
        
        
        private function drawArc(center:Point, radius:Number, color:uint, start:Number, end:Number):void
        {
            g.clear();
            {
                const SEGMENT:int = 32;
                
                g.lineStyle(2, color);
                
                for (var i:int = 0; i <= SEGMENT; i++) {
                    var angle:Number = start + (end - start) * (i / SEGMENT);
                    var x:Number = center.x + Math.cos(angle) * radius;
                    var y:Number = center.y + Math.sin(angle) * radius;
                    if (i == 0) {
                        g.moveTo(x, y);
                    } else {
                        g.lineTo(x, y);
                    }
                }
            }
            frameBuffer.draw(shape);
        }
    }
    
}

import flash.geom.Point;
import flash.display.*;
import flash.events.MouseEvent;

class ControlPoint extends Point
{
    private var main:WonderflGeometryArc;
    
    private var sprite:Sprite = new Sprite();
    private var g:Graphics = sprite.graphics;
    
    function ControlPoint(main:WonderflGeometryArc, x:Number, y:Number, color:uint)
    {
        this.main = main;
        this.x = x;
        this.y = y;
        
        g.beginFill(color, 0.5);
        g.drawCircle(0, 0, 16);
        g.endFill();
        
        sprite.x = x;
        sprite.y = y;
        sprite.buttonMode = true;
        
        sprite.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
        sprite.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
        
        main.addChild(sprite);
    }
    
    private function mouseDownHandler(e:MouseEvent):void 
    {
        sprite.startDrag();
        main.stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
    }
    
    private function mouseUpHandler(e:MouseEvent):void 
    {
        sprite.stopDrag();
        main.stage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
    }
    
    private function mouseMoveHandler(e:MouseEvent):void 
    {
        x = sprite.x;
        y = sprite.y;
        
        main.repaint();
        e.updateAfterEvent();
    }
    
}


function toDegree(radian:Number):Number
{
    return radian * 180 / Math.PI;
}

function toRadian(degree:Number):Number
{
    return degree * Math.PI / 180;
}

function minus(v:Point):Point
{
    return new Point( -v.x, -v.y);
}

function normal(v:Point):Point
{
    return new Point(v.y, -v.x);
}

function norm(v:Point):Number
{
    return Math.sqrt(v.x * v.x + v.y * v.y);
}

function normalize(v:Point):Point
{
    return div(v, norm(v));
}

function add(n:Point, m:Point):Point
{
    return new Point(n.x + m.x, n.y + m.y);
}

function addto(n:Point, m:Point):void
{
    n.x += m.x;
    n.y += m.y;
}

function sub(n:Point, m:Point):Point
{
    return new Point(n.x - m.x, n.y - m.y);
}

function mul(v:Point, f:Number):Point
{
    return new Point(v.x * f, v.y * f);
}

function div(v:Point, f:Number):Point
{
    return new Point(v.x / f, v.y / f);
}

function dot(a:Point, b:Point):Number
{
    return a.x * b.x + a.y * b.y;
}

function cross(a:Point, b:Point):Number
{
    return a.x * b.y - a.y * b.x;
}

function distanceSquared(a:Point, b:Point):Number
{
    var dx:Number = b.x - a.x;
    var dy:Number = b.y - a.y;
    return dx * dx + dy * dy;
}

function distance(a:Point, b:Point):Number
{
    return Math.sqrt(distanceSquared(a, b));
}

function lerp(n:Point, m:Point, p:Number):Point
{
    return add(mul(n, 1 - p), mul(m, p));
}

function midpoint(n:Point, m:Point):Point
{
    return new Point((n.x + m.x) * 0.5, (n.y + m.y) * 0.5);
}

function cut(v:Point, len:Number):Point
{
    // create a vector of the specified length
    return mul(normalize(v), len);
}

function getAngle(v:Point):Number
{
    return Math.atan2(v.y, v.x);
}