C# 求两个圆的交点

C# 求两个圆的交点,c#,geometry,intersection,C#,Geometry,Intersection,我需要能够计算两个圆之间的交点。我确信总会有两个交叉点。不是1,不是0,不是无限,总是2。下面是我尝试做的一个图表: 以下是我目前的尝试: public static List<Vector2> intersect(Vector3 c1, Vector3 c2, float rad1, float rad2) { List<Vector2> rLp = new List<Vector2>(); float d = Vector2.Distan

我需要能够计算两个圆之间的交点。我确信总会有两个交叉点。不是1,不是0,不是无限,总是2。下面是我尝试做的一个图表:

以下是我目前的尝试:

public static List<Vector2> intersect(Vector3 c1, Vector3 c2, float rad1, float rad2)
{
    List<Vector2> rLp = new List<Vector2>();
    float d = Vector2.Distance(c1, c2);

    if (d > (rad1 + rad2))
        return rLp;
    else if (d == 0 && rad1 == rad2)
        return rLp;
    else if ((d + Mathf.Min(rad1, rad2)) < Mathf.Max(rad1, rad2))
        return rLp;
    else
    {
        float a = (rad1 * rad1 - rad2 * rad2 + d * d) / (2 * d);
        float h = Mathf.Sqrt(rad1 * rad1 - a * a);

        Vector2 p2 = new Vector2((float)(c1.x + (a * (c2.x - c1.x)) / d), (float)(c1.y + (a * c2.y - c1.y) / d));

        Vector2 i1 = new Vector2((float)(p2.x + (h * (c2.y - c1.y)) / d), (float)(p2.y - (h * (c2.x - c1.x)) / d));
        Vector2 i2 = new Vector2((float)(p2.x - (h * (c2.y - c1.y)) / d), (float)(p2.y + (h * (c2.x - c1.x)) / d));

        if (d == (rad1 + rad2))
            rLp.Add(i1);
        else
        {
            rLp.Add(i1);
            rLp.Add(i2);
        }

        return rLp;
    }
}
公共静态列表相交(向量3 c1、向量3 c2、浮点rad1、浮点rad2)
{
List rLp=新列表();
浮动d=矢量2.距离(c1,c2);
如果(d>(rad1+rad2))
返回rLp;
else如果(d==0&&rad1==rad2)
返回rLp;
否则,如果((d+Mathf.Min(rad1,rad2))
它给了我以下结果:


如您所见,代表两个圆之间截取点的白色正方形位于错误的位置。在这方面我真的需要一些帮助。有人能看出哪里出了问题吗?

复制和粘贴数学代码对我来说几乎总是出错(例如定义中的翻转符号等)。从其他人那里调试这样的代码纯粹是一件恐怖的事情(当它深入到数学中时,调试我自己的代码已经够难了)。您应该尝试自己进行计算并将其转换为代码。如果出现错误,您可以使用调试器逐步调试它,并使用袖珍计算器进行交叉检查

你真的应该自己试试。抓起一张纸,算出正确的数字。但以下是我将使用的方法:

private void intersectionTwoCircles(double c1x, double c1y, double r1, double c2x, double c2y, double r2,
        out double a1x, out double a1y, out double a2x, out double a2y)
    {
        /* error handling is missing complettely - left as an exercise 

              A1
             /| \
         r1 / |  \ r2
           /  |   \
          /   |h   \
         /g1  |     \          (g1 means angle gamma1)
        C1----P-----C2
           d1   d2
        */
        double dx = c1x - c2x;
        double dy = c1y - c2y;
        double d = Math.Sqrt(dx*dx + dy*dy); // d = |C1-C2|
        double gamma1 = Math.Acos((r2*r2 + d*d - r1*r1)/(2*r2*d)); // law of cosines
        double d1 = r1*Math.Cos(gamma1); // basic math in right triangle
        double h = r1*Math.Sin(gamma1);
        double px = c1x + (c2x - c1x) / d*d1;
        double py = c1y + (c2y - c1y) / d*d1;
        // (-dy, dx)/d is (C2-C1) normalized and rotated by 90 degrees
        a1x = px + (-dy)/d*h;      
        a1y = py + (+dx) / d * h;
        a2x = px - (-dy) / d * h;
        a2y = py - (+dx) / d * h;
    }

提供代码后更新:

您的方法与我的方法非常相似(
a=r1cos(gamma_1)
h=r1sin(gamma_1)
)。您只需避免直接计算
gamma
。它更快(只需一个
sqrt
而不是
cos
sin
acos
)。但我认为,我的更具可读性;)考虑重载向量类的操作数(+、-、*、…)。。。您的代码将变得更易于阅读

我想我发现了你的错误

// before
Vector2 p2 = new Vector2((float)(c1.x + (a * (c2.x - c1.x)) / d), (float)(c1.y + (a * c2.y - c1.y) / d));

// after
Vector2 p2 = new Vector2((float)(c1.x + (a * (c2.x - c1.x)) / d), (float)(c1.y + a * (c2.y - c1.y) / d));

对于任何希望使用PointF而不是离散坐标实现的人,我对Alex K五年前提到的解决方案进行了修改,以生成以下内容。尽管它没有针对OP所描述的已知两点情况进行优化,但它可以工作并容纳在一点、两点或无点相交的圆

使用系统图;
使用静态系统。数学;
公共静态类循环接口{
/// 
///获取两个圆的交点
/// 
///第一个圆的圆心
///第二个圆的圆心
///第一个圆的半径
///第二个圆的半径。如果省略,则假定等于第一个圆的半径
///交点数组。可以有零、一或两个值
///改编自http://csharphelper.com/blog/2014/09/determine-where-two-circles-intersect-in-c/
公共静态PointF[]GetCircleIntersections(PointF center1、PointF center2、双半径1、双半径2=null){
var(r1,r2)=(半径1,半径2??半径1);
(双x1,双y1,双x2,双y2)=(center1.X,center1.Y,center2.X,center2.Y);
//d=从中心1到中心2的距离
双d=Sqrt(功率(x1-x2,2)+功率(y1-y2,2));
//如果没有交点,则返回空数组

如果(!(Abs(r1-r2)交叉点就是你要搜索的东西;我已经在那个页面上了,我几乎可以肯定你会在我的示例中找到那个页面上的代码。发布你在问题中尝试过的东西,而不是一些外部站点。另外,你尝试使用什么数学?这是高中几何。在发布链接之前,我总是测试,该项目允许你画两个圆圈n通过FindCircleCircleIntersections()突出显示交叉点-即A1和A2数据点请放在代码上这些是我见过的最漂亮的代码注释。说真的,这让我大跌眼镜。@BradleyUffner:i(尝试)如果没有注释,就不要注释,而是让代码变得明显。但是当涉及到数学时,我的注释:代码比率有时接近1;)