Advertisement
ulfben

FastDraw.as

Nov 24th, 2016
267
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. package com.ulfben.utils {
  2.     import flash.display.*;
  3.     import flash.geom.*;
  4.  
  5.     public class FastShapes {
  6.         public static const HORIZONTAL_LINE:String = "FastShapes.horizontal";
  7.         public static const VERTICAL_LINE:String = "FastShapes.vertical";
  8.         public static const TO_RAD:Number = (Math.PI / 180);
  9.         public static const TO_DEG:Number = (180 / Math.PI);
  10.         public static const PI2:Number = Math.PI * 2;
  11.         public static const HALF_PI:Number = Math.PI * 0.5;
  12.         public static const QUARTER_PI:Number = Math.PI * 0.25;
  13.         public static const EIGHTH_PI:Number = Math.PI * 0.125;
  14.  
  15.         /**
  16.          * Creates look up tables for sin and cos, to reduce function calls.
  17.          * index = int(angle * (2048/2PI))
  18.          */    
  19.         public static var sCosLUT:Vector.<Number> = new Vector.<Number>(0x800, true);
  20.         public static var sSinLUT:Vector.<Number> = new Vector.<Number>(0x800, true);
  21.         public static function initLUTs():void  {
  22.             for (var i:int = 0; i < 0x800; ++i)
  23.             {
  24.                 sCosLUT[i & 0x7FF] = Math.cos(i * 0.00306796157577128245943617517898); // 0.003067... is 2PI/2048
  25.                 sSinLUT[i & 0x7FF] = Math.sin(i * 0.00306796157577128245943617517898);
  26.             }
  27.         }
  28.         public static function sinLUT(x:Number):Number{
  29.             return sSinLUT[(x * 325.94932345220164765467394738691) & 2047]; // 325.949... is 2048/2PI
  30.         }
  31.         public static function cosLUT(x:Number):Number{
  32.             return sCosLUT[((x * 325.94932345220164765467394738691) & 2047)]; //325.949... is 2048/2PI
  33.         }
  34.  
  35.         public static function sinCoarse(x:Number):Number {
  36.             if (x < -3.14159265) { //always wrap input angle to -PI..PI
  37.                 x += 6.28318531;
  38.             } else if (x > 3.14159265) {
  39.                 x -= 6.28318531;
  40.             }
  41.             return (x < 0) ? (1.27323954 * x + .405284735 * x * x) : (1.27323954 * x - 0.405284735 * x * x);
  42.         }
  43.  
  44.         public static function cosCoarse(x:Number):Number {
  45.             if (x < -3.14159265) { //always wrap input angle to -PI..PI
  46.                 x += 6.28318531;
  47.             } else if (x > 3.14159265) {
  48.                 x -= 6.28318531;
  49.             }
  50.             x += 1.57079632; // //compute cosine: sin(x + PI/2) = cos(x)
  51.             if (x > 3.14159265) {
  52.                 x -= 6.28318531;
  53.             }
  54.             return (x < 0) ? (1.27323954 * x + 0.405284735 * x * x) : (1.27323954 * x - 0.405284735 * x * x);
  55.         }
  56.  
  57.         public static function sinFine(x:Number):Number {
  58.             if(x < -3.14159265) {
  59.                     x += 6.28318531;
  60.             } else if(x > 3.14159265) {
  61.                     x -= 6.28318531;
  62.             }
  63.             x = (x < 0.0) ? (1.27323954 * x + .405284735 * x * x) : (1.27323954 * x - 0.405284735 * x * x)
  64.             return (x < 0.0) ? (0.225 * (x *-x - x) + x) : (0.225 * (x * x - x) + x)
  65.         }
  66.    
  67.         public static function cosFine(x:Number): Number {
  68.             if(x < -3.14159265) {
  69.                 x += 6.28318531;
  70.             } else if(x > 3.14159265) {
  71.                 x -= 6.28318531;
  72.             }
  73.             x += 1.57079632;
  74.             if(x > 3.14159265) {
  75.                 x -= 6.28318531;
  76.             }
  77.             x = (x < 0.0) ? (1.27323954 * x + .405284735 * x * x) : (1.27323954 * x - 0.405284735 * x * x)
  78.             return (x < 0.0) ? (0.225 * (x *-x - x) + x) : (0.225 * (x * x - x) + x)
  79.         }
  80.  
  81.         public static var testCos:Function = cosFine; // cosLUT, cosCoarse, cosFine
  82.         public static var testSin:Function = sinFine; // sinLUT,  sinCoarse, sinFine
  83.  
  84.  
  85.         public function FastShapes() {
  86.             throw new ArgumentError("The FastShapes Class cannot be instanicated.");
  87.         }
  88.  
  89.         /***
  90.          * drawCircle
  91.          * Since Flash Player 8 there is an internal drawCircle-method. Before that I
  92.          * used this. At some point they should be benchmarked against eachother.
  93.          */
  94.         public static function drawCircle(target:Graphics, x:Number, y:Number, r:Number):void {
  95.             var tan:Number = Math.tan(EIGHTH_PI) * r;
  96.             var sin:Number = testSin(QUARTER_PI) * r;
  97.             target.moveTo(x + r, y);
  98.             target.curveTo(r + x, tan + y, sin + x, sin + y);
  99.             target.curveTo(tan + x, r + y, x, r + y);
  100.             target.curveTo((-tan) + x, r + y, (-sin) + x, sin + y);
  101.             target.curveTo(-r + x, tan + y, -r + x, y);
  102.             target.curveTo(-r + x, (-tan) + y, (-sin) + x, (-sin) + y);
  103.             target.curveTo((-tan) + x, -r + y, x, -r + y);
  104.             target.curveTo(tan + x, -r + y, sin + x, (-sin) + y);
  105.             target.curveTo(r + x, (-tan) + y, r + x, y);
  106.             target.moveTo(x, y);
  107.         }
  108.  
  109.         // wobbleFactor in percent. 0.04-0.08 is a good default range.
  110.         public static function handDrawLine(target:Graphics, startPoint:Point, endPoint:Point, wobbleFactor:Number = 0.05):void {
  111.             var wobble:Number = Point.distance(startPoint, endPoint) * wobbleFactor;
  112.             var r1:Number = Math.random();
  113.             var r2:Number = Math.random();
  114.             var xfactor:Number = Math.random() > 0.5 ? wobble : -wobble;
  115.             var yfactor:Number = Math.random() > 0.5 ? wobble : -wobble;
  116.             var control1:Point = new Point((endPoint.x - startPoint.x) * r1 + startPoint.x + xfactor, (endPoint.y - startPoint.y) * r1 + startPoint.y + yfactor);
  117.             var control2:Point = new Point((endPoint.x - startPoint.x) * r2 + startPoint.x - xfactor, (endPoint.y - startPoint.y) * r2 + startPoint.y - yfactor);
  118.             target.moveTo(startPoint.x, startPoint.y);
  119.             target.cubicCurveTo(control1.x, control1.y, control2.x, control2.y, endPoint.x, endPoint.y);
  120.         }
  121.  
  122.        
  123.          // Draws a dashed line from the point x1,y1 to the point x2,y2
  124.         public static function drawDash(target:Graphics, x1:Number, y1:Number, x2:Number, y2:Number, dashLength:Number = 5, spaceLength:Number = 5):void {
  125.             var x:Number = x2 - x1;
  126.             var y:Number = y2 - y1;
  127.             var hyp:Number = Math.sqrt((x) * (x) + (y) * (y));
  128.             var units:Number = hyp / (dashLength + spaceLength);
  129.             var invertedUnits:Number = 1 / units;
  130.             var dashSpaceRatio:Number = dashLength / (dashLength + spaceLength);
  131.             var dashX:Number = (x * invertedUnits) * dashSpaceRatio;
  132.             var spaceX:Number = (x * invertedUnits) - dashX;
  133.             var dashY:Number = (y * invertedUnits) * dashSpaceRatio;
  134.             var spaceY:Number = (y * invertedUnits) - dashY;
  135.  
  136.             target.moveTo(x1, y1);
  137.             while (hyp > 0) {
  138.                 x1 += dashX;
  139.                 y1 += dashY;
  140.                 hyp -= dashLength;
  141.                 if (hyp < 0) {
  142.                     x1 = x2;
  143.                     y1 = y2;
  144.                 }
  145.                 target.lineTo(x1, y1);
  146.                 x1 += spaceX;
  147.                 y1 += spaceY;
  148.                 target.moveTo(x1, y1);
  149.                 hyp -= spaceLength;
  150.             }
  151.             target.moveTo(x2, y2);
  152.         }
  153.  
  154.        
  155.         //Draws an arc from the starting position of x,y.      
  156.         public static function drawArc(target:Graphics, x:Number, y:Number, radius:Number, arc:Number, startAngle:Number = 0, yRadius:Number = 0):void {
  157.             if (yRadius == 0) {
  158.                 yRadius = radius;
  159.             }
  160.             var segAngle:Number, theta:Number, halfTheta:Number, angle:Number, angleMid:Number, segs:Number, ax:Number, ay:Number, bx:Number, by:Number, cx:Number, cy:Number;
  161.             if (FastShapes.abs(arc) > 360) {
  162.                 arc = 360; // no sense in drawing more than is needed :)
  163.             }
  164.             // Flash uses 8 segments per circle, to match that, we draw in a maximum of 45 degree segments.
  165.             segs = FastShapes.ceil(FastShapes.abs(arc) / 45);
  166.             segAngle = arc / segs;
  167.             theta = -(segAngle) * FastShapes.TO_RAD;
  168.             angle = -(startAngle) * FastShapes.TO_RAD;
  169.             ax = x - testCos(angle) * radius;
  170.             ay = y - testSin(angle) * yRadius;
  171.             if (segs > 0) {
  172.                 target.moveTo(x, y);
  173.                 halfTheta = theta * 0.5;
  174.                 var radiusCosHalfTheta:Number = radius / testCos(halfTheta);
  175.                 var yRadiusCosHalfTheta:Number = yRadius / testCos(halfTheta);
  176.                 for (var i:int = 0; i < segs; ++i) {
  177.                     angle += theta;
  178.                     angleMid = angle - halfTheta;
  179.                     bx = ax + testCos(angle) * radius;
  180.                     by = ay + testSin(angle) * yRadius;
  181.                     cx = ax + testCos(angleMid) * radiusCosHalfTheta;
  182.                     cy = ay + testSin(angleMid) * yRadiusCosHalfTheta;
  183.                     target.curveTo(cx, cy, bx, by);
  184.                 }
  185.             }
  186.         }
  187.  
  188.         // draws pie shaped wedges.  Could be employed to draw pie charts.     
  189.         public static function drawWedge(target:Graphics, x:Number, y:Number, radius:Number, arc:Number, startAngle:Number = 0, yRadius:Number = 0):void {
  190.             if (yRadius == 0) {
  191.                 yRadius = radius;
  192.             }
  193.             if (FastShapes.abs(arc) > 360) {
  194.                 arc = 360;
  195.             }
  196.             target.moveTo(x, y);
  197.             var segAngle:Number, theta:Number, halfTheta:Number, angle:Number, angleMid:Number, segs:Number, ax:Number, ay:Number, bx:Number, by:Number, cx:Number, cy:Number;
  198.             // Flash uses 8 segments per circle, to match that, we draw in a maximum of 45 degree segments.
  199.             segs = FastShapes.ceil(FastShapes.abs(arc) / 45);
  200.             segAngle = arc / segs;
  201.             theta = -(segAngle) * FastShapes.TO_RAD;
  202.             angle = -(startAngle) * FastShapes.TO_RAD;
  203.             // draw the curve in segments no larger than 45 degrees.
  204.             if (segs > 0) {
  205.                 ay = y + testSin(angle) * yRadius; //NOTE: angle is negative!
  206.                 ax = x + testCos(-angle) * radius; //NOTE: -angle == positive value here!
  207.                 target.lineTo(ax, ay);
  208.                 halfTheta = theta * 0.5;
  209.                 var radiusCosHalfTheta:Number = radius / testCos(halfTheta);
  210.                 var yRadiusCosHalfTheta:Number = yRadius / testCos(halfTheta);
  211.                 for (var i:int = 0; i < segs; ++i) {
  212.                     angle += theta;
  213.                     angleMid = angle - halfTheta;
  214.                     bx = x + testCos(angle) * radius;
  215.                     by = y + testSin(angle) * yRadius;
  216.                     cx = x + testCos(angleMid) * radiusCosHalfTheta;
  217.                     cy = y + testSin(angleMid) * yRadiusCosHalfTheta;
  218.                     target.curveTo(cx, cy, bx, by);
  219.                 }
  220.                 target.lineTo(x, y);
  221.             }
  222.         }
  223.  
  224.        
  225.         // draws a star shaped polygon.    
  226.         public static function drawStar(target:Graphics, x:Number, y:Number, points:uint, innerRadius:Number, outerRadius:Number, angle:Number = 0):void {
  227.             if (points <= 2) {
  228.                 throw ArgumentError("FastShapes.drawStar() - parameter 'points' needs to be atleast 3");
  229.                 return;
  230.             }
  231.             var step:Number, startnstep:Number, halfStep:Number, start:Number, n:Number, dx:Number, dy:Number;
  232.             step = FastShapes.PI2 / points;
  233.             halfStep = step * 0.5;
  234.             start = angle * FastShapes.TO_RAD;
  235.             target.moveTo(x + (testCos(start) * outerRadius), y - (testSin(start) * outerRadius));
  236.             for (n = 1; n <= points; ++n) {
  237.                 startnstep = start + (step * n);
  238.                 dx = x + testCos(startnstep - halfStep) * innerRadius;
  239.                 dy = y - testSin(startnstep - halfStep) * innerRadius;
  240.                 target.lineTo(dx, dy);
  241.                 dx = x + testCos(startnstep) * outerRadius;
  242.                 dy = y - testSin(startnstep) * outerRadius;
  243.                 target.lineTo(dx, dy);
  244.             }
  245.         }
  246.  
  247.         /**
  248.          * a method for creating polygon shapes.  Negative values will draw
  249.          * the polygon in reverse direction.  Negative drawing may be useful
  250.          * for creating knock-outs in masks.
  251.          */
  252.         public static function drawPolygon(target:Graphics, x:Number, y:Number, sides:uint, radius:Number, angle:Number = 0):void {
  253.             if (sides <= 2) {
  254.                 throw ArgumentError("FastShapes.drawPolygon() - parameter 'sides' needs to be atleast 3");
  255.                 return;
  256.             }
  257.             var step:Number, startnstep:Number, start:Number, n:Number, dx:Number, dy:Number;
  258.             step = FastShapes.PI2 / sides;
  259.             start = angle * FastShapes.TO_RAD;
  260.             target.moveTo(x + (testCos(start) * radius), y - (testSin(start) * radius));
  261.             for (n = 1; n <= sides; ++n) {
  262.                 startnstep = start + (step * n);
  263.                 dx = x + testCos(startnstep) * radius;
  264.                 dy = y - testSin(startnstep) * radius;
  265.                 target.lineTo(dx, dy);
  266.             }
  267.         }
  268.  
  269.         /**
  270.          * a method for creating hand drawn polygon shapes.  Negative values will draw
  271.          * the polygon in reverse direction.  Negative drawing may be useful
  272.          * for creating knock-outs in masks.   
  273.          */
  274.         public static function handDrawPolygon(target:Graphics, x:Number, y:Number, sides:uint, radius:Number, wobbleFactor:Number = 0.05, angle:Number = 0):void {
  275.             if (sides <= 2) {
  276.                 throw ArgumentError("FastShapes.handDrawPolygon() - parameter 'sides' needs to be atleast 3");
  277.                 return;
  278.             }
  279.             var step:Number, start:Number, startnstep:Number, n:Number, dx:Number, dy:Number;
  280.             step = FastShapes.PI2 / sides;
  281.             start = angle * FastShapes.TO_RAD;
  282.             var p1:Point = new Point(x + (testCos(start) * radius), y - (testSin(start) * radius))
  283.             var p2:Point = new Point();
  284.             target.moveTo(p1.x, p1.y);
  285.             for (n = 1; n <= sides; ++n) {
  286.                 startnstep = start + (step * n);
  287.                 p2.x = x + testCos(startnstep) * radius; //dx
  288.                 p2.y = y - testSin(startnstep) * radius; //dy
  289.                 handDrawLine(target, p1, p2, wobbleFactor);
  290.                 p1.x = p2.x;
  291.                 p1.y = p2.y;
  292.             }
  293.         }
  294.  
  295.         /**
  296.          * Burst is a method for drawing star bursts.  If you've ever worked
  297.          * with an advertising department, you know what they are ;-)
  298.          * Clients tend to want them, Developers tend to hate them...      
  299.          */
  300.         public static function drawBurst(target:Graphics, x:Number, y:Number, sides:uint, innerRadius:Number, outerRadius:Number, angle:Number = 0):void {
  301.             if (sides <= 2) {
  302.                 throw ArgumentError("FastShapes.drawBurst - parameter 'sides' needs to be atleast 3");
  303.                 return;
  304.             }
  305.             var step:Number, halfStep:Number, qtrStep:Number, qtrStep3:Number, start:Number, n:Number, dx:Number, dy:Number, cx:Number, cy:Number;
  306.             var startnstep:Number, innercos:Number;
  307.             step = FastShapes.PI2 / sides;
  308.             qtrStep = step * 0.25;
  309.             halfStep = step * 0.5;
  310.             qtrStep3 = step * 0.75;
  311.             start = angle * FastShapes.TO_RAD;
  312.             target.moveTo(x + (testCos(start) * outerRadius), y - (testSin(start) * outerRadius));
  313.             for (n = 1; n <= sides; ++n) {
  314.                 startnstep = start + (step * n);
  315.                 innercos = (innerRadius / testCos(qtrStep));
  316.                 cx = x + testCos(startnstep - qtrStep3) * innercos;
  317.                 cy = y - testSin(startnstep - qtrStep3) * innercos;
  318.                 dx = x + testCos(startnstep - halfStep) * innerRadius;
  319.                 dy = y - testSin(startnstep - halfStep) * innerRadius;
  320.                 target.curveTo(cx, cy, dx, dy);
  321.                 cx = x + testCos(startnstep - qtrStep) * innercos;
  322.                 cy = y - testSin(startnstep - qtrStep) * innercos;
  323.                 dx = x + testCos(startnstep) * outerRadius;
  324.                 dy = y - testSin(startnstep) * outerRadius;
  325.                 target.curveTo(cx, cy, dx, dy);
  326.             }
  327.         }
  328.          
  329.         // draws a gear shape on the Graphics target             
  330.         public static function drawGear(target:Graphics, x:Number, y:Number, sides:uint, innerRadius:Number = 80, outerRadius:Number = 4, angle:Number = 0, holeSides:Number = 2, holeRadius:Number = 0):void {
  331.             if (sides <= 2) {
  332.                 throw ArgumentError("FastShapes.drawGear() - parameter 'sides' needs to be atleast 3");
  333.                 return;
  334.             }
  335.             var step:Number, startnstep:Number, qtrStep:Number, qtrStep2:Number, qtrStep3:Number, start:Number, n:Number, dx:Number, dy:Number;
  336.             step = FastShapes.PI2 / sides;
  337.             qtrStep = step * 0.25;
  338.             qtrStep2 = (qtrStep * 2);
  339.             qtrStep3 = (qtrStep * 3);
  340.             start = angle * FastShapes.TO_RAD;
  341.             target.moveTo(x + (testCos(start) * outerRadius), y - (testSin(start) * outerRadius));
  342.             for (n = 1; n <= sides; ++n) {
  343.                 startnstep = start + (step * n);
  344.                 dx = x + testCos(startnstep - qtrStep3) * innerRadius;
  345.                 dy = y - testSin(startnstep - qtrStep3) * innerRadius;
  346.                 target.lineTo(dx, dy);
  347.                 dx = x + testCos(startnstep - qtrStep2) * innerRadius;
  348.                 dy = y - testSin(startnstep - qtrStep2) * innerRadius;
  349.                 target.lineTo(dx, dy);
  350.                 dx = x + testCos(startnstep - qtrStep) * outerRadius;
  351.                 dy = y - testSin(startnstep - qtrStep) * outerRadius;
  352.                 target.lineTo(dx, dy);
  353.                 dx = x + testCos(startnstep) * outerRadius;
  354.                 dy = y - testSin(startnstep) * outerRadius;
  355.                 target.lineTo(dx, dy);
  356.             }
  357.             // This is complete overkill... but I had it done already. :)
  358.             if (holeSides > 2) {
  359.                 step = FastShapes.PI2 / holeSides;
  360.                 target.moveTo(x + (testCos(start) * holeRadius), y - (testSin(start) * holeRadius));
  361.                 for (n = 1; n <= holeSides; ++n) {
  362.                     startnstep = start + (step * n);
  363.                     dx = x + testCos(startnstep) * holeRadius;
  364.                     dy = y - testSin(startnstep) * holeRadius;
  365.                     target.lineTo(dx, dy);
  366.                 }
  367.             }
  368.         }
  369.  
  370.         //  draws a line between two points. Make it horizontal or vertical
  371.         public static function drawLine(target:Graphics, x:Number, y:Number, length:Number, direction:String = FastShapes.HORIZONTAL_LINE):void {
  372.             switch (direction) {
  373.             case FastShapes.HORIZONTAL_LINE:
  374.                 target.moveTo(x, y);
  375.                 target.lineTo(length, y);
  376.                 break;
  377.             case FastShapes.VERTICAL_LINE:
  378.                 target.moveTo(x, y);
  379.                 target.lineTo(x, length);
  380.                 break;
  381.             }
  382.         }
  383.     }
  384. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement