Bezier Intersections
bezier intersection demo
drag dots.. red dots are intersections
more info: http://actionsnippet.com/?p=965
/**
* Copyright shapevent ( http://wonderfl.net/user/shapevent )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/oTTm
*/
// forked from shapevent's flash on 2009-8-6
package {
// bezier intersection demo
// drag dots.. red dots are intersections
// more info: http://actionsnippet.com/?p=965
import flash.display.*;
import flash.events.*;
import flash.geom.*;
dynamic public class BezierIntersections extends MovieClip {
private var resolution:Number;
private var pointNum:int;
private var bezA:Array;
private var a:Sprite;
private var b:Sprite;
private var c:Sprite;
private var bezB:Array;
private var d:Sprite;
private var e:Sprite;
private var f:Sprite;
private var ip:Point;
public function BezierIntersections(){
// init
resolution = .03;
pointNum = Math.ceil(1 / resolution);
bezA = new Array();
populateArray(bezA);
a = dot(100, 200);
b = dot(200, 100);
c = dot(300, 200);
bezB = new Array();
populateArray(bezB);
d = dot(300, 100, 0xCCCC00);
e = dot(120, 130, 0xCCCC00);
f = dot(200, 300, 0xCCCC00);
addEventListener(Event.ENTER_FRAME, onLoop);
ip = new Point();
// draggable dot
stage.addEventListener(MouseEvent.MOUSE_UP, onUp);
}
// private methods
private function onLoop(evt:Event):void {
with(graphics){
clear();
lineStyle(0, 0x000000);
// calc and draw bezier points
drawBezier(bezA, a, b, c);
drawBezier(bezB, d, e, f);
// calc collisions
var intersections:Array = calculateIntersection(bezA, bezB);
// draw collisions
beginFill(0xFF0000);
if (intersections.length> 0){
for (var i:int = 0; i<intersections.length; i++){
drawCircle(intersections[i].x, intersections[i].y, 3);
}
}
endFill();
}
}
private function populateArray(a:Array):void {
for (var i:int = 0; i<pointNum; i++){
a.push(new Point());
}
}
private function drawBezier(bez:Array, a:Sprite, b:Sprite, c:Sprite):void{
with(graphics){
bezier(bez, a.x, a.y, b.x, b.y, c.x, c.y);
var leng:Number = bez.length;
moveTo(bez[0].x, bez[0].y);
for (var i:int = 1; i<leng; i++){
lineTo(bez[i].x, bez[i].y);
}
}
}
private function bezier(bez:Array, x1:Number, y1:Number, x2:Number, y2:Number, x3:Number, y3:Number):void {
var b:Number, a2:Number, ab2:Number, b2:Number;
var pnt:Point;
var inc:int = 0;
for (var a:Number = 0; a <=1; a+=resolution) {
b= 1 - a;
a2 = a * a;
ab2 = a * b * 2;
b2 = b * b;
pnt = bez[inc];
pnt.x = a2 * x1 + ab2 * x2 + b2 * x3;
pnt.y = a2 * y1 + ab2 * y2 + b2 * y3;
inc++;
}
}
private function calculateIntersection(bezA:Array, bezB:Array):Array {
var intersections:Array = new Array();
var ip:Point;
var aLength:int = bezA.length;
var bLength:int = bezB.length;
var p1:Point, p2:Point, p3:Point, p4:Point;
// compare all line segments and check for
// intersections
for (var i:int = 1; i<aLength; i++){
p1 = bezA[i - 1];
p2 = bezA[i];
for (var j:int = 1; j<bLength; j++){
p3 = bezB[j - 1];
p4 = bezB[j];
ip = intersection(p1, p2, p3, p4);
if (ip){
intersections.push(ip.clone());
}
}
}
return intersections;
}
private function intersection(p1:Point, p2:Point, p3:Point, p4:Point):Point {
var nx:Number, ny:Number, dn:Number;
var x4_x3:Number = p4.x - p3.x;
var pre2:Number = p4.y - p3.y;
var pre3:Number = p2.x - p1.x;
var pre4:Number = p2.y - p1.y;
var pre5:Number = p1.y - p3.y;
var pre6:Number = p1.x - p3.x;
nx = x4_x3 * pre5 - pre2 * pre6;
ny = pre3 * pre5 - pre4 * pre6;
dn = pre2 * pre3 - x4_x3 * pre4;
if (dn == 0){
return null
}
nx /= dn;
ny /= dn;
// has intersection
if(nx>= 0 && nx <= 1 && ny>= 0 && ny <= 1){
ny = p1.y + nx * pre4;
nx = p1.x + nx * pre3;
ip.x = nx;
ip.y = ny;
}else{
return null;
}
return ip
}
private function dot(xp:Number, yp:Number, col:uint = 0x507399, noDrag:Boolean = false):Sprite {
var s:Sprite = Sprite(addChild(new Sprite));
s.x = xp;
s.y = yp;
with(s.graphics) beginFill(col), drawCircle(0,0,5);
if (!noDrag){
s.buttonMode = true;
s.addEventListener(MouseEvent.MOUSE_DOWN, onDrag);
}
return s;
}
private function onDrag(evt:MouseEvent):void {
evt.currentTarget.startDrag()
}
private function onUp(evt:MouseEvent):void{
stopDrag();
}
}
}