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.

This entry was posted in Math, graphics algorithms, setPixel and tagged , . Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.

3 Comments

  1. Metherfinn
    Posted October 27, 2010 at 8:20 pm | Permalink

    I can’t thank you enough. Any idea why the tangent equations on wikipedia were completely different?

  2. Posted November 22, 2010 at 4:03 pm | Permalink

    no problem, glad this post helped you. whenever I wrote this post I used the code from wikipedia to write it, so I assume someone must have changed the wikipedia post if its different now.

  3. Posted February 27, 2012 at 7:56 pm | Permalink

    Thanks man - easiest spline code example. Ported this to Lua in 3D, works great.

One Trackback

  1. [...] Quadratic Bezier Curve Bresenham line Bresenham Circle Catmull-Rom Spline [...]

Post a Comment

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

*
*