Collisions and Intersections
Are 2 circles colliding?
Section titled “Are 2 circles colliding?”// circle objects: { x:, y:, radius: }// return true if the 2 circles are colliding// c1 and c2 are circles as defined above
function CirclesColliding(c1,c2){ var dx=c2.x-c1.x; var dy=c2.y-c1.y; var rSum=c1.radius+c2.radius; return(dx*dx+dy*dy<=rSum*rSum);}Are 2 rectangles colliding?
Section titled “Are 2 rectangles colliding?”// rectangle objects { x:, y:, width:, height: }// return true if the 2 rectangles are colliding// r1 and r2 are rectangles as defined above
function RectsColliding(r1,r2){ return !( r1.x>r2.x+r2.width || r1.x+r1.width<r2.x || r1.y>r2.y+r2.height || r1.y+r1.height<r2.y );}Are a circle and rectangle colliding?
Section titled “Are a circle and rectangle colliding?”// rectangle object: { x:, y:, width:, height: }// circle object: { x:, y:, radius: }// return true if the rectangle and circle are colliding
function RectCircleColliding(rect,circle){ var dx=Math.abs(circle.x-(rect.x+rect.width/2)); var dy=Math.abs(circle.y-(rect.y+rect.height/2));
if( dx > circle.radius+rect.width/2 ){ return(false); } if( dy > circle.radius+rect.height/2 ){ return(false); }
if( dx <= rect.width ){ return(true); } if( dy <= rect.height ){ return(true); }
var dx=dx-rect.width; var dy=dy-rect.height return(dx*dx+dy*dy<=circle.radius*circle.radius);}Are 2 line segments intercepting?
Section titled “Are 2 line segments intercepting?”The function in this example returns true if two line segments are intersecting and false if not.
The example is designed for performance and uses closure to hold working variables
var p1 = {x: 100, y: 0}; // line 1var p2 = {x: 120, y: 200};var p3 = {x: 0, y: 100}; // line 2var p4 = {x: 100, y: 120};var areIntersepting = lineSegmentsIntercept (p1, p2, p3, p4); // trueThe example is easily modified to return the point of intercept. Replace the code between code point A and A end with
if(u1 >= 0 && u1 <= 1){ return { x : p0.x + v1.x * u1, y : p0.y + v1.y * u1, };}Or if you want to get the intercept point on the lines, ignoring the line segments start and ends replace the code between code point B and B end with
return { x : p2.x + v2.x * u2, y : p2.y + v2.y * u2,};Both modifications will return false if there is no intercept or return the point of intercept as {x : xCoord, y : yCoord}
Are a line segment and circle colliding?
Section titled “Are a line segment and circle colliding?”// [x0,y0] to [x1,y1] define a line segment// [cx,cy] is circle centerpoint, cr is circle radiusfunction isCircleSegmentColliding(x0,y0,x1,y1,cx,cy,cr){
// calc delta distance: source point to line start var dx=cx-x0; var dy=cy-y0;
// calc delta distance: line start to end var dxx=x1-x0; var dyy=y1-y0;
// Calc position on line normalized between 0.00 & 1.00 // == dot product divided by delta line distances squared var t=(dx*dxx+dy*dyy)/(dxx*dxx+dyy*dyy);
// calc nearest pt on line var x=x0+dxx*t; var y=y0+dyy*t;
// clamp results to being on the segment if(t<0){x=x0;y=y0;} if(t>1){x=x1;y=y1;}
return( (cx-x)*(cx-x)+(cy-y)*(cy-y) < cr*cr );}Are line segment and rectangle colliding?
Section titled “Are line segment and rectangle colliding?”// var rect={x:,y:,width:,height:};// var line={x1:,y1:,x2:,y2:};// Get interseting point of line segment & rectangle (if any)function lineRectCollide(line,rect){
// p=line startpoint, p2=line endpoint var p={x:line.x1,y:line.y1}; var p2={x:line.x2,y:line.y2};
// top rect line var q={x:rect.x,y:rect.y}; var q2={x:rect.x+rect.width,y:rect.y}; if(lineSegmentsCollide(p,p2,q,q2)){ return true; } // right rect line var q=q2; var q2={x:rect.x+rect.width,y:rect.y+rect.height}; if(lineSegmentsCollide(p,p2,q,q2)){ return true; } // bottom rect line var q=q2; var q2={x:rect.x,y:rect.y+rect.height}; if(lineSegmentsCollide(p,p2,q,q2)){ return true; } // left rect line var q=q2; var q2={x:rect.x,y:rect.y}; if(lineSegmentsCollide(p,p2,q,q2)){ return true; }
// not intersecting with any of the 4 rect sides return(false);}
// point object: {x:, y:}// p0 & p1 form one segment, p2 & p3 form the second segment// Get interseting point of 2 line segments (if any)// Attribution: http://paulbourke.net/geometry/pointlineplane/function lineSegmentsCollide(p0,p1,p2,p3) {
var unknownA = (p3.x-p2.x) * (p0.y-p2.y) - (p3.y-p2.y) * (p0.x-p2.x); var unknownB = (p1.x-p0.x) * (p0.y-p2.y) - (p1.y-p0.y) * (p0.x-p2.x); var denominator = (p3.y-p2.y) * (p1.x-p0.x) - (p3.x-p2.x) * (p1.y-p0.y);
// Test if Coincident // If the denominator and numerator for the ua and ub are 0 // then the two lines are coincident. if(unknownA==0 && unknownB==0 && denominator==0){return(null);}
// Test if Parallel // If the denominator for the equations for ua and ub is 0 // then the two lines are parallel. if (denominator == 0) return null;
// test if line segments are colliding unknownA /= denominator; unknownB /= denominator; var isIntersecting=(unknownA>=0 && unknownA<=1 && unknownB>=0 && unknownB<=1)
return(isIntersecting);}Are 2 convex polygons colliding?
Section titled “Are 2 convex polygons colliding?”Use the Separating Axis Theorem to determine if 2 convex polygons are intersecting
THE POLYGONS MUST BE CONVEX
Attribution: Markus Jarderot @ How to check intersection between 2 rotated rectangles?
// polygon objects are an array of vertices forming the polygon// var polygon1=[{x:100,y:100},{x:150,y:150},{x:50,y:150},...];// THE POLYGONS MUST BE CONVEX// return true if the 2 polygons are colliding
function convexPolygonsCollide(a, b){ var polygons = [a, b]; var minA, maxA, projected, i, i1, j, minB, maxB;
for (i = 0; i < polygons.length; i++) {
// for each polygon, look at each edge of the polygon, and determine if it separates // the two shapes var polygon = polygons[i]; for (i1 = 0; i1 < polygon.length; i1++) {
// grab 2 vertices to create an edge var i2 = (i1 + 1) % polygon.length; var p1 = polygon[i1]; var p2 = polygon[i2];
// find the line perpendicular to this edge var normal = { x: p2.y - p1.y, y: p1.x - p2.x };
minA = maxA = undefined; // for each vertex in the first shape, project it onto the line perpendicular to the edge // and keep track of the min and max of these values for (j = 0; j < a.length; j++) { projected = normal.x * a[j].x + normal.y * a[j].y; if (minA==undefined || projected < minA) { minA = projected; } if (maxA==undefined || projected > maxA) { maxA = projected; } }
// for each vertex in the second shape, project it onto the line perpendicular to the edge // and keep track of the min and max of these values minB = maxB = undefined; for (j = 0; j < b.length; j++) { projected = normal.x * b[j].x + normal.y * b[j].y; if (minB==undefined || projected < minB) { minB = projected; } if (maxB==undefined || projected > maxB) { maxB = projected; } }
// if there is no overlap between the projects, the edge we are looking at separates the two // polygons, and we know there is no overlap if (maxA < minB || maxB < minA) { return false; } } } return true;};Are 2 polygons colliding? (both concave and convex polys are allowed)
Section titled “Are 2 polygons colliding? (both concave and convex polys are allowed)”Tests all polygon sides for intersections to determine if 2 polygons are colliding.
// polygon objects are an array of vertices forming the polygon// var polygon1=[{x:100,y:100},{x:150,y:150},{x:50,y:150},...];// The polygons can be both concave and convex// return true if the 2 polygons are colliding
function polygonsCollide(p1,p2){ // turn vertices into line points var lines1=verticesToLinePoints(p1); var lines2=verticesToLinePoints(p2); // test each poly1 side vs each poly2 side for intersections for(i=0; i<lines1.length; i++){ for(j=0; j<lines2.length; j++){ // test if sides intersect var p0=lines1[i][0]; var p1=lines1[i][1]; var p2=lines2[j][0]; var p3=lines2[j][1]; // found an intersection -- polys do collide if(lineSegmentsCollide(p0,p1,p2,p3)){return(true);} }} // none of the sides intersect return(false);}// helper: turn vertices into line pointsfunction verticesToLinePoints(p){ // make sure polys are self-closing if(!(p[0].x==p[p.length-1].x && p[0].y==p[p.length-1].y)){ p.push({x:p[0].x,y:p[0].y}); } var lines=[]; for(var i=1;i<p.length;i++){ var p1=p[i-1]; var p2=p[i]; lines.push([ {x:p1.x, y:p1.y}, {x:p2.x, y:p2.y} ]); } return(lines);}// helper: test line intersections// point object: {x:, y:}// p0 & p1 form one segment, p2 & p3 form the second segment// Get interseting point of 2 line segments (if any)// Attribution: http://paulbourke.net/geometry/pointlineplane/function lineSegmentsCollide(p0,p1,p2,p3) { var unknownA = (p3.x-p2.x) * (p0.y-p2.y) - (p3.y-p2.y) * (p0.x-p2.x); var unknownB = (p1.x-p0.x) * (p0.y-p2.y) - (p1.y-p0.y) * (p0.x-p2.x); var denominator = (p3.y-p2.y) * (p1.x-p0.x) - (p3.x-p2.x) * (p1.y-p0.y);
// Test if Coincident // If the denominator and numerator for the ua and ub are 0 // then the two lines are coincident. if(unknownA==0 && unknownB==0 && denominator==0){return(null);}
// Test if Parallel // If the denominator for the equations for ua and ub is 0 // then the two lines are parallel. if (denominator == 0) return null;
// test if line segments are colliding unknownA /= denominator; unknownB /= denominator; var isIntersecting=(unknownA>=0 && unknownA<=1 && unknownB>=0 && unknownB<=1)
return(isIntersecting);}Is an X,Y point inside an arc?
Section titled “Is an X,Y point inside an arc?”Tests if the [x,y] point is inside a closed arc.
var arc={ cx:150, cy:150, innerRadius:75, outerRadius:100, startAngle:0, endAngle:Math.PI}
function isPointInArc(x,y,arc){ var dx=x-arc.cx; var dy=y-arc.cy; var dxy=dx*dx+dy*dy; var rrOuter=arc.outerRadius*arc.outerRadius; var rrInner=arc.innerRadius*arc.innerRadius; if(dxy<rrInner || dxy>rrOuter){return(false);} var angle=(Math.atan2(dy,dx)+PI2)%PI2; return(angle>=arc.startAngle && angle<=arc.endAngle);}Is an X,Y point inside a wedge?
Section titled “Is an X,Y point inside a wedge?”Tests if the [x,y] point is inside a wedge.
// wedge objects: {cx:,cy:,radius:,startAngle:,endAngle:}// var wedge={// cx:150, cy:150, // centerpoint// radius:100,// startAngle:0, endAngle:Math.PI// }// Return true if the x,y point is inside the closed wedge
function isPointInWedge(x,y,wedge){ var PI2=Math.PI*2; var dx=x-wedge.cx; var dy=y-wedge.cy; var rr=wedge.radius*wedge.radius; if(dx*dx+dy*dy>rr){return(false);} var angle=(Math.atan2(dy,dx)+PI2)%PI2; return(angle>=wedge.startAngle && angle<=wedge.endAngle);}Is an X,Y point inside a circle?
Section titled “Is an X,Y point inside a circle?”Tests if an [x,y] point is inside a circle.
// circle objects: {cx:,cy:,radius:,startAngle:,endAngle:}// var circle={// cx:150, cy:150, // centerpoint// radius:100,// }// Return true if the x,y point is inside the circle
function isPointInCircle(x,y,circle){ var dx=x-circle.cx; var dy=y-circle.cy; return(dx*dx+dy*dy<circle.radius*circle.radius);}Is an X,Y point inside a rectangle?
Section titled “Is an X,Y point inside a rectangle?”Tests if an [x,y] point is inside a rectangle.
// rectangle objects: {x:, y:, width:, height: }// var rect={x:10, y:15, width:25, height:20}// Return true if the x,y point is inside the rectangle
function isPointInRectangle(x,y,rect){ return(x>rect.x && x<rect.x+rect.width && y>rect.y && y<rect.y+rect.height);}

