Bezier Skin (smooth curveTo())

Actionscript:
  1. // graphics, vector of xy coords, closed boolean
  2. function bezierSkin(g:Graphics, bez:Vector.<Number>, closed:Boolean = true):void {
  3.     var avg:Vector.<Number> = calcAvgs(bez);
  4.     var i:int, n:int;
  5.     var leng:int = bez.length;
  6.  
  7.     if (closed){
  8.         g.moveTo(avg[0], avg[1]);
  9.         for (i = 2; i <leng; i+=2) {
  10.             n=i+1;
  11.             g.curveTo(bez[i], bez[n], avg[i], avg[n]);
  12.         }
  13.         g.curveTo(bez[0], bez[1], avg[0], avg[1]);
  14.     }else{
  15.         g.moveTo(bez[0], bez[1]);
  16.         g.lineTo(avg[0], avg[1]);
  17.         for (i = 2; i <leng-2; i+=2) {
  18.             n=i+1;
  19.             g.curveTo(bez[i], bez[n], avg[i], avg[n]);
  20.         }
  21.         g.lineTo(bez[ leng - 2], bez[ leng - 1]);
  22.     }
  23. }
  24.  
  25. // create anchor points by averaging the control points
  26. function calcAvgs(v:Vector.<Number>):Vector.<Number> {
  27.     var avg:Vector.<Number> = new Vector.<Number>();
  28.     var leng:int=v.length;
  29.     for (var i:int = 2; i<leng; i+=1) {
  30.         var prev:Number=i-2;
  31.         avg.push( (v[prev] + v[i]) / 2 );
  32.     }
  33.     // close
  34.     avg.push( (v[0] + v[ leng - 2]) / 2 );
  35.     avg.push( (v[1] + v[ leng - 1]) / 2 );
  36.     return avg;
  37. }
  38.  
  39. // test out the functions:
  40.  
  41. graphics.lineStyle(0,0x000000);
  42.  
  43. // draw a very rounded rect
  44. bezierSkin(graphics, Vector.<Number>([100,100,200,100,200,200,100,200]) );
  45.  
  46. // draw a random curve with 10 xy coords
  47. var rnd:Vector.<Number> = new Vector.<Number>();
  48. for (var i:int = 0; i<20; i++) rnd.push(Math.random()*100);
  49. bezierSkin(graphics, rnd);
  50.                        
  51. // erase everything and allow the used to draw a smooth curve with the mouse
  52. stage.addEventListener(MouseEvent.MOUSE_DOWN, onLoop);
  53. var index:int = 0;
  54. var pnts:Vector.<Number> = new Vector.<Number>();
  55.  
  56. function onLoop(evt:MouseEvent):void {
  57.      pnts.push(mouseX);
  58.      pnts.push(mouseY);
  59.    
  60.      graphics.clear();
  61.      graphics.lineStyle(0,0x000000);
  62.      
  63.       // draw a smooth curved line
  64.      bezierSkin(graphics,pnts,false);
  65. }

The above code uses averaging to generate anchor points for curveTo() calls. This is an easy way to always draw smooth curves.

This is an old one that I've seen floating around since the drawing api first came out... but I it's an important snippet, so I figured I'd post it.

This entry was posted in Graphics, bezier and tagged , , . Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*