In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

Inflated Cubic Beziers with Smoothing

Get Adobe Flash player
by generalrelativity 05 Nov 2010
/**
 * Copyright generalrelativity ( http://wonderfl.net/user/generalrelativity )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/h0jz
 */

package
{
	
	import flash.display.GraphicsPathCommand;
	import flash.display.Sprite;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.geom.Point;
	
	public class InflatedBezier extends Sprite
	{
		
		public function InflatedBezier()	
		{
			
			stage.align = StageAlign.TOP_LEFT;
			stage.scaleMode = StageScaleMode.NO_SCALE;
			
			//create the bezier points as a list of x,y pairs--anchor1, control1, control2, anchor2
			var points:Vector.<Number> = Vector.<Number>( [ 100, 100, 200, 100, 200, 200, 300, 200 ] );
			var curve:CubicBezier = new CubicBezier( points );
			
			//draw this curve using a gaussian smoothing
			renderInflatedBezier( curve, new Gaussian( 4.0, 0.5, 0.2 ) );
			
			//move the curve so we can draw it again
			curve.translate( 0, 100 );
			//draw the curve with a sine smoothing function
			renderInflatedBezier( curve, new Sine( 4.0 ) );
			
		}
		
		private function renderInflatedBezier( curve:CubicBezier, g:ISmoothingFunction ) : void
		{
			
			var B:Point = curve.getPoint( 0 ); //point on curve
			var BDot:Point; //derivative 
			var t:Number;
			
			graphics.beginFill( 0 );
			graphics.moveTo( B.x, B.y );
			
			//hold a list of points to draw on the opposite side
			var c:Vector.<Number> = new Vector.<Number>( [ B.x, B.y ] );
			
			//defines the resolution of the curve
			//the lower the number the more polygonal
			var resolution:uint = 100;
			for( var i:uint = 1; i <= resolution; i++ )
			{
				t = i / resolution;
				B = curve.getPoint( t );
				BDot = curve.getDerivative( t );
				BDot.normalize( g.eval( t ) ); //this scales the normalized derivative to the smoothed value we want 
				graphics.lineTo( B.x - BDot.y, B.y + BDot.x ); //now move that magnitude off the curve perpendicularly 
				c.push( B.x + BDot.y, B.y - BDot.x );
			}
			
			//draw the other side of the curve
			for( i = c.length - 2; i > 0; i -= 2 )
			{
				graphics.lineTo( c[ i ], c[ i + 1 ] );
			}
			
		}
		
	}
	
}

interface ISmoothingFunction
{
	function eval( t:Number ) : Number
}

class Gaussian implements ISmoothingFunction
{
	
	private var a:Number;
	private var b:Number;
	private var c:Number;
	
	public function Gaussian( max:Number, center:Number, decay:Number )
	{
		a = max;
		b = center;	
		c = 2 * decay * decay;
	}
	
	public function eval( t:Number ) : Number	
	{
		return a * Math.exp( -Math.pow( t - b, 2 ) / c ); 	
	}
	
}

class Sine implements ISmoothingFunction
{
	
	private var max:Number;
	
	public function Sine( max:Number )
	{
		this.max = max;
	}
	
	public function eval( t:Number ) : Number	
	{
		return Math.sin( Math.PI * t ) * max;
	}
	
}

import flash.geom.Point;

class CubicBezier	
{
		
	private var P:Vector.<Number>
	
	public function CubicBezier( points:Vector.<Number> )
	{
		if( points.length != 8 )	
		{
			throw new Error( "Must provide x,y pairs for both anchors and both control points" );	
		}
		this.P = points;
	}
	
	public function getPoint( t:Number ) : Point	
	{
		
		var tSq:Number = t * t;
		var tCu:Number = tSq * t;
		var omt:Number = 1 - t;
		var omtSq:Number = omt * omt;
		var omtCu:Number = omtSq * omt;
		
		var B:Point = new Point();
		
		B.x = P[ 0 ] * omtCu + P[ 2 ] * 3 * omtSq * t + P[ 4 ] * 3 * omt * tSq + P[ 6 ] * tCu;
		B.y = P[ 1 ] * omtCu + P[ 3 ] * 3 * omtSq * t + P[ 5 ] * 3 * omt * tSq + P[ 7 ] * tCu;
		
		return B;
		
	}
	
	public function getDerivative( t:Number ) : Point
	{
		
		var omt:Number = 1 - t;
		var tSq:Number = t * t;
		var o6t:Number = 6 * omt * t;
		
		var coef1:Number = -3 * omt * omt;
		var coef2:Number = -coef1 - o6t;
		var coef3:Number = o6t - 3 * tSq;
		var coef4:Number = 3 * tSq;
		
		var B:Point = new Point();
		
		B.x = P[ 0 ] * coef1 + P[ 2 ] * coef2 + P[ 4 ] * coef3 + P[ 6 ] * coef4;
		B.y = P[ 1 ] * coef1 + P[ 3 ] * coef2 + P[ 5 ] * coef3 + P[ 7 ] * coef4;
		
		return B;
		
	}
	
	public function translate( x:Number, y:Number ) : void
	{
		for( var i:uint = 0; i < 8; i += 2 )
		{
			P[ i ] += x;
			P[ i + 1 ] += y;
		}
	}
	
}