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

两圆相交。假定圆心分别为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;
}
运行结果:



  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值