Slow Line Drawing

Actionscript:
  1. var canvas:BitmapData = Bitmap(addChild(new Bitmap(new BitmapData(400, 400, false, 0x000000)))).bitmapData;
  2.  
  3. function line(x1:Number, y1:Number, x2:Number, y2:Number, res:int=10):void{
  4.     var dx:Number = x2 - x1;
  5.     var dy:Number = y2 - y1;
  6.     var dist:Number = Math.sqrt((dx * dx) + (dy * dy));
  7.     var step:Number = 1 / (dist / res);
  8.     for (var i:Number = 0; i<=1; i+= step){
  9.         // lerp : a  + (b - a) * f
  10.         canvas.setPixel(x1 + dx * i, y1 + dy * i, 0xFFFFFF);
  11.     }
  12. }
  13.  
  14. addEventListener(Event.ENTER_FRAME, onLoop);
  15. function onLoop(evt:Event):void {
  16.    canvas.fillRect(canvas.rect, 0x000000);
  17.   line(100 , 100, mouseX, mouseY,1);
  18.   line(100 + 50, 100, mouseX+ 50, mouseY,5);
  19. }

Yesterday I posted an implementation of the Bresenham Line Algorithm. Today I'm posting a comparatively slow way to draw a line with setPixel(). This snippet uses lerp and the Pythagorean theorem. It works nicely for small numbers of lines, its easy to draw dotted lines with it and its easy to explain. In a real app where you needed to use setPixel() to draw a line you should use one of the fast algorithms like Wu or Bresenham.

I didn't originally write this snippet to use set pixel... a few weeks ago I wrote something very similar to calculate a set of x y coords between two given points. In the program I used it in speed wasn't an issue (as I only needed to run the function one time). I've needed this kind of function many times before in games and small apps...

This was the original:

Actionscript:
  1. function calculatePoints(x1:Number, y1:Number, x2:Number, y2:Number, res:int=10):Array{
  2.     var points:Array = new Array();
  3.     var dx:Number = x2 - x1;
  4.     var dy:Number = y2 - y1;
  5.     var dist:Number = Math.sqrt((dx * dx) + (dy * dy));
  6.     var step:Number = 1 / (dist / res);
  7.     for (var i:Number = 0; i<=1; i+= step){
  8.         points.push(new Point(x1 + dx * i, y1 + dy * i));
  9.     }
  10.     return points;
  11. }
  12.  
  13. trace(calculatePoints(0,0,100,0,10));
  14. /* outputs:
  15. (x=0, y=0),(x=10, y=0),(x=20, y=0),(x=30.000000000000004, y=0),(x=40, y=0),(x=50, y=0),(x=60, y=0),(x=70, y=0),(x=80, y=0),(x=89.99999999999999, y=0),(x=99.99999999999999, y=0)
  16. */

...and another version to allow you to specify the number of points to calculate rather than the pixel interval at which they should be calculated:

Actionscript:
  1. function calculatePoints(x1:Number, y1:Number, x2:Number, y2:Number, pointNum:int=10):Array{
  2.     var points:Array = new Array();
  3.     var step:Number = 1 / (pointNum + 1);
  4.     for (var i:Number = 0; i<=1; i+= step){
  5.         points.push(new Point(x1 + (x2 - x1) * i, y1 + (y2 - y1) * i));
  6.     }
  7.     return points;
  8. }
  9.  
  10. trace(calculatePoints(0,30,30,0,1));
  11. /* outputs:
  12. (x=0, y=30),(x=15, y=15),(x=30, y=0)
  13. */

This last version isn't perfect, sometimes the pointNum will be off by 1, I may fix that in a future post.

Posted in Math, graphics algorithms, misc, pixel manipulation, setPixel | Tagged , | Leave a comment

Bresenham line

