Introduction
Collision detection and response between a moving circle and a static line segment in two dimensions is not an easy task. This algorithm in this tutorial is intended to accurately find the location of the collision and calculate the resultant velocity without using discrete time steps (moving the circle forward until a collision occurs). Thus the algorithm works with dynamic circles that respond to impulse forces. It is designed to use linear algebra in order to avoid using (relatively) computationally costly square roots, so some logic may seem quite roundabout.
This tutorial assumes basic knowledge of a programming language (Java in particular) and knowledge of basic algebra and geometry. Circles in this algorithm are assumed to be non-rotating.
Object Definitions
|
|
Moving circle (
circle )
The movement vector is |
Static line segment (
line )
|
Line-Line Intersection
Steps
- Start with two line segments, one described by endpoints
(x1, y1)
and(x2, y2)
and the other by(x3, y3)
and(x4, y4)
. - Take the endpoints of each of the line segments and turn
it into an equation of the form
Ax + By = C
. - Rearrange into a linear system of equations.
- Find the determinant
of the two equations algebraically:
determinant = A1 * B2 - A2 * B1
. - Use Cramer's
Rule to solve for the point of intersection.
If the determinant is zero, the lines are parallel or equal, and thus there is no point of intersection.
- Make sure the point of intersection is between the
endpoints of the two line segments (or else only the infinite
lines have intersected, which always occurs for non-parallel
lines).
Java code
Point checklinescollide(float x1, float y1, float x2, float y2,
float x3, float y3, float x4, float y4){
float A1 = y2-y1;
float B1 = x1-x2;
float C1 = A1*x1 + B1*y1;
float A2 = y4-y3;
float B2 = x3-x4;
float C2 = A2*x3 + B2*y3;
float det = A1*B2-A2*B1;
if(det != 0){
float x = (B2*C1 - B1*C2)/det;
float y = (A1*C2 - A2*C1)/det;
if(x >= Math.min(x1, x2) && x <= Math.max(x1, x2)
&& x >= Math.min(x3, x4) && x <= Math.max(x3, x4)
&& y >= Math.min(y1, y2) && y <= Math.max(y1, y2)
&& y >= Math.min(y3, y4) && y <= Math.max(y3, y4))
return new Point(x, y);
}
return null;
}
The Closest Point on a Line to a Point Algorithm
Steps
- Start with a given point
(x0, y0)
and a given line segment, described by endpoints(lx1, ly1)
and(lx2, ly2)
. - Take the endpoints of the line segment and turn it into an
equation of the form
Ax + By = C
. - The equation of the line perpendicular to the
initial line segment is given by
-Bx + Ay = C
, but this time(x, y)
is the given point so that the new equation crosses through the given point. - Find the determinant of the two
equations algebraically:
determinant = A*A + B*B
. - Use Cramer's Rule to solve
for the point of intersection of the original line and the
perpendicular line, and that gives us the closest point on the
given line to given point.
If the
determinant = 0
, then the point is on the line, and thus the closest point on the line to the point is the point itself!
Java Code
Point closestpointonline(float lx1, float ly1,
float lx2, float ly2, float x0, float y0){
float A1 = ly2 - ly1;
float B1 = lx1 - lx2;
double C1 = (ly2 - ly1)*lx1 + (lx1 - lx2)*ly1;
double C2 = -B1*x0 + A1*y0;
double det = A1*A1 - -B1*B1;
double cx = 0;
double cy = 0;
if(det != 0){
cx = (float)((A1*C1 - B1*C2)/det);
cy = (float)((A1*C2 - -B1*C1)/det);
}else{
cx = x0;
cy = y0;
}
return new Point(cx, cy);
}
Collision Detection
Collision detection is the process of detecting whether or not two objects have collided. We need to check if the circle has already collided with the line or if the circle will collide with the line before the end of the movement vector.
Note that distance refers to Euclidean distance, which is basically the Pythagorean theorem.
Static Circle and Static Line Segment
Determine the distance from the circle to the line by
first finding the closest point on the line to the center of
the circle (
|
Moving Circle and Static Line Segment
|
Find several other points:
|
|
The circle's position at the time of collision (point2 )
can then be found using a similar triangle formed by point1 ,
a , r (the circle's radius), and C
(the center of the circle). This is described in the
equation below:v
is the movement vector of the circle and
C
is the location of the circle.
|
|
The closest point on the line to point2 , the point of
contact between the circle and the line (pointC )
can then be found. To determine the collision response algorithm to use:
|
|
If the circle has collided with an endpoint, it becomes
a subset of the moving circle - static circle collision problem, as long as we treat
the endpoint as a static circle with zero radius:
|
Collision Response
Since the line is static, no energy should be lost
to the line (making the collision elastic) and the only part
of the velocity that changes is the direction.
|
Conclusion
Once collision detection and collision response are combined, you have a working line-circle collision simulation algorithm! Of course, this algorithm isn't perfect, because we treat the endpoints as circles with zero radii, but the errors that result aren't major. The problems are detailed more throughly in my paper.
External Links
Algorithm Tutorials - covers the line-line collision detection formula and more.
N Tutorial A - Collision Detection and Response - deals with rectangles and specialized shapes and has a useful appendix.
Pool Hall Lessons: Fast, Accurate Collision Detection Between Circles or Spheres - deals with circle-circle collision, which can be used to give thickness to the line.