Posted By

adrianparr on 10/03/12


Tagged

line graphics draw Drawing as3 dash Shape Star Gear wedge shapes polygon arc burst dashed


Versions (?)

AS3 Drawing Shapes (ARC, BURST, DASHED-LINE, GEAR, POLYGON, STAR, WEDGE, LINE)


 / Published in: ActionScript 3
 

Credit for this goes to Adobe, Ric Ewing, Kevin Williams, Aden Forshaw and Sidney de Koning.

  1. package nl.funkymonkey.drawing
  2. {
  3. import flash.display.*;
  4.  
  5. /**
  6. * based on source code found at:
  7. * http://www.macromedia.com/devnet/mx/flash/articles/adv_draw_methods.html
  8. *
  9. * @author Ric Ewing - version 1.4 - 4.7.2002
  10. * @author Kevin Williams - version 2.0 - 4.7.2005
  11. * @author Aden Forshaw - Version AS3 - 19.4.2010
  12. * @author Sidney de Koning - Version AS3 - 20.4.2010 - errors/correct datatypes/optimized math operations
  13. *
  14. * Usage:
  15. * var s : Shape = new Shape( ); // Or Sprite of MovieClip or any other Class that makes use of the Graphics class
  16. *
  17. * // Draw an ARC
  18. * s.graphics.lineStyle( 4, 0xE16606 );
  19. * DrawingShapes.drawArc( s.graphics, 50, 50, 10, 150, 60 );
  20. *
  21. * // Draw an BURST
  22. * s.graphics.lineStyle( 3, 0x000000 );
  23. * DrawingShapes.drawBurst( s.graphics, 80, 60, 3, 15, 6, 27 );
  24. *
  25. * // Draw an DASHED-LINE like so - - - -
  26. * s.graphics.lineStyle( 1, 0x3C3C39 );
  27. * DrawingShapes.drawDash( s.graphics, 120, 60, 150, 80, 2, 2 );
  28. *
  29. * // Draw an GEAR
  30. * s.graphics.lineStyle( 3, 0xE16606 );
  31. * DrawingShapes.drawGear( s.graphics, 200, 60, 13, 31, 26, 0, 7, 13 );
  32. *
  33. * // Draw a POLYGON
  34. * s.graphics.lineStyle( 3, 0x0074B9 );
  35. * DrawingShapes.drawPolygon( s.graphics, 270, 60, 7, 30, 45 );
  36. *
  37. * // Draw a STAR
  38. * s.graphics.lineStyle( 2, 0x000000 );
  39. * DrawingShapes.drawStar( s.graphics, 340, 60, 18, 24, 19, 27 );
  40. *
  41. * // Draw an WEDGE - good for pie charts or pacmans
  42. * s.graphics.lineStyle( 2, 0xFFCC00 );
  43. * DrawingShapes.drawWedge( s.graphics, 400, 60, 30, 309, 209 );
  44. *
  45. * // Draw a LINE
  46. * s.graphics.lineStyle( 2, 0x0074B9 );
  47. * DrawingShapes.drawLine( s.graphics, 440, 85, 30, DrawingShapes.VERTICAL_LINE );
  48. *
  49. * addChild( s );
  50. */
  51. public class DrawingShapes
  52. {
  53.  
  54. public static const HORIZONTAL_LINE:String = "DrawingShapes.horizontal";
  55. public static const VERTICAL_LINE:String = "DrawingShapes.vertical";
  56.  
  57.  
  58. public function DrawingShapes()
  59. {
  60. throw new ArgumentError("The DrawingShapes Class cannot be instanicated.");
  61. }
  62.  
  63. /**
  64. * drawDash
  65. * Draws a dashed line from the point x1,y1 to the point x2,y2
  66. *
  67. * @param target Graphics the Graphics Class on which the dashed line will be drawn.
  68. * @param x1 Number starting position on x axis - <strong>required</strong>
  69. * @param y1 Number starting position on y axis - <strong>required</strong>
  70. * @param x2 Number finishing position on x axis - <strong>required</strong>
  71. * @param y2 Number finishing position on y axis - <strong>required</strong>
  72. * @param dashLength [optional] Number the number of pixels long each dash
  73. * will be. Default = 5
  74. * @param spaceLength [optional] Number the number of pixels between each
  75. * dash. Default = 5
  76. */
  77. public static function drawDash(target:Graphics, x1:Number, y1:Number, x2:Number, y2:Number, dashLength:Number=5, spaceLength:Number=5):void
  78. {
  79.  
  80. var x:Number = x2 - x1;
  81. var y:Number = y2 - y1;
  82. var hyp:Number = Math.sqrt((x) * (x) + (y) * (y));
  83. var units:Number = hyp / (dashLength + spaceLength);
  84. var dashSpaceRatio:Number = dashLength / (dashLength + spaceLength);
  85. var dashX:Number = (x / units) * dashSpaceRatio;
  86. var spaceX:Number = (x / units) - dashX;
  87. var dashY:Number = (y / units) * dashSpaceRatio;
  88. var spaceY:Number = (y / units) - dashY;
  89.  
  90. target.moveTo(x1, y1);
  91. while (hyp > 0)
  92. {
  93. x1 += dashX;
  94. y1 += dashY;
  95. hyp -= dashLength;
  96. if (hyp < 0)
  97. {
  98. x1 = x2;
  99. y1 = y2;
  100. }
  101. target.lineTo(x1, y1);
  102. x1 += spaceX;
  103. y1 += spaceY;
  104. target.moveTo(x1, y1);
  105. hyp -= spaceLength;
  106. }
  107. target.moveTo(x2, y2);
  108. }
  109.  
  110. /**
  111. * Draws an arc from the starting position of x,y.
  112. *
  113. * @param target the Graphics Class that the Arc is drawn on.
  114. * @param x x coordinate of the starting pen position
  115. * @param y y coordinate of the starting pen position
  116. * @param radius radius of Arc.
  117. * @param arc = sweep of the arc. Negative values draw clockwise.
  118. * @param startAngle = [optional] starting offset angle in degrees.
  119. * @param yRadius = [optional] y radius of arc. if different than
  120. * radius, then the arc will draw as the arc of an oval.
  121. * default = radius.
  122. *
  123. * Based on mc.drawArc by Ric Ewing.
  124. * the version by Ric assumes that the pen is at x:y before this
  125. * method is called. I explictily move the pen to x:y to be
  126. * consistent with the behaviour of the other methods.
  127. */
  128. public static function drawArc(target:Graphics, x:Number, y:Number, radius:Number, arc:Number, startAngle:Number=0, yRadius:Number=0):void
  129. {
  130.  
  131. if (arguments.length < 5)
  132. {
  133. throw new ArgumentError("DrawingShapes.drawArc() - too few parameters, need atleast 5.");
  134. return;
  135. }
  136.  
  137. // if startAngle is undefined, startAngle = 0
  138. if (startAngle == 0)
  139. {
  140. startAngle = 0;
  141. }
  142. // if yRadius is undefined, yRadius = radius
  143. if (yRadius == 0)
  144. {
  145. yRadius = radius;
  146. }
  147.  
  148. // Init vars
  149. var segAngle:Number, theta:Number, angle:Number, angleMid:Number, segs:Number, ax:Number, ay:Number, bx:Number, by:Number, cx:Number, cy:Number;
  150. // no sense in drawing more than is needed :)
  151. if (DrawingShapes.abs(arc) > 360)
  152. {
  153. arc = 360;
  154. }
  155. // Flash uses 8 segments per circle, to match that, we draw in a maximum
  156. // of 45 degree segments. First we calculate how many segments are needed
  157. // for our arc.
  158. segs = DrawingShapes.ceil(DrawingShapes.abs(arc) / 45);
  159. // Now calculate the sweep of each segment
  160. segAngle = arc / segs;
  161. // The math requires radians rather than degrees. To convert from degrees
  162. // use the formula (degrees/180)*Math.PI to get radians.
  163. theta = -(segAngle / 180) * Math.PI;
  164. // convert angle startAngle to radians
  165. angle = -(startAngle / 180) * Math.PI;
  166. // find our starting points (ax,ay) relative to the secified x,y
  167. ax = x - Math.cos(angle) * radius;
  168. ay = y - Math.sin(angle) * yRadius;
  169. // if our arc is larger than 45 degrees, draw as 45 degree segments
  170. // so that we match Flash's native circle routines.
  171. if (segs > 0)
  172. {
  173. target.moveTo(x, y);
  174. // Loop for drawing arc segments
  175. for (var i:int = 0; i < segs; ++i)
  176. {
  177. // increment our angle
  178. angle += theta;
  179. // find the angle halfway between the last angle and the new
  180. angleMid = angle - (theta / 2);
  181. // calculate our end point
  182. bx = ax + Math.cos(angle) * radius;
  183. by = ay + Math.sin(angle) * yRadius;
  184. // calculate our control point
  185. cx = ax + Math.cos(angleMid) * (radius / Math.cos(theta / 2));
  186. cy = ay + Math.sin(angleMid) * (yRadius / Math.cos(theta / 2));
  187. // draw the arc segment
  188. target.curveTo(cx, cy, bx, by);
  189. }
  190. }
  191. }
  192.  
  193. /**
  194. * draws pie shaped wedges. Could be employeed to draw pie charts.
  195. *
  196. * @param target the Graphics on which the wedge is to be drawn.
  197. * @param x x coordinate of the center point of the wedge
  198. * @param y y coordinate of the center point of the wedge
  199. * @param radius the radius of the wedge
  200. * @param arc the sweep of the wedge. negative values draw clockwise
  201. * @param startAngle the starting angle in degrees
  202. * @param yRadius [optional] the y axis radius of the wedge.
  203. * If not defined, then yRadius = radius.
  204. *
  205. * based on mc.drawWedge() - by Ric Ewing (ric at formequalsfunction.com) - version 1.4 - 4.7.2002
  206. */
  207. public static function drawWedge(target:Graphics, x:Number, y:Number, radius:Number, arc:Number, startAngle:Number=0, yRadius:Number=0):void
  208. {
  209.  
  210. // if yRadius is undefined, yRadius = radius
  211. if (yRadius == 0)
  212. {
  213. yRadius = radius;
  214. }
  215.  
  216. // move to x,y position
  217. target.moveTo(x, y);
  218. // if yRadius is undefined, yRadius = radius
  219. if (yRadius == 0)
  220. {
  221. yRadius = radius;
  222. }
  223. // Init vars
  224. var segAngle:Number, theta:Number, angle:Number, angleMid:Number, segs:Number, ax:Number, ay:Number, bx:Number, by:Number, cx:Number, cy:Number;
  225. // limit sweep to reasonable numbers
  226. if (DrawingShapes.abs(arc) > 360)
  227. {
  228. arc = 360;
  229. }
  230. // Flash uses 8 segments per circle, to match that, we draw in a maximum
  231. // of 45 degree segments. First we calculate how many segments are needed
  232. // for our arc.
  233. segs = DrawingShapes.ceil(DrawingShapes.abs(arc) / 45);
  234. // Now calculate the sweep of each segment.
  235. segAngle = arc / segs;
  236. // The math requires radians rather than degrees. To convert from degrees
  237. // use the formula (degrees/180)*Math.PI to get radians.
  238. theta = -(segAngle / 180) * Math.PI;
  239. // convert angle startAngle to radians
  240. angle = -(startAngle / 180) * Math.PI;
  241. // draw the curve in segments no larger than 45 degrees.
  242. if (segs > 0)
  243. {
  244. // draw a line from the center to the start of the curve
  245. ax = x + Math.cos(startAngle / 180 * Math.PI) * radius;
  246. ay = y + Math.sin(-startAngle / 180 * Math.PI) * yRadius;
  247. target.lineTo(ax, ay);
  248. // Loop for drawing curve segments
  249. for (var i:int = 0; i < segs; ++i)
  250. {
  251. angle += theta;
  252. angleMid = angle - (theta / 2);
  253. bx = x + Math.cos(angle) * radius;
  254. by = y + Math.sin(angle) * yRadius;
  255. cx = x + Math.cos(angleMid) * (radius / Math.cos(theta / 2));
  256. cy = y + Math.sin(angleMid) * (yRadius / Math.cos(theta / 2));
  257. target.curveTo(cx, cy, bx, by);
  258. }
  259. // close the wedge by drawing a line to the center
  260. target.lineTo(x, y);
  261. }
  262. }
  263.  
  264. /**
  265. * start draws a star shaped polygon.
  266. *
  267. * <blockquote>Note that the stars by default 'point' to
  268. * the right. This is because the method starts drawing
  269. * at 0 degrees by default, putting the first point to
  270. * the right of center. Negative values for points
  271. * draws the star in reverse direction, allowing for
  272. * knock-outs when used as part of a mask.</blockquote>
  273. *
  274. * @param target the Graphics that the star is drawn on
  275. * @param x x coordinate of the center of the star
  276. * @param y y coordinate of the center of the star
  277. * @param points the number of points on the star
  278. * @param innerRadius the radius of the inside angles of the star
  279. * @param outerRadius the radius of the outside angles of the star
  280. * @param angle [optional] the offet angle that the start is rotated
  281. *
  282. * based on mc.drawStar() - by Ric Ewing (ric at formequalsfunction.com) - version 1.4 - 4.7.2002
  283. */
  284. public static function drawStar(target:Graphics, x:Number, y:Number, points:uint, innerRadius:Number, outerRadius:Number, angle:Number=0):void
  285. {
  286.  
  287. // check that points is sufficient to build polygon
  288. if (points <= 2)
  289. {
  290. throw ArgumentError("DrawingShapes.drawStar() - parameter 'points' needs to be atleast 3");
  291. return;
  292. }
  293. if (points > 2)
  294. {
  295. // init vars
  296. var step:Number, halfStep:Number, start:Number, n:Number, dx:Number, dy:Number;
  297. // calculate distance between points
  298. step = (Math.PI * 2) / points;
  299. halfStep = step / 2;
  300. // calculate starting angle in radians
  301. start = (angle / 180) * Math.PI;
  302. target.moveTo(x + (Math.cos(start) * outerRadius), y - (Math.sin(start) * outerRadius));
  303. // draw lines
  304. for (n = 1; n <= points; ++n)
  305. {
  306. dx = x + Math.cos(start + (step * n) - halfStep) * innerRadius;
  307. dy = y - Math.sin(start + (step * n) - halfStep) * innerRadius;
  308. target.lineTo(dx, dy);
  309. dx = x + Math.cos(start + (step * n)) * outerRadius;
  310. dy = y - Math.sin(start + (step * n)) * outerRadius;
  311. target.lineTo(dx, dy);
  312. }
  313. }
  314. }
  315.  
  316. /**
  317. * a method for creating polygon shapes. Negative values will draw
  318. * the polygon in reverse direction. Negative drawing may be useful
  319. * for creating knock-outs in masks.
  320. *
  321. * @param target the Graphics that the polygon is to be drawn on
  322. * @param x x coordinate of the center of the polygon
  323. * @param y y coordinate of the center of the polygon
  324. * @param sides the number of sides (must be > 2)
  325. * @param radius the radius from the center point to the points
  326. * on the polygon
  327. * @param angle [optional] the starting offset angle (degrees) from
  328. * 0. Default = 0
  329. *
  330. * based on mc.drawPoly() - by Ric Ewing (ric at formequalsfunction.com) - version 1.4 - 4.7.2002
  331. */
  332. public static function drawPolygon(target:Graphics, x:Number, y:Number, sides:uint, radius:Number, angle:Number=0):void
  333. {
  334.  
  335. // check that sides is sufficient to build
  336. if (sides <= 2)
  337. {
  338. throw ArgumentError("DrawingShapes.drawPolygon() - parameter 'sides' needs to be atleast 3");
  339. return;
  340. }
  341. if (sides > 2)
  342. {
  343. // init vars
  344. var step:Number, start:Number, n:Number, dx:Number, dy:Number;
  345. // calculate span of sides
  346. step = (Math.PI * 2) / sides;
  347. // calculate starting angle in radians
  348. start = (angle / 180) * Math.PI;
  349. target.moveTo(x + (Math.cos(start) * radius), y - (Math.sin(start) * radius));
  350. // draw the polygon
  351. for (n = 1; n <= sides; ++n)
  352. {
  353. dx = x + Math.cos(start + (step * n)) * radius;
  354. dy = y - Math.sin(start + (step * n)) * radius;
  355. target.lineTo(dx, dy);
  356. }
  357. }
  358. }
  359.  
  360. /**
  361. * Burst is a method for drawing star bursts. If you've ever worked
  362. * with an advertising department, you know what they are ;-)
  363. * Clients tend to want them, Developers tend to hate them...
  364. *
  365. * @param target Graphics where the Burst is to be drawn.
  366. * @param x x coordinate of the center of the burst
  367. * @param y y coordinate of the center of the burst
  368. * @param sides number of sides or points
  369. * @param innerRadius radius of the indent of the curves
  370. * @param outerRadius radius of the outermost points
  371. * @param angle [optional] starting angle in degrees. (defaults to 0)
  372. *
  373. * based on mc.drawBurst() - by Ric Ewing (ric at formequalsfunction.com) - version 1.4 - 4.7.2002
  374. */
  375. public static function drawBurst(target:Graphics, x:Number, y:Number, sides:uint, innerRadius:Number, outerRadius:Number, angle:Number=0):void
  376. {
  377.  
  378. // check that sides is sufficient to build
  379. if (sides <= 2)
  380. {
  381. throw ArgumentError("DrawingShapes.drawBurst() - parameter 'sides' needs to be atleast 3");
  382. return;
  383. }
  384. if (sides > 2)
  385. {
  386. // init vars
  387. var step:Number, halfStep:Number, qtrStep:Number, start:Number, n:Number, dx:Number, dy:Number, cx:Number, cy:Number;
  388. // calculate length of sides
  389. step = (Math.PI * 2) / sides;
  390. halfStep = step / 2;
  391. qtrStep = step / 4;
  392. // calculate starting angle in radians
  393. start = (angle / 180) * Math.PI;
  394. target.moveTo(x + (Math.cos(start) * outerRadius), y - (Math.sin(start) * outerRadius));
  395. // draw curves
  396. for (n = 1; n <= sides; ++n)
  397. {
  398. cx = x + Math.cos(start + (step * n) - (qtrStep * 3)) * (innerRadius / Math.cos(qtrStep));
  399. cy = y - Math.sin(start + (step * n) - (qtrStep * 3)) * (innerRadius / Math.cos(qtrStep));
  400. dx = x + Math.cos(start + (step * n) - halfStep) * innerRadius;
  401. dy = y - Math.sin(start + (step * n) - halfStep) * innerRadius;
  402. target.curveTo(cx, cy, dx, dy);
  403. cx = x + Math.cos(start + (step * n) - qtrStep) * (innerRadius / Math.cos(qtrStep));
  404. cy = y - Math.sin(start + (step * n) - qtrStep) * (innerRadius / Math.cos(qtrStep));
  405. dx = x + Math.cos(start + (step * n)) * outerRadius;
  406. dy = y - Math.sin(start + (step * n)) * outerRadius;
  407. target.curveTo(cx, cy, dx, dy);
  408. }
  409. }
  410. }
  411.  
  412. /**
  413. * draws a gear shape on the Graphics target. The gear position
  414. * is indicated by the x and y arguments.
  415. *
  416. * @param target Graphics on which the gear is to be drawn.
  417. * @param x x coordinate of the center of the gear
  418. * @param y y coordinate of the center of the gear
  419. * @param sides number of teeth on gear. (must be > 2)
  420. * @param innerRadius radius of the indent of the teeth.
  421. * @param outerRadius outer radius of the teeth.
  422. * @param angle = [optional] starting angle in degrees. Defaults to 0.
  423. * @param holeSides [optional] draw a polygonal hole with this many sides (must be > 2)
  424. * @param holeRadius [optional] size of hole. Default = innerRadius/3.
  425. *
  426. * based on mc.drawGear() - by Ric Ewing (ric at formequalsfunction.com) - version 1.4 - 4.7.2002
  427. */
  428. 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
  429. {
  430.  
  431. // check that sides is sufficient to build polygon
  432. if (sides <= 2)
  433. {
  434. throw ArgumentError("DrawingShapes.drawGear() - parameter 'sides' needs to be atleast 3");
  435. return;
  436. }
  437. if (sides > 2)
  438. {
  439. // init vars
  440. var step:Number, qtrStep:Number, start:Number, n:Number, dx:Number, dy:Number;
  441. // calculate length of sides
  442. step = (Math.PI * 2) / sides;
  443. qtrStep = step / 4;
  444. // calculate starting angle in radians
  445. start = (angle / 180) * Math.PI;
  446. target.moveTo(x + (Math.cos(start) * outerRadius), y - (Math.sin(start) * outerRadius));
  447. // draw lines
  448. for (n = 1; n <= sides; ++n)
  449. {
  450. dx = x + Math.cos(start + (step * n) - (qtrStep * 3)) * innerRadius;
  451. dy = y - Math.sin(start + (step * n) - (qtrStep * 3)) * innerRadius;
  452. target.lineTo(dx, dy);
  453. dx = x + Math.cos(start + (step * n) - (qtrStep * 2)) * innerRadius;
  454. dy = y - Math.sin(start + (step * n) - (qtrStep * 2)) * innerRadius;
  455. target.lineTo(dx, dy);
  456. dx = x + Math.cos(start + (step * n) - qtrStep) * outerRadius;
  457. dy = y - Math.sin(start + (step * n) - qtrStep) * outerRadius;
  458. target.lineTo(dx, dy);
  459. dx = x + Math.cos(start + (step * n)) * outerRadius;
  460. dy = y - Math.sin(start + (step * n)) * outerRadius;
  461. target.lineTo(dx, dy);
  462. }
  463. // This is complete overkill... but I had it done already. :)
  464. if (holeSides > 2)
  465. {
  466. step = (Math.PI * 2) / holeSides;
  467. target.moveTo(x + (Math.cos(start) * holeRadius), y - (Math.sin(start) * holeRadius));
  468. for (n = 1; n <= holeSides; ++n)
  469. {
  470. dx = x + Math.cos(start + (step * n)) * holeRadius;
  471. dy = y - Math.sin(start + (step * n)) * holeRadius;
  472. target.lineTo(dx, dy);
  473. }
  474. }
  475. }
  476. }
  477.  
  478. /**
  479. * draws a line between two points. Make it horizontal or vertical
  480. *
  481. * @param target Graphics on which the gear is to be drawn.
  482. * @param x x coordinate of the center of the gear
  483. * @param y y coordinate of the center of the gear
  484. * @param sides number of teeth on gear. (must be > 2)
  485. *
  486. *
  487. */
  488. public static function drawLine(target:Graphics, x:Number, y:Number, length:Number, direction:String=DrawingShapes.HORIZONTAL_LINE):void
  489. {
  490. target.moveTo(x, y);
  491. switch (direction)
  492. {
  493. case DrawingShapes.HORIZONTAL_LINE:
  494. target.lineTo(length, y);
  495. break;
  496. case DrawingShapes.VERTICAL_LINE:
  497. target.moveTo(x, y);
  498. target.lineTo(x, length);
  499. break;
  500. }
  501. }
  502.  
  503. /*
  504. * new abs function, about 25x faster than Math.abs
  505. */
  506. private static function abs(value:Number):Number
  507. {
  508. return value < 0 ? -value : value;
  509. }
  510.  
  511. /*
  512. * new ceil function about 75% faster than Math.ceil.
  513. */
  514. private static function ceil(value:Number):Number
  515. {
  516. return (value % 1) ? int(value) + 1 : value;
  517. }
  518. }
  519. }

Report this snippet  

You need to login to post a comment.