Bezier Curved Jigsaw Pattern
// forked from PESakaTFM's Bezier Curved Jigsaw edge
// forked from PESakaTFM's Bezier - Closed Loop
package
{
import flash.display.Graphics;
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.geom.Point;
public class JigsawEdge extends Sprite
{
public var pts:Vector.<Point> = new Vector.<Point>();
public function JigsawEdge()
{
var i:int=0;
var j:int=0;
for(i=0; i<8; i++)
{
for(j=0; j<8; j++)
{
if(i == 0)
{
graphics.lineStyle(1,0x000000);
graphics.moveTo(0, 50*j);
graphics.lineTo(0, 50*(j+1));
graphics.moveTo(50*j, 0);
graphics.lineTo(50*(j+1), 0);
}
else
{
generateEdge(new Point(50*i, 50*j), new Point(50*i, 50*(j+1)));
draw();
generateEdge(new Point(50*j, 50*i), new Point(50*(j+1), 50*i));
draw();
}
}
}
for(j=0; j<8; j++)
{
graphics.lineStyle(1,0x000000);
graphics.moveTo(50*i, 50*j);
graphics.lineTo(50*i, 50*(j+1));
graphics.moveTo(50*j, 50*i);
graphics.lineTo(50*(j+1), 50*i);
}
}
protected function generateEdge(p1:Point, p2:Point):void
{
var p:Point = Point.interpolate(p1, p2, 0);
var dist:Number = Point.distance(p1,p2);
var perp:Point = new Point(.35*(p2.y-p1.y), .35*(p1.x-p2.x));
var jit:Number = dist*.01;
pts[0] = p;
p = Point.interpolate(p1,p2, .4+.15*Math.random());
p.x += jit*Math.random() >> 0;
p.y += jit*Math.random() >> 0;
pts[1] = p;
var sign:Number = 2*Math.random()-1;
sign = (sign > 0)? 1 : -1;
p = Point.interpolate(p1,p2, .24+.16*Math.random());
p.x += sign*perp.x + jit*Math.random() >> 0;
p.y += sign*perp.y + jit*Math.random() >> 0;
pts[2] = p;
p = Point.interpolate(p1,p2, .6+.16*Math.random());
p.x += sign*perp.x + jit*Math.random() >> 0;
p.y += sign*perp.y + jit*Math.random() >> 0;
pts[3] = p;
p = Point.interpolate(p1,p2, .45+.15*Math.random());
p.x += jit*Math.random() >> 0;
p.y += jit*Math.random() >> 0;
pts[4] = p;
p = Point.interpolate(p1,p2, 1);
pts[5] = p;
}
public function drawSide(pnts:Vector.<Point>, accuracy:int=20):void
{
var p:Vector.<Point> = new Vector.<Point>(3,true);
p[0] = pnts[0];
p[1] = pnts[1];
p[2] = Point.interpolate(pnts[1], pnts[2], .5);
drawCurve(p, accuracy);
for(var i:int=1; i<pnts.length-3; i++)
{
p[0] = Point.interpolate(pnts[i], pnts[i+1], .5);
p[1] = pnts[i+1];
p[2] = Point.interpolate(pnts[i+1], pnts[i+2], .5);
drawCurve(p, accuracy);
}
p[0] = Point.interpolate(pnts[i], pnts[i+1], .5);
p[1] = pnts[i+1];
p[2] = pnts[i+2];
drawCurve(p, accuracy);
}
public function drawCurve(pnts:Vector.<Point>, accuracy:int=20):void
{
var g:Graphics = this.graphics;
var a:int;
var p:Point;
g.moveTo(pnts[0].x, pnts[0].y);
for(a=0; a <= accuracy; a++)
{
p = getPointAt(pnts, a/accuracy);
g.lineTo(p.x, p.y);
}
}
protected function getPointAt(pnts:Vector.<Point>, t:Number):Point
{
var n:int = pnts.length-1;
var m:Number = Math.pow((1-t), n);
var p:Point = new Point(pnts[0].x * m, pnts[0].y * m);
for(var i:int=1; i<=n; i++)
{
m = Math.pow((1-t), n-i)*bc(n, i)*Math.pow(t, i);
p = p.add(new Point(pnts[i].x * m, pnts[i].y * m));
}
return p;
}
protected function bc(n:int, k:int):int // Binomial Coefficient
{
return (f(n)/(f(k)*f(n-k)));
}
protected function f(value:int):int // Factorial
{
var i:int = value;
var result:int = 1;
for(; i>0; i--)
{
result *= i;
}
return result;
}
protected function draw():void
{
graphics.lineStyle(1,0x000000);
drawSide(pts, 10);
graphics.endFill();
}
}
}