intersection of two circles

Problem description:
Given two intersecting circles, the center of the first circle is (x1, y1), the radius is r1, the center of the second circle is (x2, y2), and the radius is r2, find the intersection of the two circles .


Problem analysis:
The template for finding the intersection of two circles in the "Training Guide" uses library functions such as atan2 and acos, and the accuracy loss is relatively serious.
The following introduces a method with less precision loss:
Original address


First , let’s review the two representations of


circles: the standard equation of the circle: (x−x0)2+(y−y0)2=r2
The parametric equation of the circle: {x =x0+r⋅cosθy=y0+r⋅sinθ
brings the parametric equation of the first circle into the standard equation of the second circle:
(x1+r1cosθ−x2)2+(y1+r1sinθ−y2)2=
r22Expand Then we get:
2r1(x1−x2)cosθ+2r1(y1−y2)sinθ=r22−r21−(x1−x2)2−(y1−y2)2
Let:
a=2r1(x1−x2)
b=2r1( y1−y2)
c=r22−r21−(x1−x2)2−(y1−y2)2
The original formula becomes:
acosθ+bsinθ=c
Let cosθ=x,sinθ=1−x2−−−−−√, The positive and negative of sinθ will be judged later.
Substituting into the equation, we get, ax+b1−x2−−−−−√=c
shift term and square on both sides, (ax−c)2=b2(1−x2)
, (a2+b2)x2−2acx+c2 −b2=0
The following is the solution of the quadratic equation in one variable.


Substitute sinθ and cosθ back into the parametric equation of the first circle to get the coordinates of the intersection.
If the point is not on the second circle, sinθ is a negative number, and this intersection point needs to be adjusted slightly.
There is also a special case, if it has been determined that there are two different intersection points, but only one cosθ value is solved.
It shows that the corresponding sinθ value must be positive and negative.


#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>


typedef long double LD;


const LD eps = 1e-10;


int dcmp(LD x) {
    if(fabs(x ) < eps) return 0;
    return x < 0 ? -1 : 1;
}


LD sqr(LD x) { return x * x; }


struct Point
{
    LD x, y;
    Point(LD x = 0, LD y = 0 ):x(x), y(y) {}
    void read() { cin >> x >> y; }
};


Point operator - (const Point& A, const Point& B) {
    return Point(A.x - B.x, A.y - B.y);
}


bool operator == (const Point& A, const Point& B) {
    return dcmp(A.x - B.x) == 0 && dcmp(A.y - B.x) == 0;
}


LD Dot(const Point& A, const Point& B) {
    return A.x * B.x + A.y * B.y;
}


LD Length(const Point& A) { return sqrt(Dot(A, A)); }


struct Circle
{
    Point c;
    LD r;
    Circle() {}
    Circle(Point c, LD r):c(c), r(r) {}
};


int getCircleIntersection(Circle C1, Circle C2) {
    LD &r1 = C1.r, &r2 = C2.r;
    LD &x1 = C1.c.x, &x2 = C2.c.x, &y1 = C1.c.y, &y2 = C2.c.y;
    LD d = Length(C1.c - C2.c);
    if(dcmp(fabs(r1-r2) - d) > 0) return -1;
    if(dcmp(r1 + r2 - d) < 0) return 0;
    LD d2 = Dot(C1.c - C2.c, C1.c - C2.c);
    LD a = r1*(x1-x2)*2, b = r1*(y1-y2)*2, c = r2*r2-r1*r1-d*d;
    LD p = a*a+b*b, q = -a*c*2, r = c*c-b*b;


    LD cosa, sina, cosb, sinb;
    //One Intersection
    if(dcmp(d - (r1 + r2)) == 0 || dcmp(d - fabs(r1 - r2)) == 0) {
        cosa = -q / p / 2;
        sina = sqrt(1 - sqr(cosa));
        Point p(x1 + C1.r * cosa, y1 + C1.r * sina);
        if(!OnCircle(p, C2)) p.y = y1 - C1.r * sina;
        inter.push_back(p);
        return 1;
    }
    //Two Intersections
    LD delta = sqrt(q * q - p * r * 4);
    cosa = (delta - q) / p / 2;
    cosb = (-delta - q) / p / 2;
    sina = sqrt(1 - sqr(cosa));
    sinb = sqrt(1 - sqr(cosb));
    Point p1(x1 + C1.r * cosa, y1 + C1.r * sina);
    Point p2(x1 + C1.r * cosb, y1 + C1.r * sinb);
    if(!OnCircle(p1, C2)) p1.y = y1 - C1.r * sina;
    if(!OnCircle(p2, C2)) p2.y = y1 - C1.r * sinb;
    if(p1 == p2)  p1.y = y1 - C1.r * sina;
    inter.push_back(p1);
    inter.push_back(p2);
    return 2;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324474140&siteId=291194637