/** @author Andreas Weber, webweber@motiondraw.com, December 2005 Version 1.0 Disclaimer Yep, everything. 'Who - me? I haven't even heard of Catmull-Rom!' License Free for whatever. Giving credit would be nice. Sending a link to what you do with it would be nice. Want to make a donation? http://www.icrc.org/ http://www.motiondraw.com/md/as_samples/t/CatmullRomSpline/tween.html Catmull-Rom is a fast spline algorithm. A spline connects a number of points ('verteces') with one curve More on Catmull-Rom splines: http://www.mvps.org/directx/articles/catmull/ Alternatives: An ActionSpript implementation of a Parametric (Natural) Spline by Jim Armstrong: http://www.2112fx.com/blog/pivot/entry.php?id=37#body Produces perfect, beautiful splines which connect the points in a less direct, kind of 'rounder' style than the Catmull-Rom splines Downside: much slower than Catmull-Rom, especially when the spline is defined by a large number of verteces Constructor: CatmullRomSpline(vertexPoints:Array) vertexPoints an Array of points (objects with x and y properties). All these points will be connected through the spline example import com.motiondraw.geometry.CatmullRomSpline; var points:Array = new Array({x:20, y:50}, {x:200, y:100}, {x:50, y:20}, {x:50, y:100}); var spline:CatmullRomSpline = new CatmullRomSpline(points); plotAll(canvas:MovieClip [, approxLineLength:Number]):Void; Easy way to render the spline canvas a MovieClip instance to draw on. Make sure to call lineStyle() on the canvas clip before passing it to this function. approxLineLength the spline is rendered by connecting a big number of points with straight lines. approxLineLength is the approximate length of one of these lines in pixels. Optional, Default is 5 (i.e. a spline with a total length of 500 will be represented by about 100 straight lines) The smaller this value (e.g. 1) the less 'jaggy' the spline, but also the slower as more lines are drawn. returns nothing example import com.motiondraw.geometry.CatmullRomSpline; var points:Array = new Array({x:20, y:50}, {x:200, y:100}, {x:50, y:20}, {x:50, y:100}); var spline:CatmullRomSpline = new CatmullRomSpline(points); // create a clip to draw on this.createEmptyMovieClip('canvas', this.getNextHighestDepth()); canvas._x = canvas._y = 100; // don't forget: first define the lineStyle canvas.lineStyle(3, 0); // the shorter the lines the nicer - but also the slower var approxLineLength:Number = 5; spline.plotAll(canvas, approxLineLength); getAllPoints([approxLineLength:Number]):Array Get points on the whole spline (from t=0 to t=1). Handy to plot the spline in one fell swoop approxLineLength see above 'plotAll' for explanation returns an Array with all the points (objects with x and y properties) on the spline example: see the plotAll method getPointsInRange(fromT:Number, toT:Number, approxLineLength:Number):Array Get points on a segment of the spline (from t=fromT to t=toT) Handy to plot the spline piece by piece, e.g. to mimic a drawing hand or to apply some easing. Typically called in an interval. fromT the starting t (range 0 to 1) toT the ending t (range 0 to 1, must be greater than fromT) approxLineLength see above 'plotAll' for explanation returns an Array with all the points (objects with x and y properties) in the defined range of the spline example: import com.motiondraw.geometry.CatmullRomSpline; var numPoints = 15; numIntervals = 50; tweenIntervals = new Array(); for(var i=0; i<=numIntervals; i++){ // a linear tween - use any other fancy tween instead (see Robert Penner functions) tweenIntervals[i] = i * (1/50); } var points:Array = new Array({x:20, y:50}, {x:200, y:100}, {x:50, y:20}, {x:50, y:100}); var spline:CatmullRomSpline = new CatmullRomSpline(points); this.createEmptyMovieClip('canvas', this.getNextHighestDepth()); canvas._x = canvas._y = 0; canvas.lineStyle(1, 0); canvas.moveTo(points[0].x, points[0].y); count = 1; this.onEnterFrame = function(){ if(count > numIntervals){delete this.onEnterFrame;} var fromT = tweenIntervals[count-1]; var toT = tweenIntervals[count]; var approxLineLength = 5; var points = spline.getPointsInRange(fromT, toT, approxLineLength); for ( var i=0; i= p1.t && fromT < p2.t){ var dist:Number = lengths[i]; var t:Number = 1/(dist/approxLineLength); var l2 = (toT > p2.t) ? 1 : (toT-p1.t)/(p2.t-p1.t); for(var j= (fromT - p1.t)/(p2.t-p1.t); j p2.t){ fromT = p2.t; }else if(l2 <= 1){ break; } } } return p; } function getPointAtT(t:Number):Object{ if(!lengths.length){getSegmentLengths();} var v:Array = vertecesPlus; var c:Number = 0; for(var i=0, l1=v.length; i= p1.t && t <= p2.t){ var t2:Number = (t-p1.t)/(p2.t-p1.t); return catmullRom(t2, v[i], p1, p2, v[i+3]); } } } function getTOfVertex(index:Number):Number{ if(!lengths.length){getSegmentLengths();} return verteces[index].t } private function getSegmentLengths():Void{ if(!vertecesPlus){makeVertecesPlus();} var v:Array = vertecesPlus; lengths = new Array(); totalLength = 0; for(var i=0, len=v.length; i