Actionscript:
  1. var canvas:BitmapData = Bitmap(addChild(new Bitmap(new BitmapData(400,400, false, 0x000000)))).bitmapData;
  2.  
  3. drawLine(10,10,100,90, 0xFF0000);
  4. drawLine(100,90,60,80, 0xFF0000);
  5. drawLine(100,90,95,60, 0xFF0000);
  6.    
  7. for (var i:int = 0; i<100; i+=1){
  8.     drawLine(i *4, 100 + i, 200, 390);
  9. }
  10. // code ported from here:
  11. // http://www.edepot.com/linebenchmark.html
  12. function drawLine(x1:int, y1:int, x2:int, y2:int, col:uint = 0xFFFFFF){
  13.     var x:int, y:int;
  14.     var dx:int, dy:int;
  15.     var incx:int , incy:int
  16.     var balance:int;
  17.  
  18.     if (x2>= x1){
  19.         dx = x2 - x1;
  20.         incx = 1;
  21.     }else{
  22.         dx = x1 - x2;
  23.         incx = -1;
  24.     }
  25.  
  26.     if (y2>= y1){
  27.         dy = y2 - y1;
  28.         incy = 1;
  29.     }else{
  30.         dy = y1 - y2;
  31.         incy = -1;
  32.     }
  33.  
  34.     x = x1;
  35.     y = y1;
  36.  
  37.     if (dx>= dy){
  38.         dy <<= 1;
  39.         balance = dy - dx;
  40.         dx <<= 1;
  41.  
  42.         while (x != x2){
  43.             canvas.setPixel(x, y, col);
  44.             if (balance>= 0){
  45.                 y += incy;
  46.                 balance -= dx;
  47.             }
  48.             balance += dy;
  49.             x += incx;
  50.         }
  51.         canvas.setPixel(x, y, col);
  52.     }else{
  53.         dx <<= 1;
  54.         balance = dx - dy;
  55.         dy <<= 1;
  56.  
  57.         while (y != y2){
  58.             canvas.setPixel(x, y, col);
  59.             if (balance>= 0){
  60.                 x += incx;
  61.                 balance -= dy;
  62.             }
  63.             balance += dx;
  64.             y += incy;
  65.         }
  66.         canvas.setPixel(x, y, col);
  67.     }
  68. }

This snippet shows Brensenham's line drawing algorithm. I ported this implementation from here... all the line algorithms in that link are easy to port to actionscript. I've messed with them all at some point.

Tomorrow I'm going to post a super slow line drawing algorithm... so I figured I'd post a fast line drawing algorithm today.

Posted in BitmapData, graphics algorithms, setPixel | Tagged , | Leave a comment

Harmonic Series

Actionscript:
  1. var harmonic:Number = 0;
  2. var k:Number = 1;
  3. addEventListener(Event.ENTER_FRAME, onLoop);
  4. function onLoop(evt:Event):void {
  5.      harmonic += 1 / k;
  6.      trace("+");
  7.      trace("1 / " + k + "              =              " + harmonic);
  8.      k+=1;
  9. }

Read more about the harmonic series at wikipedia.


1 / 1 = 1
+
1 / 2 = 1.5
+
1 / 3 = 1.8333333333333333
+
1 / 4 = 2.083333333333333
+
...

Posted in Math | Tagged , , | Leave a comment

Formating Numbers with Commas

Actionscript:
  1. trace(formatNum(1000));
  2. trace(formatNum(10000000));
  3. trace(formatNum(1000000.39485));
  4.  
  5. function formatNum(num:Number):String {
  6.     var newStr:String = "";
  7.     var str:String = num.toString();
  8.    
  9.     var parts:Array = str.split(".");
  10.     str = parts[0];
  11.     var end:String = (parts[1]) ? "." + parts[1] : "";
  12.    
  13.     var i:int = str.length;
  14.     while(i--> 0){
  15.          var char:String = str.charAt(i);
  16.          if ((str.length - i) % 3 == 0){
  17.             newStr = "," + char +newStr;
  18.          }else{
  19.             newStr = char +  newStr;
  20.          }
  21.     }
  22.     return newStr + end;
  23. }
  24. /*
  25. outputs:
  26. 1,000
  27. 10,000,000
  28. 1,000,000.39485
  29. */

The function formatNum() returns a string given a number argument ... it adds commas where appropriate and takes into account decimal values. This is useful anywhere you need to display numbers over 1,000, in a game, in a calculator app etc...

Posted in string manipulation | Tagged , | Leave a comment