Skip to content
Zorro edited this page Nov 24, 2021 · 7 revisions

Point collisions

Point versus point

If two points are the same, they collide. You are probably looking for something with a little more give, like a circle vs circle collision.

See Circle Collision 2D

Point versus AABB

To check if a point is within an axis-aligned bounding box is straight forward. To collide it must be within the shape, and hence within the boundaries of the rectangle.

bool PointInsideAABB(double x1 , double y1 , Rectangle r) {
   return (!(x1 < r.x ||
             y1 < r.y ||
             x1 > r.rx ||
             y1 > r.by));
}

Point versus circle

To check if a point is within a circle is simple. All you do is check whether the distance between the point and the center of the circle is less than or equal to the radius of the circle. To simplify the calculation we use the distance squared versus the radius squared.

bool PointInsideCircle(double x1 , double y1 , double cx , double cy , double cradius) {
   const double dsq = (cx - x1)*(cx - x1) + (cy - y1)*(cy - y1);
   return dsq <= cradius*cradius;
}

Point versus line

Here we'll take advantage of the dot product to test the scalar projection of the point unto a line perpendicular to the one we want to check. We'll be testing which side of the line a point is on, or whether it is directly on the line.

Pick two points on your line, call them x1,y1 and x2,y2. The point you want to check against the line will be defined as x3,y3. Now make a vector from point 1 to point 2 and find the relative difference between them. We will consider point 1 to be the origin for simplicity's sake.

Vector 1 (from point 1 to point 2)

dx = x2 - x1
dy = y2 - y1

Vector 2 (from point 1 to point 3)

dx2 = x3 - x1
dy2 = y3 - y1

dx and dy are the magnitudes of the vector components in the x and y direction. We want a line that is perpendicular and rotated 90 degrees to the right. To do this, add dy to x1 and -dx to y1. Vector 3 is the vector from point 2 to point 1 rotated to the right by 90 degrees.

Vector 3 (Vector 1 rotated 90 degrees clockwise)

dx3 = dy
dy3 = -dx

Now we have our perpendicular vector and our point vector. We use the scalar projection of vector 2 unto vector 3 to find how much point 3 is to one side or the other of vector 1, our line. This is also known as the scalar rejection of Vector 2 unto Vector 1.

The scalar projection is closely related to the Collision Equations#dot-product. In fact the scalar projection is defined as the dot product of two vectors divided by the magnitude of the second vector.

SP = (a.b)/|b| = (ax*bx + ay*by)/|b|

As long as the second vector is not of zero length, we can safely ignore it because all we want is the sign of the dot product to determine which side of the line the point is on. So we have :

Sign(V2.V3) = Sign(dy*dx2 - dx*dy2)

If this value is positive, the point is on the right side of the line. If negative, on the left, and if zero, directly on the line.

NOTE If you reverse the direction of vector one, the sign is reversed. It entirely depends on your choice of points, and which side of the line you want to designate as "to the right".

Point versus triangle

Point versus triangle is made much easier now that we've done point versus line. It consists of 3 point versus line checks using the vertices of the triangle as the points on the lines.

Depending on which way you wrap your vertices on your triangle (clockwise or counter clockwise winding order), to the right will be either inside or outside of the triangle. If clockwise, right is inside, and left is outside. If counter clockwise, right will be outside, and left will be inside.

Perform 3 point versus line checks. If the sign of each indicates the point is to the right (for clockwise winding), then it must be inside the triangle. If some are zero, but the rest are to the right, it is on the edge of one of the lines, but still technically inside the triangle. If any of the signs oppose each other or if any points to the left, it is outside of the triangle.

Return to Collision Detection 2D

Clone this wiki locally