计算任意两个圆的交点

这里是算法的数学思想:

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 }

 

当然上面说的方法需要两个圆平行于x轴,否则说不通。在数学计算上其实经常有这样的现象,就是变换坐标轴位置和方向,使计算简单。所以,这里思来想去需要另外一个工具函数来帮忙。

以某个点为中心点逆时针旋转Angle角度:(代码是网上找的)

 

 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;
}

转载于:https://www.cnblogs.com/william7neral/p/4182398.html

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
VB编程大赛:弧相交点代码 这是一个两圆弧相交点的程序。界面中有图区,操作及显示区。操作分为两个步骤: 1· 创建弧" 。 点击“创建槐按钮,可进入创建弧工作状态。进入创建弧工作状态以后,光标进入有坐标线的图区变为十字线,图区的下面显示光标坐标。在适当位置点击左键,这是弧的一个端点,有一个黑点显示在那里,同时把这点显示出来。移动光标后在适当位置再次点击左键,这是上的一个点,有一个绿点显示在那里,同时把这点显示出来,同时出现一蓝色的皮筋弧在随光标移动,心点由土黄色的点来表示。皮筋弧以黑点为正向(逆时针),在适当位置再次点击左键,弧变为绿色并固定下来,把这点显示出来,这个弧就创建好了,同时把这个弧的参数显示出来。可以继续创建新的唬 2· 选取弧,当创建了两个两个弧时,“选取槐按钮开始有效,点击“选取槐按钮,可进入选取弧工作状态。光标在接近已创建的弧时,那个弧会变成红色,点击左键,这个弧变为紫色,表示被选取的第一个唬当光标再次接近其它已创建的弧时,那个弧会变成红色,点击左键,这个弧变为黑色,表示被选取的第二个唬每次选取的弧参数都被显示出来,当选取弧了两个弧后,开始计算这时两个弧的交点并显示结果。通常有2个交点,分别用红蓝两色点表示。无效交点用灰色点表示,数据也用灰色显示。如无交点也有显示。 点击“重 新 选 缺按钮,将清除刚才的结果,可以重新选取,在运行中,下部的信息栏中显示运行状态并提示下一步的操作,由于这只是一个两圆弧相交点的程序,所以只采用了在屏幕上三点(不在一条直线上)做弧的方法创建弧,略去其它方法,并且略去弧编辑、修改、删除、比例等功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值