Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package com.ulfben.utils {
- import flash.display.*;
- import flash.geom.*;
- public class FastShapes {
- public static const HORIZONTAL_LINE:String = "FastShapes.horizontal";
- public static const VERTICAL_LINE:String = "FastShapes.vertical";
- public static const TO_RAD:Number = (Math.PI / 180);
- public static const TO_DEG:Number = (180 / Math.PI);
- public static const PI2:Number = Math.PI * 2;
- public static const HALF_PI:Number = Math.PI * 0.5;
- public static const QUARTER_PI:Number = Math.PI * 0.25;
- public static const EIGHTH_PI:Number = Math.PI * 0.125;
- /**
- * Creates look up tables for sin and cos, to reduce function calls.
- * index = int(angle * (2048/2PI))
- */
- public static var sCosLUT:Vector.<Number> = new Vector.<Number>(0x800, true);
- public static var sSinLUT:Vector.<Number> = new Vector.<Number>(0x800, true);
- public static function initLUTs():void {
- for (var i:int = 0; i < 0x800; ++i)
- {
- sCosLUT[i & 0x7FF] = Math.cos(i * 0.00306796157577128245943617517898); // 0.003067... is 2PI/2048
- sSinLUT[i & 0x7FF] = Math.sin(i * 0.00306796157577128245943617517898);
- }
- }
- public static function sinLUT(x:Number):Number{
- return sSinLUT[(x * 325.94932345220164765467394738691) & 2047]; // 325.949... is 2048/2PI
- }
- public static function cosLUT(x:Number):Number{
- return sCosLUT[((x * 325.94932345220164765467394738691) & 2047)]; //325.949... is 2048/2PI
- }
- public static function sinCoarse(x:Number):Number {
- if (x < -3.14159265) { //always wrap input angle to -PI..PI
- x += 6.28318531;
- } else if (x > 3.14159265) {
- x -= 6.28318531;
- }
- return (x < 0) ? (1.27323954 * x + .405284735 * x * x) : (1.27323954 * x - 0.405284735 * x * x);
- }
- public static function cosCoarse(x:Number):Number {
- if (x < -3.14159265) { //always wrap input angle to -PI..PI
- x += 6.28318531;
- } else if (x > 3.14159265) {
- x -= 6.28318531;
- }
- x += 1.57079632; // //compute cosine: sin(x + PI/2) = cos(x)
- if (x > 3.14159265) {
- x -= 6.28318531;
- }
- return (x < 0) ? (1.27323954 * x + 0.405284735 * x * x) : (1.27323954 * x - 0.405284735 * x * x);
- }
- public static function sinFine(x:Number):Number {
- if(x < -3.14159265) {
- x += 6.28318531;
- } else if(x > 3.14159265) {
- x -= 6.28318531;
- }
- x = (x < 0.0) ? (1.27323954 * x + .405284735 * x * x) : (1.27323954 * x - 0.405284735 * x * x)
- return (x < 0.0) ? (0.225 * (x *-x - x) + x) : (0.225 * (x * x - x) + x)
- }
- public static function cosFine(x:Number): Number {
- if(x < -3.14159265) {
- x += 6.28318531;
- } else if(x > 3.14159265) {
- x -= 6.28318531;
- }
- x += 1.57079632;
- if(x > 3.14159265) {
- x -= 6.28318531;
- }
- x = (x < 0.0) ? (1.27323954 * x + .405284735 * x * x) : (1.27323954 * x - 0.405284735 * x * x)
- return (x < 0.0) ? (0.225 * (x *-x - x) + x) : (0.225 * (x * x - x) + x)
- }
- public static var testCos:Function = cosFine; // cosLUT, cosCoarse, cosFine
- public static var testSin:Function = sinFine; // sinLUT, sinCoarse, sinFine
- public function FastShapes() {
- throw new ArgumentError("The FastShapes Class cannot be instanicated.");
- }
- /***
- * drawCircle
- * Since Flash Player 8 there is an internal drawCircle-method. Before that I
- * used this. At some point they should be benchmarked against eachother.
- */
- public static function drawCircle(target:Graphics, x:Number, y:Number, r:Number):void {
- var tan:Number = Math.tan(EIGHTH_PI) * r;
- var sin:Number = testSin(QUARTER_PI) * r;
- target.moveTo(x + r, y);
- target.curveTo(r + x, tan + y, sin + x, sin + y);
- target.curveTo(tan + x, r + y, x, r + y);
- target.curveTo((-tan) + x, r + y, (-sin) + x, sin + y);
- target.curveTo(-r + x, tan + y, -r + x, y);
- target.curveTo(-r + x, (-tan) + y, (-sin) + x, (-sin) + y);
- target.curveTo((-tan) + x, -r + y, x, -r + y);
- target.curveTo(tan + x, -r + y, sin + x, (-sin) + y);
- target.curveTo(r + x, (-tan) + y, r + x, y);
- target.moveTo(x, y);
- }
- // wobbleFactor in percent. 0.04-0.08 is a good default range.
- public static function handDrawLine(target:Graphics, startPoint:Point, endPoint:Point, wobbleFactor:Number = 0.05):void {
- var wobble:Number = Point.distance(startPoint, endPoint) * wobbleFactor;
- var r1:Number = Math.random();
- var r2:Number = Math.random();
- var xfactor:Number = Math.random() > 0.5 ? wobble : -wobble;
- var yfactor:Number = Math.random() > 0.5 ? wobble : -wobble;
- var control1:Point = new Point((endPoint.x - startPoint.x) * r1 + startPoint.x + xfactor, (endPoint.y - startPoint.y) * r1 + startPoint.y + yfactor);
- var control2:Point = new Point((endPoint.x - startPoint.x) * r2 + startPoint.x - xfactor, (endPoint.y - startPoint.y) * r2 + startPoint.y - yfactor);
- target.moveTo(startPoint.x, startPoint.y);
- target.cubicCurveTo(control1.x, control1.y, control2.x, control2.y, endPoint.x, endPoint.y);
- }
- // Draws a dashed line from the point x1,y1 to the point x2,y2
- public static function drawDash(target:Graphics, x1:Number, y1:Number, x2:Number, y2:Number, dashLength:Number = 5, spaceLength:Number = 5):void {
- var x:Number = x2 - x1;
- var y:Number = y2 - y1;
- var hyp:Number = Math.sqrt((x) * (x) + (y) * (y));
- var units:Number = hyp / (dashLength + spaceLength);
- var invertedUnits:Number = 1 / units;
- var dashSpaceRatio:Number = dashLength / (dashLength + spaceLength);
- var dashX:Number = (x * invertedUnits) * dashSpaceRatio;
- var spaceX:Number = (x * invertedUnits) - dashX;
- var dashY:Number = (y * invertedUnits) * dashSpaceRatio;
- var spaceY:Number = (y * invertedUnits) - dashY;
- target.moveTo(x1, y1);
- while (hyp > 0) {
- x1 += dashX;
- y1 += dashY;
- hyp -= dashLength;
- if (hyp < 0) {
- x1 = x2;
- y1 = y2;
- }
- target.lineTo(x1, y1);
- x1 += spaceX;
- y1 += spaceY;
- target.moveTo(x1, y1);
- hyp -= spaceLength;
- }
- target.moveTo(x2, y2);
- }
- //Draws an arc from the starting position of x,y.
- public static function drawArc(target:Graphics, x:Number, y:Number, radius:Number, arc:Number, startAngle:Number = 0, yRadius:Number = 0):void {
- if (yRadius == 0) {
- yRadius = radius;
- }
- 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;
- if (FastShapes.abs(arc) > 360) {
- arc = 360; // no sense in drawing more than is needed :)
- }
- // Flash uses 8 segments per circle, to match that, we draw in a maximum of 45 degree segments.
- segs = FastShapes.ceil(FastShapes.abs(arc) / 45);
- segAngle = arc / segs;
- theta = -(segAngle) * FastShapes.TO_RAD;
- angle = -(startAngle) * FastShapes.TO_RAD;
- ax = x - testCos(angle) * radius;
- ay = y - testSin(angle) * yRadius;
- if (segs > 0) {
- target.moveTo(x, y);
- halfTheta = theta * 0.5;
- var radiusCosHalfTheta:Number = radius / testCos(halfTheta);
- var yRadiusCosHalfTheta:Number = yRadius / testCos(halfTheta);
- for (var i:int = 0; i < segs; ++i) {
- angle += theta;
- angleMid = angle - halfTheta;
- bx = ax + testCos(angle) * radius;
- by = ay + testSin(angle) * yRadius;
- cx = ax + testCos(angleMid) * radiusCosHalfTheta;
- cy = ay + testSin(angleMid) * yRadiusCosHalfTheta;
- target.curveTo(cx, cy, bx, by);
- }
- }
- }
- // draws pie shaped wedges. Could be employed to draw pie charts.
- public static function drawWedge(target:Graphics, x:Number, y:Number, radius:Number, arc:Number, startAngle:Number = 0, yRadius:Number = 0):void {
- if (yRadius == 0) {
- yRadius = radius;
- }
- if (FastShapes.abs(arc) > 360) {
- arc = 360;
- }
- target.moveTo(x, y);
- 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;
- // Flash uses 8 segments per circle, to match that, we draw in a maximum of 45 degree segments.
- segs = FastShapes.ceil(FastShapes.abs(arc) / 45);
- segAngle = arc / segs;
- theta = -(segAngle) * FastShapes.TO_RAD;
- angle = -(startAngle) * FastShapes.TO_RAD;
- // draw the curve in segments no larger than 45 degrees.
- if (segs > 0) {
- ay = y + testSin(angle) * yRadius; //NOTE: angle is negative!
- ax = x + testCos(-angle) * radius; //NOTE: -angle == positive value here!
- target.lineTo(ax, ay);
- halfTheta = theta * 0.5;
- var radiusCosHalfTheta:Number = radius / testCos(halfTheta);
- var yRadiusCosHalfTheta:Number = yRadius / testCos(halfTheta);
- for (var i:int = 0; i < segs; ++i) {
- angle += theta;
- angleMid = angle - halfTheta;
- bx = x + testCos(angle) * radius;
- by = y + testSin(angle) * yRadius;
- cx = x + testCos(angleMid) * radiusCosHalfTheta;
- cy = y + testSin(angleMid) * yRadiusCosHalfTheta;
- target.curveTo(cx, cy, bx, by);
- }
- target.lineTo(x, y);
- }
- }
- // draws a star shaped polygon.
- public static function drawStar(target:Graphics, x:Number, y:Number, points:uint, innerRadius:Number, outerRadius:Number, angle:Number = 0):void {
- if (points <= 2) {
- throw ArgumentError("FastShapes.drawStar() - parameter 'points' needs to be atleast 3");
- return;
- }
- var step:Number, startnstep:Number, halfStep:Number, start:Number, n:Number, dx:Number, dy:Number;
- step = FastShapes.PI2 / points;
- halfStep = step * 0.5;
- start = angle * FastShapes.TO_RAD;
- target.moveTo(x + (testCos(start) * outerRadius), y - (testSin(start) * outerRadius));
- for (n = 1; n <= points; ++n) {
- startnstep = start + (step * n);
- dx = x + testCos(startnstep - halfStep) * innerRadius;
- dy = y - testSin(startnstep - halfStep) * innerRadius;
- target.lineTo(dx, dy);
- dx = x + testCos(startnstep) * outerRadius;
- dy = y - testSin(startnstep) * outerRadius;
- target.lineTo(dx, dy);
- }
- }
- /**
- * a method for creating polygon shapes. Negative values will draw
- * the polygon in reverse direction. Negative drawing may be useful
- * for creating knock-outs in masks.
- */
- public static function drawPolygon(target:Graphics, x:Number, y:Number, sides:uint, radius:Number, angle:Number = 0):void {
- if (sides <= 2) {
- throw ArgumentError("FastShapes.drawPolygon() - parameter 'sides' needs to be atleast 3");
- return;
- }
- var step:Number, startnstep:Number, start:Number, n:Number, dx:Number, dy:Number;
- step = FastShapes.PI2 / sides;
- start = angle * FastShapes.TO_RAD;
- target.moveTo(x + (testCos(start) * radius), y - (testSin(start) * radius));
- for (n = 1; n <= sides; ++n) {
- startnstep = start + (step * n);
- dx = x + testCos(startnstep) * radius;
- dy = y - testSin(startnstep) * radius;
- target.lineTo(dx, dy);
- }
- }
- /**
- * a method for creating hand drawn polygon shapes. Negative values will draw
- * the polygon in reverse direction. Negative drawing may be useful
- * for creating knock-outs in masks.
- */
- public static function handDrawPolygon(target:Graphics, x:Number, y:Number, sides:uint, radius:Number, wobbleFactor:Number = 0.05, angle:Number = 0):void {
- if (sides <= 2) {
- throw ArgumentError("FastShapes.handDrawPolygon() - parameter 'sides' needs to be atleast 3");
- return;
- }
- var step:Number, start:Number, startnstep:Number, n:Number, dx:Number, dy:Number;
- step = FastShapes.PI2 / sides;
- start = angle * FastShapes.TO_RAD;
- var p1:Point = new Point(x + (testCos(start) * radius), y - (testSin(start) * radius))
- var p2:Point = new Point();
- target.moveTo(p1.x, p1.y);
- for (n = 1; n <= sides; ++n) {
- startnstep = start + (step * n);
- p2.x = x + testCos(startnstep) * radius; //dx
- p2.y = y - testSin(startnstep) * radius; //dy
- handDrawLine(target, p1, p2, wobbleFactor);
- p1.x = p2.x;
- p1.y = p2.y;
- }
- }
- /**
- * Burst is a method for drawing star bursts. If you've ever worked
- * with an advertising department, you know what they are ;-)
- * Clients tend to want them, Developers tend to hate them...
- */
- public static function drawBurst(target:Graphics, x:Number, y:Number, sides:uint, innerRadius:Number, outerRadius:Number, angle:Number = 0):void {
- if (sides <= 2) {
- throw ArgumentError("FastShapes.drawBurst - parameter 'sides' needs to be atleast 3");
- return;
- }
- var step:Number, halfStep:Number, qtrStep:Number, qtrStep3:Number, start:Number, n:Number, dx:Number, dy:Number, cx:Number, cy:Number;
- var startnstep:Number, innercos:Number;
- step = FastShapes.PI2 / sides;
- qtrStep = step * 0.25;
- halfStep = step * 0.5;
- qtrStep3 = step * 0.75;
- start = angle * FastShapes.TO_RAD;
- target.moveTo(x + (testCos(start) * outerRadius), y - (testSin(start) * outerRadius));
- for (n = 1; n <= sides; ++n) {
- startnstep = start + (step * n);
- innercos = (innerRadius / testCos(qtrStep));
- cx = x + testCos(startnstep - qtrStep3) * innercos;
- cy = y - testSin(startnstep - qtrStep3) * innercos;
- dx = x + testCos(startnstep - halfStep) * innerRadius;
- dy = y - testSin(startnstep - halfStep) * innerRadius;
- target.curveTo(cx, cy, dx, dy);
- cx = x + testCos(startnstep - qtrStep) * innercos;
- cy = y - testSin(startnstep - qtrStep) * innercos;
- dx = x + testCos(startnstep) * outerRadius;
- dy = y - testSin(startnstep) * outerRadius;
- target.curveTo(cx, cy, dx, dy);
- }
- }
- // draws a gear shape on the Graphics target
- 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 {
- if (sides <= 2) {
- throw ArgumentError("FastShapes.drawGear() - parameter 'sides' needs to be atleast 3");
- return;
- }
- var step:Number, startnstep:Number, qtrStep:Number, qtrStep2:Number, qtrStep3:Number, start:Number, n:Number, dx:Number, dy:Number;
- step = FastShapes.PI2 / sides;
- qtrStep = step * 0.25;
- qtrStep2 = (qtrStep * 2);
- qtrStep3 = (qtrStep * 3);
- start = angle * FastShapes.TO_RAD;
- target.moveTo(x + (testCos(start) * outerRadius), y - (testSin(start) * outerRadius));
- for (n = 1; n <= sides; ++n) {
- startnstep = start + (step * n);
- dx = x + testCos(startnstep - qtrStep3) * innerRadius;
- dy = y - testSin(startnstep - qtrStep3) * innerRadius;
- target.lineTo(dx, dy);
- dx = x + testCos(startnstep - qtrStep2) * innerRadius;
- dy = y - testSin(startnstep - qtrStep2) * innerRadius;
- target.lineTo(dx, dy);
- dx = x + testCos(startnstep - qtrStep) * outerRadius;
- dy = y - testSin(startnstep - qtrStep) * outerRadius;
- target.lineTo(dx, dy);
- dx = x + testCos(startnstep) * outerRadius;
- dy = y - testSin(startnstep) * outerRadius;
- target.lineTo(dx, dy);
- }
- // This is complete overkill... but I had it done already. :)
- if (holeSides > 2) {
- step = FastShapes.PI2 / holeSides;
- target.moveTo(x + (testCos(start) * holeRadius), y - (testSin(start) * holeRadius));
- for (n = 1; n <= holeSides; ++n) {
- startnstep = start + (step * n);
- dx = x + testCos(startnstep) * holeRadius;
- dy = y - testSin(startnstep) * holeRadius;
- target.lineTo(dx, dy);
- }
- }
- }
- // draws a line between two points. Make it horizontal or vertical
- public static function drawLine(target:Graphics, x:Number, y:Number, length:Number, direction:String = FastShapes.HORIZONTAL_LINE):void {
- switch (direction) {
- case FastShapes.HORIZONTAL_LINE:
- target.moveTo(x, y);
- target.lineTo(length, y);
- break;
- case FastShapes.VERTICAL_LINE:
- target.moveTo(x, y);
- target.lineTo(x, length);
- break;
- }
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement