9
votes

I'm struggling to find a rock solid solution to detecting collisions between a circle and a circle segment. Imagine a Field of View cone for a game enemy, with the circles representing objects of interest.

The diagram at the bottom is something I drew to try and work out some possible cases, but i'm sure there are more.

I understand how to quickly exlude extreme cases, I discard any targets that don't collide with the entire circle, and any cases where the center of the main circle is within the target circle are automatically true (E in the diagram).

I'm struggling to find a good way to check the rest of the cases. I've tried comparing distances between circle centers and the end points of the segments outer lines, and i've tried working out the angle of the center of the target circle from the center of the main circle and determining whether that is within the segment, but neither way seems to catch all cases.

Specifically it seems to go funky if the target circle is close to the center but not touching it (somewhere between E and B below), or if the segment is narrower than the target circle (so that the center is within the segment but both edges are outside it).

Is there a reliable method for doing this?

Extra info: The segment is described by position P, orientation O (whose magnitude is the circle radius), and a view size, S.

My most successful attempt to date involved determining the angles of the vectors ca1 and ca2, and checking if either of them lies between the angles of vectors a1 and a2. This works for some cases as explained above, but not situations where the target circle is larger than the segment.

Edit 2 After implementing the best suggestion from below, there is still a false positive which I am unsure how best to eliminate. See the pink diagram below. The circle in the lower right is reporting as colliding with the segment because it's bounds overlap both half spaces and the main circle.

collision typescurrent solution

false positiveedge case


Final Edit

After discovering another edge case (4th image), i've settled on an approach which combines the two top answers from below and seems to cover all bases. I'll describe it here for the sake of those who follow.

First exclude anything that fails a quick circle-to-circle test.

Then test for collision between the circle and the two outer lines of the segment. If it touches either, return true.

Finally, do a couple of point-to-halfspace tests using the center of the circle and the two outer lines (as described by Gareth below). If it passes both of those it's in, otherwise return false.

2

2 Answers

5
votes

A. Check if it is intersecting the whole cirlce.
B. Check if it is intersecting either of the straight segment lines.
C. If not, check if the angle between the circle centres lies in the angular range of the segment (dot product is good for this).

Intersection requires A && (B || C)

4
votes

A circular segment (with central angle less than 180°) is the intersection of three figures: a circle, and two half-planes:

alt text

So a figure intersects the circular segment only if it intersects all three of these figures. [That's only if but not if; see below.]

Circle/circle intersection is easy (compare the distance between their centres with the sum of their radii).

For circle/half-plane intersection, represent the half-plane in the form p · nk (where p is the point to be tested, n is a unit vector that's normal to the line defining the half-plane, and k is a constant). Then a circle with centre x and radius r intersects the half-plane if x · nk + r.

(If you need to handle a circular segment with central angle greater than 180°, split it into two segments with central angle less than 180°. If I understand your problem description correctly, you won't need to do this, since your field of view will always be less than 180°, but it's worth mentioning.)

Edited to add: as pointed out by beeglebug, a circle can intersect all three figures without intersecting their intersection. Oops. But I believe that this can only happen when the circle is behind the centre of the segment, as in the diagram below, and in this case we can apply the separating axis test for convex figures.

A circle failing to intersect a circular segment, with an axis shown separating them

The separating axis theorem says that two convex figures fail to intersect if there exists a line such that one figure falls entirely on one side of the line, and the other figure on the other.

If any separating axis exists in this case, then the axis that's perpendicular to the line between the centre of the circle and the centre of the segment is a separating axis (as shown).

Let the centre of the segment be at the origin, let the circle have centre x and radius r, and let the two half-planes have (outward) normals n₁ and n₂. The circle is "behind" the segment if

x · n₁ > 0 and x · n₂ > 0

and the axis separates it from the segment if

|x| > r

A circle failing to intersect a circular segment, with an axis shown separating them, with points, normals and radius marked