C# 求圆和线的交点

C# 求圆和线的交点,c#,C#,我试图找到一条线是否与圆相交 我写的代码,但似乎与该代码的一些问题 private Point2d[] IntersectionPoint(Point2d p1, Point2d p2, Point2d sc, double r) { Point2d[] sect = null; double a, b, c; double bb4ac; double mu1, mu2; Point2d dp;

我试图找到一条线是否与圆相交

我写的代码,但似乎与该代码的一些问题

private Point2d[] IntersectionPoint(Point2d p1, Point2d p2, Point2d sc, double r)
    {
        Point2d[] sect = null;
        double a, b, c;
        double bb4ac;
        double mu1, mu2;
        Point2d dp;

        dp = p2 - p1;

        a = dp.X * dp.X + dp.Y * dp.Y;
        b = 2 * (dp.X * (p1.X - sc.X) + dp.Y * (p1.Y - sc.Y));
        c = sc.X * sc.X + sc.Y * sc.Y;
        c += p1.X * p1.X + p1.Y * p1.Y;
        c -= 2 * (sc.X * p1.X + sc.Y * p1.Y);
        c -= r * r;
        bb4ac = b * b - 4 * a * c;

        if (Math.Abs(a) < Double.Epsilon || bb4ac < 0)
        {
            return new Point2d[0];
        }

        mu1 = (-b + Math.Sqrt(bb4ac)) / (2 * a);
        mu2 = (-b - Math.Sqrt(bb4ac)) / (2 * a);

        // no intersection
        if ((mu1 < 0 || mu1 > 1) && (mu2 < 0 || mu2 > 1))
        {
            sect = new Point2d[0];
        }
        // one point on mu1
        else if (mu1 > 0 && mu1 < 1 && (mu2 < 0 || mu2 > 1))
        {
            sect = new Point2d[1];
            sect[0] = p1 + ((p2 - p1) * mu1);
        }
        // one point on mu2
        else if (mu2 > 0 && mu2 < 1 && (mu1 < 0 || mu1 > 1))
        {
            sect = new Point2d[1];
            sect[0] = p1 + ((p2 - p1) * mu2);
        }
        //  one or two points
        else if (mu1 > 0 && mu1 < 1 && mu2 > 0 && mu2 < 1)
        {
            //  tangential
            if (mu1 == mu2)
            {
                sect = new Point2d[1];
                sect[0] = p1 + ((p2 - p1) * mu1);
            }
            //  two points
            else
            {
                sect = new Point2d[2];
                sect[0] = p1 + ((p2 - p1) * mu1);
                sect[1] = p1 + ((p2 - p1) * mu2);
            }
        }
        else
        {
            //  should NEVER get here
            sect = new Point2d[0];
        }
        return sect;
    }
当我尝试使用这些坐标时,它失败了

30,-30

80,-40

十,


编辑:向量现在是C#

下面是我的相交代码:

