检查一个点是否在线段上,除了某些情况下有效(舍入错误?)

对于下面的问题,是否是我如此接近零,但将零与容差进行比较不起作用?数字越精确,我对直线上圆弧点的检查就越失败,而越不精确,它就越有效。CAD 绘图确实有一个弧线,该弧线在线段上有一个点,这就是我在此测试中获取输入坐标的地方。


class Line

{

   public Point Point1 {get;set;}

   public Point Point2 {get;set;}

   public Line(double x1, double y1, double x2, double y2)

   {

      Point1 = new Point(x1,y1); Point2 = new Point(x2,y2);

   }

}


class Point

   public double X {get;set;}

   public double Y {get;set;}

   public Point (double x, double y)

   {

       X = x; Y = y;

  }

}


//4 decimal place numbers, works

Point arcEnd = new Point(3.8421, 16.9538); // these numbers don't 

//3.84212141717697, 

//16.9538136440052

Point arcStart = new Point(4.0921, 17.2038);


//test an arc point on/off the line

Line line = new Line(3.9336, 16.9538, 3.7171, 16.9538); 

//these numbers don't 3.93362776812308, 16.9538136440053, 

//3.71712141717697, 16.9538136440054


bool on_line = Sign(line.Point1, line.Point2, arcEnd) //true


//more precise numbers, from CAD / dxf drawing for line and arc, arc end 

//point touches somewhere on the line (included in comments above, fail)

//so on_line = true for the above inputs and the Sign function gives zero, 

//but when using the commented precise numbers sign gives back 1 and the 

//value computed in sign is 3.0639866299190109E-14.





public static bool Sign(Point Point1, Point Point2, Point point)

{

    double value = (Point2.X - Point1.X) * (p.Y - Point1.Y) - (Point2.Y - Point1.Y) * (p.X - Point1.X);


    return Equals(Math.Sign(value), 0);

}


public static bool Equals(double d1, double d2, double tolerance=0.000001)

{

    double a = Math.Abs(d1 - d2);

    double b = Math.Abs(d1 * tolerance);


    if (a <= b)

    {

       return true;

    }


    return false;

}

检查了公式和堆栈溢出,该算法在大多数情况下都有效,但发现它失败的情况,我将其追溯到包含的示例,并确定我的检查针对上述输入返回 Sign = 1 而不是 Sign = 0,并且精度更高。


暮色呼如
浏览 73回答 1
1回答

杨魅力

你犯了两个错误。首先,您在“Return Equals(Math.Sign(value), 0);”中使用了 Sign 函数,它将为任何正数提供 1 的值,为任何负数提供 -1 的值。这会破坏你使用宽容的尝试。其次,您尝试将差异与第一个数字“b = Math.Abs(d1 * 容差)”的比率进行比较,这将始终返回 False。我建议你将它与宽容本身进行比较,就像这样。public static bool Sign(Point Point1, Point Point2, Point point){&nbsp; &nbsp; double value = (Point2.X - Point1.X) * (point.Y - Point1.Y) - (Point2.Y - Point1.Y) * (point.X - Point1.X);&nbsp; &nbsp; return Equals(value, 0);}public static bool Equals(double d1, double d2, double tolerance = 0.000001){&nbsp; &nbsp; double a = Math.Abs(d1 - d2);&nbsp; &nbsp; if (a <= tolerance)&nbsp; &nbsp; &nbsp; &nbsp; return true;&nbsp; &nbsp; return false;}
打开App,查看更多内容
随时随地看视频慕课网APP