/**
* 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;
}
}
}