Tag Archives: actionscript

ActionScript Wiki

Just wanted to post a link to Joa Ebert’s ActionScript Wiki. Looks like there’s some great stuff there…

Posted in misc | Also tagged | Leave a comment

Catmull-Rom Spline

Actionscript:
  1. var canvas:BitmapData = new BitmapData(400,400,false, 0x000000);
  2. addChild(new Bitmap(canvas));
  3.  
  4. var p0:Sprite = dot(100, 100);
  5. var p1:Sprite = dot(120, 180);
  6. var p2:Sprite = dot(220, 180);
  7. var p3:Sprite = dot(250, 250);
  8.  
  9. addEventListener(Event.ENTER_FRAME, onLoop);
  10. function onLoop(evt:Event):void {
  11.     canvas.lock();  
  12.     canvas.fillRect(canvas.rect, 0x000000);
  13.  
  14.     curve(p0, p1, p2, p3);
  15.     canvas.unlock();
  16. }
  17.  
  18.  
  19. // all math from http://en.wikipedia.org/wiki/Cubic_Hermite_spline
  20. function curve(p0:Sprite, p1:Sprite, p2:Sprite, p3:Sprite, rez:Number=.02):void{
  21.     var px:Number = 0;
  22.     var py:Number = 0;
  23.     var m0:Point = tangent(p1, p0);
  24.     var m1:Point = tangent(p2, p0);
  25.     var m2:Point = tangent(p3, p1);
  26.     var m3:Point = tangent(p3, p2);
  27.    
  28.     for (var t:Number = 0; t <1; t+=rez){
  29.          var t_2:Number = t * t;
  30.          var _1_t:Number = 1 - t;
  31.          var _2t:Number = 2 * t;
  32.          
  33.          var h00:Number =  (1 + _2t) * (_1_t) * (_1_t);
  34.          var h10:Number =  t  * (_1_t) * (_1_t);
  35.          var h01:Number =  t_2 * (3 - _2t);
  36.          var h11:Number =  t_2 * (t - 1);
  37.          
  38.          px = h00 * p0.x + h10 * m0.x + h01 * p1.x + h11 * m1.x;
  39.          py = h00 * p0.y + h10 * m0.y + h01 * p1.y + h11 * m1.y;
  40.          canvas.setPixel(px, py, 0xFFFFFF);
  41.          
  42.          px = h00 * p1.x + h10 * m1.x + h01 * p2.x + h11 * m2.x;
  43.          py = h00 * p1.y + h10 * m1.y + h01 * p2.y + h11 * m2.y;
  44.          canvas.setPixel(px, py, 0xFFFFFF);
  45.          
  46.          px = h00 * p2.x + h10 * m2.x + h01 * p3.x + h11 * m3.x;
  47.          py = h00 * p2.y + h10 * m2.y + h01 * p3.y + h11 * m3.y;
  48.          canvas.setPixel(px, py, 0xFFFFFF);
  49.     }
  50. }
  51.  
  52. function tangent(pk1:Sprite, pk_1:Sprite){
  53.     return new Point((pk1.x - pk_1.x) / 2, (pk1.y - pk_1.y) / 2);
  54. }
  55.  
  56. // draggable dot
  57. function dot(xp:Number, yp:Number, col:uint = 0x507399, rad:Number=5):Sprite {
  58.     var s:Sprite = Sprite(addChild(new Sprite));
  59.     s.x = xp;
  60.     s.y = yp;
  61.     with(s.graphics) beginFill(col), drawCircle(0,0,rad);
  62.     s.buttonMode = true;
  63.     s.addEventListener(MouseEvent.MOUSE_DOWN, onDrag);
  64.     return s;
  65. }
  66. function onDrag(evt:MouseEvent):void {
  67.     evt.currentTarget.startDrag()
  68. }
  69. stage.addEventListener(MouseEvent.MOUSE_UP, onUp);
  70. function onUp(evt:MouseEvent):void{
  71.     stopDrag();
  72. }

This is snippet draws a Catmull-Rom spline based on 4 control points. A nice feature of Catmull-Rom splines is that they always pass through each of their control points.


have a look at the swf here:

I first learned about Catmull-Rom splines somewhere in the processing forums.

I got all my info for this snippet from this wikipedia page.

There is a good deal of room for optimization here... I may post an optimized version in the future.

Posted in Math, graphics algorithms, setPixel | Also tagged | 5 Comments

Cubic Hermite Spline

Actionscript:
  1. var canvas:BitmapData = new BitmapData(400,400,false, 0x000000);
  2. addChild(new Bitmap(canvas));
  3.  
  4. // create some draggable dots
  5. var p0:Sprite = dot(100, 100);
  6. var p1:Sprite = dot(200, 200);
  7. var m0:Sprite = dot(200, 100, 0xFFFFFF, 3)
  8. var m1:Sprite = dot(100, 200, 0xFFFFFF, 3);
  9.  
  10. addEventListener(Event.ENTER_FRAME, onLoop);
  11. function onLoop(evt:Event):void {
  12.     canvas.fillRect(canvas.rect, 0x000000);
  13.     var px:Number = 0;
  14.     var py:Number = 0;
  15.     for (var t:Number = 0; t <1; t+=.01){
  16.         var t_2:Number = t * t;
  17.         var t_3:Number = t_2 * t;
  18.        
  19.         // some repetitive math for clarity
  20.         px = (2 * t_3  - 3 * t_2 + 1) * p0.x +(t_3 - 2 * t_2 + t) *
  21.                  m0.x + (-2 * t_3 + 3 * t_2) * p1.x + (t_3 - t_2) * m1.x;
  22.         py = (2 * t_3  - 3 * t_2 + 1) * p0.y +(t_3 - 2 * t_2 + t) *
  23.                  m0.y + (-2 * t_3 + 3 * t_2) * p1.y + (t_3 - t_2) * m1.y;
  24.         canvas.setPixel(px, py, 0xFF0000);
  25.     }
  26. }
  27. // draggable dot
  28. function dot(xp:Number, yp:Number, col:uint = 0x507399, rad:Number=5):Sprite {
  29.     var s:Sprite = Sprite(addChild(new Sprite()));
  30.     s.x = xp;
  31.     s.y = yp;
  32.     with(s.graphics) beginFill(col), drawCircle(0,0,rad);
  33.     s.buttonMode = true;
  34.     s.addEventListener(MouseEvent.MOUSE_DOWN, onDrag);
  35.     return s;
  36. }
  37. function onDrag(evt:MouseEvent):void {
  38.     evt.currentTarget.startDrag()
  39. }
  40. stage.addEventListener(MouseEvent.MOUSE_UP, onUp);
  41. function onUp(evt:MouseEvent):void{
  42.     stopDrag();
  43. }

