Zoeken…
Komen 2 cirkels in botsing?
// 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);
}
Komen 2 rechthoeken in botsing?
// 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
);
}
Zijn een cirkel en een rechthoek botsen?
// 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);
}
Onderscheppen 2 lijnsegmenten?
De functie in dit voorbeeld retourneert true
als twee lijnsegmenten elkaar kruisen en false
als dat niet het geval is.
Het voorbeeld is ontworpen voor prestaties en maakt gebruik van sluiting om werkvariabelen vast te houden
// point object: {x:, y:} // p0 & p1 form one segment, p2 & p3 form the second segment // Returns true if lines segments are intercepting var lineSegmentsIntercept = (function(){ // function as singleton so that closure can be used var v1, v2, v3, cross, u1, u2; // working variable are closed over so they do not need creation // each time the function is called. This gives a significant performance boost. v1 = {x : null, y : null}; // line p0, p1 as vector v2 = {x : null, y : null}; // line p2, p3 as vector v3 = {x : null, y : null}; // the line from p0 to p2 as vector function lineSegmentsIntercept (p0, p1, p2, p3) { v1.x = p1.x - p0.x; // line p0, p1 as vector v1.y = p1.y - p0.y; v2.x = p3.x - p2.x; // line p2, p3 as vector v2.y = p3.y - p2.y; if((cross = v1.x * v2.y - v1.y * v2.x) === 0){ // cross prod 0 if lines parallel return false; // no intercept } v3 = {x : p0.x - p2.x, y : p0.y - p2.y}; // the line from p0 to p2 as vector u2 = (v1.x * v3.y - v1.y * v3.x) / cross; // get unit distance along line p2 p3 // code point B if (u2 >= 0 && u2 <= 1){ // is intercept on line p2, p3 u1 = (v2.x * v3.y - v2.y * v3.x) / cross; // get unit distance on line p0, p1; // code point A return (u1 >= 0 && u1 <= 1); // return true if on line else false. // code point A end } return false; // no intercept; // code point B end } return lineSegmentsIntercept; // return function with closure for optimisation. })();
Gebruiksvoorbeeld
var p1 = {x: 100, y: 0}; // line 1
var p2 = {x: 120, y: 200};
var p3 = {x: 0, y: 100}; // line 2
var p4 = {x: 100, y: 120};
var areIntersepting = lineSegmentsIntercept (p1, p2, p3, p4); // true
Het voorbeeld kan eenvoudig worden aangepast om het onderscheppingspunt terug te geven. Vervang de code tussen code point A
en A end
door
if(u1 >= 0 && u1 <= 1){
return {
x : p0.x + v1.x * u1,
y : p0.y + v1.y * u1,
};
}
Of als u het onderscheppingspunt op de lijnen wilt krijgen, negeert u het begin en einde van de lijnsegmenten en vervangt u de code tussen code point B
en B end
door
return {
x : p2.x + v2.x * u2,
y : p2.y + v2.y * u2,
};
Beide wijzigingen retourneren false als er geen onderschepping is of retourneren het punt van onderscheppen als {x : xCoord, y : yCoord}
Zijn een lijnsegment en cirkel botsen?
// [x0,y0] to [x1,y1] define a line segment
// [cx,cy] is circle centerpoint, cr is circle radius
function 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 );
}
Zijn lijnsegment en rechthoek botsen?
// 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);
}
Komen 2 convexe polygonen in botsing?
Gebruik de stelling van de scheidingsas om te bepalen of 2 convexe polygonen elkaar snijden
DE POLYGONS MOETEN CONVEX ZIJN
Naamsvermelding: Markus Jarderot @ Hoe kan ik de kruising tussen 2 geroteerde rechthoeken controleren?
// 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;
};
Komen 2 polygonen in botsing? (zowel concave als convexe polys zijn toegestaan)
Test alle polygoonzijden op kruispunten om te bepalen of 2 polygonen botsen.
// 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 points
function 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 een X, Y punt binnen een boog?
Test of het [x, y] -punt zich in een gesloten boog bevindt.
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);
}
Staat een X, Y binnen een wig?
Test of het [x, y] -punt zich binnen een wig bevindt.
// 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);
}
Staat een X, Y binnen een cirkel?
Test of een [x, y] punt zich binnen een cirkel bevindt.
// 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 een X, Y punt binnen een rechthoek?
Test of een [x, y] punt zich binnen een rechthoek bevindt.
// 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);
}