# 计算任意两个圆的交点

http://mathworld.wolfram.com/Circle-CircleIntersection.html

1 计算两个圆心之间的距离L
2 如果 L>r1+r2 无交点
3 如果 l = r1 + r2 则一个交点， 用圆心的坐标可以计算出具体点
4 假定 两个交点的连线和圆心连线的交点是D，D到第一个圆心的距离是d, 则
d*d + y*y = r1*r1
(l-d)*(l-d) + y*y = r2 * r2
其中y就是两交点连线距离的一半了
合并一下可得到：
r2*r2 - r1*r1 = l*l - 2dl
d = (l*l - r2*r2 + r1*r1) / 2l
5 根据前面的公式，还可以确定出来 y的数值
6 y = sqrt(r1*r1-d*d)

 1 /// <summary>
2 /// 判断两个平行于x轴的圆的交点
3 /// </summary>
4 /// <param name="centerA">第一个圆的中点</param>
5 /// <param name="rA">半径</param>
6 /// <param name="centerB">第二个圆的中点</param>
7 /// <param name="rB">半径</param>
8 /// <param name="ptInter1">交点1(若不存在返回65536)</param>
9 /// <param name="ptInter2">交点1(若不存在返回65536)</param>
10 public static void CircleInterCircleOnXAxis(PointF centerA, double rA, PointF centerB, double rB, ref PointF ptInter1, ref PointF ptInter2)
11 {
12     ptInter1.X = ptInter2.X = 65536.0f;
13     ptInter1.Y = ptInter2.Y = 65536.0f;
14     PointF centerLeft;
15     double R, r, d;
16     if (centerA.X < centerB.X)
17     {
18         centerLeft = centerA;
19         R = rA;
20         r = rB;
21         d = centerB.X - centerA.X;
22     }
23     else
24     {
25         centerLeft = centerB;
26         R = rB;
27         r = rA;
28         d = centerA.X - centerB.X;
29     }
30     double R2 = R * R;
31     double x = (d*d - r*r + R2)/(2*d);
32     double y = Math.Sqrt(R2 - x * x);
33     ptInter1.X = centerLeft.X + (int)x;
34     ptInter1.Y = centerLeft.Y + (int)y;
35     ptInter2.X = centerLeft.X + (int)x;
36     ptInter2.Y = centerLeft.Y - (int)y;
37 }

 1 /// <summary>
2 /// 以中心点逆时针旋转Angle角度
3 /// </summary>
4 /// <param name="center">中心点</param>
5 /// <param name="p1">待旋转的点</param>
6 /// <param name="angle">旋转角度（弧度）</param>
7 public static PointF PointRotate(PointF center, PointF p1, double angle)
8 {
9     double x1 = (p1.X - center.X) * Math.Cos(angle) + (p1.Y - center.Y) * Math.Sin(angle) + center.X;
10     double y1 = -(p1.X - center.X) * Math.Sin(angle) + (p1.Y - center.Y) * Math.Cos(angle) + center.Y;
11     return new PointF((float)x1, (float)y1);
12 }

 1 /// <summary>
2 /// 计算两个向量的夹角
3 /// </summary>
4 /// <param name="Va"></param>
5 /// <param name="Vb"></param>
6 /// <returns></returns>
7 public static double GetAngleOfVectors(PointF Va, PointF Vb)
8 {
9     double da = Math.Sqrt(Va.X*Va.X + Va.Y*Va.Y);
10     double db = Math.Sqrt(Vb.X*Vb.X + Vb.Y*Vb.Y);
11     double theta = Math.Acos((Va.X*Vb.X + Va.Y*Vb.Y)/(da*db));
12     return theta;
13 }

好吧，还是贴出来好了：

/// <summary>
///     求任意两个圆的交点
/// </summary>
/// <param name="centerA">第一个圆的中点</param>
/// <param name="rA">半径</param>
/// <param name="centerB">第二个圆的中点</param>
/// <param name="rB">半径</param>
/// <param name="ptInter1">交点1(若不存在返回65536)</param>
/// <param name="ptInter2">交点1(若不存在返回65536)</param>
public static void CircleInterCircle(PointF centerA, double rA, PointF centerB, double rB, ref PointF ptInter1,
ref PointF ptInter2)
{
var v = new PointF(centerB.X - centerA.X, centerB.Y - centerA.Y);
double angle = GetAngleWithXAxis(v);
PointF bb = PointRotate(centerA, centerB, angle);
PointF p1 = Point.Empty, p2 = Point.Empty;
CircleInterCircleOnXAxis(centerA, rA, bb, rB, ref p1, ref p2);
if (!Equal(p1.X, 65536.0f))
{
p1 = PointRotate(centerA, p1, -angle);
}
if (!Equal(p2.X, 65536.0f))
{
p2 = PointRotate(centerA, p2, -angle);
}
ptInter1 = p1;
ptInter2 = p2;
}

• 1
点赞
• 0
评论
• 0
收藏
• 一键三连
• 扫一扫，分享海报

07-05
12-15

03-07 2551
02-28 4960
01-23 2564
06-11 3823
12-19 2万+
11-07 2556
09-29 4246
11-24 2万+
12-27 7850
01-25 6359
07-25 9552