问题描述
求2个圆c1、c2的交点。
输入:
输入按照下述格式给出:
c1x c1y c1r
c2x c2y c2r
c1x、c1y、c1r分别表示第1个圆的圆心x坐标、y坐标以及半径。同理,c2x、c2y、c2r表示第2个圆的坐标与半径。上述输入均为整数。
输出:
按下述规则输出交点p1、p2的坐标(x1, y1)、(x2, y2),相邻数据之间用空格隔开:
只有1个交点时输出2个相同的坐标
先输出x坐标较小的点。x坐标相同时先输出y坐标较小的点
允许误差不超过0.000001。
限制:
2个圆存在交点且圆心不同
-10000 ≤ c1x, c1y, c2x, c2y ≤ 10000
1 ≤ c1r, c2r ≤ 10000
输入示例
0 0 2
2 0 2
输出示例
1.0000000 -1.7320508 1.0000000 1.7320508
讲解
求两个圆交点的方法有很多,这里我们学习的算法使用了向量运算和余弦定理。
先求出两个圆的圆心距d。这个圆心距就是c1.到c2.的向量(反过来亦可)的大小
由两圆圆心以及其中一个交点所组成的三角形的三条边分别为c1.r、c2.r、d,根据余弦定理可求出向量c2.c - c1.c与c1.c到某交点的向量的夹角a。然后我们再求出c2.c - c1.c与x轴的夹角t备用
这样一来,我们所求的交点就是以圆心c1.c为起点,大小为c1.r,角度为t + a和t - a的两个向量
求圆c1与圆c2交点的程序可以像下面这样写。
圆c1与圆c2的交点:
double arg(Vector p) {
return atan2(p.y, p.x); }
Vector polar(double a, double r) {
return Point(cos(r) * a, sin(r) * a); }
pair<Point, Point> getCrossPoints(Circle c1, Circle c2) {
assert(intersect(c1, c2));
double d = abs(c1.c - c2.c);
double a = acos((c1.r * c1.r + d * d - c2.r * c2.r) / (2 * c1.r * d));
double t = arg(c2.c - c1.c);
return make_pair(c1.c + polar(c1.r, t + a), c1.c + polar(c1.r, t - a));
}
AC代码如下
#include<stdio.h>