This is the start of my exploration of Cubic Hermite Splines (like Catmull–Rom)... I wrote this snippet while skimming the wikipedia article on the subject.... at first I wasn't sure if this was correct, but I added tangent calculations for a Catmull-Rom and it worked nicely... will post that tomorrow.

Posted in Math, graphics algorithms, setPixel | Also tagged | Leave a comment

more(nesting(functions(graphDrawing)));

Actionscript:
  1. [SWF(width=800, height=600)]
  2.  
  3. var canvas:Graphics;
  4. var graphData:Array = sineData();
  5.  
  6. var graph0:Shape = Shape(addChild(new Shape()));
  7. graph0.x = 50;
  8. graph0.y = 150;
  9.  
  10. var graph1:Shape = Shape(addChild(new Shape()));
  11. graph1.x = 400;
  12. graph1.y = 150;
  13.  
  14. var graph2:Shape = Shape(addChild(new Shape()));
  15. graph2.x = 50;
  16. graph2.y = 400;
  17.  
  18. // use graphData to draw 3 different looking graphs:
  19.  
  20. canvas = graph0.graphics;
  21. axis(lines(graphData));
  22.  
  23. canvas = graph1.graphics;
  24. axis(dots(graphData, 0xFF0000), 0xFFCC00, 2);
  25.  
  26. canvas = graph2.graphics;
  27. axis(dots(dots(lines(lines(graphData, 0xCCCCCC, 20))), 0x0022FF, 0, 4), 0xFF);
  28.  
  29.  
  30. // generate data
  31. function sineData():Array{
  32.     var dat:Array = new Array();
  33.     for (var i:int = 0; i<60; i++){
  34.         dat.push(new Point(i * 4,  (30 + i) * Math.sin(i * 24 * Math.PI/180)));
  35.     }            
  36.     return dat;
  37. }
  38.  
  39. // render lines
  40. function lines(dat:Array, col:uint=0x000000, thick:Number=0):Array{
  41.     canvas.lineStyle(thick, col);
  42.     canvas.moveTo(dat[0].x, dat[0].y)
  43.     for (var i:int = 1; i<dat.length; i++){
  44.          canvas.lineTo(dat[i].x, dat[i].y);
  45.     }
  46.     return dat;
  47. }
  48.  
  49. // render dots
  50. function dots(dat:Array, col:uint=0xFF0000, thick:Number=0, rad:Number=1.5):Array{
  51.     canvas.lineStyle(thick, col);
  52.     for (var i:int = 0; i<dat.length; i++){
  53.          canvas.drawCircle(dat[i].x, dat[i].y, rad);
  54.     }
  55.     return dat;
  56. }
  57.  
  58. // render graph axis
  59. function axis(dat:Array, col:uint=0x000000, thick:Number=0):Array{
  60.     var d:Array = dat.concat();
  61.     d.sortOn("y", Array.NUMERIC);
  62.     var lastIndex:int = d.length - 1;
  63.     var minY:Number = d[0].y;
  64.     var maxY:Number = d[lastIndex].y;
  65.     d.sortOn("x", Array.NUMERIC);
  66.     var minX:Number = d[0].x;
  67.     var maxX:Number = d[lastIndex].x;
  68.     canvas.lineStyle(thick, col, .2);
  69.     canvas.moveTo(minX, 0);
  70.     canvas.lineTo(maxX, 0);
  71.     canvas.lineStyle(thick, col);
  72.     canvas.moveTo(minX, minY);
  73.     canvas.lineTo(minX, maxY);
  74.     canvas.lineTo(maxX, maxY);
  75.     return dat;
  76. }

This is something I've been meaning to post for awhile. Finally had time to write it today... It contains functions that are designed to be nested for the purpose of rendering a small data set in a few different ways...

The upper left image is rendered with axis labels and lines... and it defaults to the color black (line 21):

axis(lines(graphData));

The upper right image is rendered with yellow axis and red dots (line 24):

axis(dots(graphData, 0xFF0000), 0xFFCC00, 2);

etc... (line 27)
axis(dots(dots(lines(lines(graphData, 0xCCCCCC, 20))), 0x0022FF, 0, 4), 0xFF);

Alternatively you could write each function call on one line:

lines(graphData, 0xCCCCCC, 20);
lines(graphData);
dots(graphData);
dots(graphData, 0x0022FF, 0, 4)
axis(graphData, 0xFF);

NOTE: If you think this post is insane, please read the warning page of this site...

Posted in Graphics, functions, misc | Also tagged | Leave a comment