计算几何--两圆的位置关系(求交点个数及交点坐标)

时间:2021-11-03 16:18:39

两圆相交。假定圆心分别为C1和C2,半径为r1和r2,圆心距为d,根据余弦定理可以算出C1C2到C1P1的角da,根据向量C1C2的极角a,加减da就可以得到C1P1和C1P2的极角。有了极角,就可以很方便地计算出P1和P2的坐标了。

代码如下:

#include<iostream>
#include<cmath>
#include<vector>
using namespace std;
struct Point
{
double x, y;
Point(double x = 0, double y = 0) :x(x), y(y) {}
};

typedef Point Vector;

Vector operator - (Point A, Point B)
{
return Vector(A.x + B.x, A.y + B.y);
}

Vector operator + (Vector A, Vector B)
{
return Vector(A.x + B.x, A.y + B.y);
}

Vector operator * (Vector A, double p)
{
return Vector(A.x * p, A.y * p);
}

Vector operator / (Vector A, double p)
{
return Vector(A.x / p, A.y / p);
}

double Dot(Vector A,Vector B)
{
return A.x * B.x + A.y * B.y;
}

double Length(Vector A)
{
return sqrt(Dot(A,A));
}

double Angle(Vector A,Vector B) //求角度
{
return acos(Dot(A,B) / Length(A) / Length(B));
}

double angle(Vector v)
{
return atan2(v.y,v.x);
}

const double eps = 1e-10;
int dcmp(double x)
{
if(fabs(x) < eps) return 0;
else
return x < 0 ? -1 : 1;
}

bool operator < (const Point& a,const Point& b)
{
return a.x < b.x || (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.y) == 0;
}

struct Circle
{
Point c;
double r;
Circle(Point c, double r) :c(c), r(r) {}
Point point(double a)
{
return Point(c.x + cos(a) * r, c.y + sin(a) * r);
}
};

int getCircleCircleIntersection(Circle C1,Circle C2,vector<Point>& sol) //求圆和圆的交点
{
double d = Length(C1.c - C2.c);
if(dcmp(d) == 0) //首先圆心要重合
{
if(dcmp(C1.r - C2.r) == 0) return -1; //其次半径要相同,然后就可以推出两圆重合
return 0;
}
if(dcmp(C1.r + C2.r - d) < 0) return 0; //相离没交点
if(dcmp(fabs(C1.r - C2.r) - d) > 0) return 0; //圆在圆中,没有交点

double a = angle(C2.c - C1.c); //向量C1C2的极角
double da = acos((C1.r * C1.r + d * d - C2.r * C2.r) / (2 * C1.r * d)); //C1C2到C1P1的角
Point p1 = C1.point(a-da),p2 = C1.point(a+da);

sol.push_back(p1);
if(p1 == p2) return 1; //相切
sol.push_back(p2);
return 2; //相交
}

int main()
{
double num1,num2,num3,num4;
double r1,r2;
vector<Point> a;
vector<Point>::iterator itr;
while(cin>>num1>>num2>>num3>>num4>>r1>>r2)
{ //圆心坐标,半径
while(!a.empty())
{
a.pop_back();
}
Circle c1(Point(num1,num2),r1),c2(Point(num3,num4),r2);
cout<<"have "<<getCircleCircleIntersection(c1,c2,a)<<" intersection(s)"<<endl;
itr = a.begin();
while(itr != a.end())
{
cout<<itr->x<<","<<itr->y<<endl;
itr++;
}
}
return 0;
}
运行结果:

计算几何--两圆的位置关系(求交点个数及交点坐标)