Circle Line Segment Collision
I need to detect collision circle with any line. I have array with verticles of polygon (x, y) and draw this polygon in loop. For detection I use algorithm, which calculate triangl
Solution 1:
Circle line segment intercept
UPDATE
This answer includes line line intercept, moving a line along its normal, distance point (circle) to line, and circle line intercept.
The circle is
varcircle= {
radius :500,
center :point(1000,1000),
}
The line segment is
varline= {
p1 :point(500,500),
p2 :point(2000,1000),
}
A point is
varpoint= {
x :100,
y :100,
}
Thus the function to find the intercept of a line segment width a circle
The function returns an array of up to two point on the line segment. If no points found returns an empty array.
functioninteceptCircleLineSeg(circle, line){
var a, b, c, d, u1, u2, ret, retP1, retP2, v1, v2;
v1 = {};
v2 = {};
v1.x = line.p2.x - line.p1.x;
v1.y = line.p2.y - line.p1.y;
v2.x = line.p1.x - circle.center.x;
v2.y = line.p1.y - circle.center.y;
b = (v1.x * v2.x + v1.y * v2.y);
c = 2 * (v1.x * v1.x + v1.y * v1.y);
b *= -2;
d = Math.sqrt(b * b - 2 * c * (v2.x * v2.x + v2.y * v2.y - circle.radius * circle.radius));
if(isNaN(d)){ // no interceptreturn [];
}
u1 = (b - d) / c; // these represent the unit distance of point one and two on the line
u2 = (b + d) / c;
retP1 = {}; // return points
retP2 = {}
ret = []; // return arrayif(u1 <= 1 && u1 >= 0){ // add point if on the line segment
retP1.x = line.p1.x + v1.x * u1;
retP1.y = line.p1.y + v1.y * u1;
ret[0] = retP1;
}
if(u2 <= 1 && u2 >= 0){ // second add point if on the line segment
retP2.x = line.p1.x + v1.x * u2;
retP2.y = line.p1.y + v1.y * u2;
ret[ret.length] = retP2;
}
return ret;
}
UPDATE
Line line intercept.
Returns a point if found else returns undefined.
functioninterceptLines(line,line1){
var v1, v2, c, u;
v1 = {};
v2 = {};
v3 = {};
v1.x = line.p2.x - line.p1.x; // vector of line
v1.y = line.p2.y - line.p1.y;
v2.x = line1.p2.x - line1.p1.x; //vector of line2
v2.y = line1.p2.y - line1.p1.y;
var c = v1.x * v2.y - v1.y * v2.x; // cross of the two vectorsif(c !== 0){
v3.x = line.p1.x - line1.p1.x;
v3.y = line.p1.y - line1.p1.y;
u = (v2.x * v3.y - v2.y * v3.x) / c; // unit distance of intercept point on this linereturn {x : line.p1.x + v1.x * u, y : line.p1.y + v1.y * u};
}
returnundefined;
}
Lift Line
Move line along its normal
functionliftLine(line,dist){
var v1,l
v1 = {};
v1.x = line.p2.x - line.p1.x; // convert line to vector
v1.y = line.p2.y - line.p1.y;
l = Math.sqrt(v1.x * v1.x + v1.y * v1.y); // get length;
v1.x /= l; // Assuming you never pass zero length lines
v1.y /= l;
v1.x *= dist; // set the length
v1.y *= dist;
// move the line along its normal the required distance
line.p1.x -= v1.y;
line.p1.y += v1.x;
line.p2.x -= v1.y;
line.p2.y += v1.x;
return line; // if needed
}
Distance circle (or point) to a line segment
Returns the closest distance to the line segment. It is just the circle center that I am using. So you can replace circle with a point
functioncircleDistFromLineSeg(circle,line){
var v1, v2, v3, u;
v1 = {};
v2 = {};
v3 = {};
v1.x = line.p2.x - line.p1.x;
v1.y = line.p2.y - line.p1.y;
v2.x = circle.center.x - line.p1.x;
v2.y = circle.center.y - line.p1.y;
u = (v2.x * v1.x + v2.y * v1.y) / (v1.y * v1.y + v1.x * v1.x); // unit dist of point on lineif(u >= 0 && u <= 1){
v3.x = (v1.x * u + line.p1.x) - circle.center.x;
v3.y = (v1.y * u + line.p1.y) - circle.center.y;
v3.x *= v3.x;
v3.y *= v3.y;
returnMath.sqrt(v3.y + v3.x); // return distance from line
}
// get distance from end points
v3.x = circle.center.x - line.p2.x;
v3.y = circle.center.y - line.p2.y;
v3.x *= v3.x; // square vectors
v3.y *= v3.y;
v2.x *= v2.x;
v2.y *= v2.y;
returnMath.min(Math.sqrt(v2.y + v2.x), Math.sqrt(v3.y + v3.x)); // return smaller of two distances as the result
}
Post a Comment for "Circle Line Segment Collision"