/// <summary> /// Computes an intersection of the circles /// </summary> /// <returns>True if the circles intersect or one circle is contained within the other</returns> public static bool IntersectCircleCircle(Circle circleA, Circle circleB, out IntersectionCircleCircle intersection) { return(IntersectCircleCircle(circleA.center, circleA.radius, circleB.center, circleB.radius, out intersection)); }
/// <summary> /// Computes an intersection of the circles /// </summary> /// <returns>True if the circles intersect or one circle is contained within the other</returns> public static bool IntersectCircleCircle(Vector2 centerA, float radiusA, Vector2 centerB, float radiusB, out IntersectionCircleCircle intersection) { intersection = new IntersectionCircleCircle(); Vector2 fromBtoA = centerA - centerB; float distanceFromBtoASqr = fromBtoA.sqrMagnitude; if (distanceFromBtoASqr < EpsilonSqr) { if (Mathf.Abs(radiusA - radiusB) < Epsilon) { // Circles are coincident intersection.type = IntersectionType.Circle; return(true); } // One circle is inside the other intersection.type = IntersectionType.None; return(true); } float sumOfRadii = radiusA + radiusB; float sumOfRadiiSqr = sumOfRadii * sumOfRadii; if (distanceFromBtoASqr > sumOfRadiiSqr) { // No intersections, circles are separate intersection.type = IntersectionType.None; return(false); } if (Mathf.Abs(distanceFromBtoASqr - sumOfRadiiSqr) < EpsilonSqr) { // One intersection outside intersection.type = IntersectionType.Point; intersection.pointA = centerB + fromBtoA * (radiusB / sumOfRadii); return(true); } float differenceOfRadii = radiusA - radiusB; float differenceOfRadiiSqr = differenceOfRadii * differenceOfRadii; if (distanceFromBtoASqr < differenceOfRadiiSqr) { // One circle is contained within the other intersection.type = IntersectionType.None; return(true); } if (Mathf.Abs(distanceFromBtoASqr - differenceOfRadiiSqr) < EpsilonSqr) { // One intersection inside intersection.type = IntersectionType.Point; intersection.pointA = centerB - fromBtoA * (radiusB / differenceOfRadii); return(true); } // Two intersections intersection.type = IntersectionType.TwoPoints; float radiusASqr = radiusA * radiusA; float distanceToMiddle = 0.5f * (radiusASqr - radiusB * radiusB) / distanceFromBtoASqr + 0.5f; Vector2 middle = centerA - fromBtoA * distanceToMiddle; float discriminant = radiusASqr / distanceFromBtoASqr - distanceToMiddle * distanceToMiddle; if (discriminant < 0) { discriminant = 0; } Vector2 offset = fromBtoA.Perp() * Mathf.Sqrt(discriminant); intersection.pointA = middle + offset; intersection.pointB = middle - offset; return(true); }
/// <summary> /// Computes an intersection of the circles /// </summary> /// <returns>True if the circles intersect or one circle is contained within the other</returns> public static bool CircleCircle(Vector2 centerA, float radiusA, Vector2 centerB, float radiusB, out IntersectionCircleCircle intersection) { Vector2 fromBtoA = centerA - centerB; float distanceFromBtoASqr = fromBtoA.sqrMagnitude; if (distanceFromBtoASqr < Geometry.Epsilon) { if (Mathf.Abs(radiusA - radiusB) < Geometry.Epsilon) { // Circles are coincident intersection = IntersectionCircleCircle.Circle(); return(true); } // One circle is inside the other intersection = IntersectionCircleCircle.None(); return(true); } // For intersections on the circle's edge magnitude is more stable than sqrMagnitude float distanceFromBtoA = Mathf.Sqrt(distanceFromBtoASqr); float sumOfRadii = radiusA + radiusB; if (Mathf.Abs(distanceFromBtoA - sumOfRadii) < Geometry.Epsilon) { // One intersection outside intersection = IntersectionCircleCircle.Point(centerB + fromBtoA * (radiusB / sumOfRadii)); return(true); } if (distanceFromBtoA > sumOfRadii) { // No intersections, circles are separate intersection = IntersectionCircleCircle.None(); return(false); } float differenceOfRadii = radiusA - radiusB; float differenceOfRadiiAbs = Mathf.Abs(differenceOfRadii); if (Mathf.Abs(distanceFromBtoA - differenceOfRadiiAbs) < Geometry.Epsilon) { // One intersection inside intersection = IntersectionCircleCircle.Point(centerB - fromBtoA * (radiusB / differenceOfRadii)); return(true); } if (distanceFromBtoA < differenceOfRadiiAbs) { // One circle is contained within the other intersection = IntersectionCircleCircle.None(); return(true); } // Two intersections float radiusASqr = radiusA * radiusA; float distanceToMiddle = 0.5f * (radiusASqr - radiusB * radiusB) / distanceFromBtoASqr + 0.5f; Vector2 middle = centerA - fromBtoA * distanceToMiddle; float discriminant = radiusASqr / distanceFromBtoASqr - distanceToMiddle * distanceToMiddle; Vector2 offset = fromBtoA.RotateCCW90() * Mathf.Sqrt(discriminant); intersection = IntersectionCircleCircle.TwoPoints(middle + offset, middle - offset); return(true); }