Finding angle covered by circle intersecting another circle

I can’t find the right way to word this, so here’s a diagram:

I am looking for the theta angles depicted (θA or θB) given a center point C, a radius rC, and a position and radius of a given circle (A or B).

B is an edge case where the center point is outside of the circle C, but its radius is large enough to intersect.

Another way of wording it is by what angle do I need to rotate the center line rC to no longer intersect with circle E:

Thanks!

1 Like

Your red and green circles show two different cases. In the title you said intersection and the green one seems to show that. However the red one simply shows the tangents to the circle, so simply the angular size as seen from the center. Your second image also seem to suggest that you want to know the angular size of the circle. Is that right? If not you should clarify what you mean by intersection.

If you mean that when the circle center is inside the big circle you want to get half of the angular size of the circle and when the center is outside the big circle you only want to know the length of the intersection cord?

Well, the first case is the simplest one as you just need some trig identity. Specifically

sin(a) = rE / |CE|

So “rE” is the radius of the small circle while “|CE|” is simply the distance from C to E. So take the “Asin” from the result and you get the angle

float angRad = Mathf.Asin(rE / (E-C).magnitude);

This will give you the angle in radian assuming rE is a float indicating the radius and C and E are the position vectors.

As for the second case, that’s more complicated, but not too difficult. Though I currently don’t have time to think it through ^^. Maybe someone else has the time. Of course you have a limit at |CE| > rC + rE because at this point the circle E would be completely outside the big circle and there is no intersection and no angle to calculate.

It usually helps when you can give some background of the actual usecase where / why you need this information.

edit
Just thought about it for a minute and for the second case all you would need it the law if cosines. As we know the length of 3 side of a non right triangle between rE, rC and |CE|, we can use the law of cosines to get any of the angles.

a² = b² + c² - 2bc*cos(alpha)

Just rearrange to alpha and insert our 3 sides accordingly. a is rE, b is rC and c is |CE|

first, rearrange:

(b²+c²-a²) / 2bc = cos(alpha)

then just insert our values:

float c = (E-C).magnitude;
float alpha = Mathf.Acos((rC*rC + c*c - rE*rE) / 2*rC*c);

This should again give you the angle in radians. If you need / want degrees you can multiply the angle in radians with Mathf.Rad2Deg to get degrees

3 Likes

Amazing, thank you for the detailed response!

Yes you got it right, I am trying to calculate the angular size of the circle, but smoothly replace that with the angular size of the intersection cord as it crosses the edge. The use case is for an aim assist system where we create a graph of targets within a radius, which can be smoothed to create more consistent and controllable snapping.

Thanks again! Marking as resolved :slight_smile:

One more important thing is knowing when to switch between formulas for case 1 and 2. You might think it’s when center of second circle is on the first big circle. It’s close but not quite. I initially tried to think about it geometrically but by my brains weren’t working in that direction at that moment. So I decided to brute force it by writing an equation to find at which distance |CE| both angles are identical. That is

asin (rE / |EC|) = acos(rC^2 + |EC|^2 - rE^2) / 2rC|EC|)

After whole page of transformations result ended up simpler than I expected:

|EC| = sqrt(rC^2 + rE^2)

It makes sense once you draw it, someone who is better at reasoning about geometrical drawing probably could have guessed without whole page of equation solving. (ignore letters in my drawings, in formulas I use same names as initial drawings and what Bunny used)

On the other hand you can’t always trust drawings, because things might look like they are the same point but might actually be two points very close to each other especially if you are drawing on paper.

Placing smaller circle center on the radius of big circle is good example of how drawing might be misleading. It looks like the tangents go through the points where circles intersect in both cases but that’s not true. As previous formula means that center of smaller circle needs to be slightly outside for those points to match.

So if |CE| < sqrt(rE^2 + rC^2) you need to use case 1) and if sqrt(rE^2 + rC^2) < |CE| < rC+rE you need to apply case 2).

There are few more edge cases that you need to take care of like when center of main circle is inside the second circle. I guess it depends on your game whether you want to consider that as “> 180°” , 360° or something else. Or maybe such situation is impossible in your game.


8436362--1117535--upload_2022-9-13_16-58-50.png

EDIT: most of the stuff I wrote probably doesn’t apply to your usecase. I wrote this before I saw your comment about aim assist.

2 Likes

:smile: I knew someone would catch that :slight_smile: I couldn’t be bothered at the moment about that, but yes, I’ve noticed that. Though if the ratio between the two circles is large, it’s really just a tiny bit.

The two edge cases you mentioned are pretty irrelevant as that would mean you, the player / camera has to be inside the enemy / target which probably won’t happen.

As I understand the situation, the big circle should be some kind of weapon range while the small circle is the size of the enemy / target. He wants to find the area that the target is covering. If you’re inside the target, it doesn’t really matter where to aim since you’re surrounded by your target.

Though you’re right that it should be evalulated which extreme values could be possible, especially to avoid issues in the calculations. Especially with Asin / Acos you can easily get a NaN value which can “infect” everything else you do afterwards. Asin and Acos will return NaN whenever the supplied value is larger than 1 or smaller than -1, even the tiniest amount is enough. To be on the safe side I would always use a Mathf.Clamp before using those to ensure we stay inside the safe range.

ps:

Of course the correct limit when to switch between the two calculation methods is when the two radius of the two circles form a right angle at the intersection point. So the proper distance is simply
rLimit = sqrt(rC² + rE²)

So when the center of circle E is “rLimit” away from C, that’s where you should switch.

1 Like