public static Vector3? IntersectRayCircle(Vector3 rayStart, Vector3 rayPoint, Vector3 circlePosition, float circleRadiusSquared)
{
    if (rayStart == rayPoint || circleRadiusSquared <= 0)
    {
        return null;
    }

    Vector3 nearest = GetNearestPoint(circlePosition, rayStart, rayPoint, false, false);
    float distanceSquared = Vector3.DistanceSquared(nearest, circlePosition);

    if (distanceSquared > circleRadiusSquared)
    {
        return null;
    }

    Vector3 offset = Vector3.Normalize(rayPoint - rayStart) * (float)Math.Sqrt(circleRadiusSquared - distanceSquared);

    if (Vector3.DistanceSquared(circlePosition, rayStart) < circleRadiusSquared)
    {
        return nearest + offset;
    }
    else
    {
        return nearest - offset;
    }
}
公共静态向量3?相交光线圆(矢量3光线起点、矢量3光线点、矢量3圆圈位置、浮动圆圈半径平方)
{
if(光线起点==光线点| |圆度平方圆度平方圆度平方)
{
返回null;
}
Vector3偏移=Vector3.规格化(光线点-光线开始)*(浮点)数学.Sqrt(circleRadiusSquared-距离平方);
if(矢量3.距离平方(圆位置,光线开始)

public static Vector3 GetNearestPoint(Vector3位置、Vector3段开始、Vector3段结束、bool trimStart、bool trimsend)
{
如果(分段开始==分段结束)
{
抛出新ArgumentException(“segmentStart不能等于segmentEnd”);
}
Vector3 AP=位置-分段开始;
Vector3 AB=分段结束-分段开始;
浮点数AB=AB.长度平方();
float ABAPproduct=Vector3.Dot(AP,AB);
浮动距离=ABAPproduct/magnificatab;
返回(距离<0&&trimStart)?分段开始:(距离>1&&trimEnd)?分段结束:分段开始+AB*距离;
}

你可以做一些线性代数:

  • 将直线表示为原点
    P1
    和标准化方向向量
    N

  • 将圆的中心投影到直线上:
    PC=P1+dot(C-P1,N)*N

  • 计算点
    C
    PC
    之间的距离平方
    dSquared

  • 如果等于(带有一些小公差)半径平方
    PC
    位于圆上,是单个交点

  • 如果大于半径平方,则无交叉点

  • 否则,两个交点由

  • offset=sqrt(radiusquared-dSquared)
  • 交点=
    PC+/-偏移*N

  • //在查看代码之后,看起来您的代码实际上就是从这里开始的我的一些代码也是基于那里编写的,我遇到了一个问题,
    bb4ac
    有时非常接近于零(但仍然不应该是;与球体的切线),以至于无法通过相交测试。//我认为您需要将
    bb4ac
    与epsilonI进行比较,因为我无法构建此代码@另一位用户我也不相信那些编写包含数学公式的代码的人,除了“似乎有些问题”和“它失败了”之外,不能提供任何关于出错原因的信息。要么代码与您的设计不匹配(您可以进行调试),要么您的设计有缺陷,我们现在还不应该查看代码。您实际上是在检查半径是否小于直线中间的距离。是的,我正在按照图表进行检查@TAWVACTOR在C#中不可用@AgentFire@PrinceChopra-拜托,你不能自己做向量类?这就像是最基本的任务:)如果你看不到
    public static Vector3? IntersectRayCircle(Vector3 rayStart, Vector3 rayPoint, Vector3 circlePosition, float circleRadiusSquared)
    {
        if (rayStart == rayPoint || circleRadiusSquared <= 0)
        {
            return null;
        }
    
        Vector3 nearest = GetNearestPoint(circlePosition, rayStart, rayPoint, false, false);
        float distanceSquared = Vector3.DistanceSquared(nearest, circlePosition);
    
        if (distanceSquared > circleRadiusSquared)
        {
            return null;
        }
    
        Vector3 offset = Vector3.Normalize(rayPoint - rayStart) * (float)Math.Sqrt(circleRadiusSquared - distanceSquared);
    
        if (Vector3.DistanceSquared(circlePosition, rayStart) < circleRadiusSquared)
        {
            return nearest + offset;
        }
        else
        {
            return nearest - offset;
        }
    }
    
    public static Vector3 GetNearestPoint(Vector3 location, Vector3 segmentStart, Vector3 segmentEnd, bool trimStart, bool trimEnd)
    {
        if (segmentStart == segmentEnd)
        {
            throw new ArgumentException("segmentStart cannot be equal to segmentEnd.");
        }
    
        Vector3 AP = location - segmentStart;
        Vector3 AB = segmentEnd - segmentStart;
    
        float magnitudeAB = AB.LengthSquared();
        float ABAPproduct = Vector3.Dot(AP, AB);
        float distance = ABAPproduct / magnitudeAB;
    
        return (distance < 0 && trimStart) ? segmentStart : (distance > 1 && trimEnd) ? segmentEnd : segmentStart + AB * distance;
    }