博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
计算任意两个圆的交点
阅读量:5157 次
发布时间:2019-06-13

本文共 3127 字,大约阅读时间需要 10 分钟。

这里是算法的数学思想:

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 ///  2 /// 判断两个平行于x轴的圆的交点 3 ///  4 /// 第一个圆的中点 5 /// 半径 6 /// 第二个圆的中点 7 /// 半径 8 /// 交点1(若不存在返回65536) 9 /// 交点1(若不存在返回65536)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     else24     {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 ///  2 /// 以中心点逆时针旋转Angle角度 3 ///  4 /// 中心点 5 /// 待旋转的点 6 /// 旋转角度(弧度) 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 ///  2 /// 计算两个向量的夹角 3 ///  4 ///  5 ///  6 /// 
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 }

全部的代码我就不贴了,一方面是写的搓,一方面是希望各位自己也动动脑。哈

以上代码已经经过简单测试

 好吧,还是贴出来好了:

/// ///     求任意两个圆的交点/// /// 第一个圆的中点/// 半径/// 第二个圆的中点/// 半径/// 交点1(若不存在返回65536)/// 交点1(若不存在返回65536)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

你可能感兴趣的文章
C语言基础小结(一)
查看>>
STL中的优先级队列priority_queue
查看>>
UE4 使用UGM制作血条
查看>>
浏览器对属性兼容性支持力度查询网址
查看>>
OO学习总结与体会
查看>>
虚拟机长时间不关造成的问题
查看>>
校门外的树2 contest 树状数组练习 T4
查看>>
面试整理:Python基础
查看>>
Python核心编程——多线程threading和队列
查看>>
Program exited with code **** 相关解释
查看>>
植物大战僵尸中文年度版
查看>>
26、linux 几个C函数,nanosleep,lstat,unlink
查看>>
投标项目的脚本练习2
查看>>
201521123107 《Java程序设计》第9周学习总结
查看>>
Caroline--chochukmo
查看>>
iOS之文本属性Attributes的使用
查看>>
从.Net版本演变看String和StringBuilder性能之争
查看>>
Excel操作 Microsoft.Office.Interop.Excel.dll的使用
查看>>
解决Ubuntu下博通网卡驱动问题
查看>>
【bzoj2788】Festival
查看>>