Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to determine whether two circular sectors overlap with each other

Tags:

java

algorithm

Each sector can be represented as (x,y,r,a,d), where x,y is the location, r is the radius, d is the direction, and a is the angle. Given these information of two circular sectors, how to determine whether they overlap with each other? Is there any efficient algorithm for solving it? Thanks!

like image 730
wzb5210 Avatar asked May 22 '12 01:05

wzb5210


3 Answers

I know of one very quick way to discount the possibility, since I've used that for circle collisions before.

Work out the distance between the two centers and then, if that's greater than the sum of the radii, there can be no collision. For efficiency, don't use square root, just work directly on the squared values:

if (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1) > (r1 + r2) * (r1 + r2):
    # No chance of collision.

Working it out for circle segments will be a little tougher.


Your choice of method depends on how accurate you need it to be. If you're doing actual math, you probably need high accuracy. But, for example, if you're doing this for something like a computer game, close enough may be good enough.

If that were the case, I'd look into transforming the arc into a series of straight lines (the number of which would probably depend on a, the "spread" of the arc - you could probably get away with a couple of lines for a spread of one degree of arc but that wouldn't work too well for 180 degrees).

Straight line collision detection is a much better known method although you have to deal with the fact that the number of comparisons may rise quickly.


If you don't want to use line segments, then here's the process to follow. It uses a circle collision algorithm to find out the zero, one or two points of collisions for the full circles, then checks those points to see if they're within both arcs.

First, run that check above to detect the case where no collision is possible. If no collision is possible between the circles, then neither can the arcs collide.

Secondly, check if the circles have a single collision point. That's the case if:

(x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1) == (r1 + r2) * (r1 + r2)

within a suitable error range, of course. We should all know by now that comparing floating point numbers for equality should use some sort of delta comparison.

If that's the case, you have one point to check and you can find out that point easily. It's the point r1 units along the straight line leading from (x1,y1) to (x2,y2) or, looking at it as moving some fraction along that line:

(x1 + (x2-x1) * (r1+r2) / r1, y1 + (y2-y1) * (r1+r2) / r1)

Otherwise, there are two points to check and you can use the answers to a question like this one to establish what those two points are.

Once you have some collision points, it's a much simpler method to find out if those points are on an arc, keeping in mind that the candidate point will need to be on both arcs for them to collide, not just on one.

like image 60
paxdiablo Avatar answered Nov 15 '22 18:11

paxdiablo


There's two steps. First is to figure out if the two centres are close enough to each other to allow a collision, which can be done by comparing the distance between them to the sum of their radii:

if (((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)) > ((r1 + r2) * (r1 + r2)))
    // No collision.

Then you need to check whether the line between the centres falls within the arcs defined by your various angles:

float angle1to2 = Math.atan2(y2 - y1, x2 - x1);
if (angle1to2 < (d1 - a1/2) || angle1to2 > (d1 + a1/2))
    // No collision
float angle2to1 = angle1to2 + Math.PI;
if (angle2to1 < (d2 - a2/2) || angle2to1 > (d2 + a2/2))
    // No collision

If you get through these checks without the possibility of a collision being excluded, then you have successfully detected a collision.

Caveat: this code isn't tested at all. In particular, the atan2 calls may need some tweaking depending on your coordinate system.

EDIT: just realised this misses an important corner case, where the arcs are not "pointing" at each other but still overlap. Will ruminate upon this and return...

like image 28
Mac Avatar answered Nov 15 '22 17:11

Mac


Since we have circular sectors, angle and direction do not matter if you are doing this in real time. The following applies only to full circle sectors, or if both sectors are pointing to each other.

you can follow the next steps:

1) Find the distance between each sector, 2) Subtract both radius to that distance, 3) if the result is negative, there has been a collision between both sectors. otherwise, its the distance to collision.

for example, we have two sectors, both with a 50 unit radius. the distance between their center points is 80. subtract 80-50-50 = -20, so you know there has been a collision 20 units in distance.

otherwise, if the distance was 500, 500-50-50 = 400, a positive value, now you know that these two sectors are 400 units apart.

now, if the circles are too close, say, 1 unit apart, 1-50-50 = -99, which means they are almost totally overlapping.

For true segmented circular sectors which is what you specified on the comments, you should use paxdiablos or Macs answers.

like image 25
Basilio German Avatar answered Nov 15 '22 17:11

Basilio German