Поиск…
Встречаются ли 2 круга?
// 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);
}
Возникают два прямоугольника?
// 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
);
}
Встречаются ли круг и прямоугольник?
// 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);
}
Перехватываются ли 2 сегмента?
Функция в этом примере возвращает true
если два сегмента линии пересекаются, а false
нет.
Пример предназначен для производительности и использует закрытие для хранения рабочих переменных
// 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. })();
Пример использования
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
Пример легко модифицируется, чтобы вернуть точку перехвата. Замените код между code point A
и A end
с помощью
if(u1 >= 0 && u1 <= 1){
return {
x : p0.x + v1.x * u1,
y : p0.y + v1.y * u1,
};
}
Или, если вы хотите получить точку перехвата на линиях, игнорируя начало и конец сегментов линии, замените код между code point B
и B end
на
return {
x : p2.x + v2.x * u2,
y : p2.y + v2.y * u2,
};
Обе модификации вернут false, если нет перехвата или возврата точки перехвата как {x : xCoord, y : yCoord}
Являются ли сегмент линии и круг сталкивающимися?
// [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 );
}
Возникают ли сегменты линии и прямоугольник?
// 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);
}
Возникают два выпуклых многоугольника?
Используйте теорему разделительной оси, чтобы определить, пересекаются ли два выпуклых многоугольника
ПОЛИГОНЫ ДОЛЖНЫ БЫТЬ КОНВЭКСОМ
Attribution: Markus Jarderot @ Как проверить пересечение между двумя поворотными прямоугольниками?
// 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;
};
Возникают ли 2 многоугольника? (допускаются как вогнутые, так и выпуклые полисы)
Проверяет все стороны многоугольника для пересечений, чтобы определить, сталкиваются ли 2 многоугольника.
// 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);
}
Является ли точка X, Y внутри дуги?
Проверяет, находится ли точка [x, y] внутри замкнутой дуги.
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);
}
Является ли точка X, Y внутри клина?
Проверяет, находится ли точка [x, y] внутри клина.
// 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);
}
Является ли точка X, Y внутри круга?
Проверяет, находится ли точка [x, y] внутри круга.
// 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);
}
Является ли точка X, Y внутри прямоугольника?
Проверяет, находится ли точка [x, y] внутри прямоугольника.
// 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);
}