I have a function that checks if two circle annulus overlaps and works perfectly fine for small circles:
public static bool Overlaps(in Circle circle1, in float annulus1, in Circle circle2, in float annulus2)
{
double h1 = annulus1 * 0.5f;
double h2 = annulus2 * 0.5f;
var innerRadius1 = circle1.Radius - h1;
var outerRadius1 = circle1.Radius + h1;
var innerRadius2 = circle2.Radius - h2;
var outerRadius2 = circle2.Radius + h2;
var d = math.distance(circle1.Origin, circle2.Origin);
return d < outerRadius1 + outerRadius2 &&
d > innerRadius1 - outerRadius2 &&
d > innerRadius2 - outerRadius1;
}
However the problem is for very large circles, it does not detect overlap for example:
This shows green suggesting there is no overlap. The input data is:
Circle 1:
Origin: (2502,3.09)
Radius: 2500
Annulus: 1
Circle 2:
Origin: (6.33,2.39)
Radius: 2.43
Annulus: 1
The reason I need to support very large circles is because i am actually using arcs, and i use a circle annulus overlap test to early exit from doing the more heavy computations for arc intersections calculations.
How can i make this more stable? I tried using double
but that still failed to correctly detect overlap.
There are two extremes where the shapes don't overlap. When they are far apart, and when one shape is completely inside the other. You need to ignore where it is impossible for one shape to fit inside the other.
d < outerRadius1 + outerRadius2 &&
(d > innerRadius1 - outerRadius2 || innerRadius1 < outerRadius2) &&
(d > innerRadius2 - outerRadius1 || innerRadius2 < outerRadius1)
Still I think its easier to read & reason about the following;
var max = outerRadius1 + outerRadius2;
var min = 0f;
if (min < innerRadius1 - outerRadius2)
min = innerRadius1 - outerRadius2;
if (min < innerRadius2 - outerRadius1)
min = innerRadius2 - outerRadius1;
return d >= min && d <= max;