在c#中圈出问题

本文关键字:出问题 | 更新日期: 2023-09-27 18:21:31

我需要这部分的帮助

旁注:我有两个圆圈。

  • 我需要创建5种方法来找到一个圆:

相交(圆c),

切线输出(圆c),

切线In(圆),

不相交(圆)

和包含(圆圈),

(基本上,我需要决定另一个圆c是否与该圆相交,是否从外部与该圆相切,是否在该圆内部但在某个点相交,是否在没有任何接触的情况下在该圆外部,或是否完全在该圆内。)

为了确定它是否与另一个圆相交,我制作了以下代码:

    public bool intersect(Circle c)
    {
        Point p = new Point(), myCenter = new Point();
        p.setPoint(c.x, c.y);
        myCenter.setPoint(x, y);
        return myCenter.dist(p) < radius + c.radius;
    }

但是当我做两个圆(0,0,1)和(0,0,5)时。这表明圆相交。难道它不应该表明它不相交吗?

我还需要其他方法的帮助。

提前感谢!

这是我的代码:

public static void Main(string[] args)
{
    Circle c1 = new Circle(0, 0, 1), c2 = new Circle(1, 0, 1);
    Point p1 = new Point();
    p1.setPoint(0, 1);
    p1.print();
    Console.Write(", ");
    c1.print();
    Console.WriteLine();
    if (c1.onCircle(p1))
    {
       // Console.Write(" Point ");
        p1.print();
        Console.Write (" on ");
        c1.print();
        Console.WriteLine();
    }
    else
        Console.WriteLine("Point NOT on circle");
    if (c1.intersect(c2))
    {
       // Console.WriteLine("Two circles intersect");
        c1.print();
        Console.Write(" intersects ");
        c2.print();
        Console.WriteLine();
    }
    else
        Console.WriteLine("Two circles do NOT intersect");
}

我的班级:

class Circle : Point
{
    private double radius;
    public Circle(double xV, double yV, double r)
    {
        this.x = xV;
        this.y = yV;
        this.radius = r;
    }
    public void setRadius(double r)
    {
        radius = r > 0 ? radius : 0;
    }
    public bool onCircle(Point p)
    {
        return dist(p) == radius;
    }
    public bool intersect (Circle c)
    {
        Point p = new Point (), myCenter = new Point();
        p.setPoint (c.x, c.y);
        myCenter.setPoint (x, y);
        return myCenter.dist(p) < radius + c.radius;
    }
    public void print()
    {
        Console.Write("Circle: ({0}, {1}, {2})", x, y, radius);
    }
}

点的类别:

public class Point
{
    protected double x; // x coordiate of Point
    protected double y; // y coordinate of Point
    public void setPoint (double xCoor, double yCoor) {
        x = xCoor;
        y = yCoor;
    }
    public double dist(Point p)  // compute the distance of point p to the current point
    {
        double distance;
        distance = Math.Sqrt((x - p.x) * (x - p.x) + (y - p.y) * (y - p.y));
        return distance;
    }
    public void print()
    {
        Console.Write("Point: ({0}, {1})", x, y);
    }
}

在c#中圈出问题

您的编码风格看起来不确定-我只会在数学上帮助您。

取两个圆,A(中心c1,半径r1)和B(中心c2,半径r2)。设d = c1.dist(c2)

  • tangentOut:条件是d = r1 + r2
  • tangentIn:d = abs(r2 - r1)
  • disjoint:d > r1 + r2
  • contained:d < abs(r2 - r1)

此外,考虑到数值精度,将任何等式更改为deltaε比较。例如,a = b变为abs(a - b) < e,其中e是某个最大阈值。

您应该重新检查您的逻辑是否存在交集。现在的方法只适用于当一个圆没有完全包围另一个圆时不相交的圆。你选择测试的情况,同心圆,显示为中心之间的距离为0,实际上小于半径的总和。另一种可能不会被发现的情况是单个退化交点的情况。

我建议阅读Wolfram Alpha关于Circle Circle Intersection的文章,以找到更好的测试方法。

您的intersect方法看起来应该会产生准确的结果,但由于Circle源自Point,因此可以大大简化:

public bool intersect(Circle c)
{
    return dist(c) < radius + c.radius;
}

所有其他操作都类似:

public bool tangentOut(Circle c)
{
    return dist(c) == radius + c.radius;
}
public bool tangentIn(Circle c)
{
    return dist(c) == Math.Abs(c.radius - radius);
}
public bool disjoint(Circle c)
{
    return dist(c) > radius + c.radius;
}
public bool contains(Circle c)
{
    return dist(c) <= radius - c.radius
}

关于Epsilon值的漫谈如下

CCD_ 20和CCD_ 21中的比较需要稍微改变以解决准确性问题。在使用较大的值时,使用静态epsilon数字(如您与willywonka的评论交流中所示)会带来麻烦。相反,您可以根据所比较的数字来缩放ε。

ε的基数是1和下一个可能的数字之间的差,通过设置值的二进制表示中的最低位。根据维基百科上关于双精度浮点格式的条目(我通过测试证实了这一点),这大约是2E-16。这对0到2-E之间的数字来说很好,但当你超出这个范围时就不起作用了。同样,使用更大的值会给你更大的范围,但会在某个时候停止工作。

因此,与其使用静态数字,不如将最大值缩小一个有用的量,比如10^9的一部分,并将其用作ε。一个示例扩展方法:

public static class Extensions
{
    public static bool EpsilonEqual(this double l, double r, double eScale = 1e+9)
    {
        double d = Math.Abs(l - r);
        double e = Math.Abs(Math.Max(l, r)) / 1e+9;
        return d <= e;
    }
}

调整比例因子以满足您的精度要求。然后你可以这样做:

public bool tangentOut(Circle c)
{
    return dist(c).EpsilonEquals(radius + c.radius);
}
public bool tangentIn(Circle c)
{
    return dist(c).EpsilonEquals(Math.Abs(c.radius - radius));
}