C# 多段线内点的算法莫名其妙地失败(AutoCAD)

C# 多段线内点的算法莫名其妙地失败(AutoCAD),c#,com,autocad,C#,Com,Autocad,我使用的是用于Autocad的.NET API,我有一个算法(我没有编写),用于确定点是否位于多边形内(仅限于直线) 我已经在同一个51多边形上反复测试了我的命令。99%它将完美工作。每隔一段时间,它就会在一个或多个多边形上失败,对于我在多段线的边界框内创建的2000多个点返回false。我见过当多段线是一个简单的矩形,并且所有的点都分布在多段线内的网格中时,它失败了。在这种情况下,它应该返回真值超过2000次。它永远不会因为其中的一个点而失败,它会让所有的点都失败。我已经确认,点在我期望的位置

我使用的是用于Autocad的.NET API,我有一个算法(我没有编写),用于确定点是否位于多边形内(仅限于直线)

我已经在同一个51多边形上反复测试了我的命令。99%它将完美工作。每隔一段时间,它就会在一个或多个多边形上失败,对于我在多段线的边界框内创建的2000多个点返回false。我见过当多段线是一个简单的矩形,并且所有的点都分布在多段线内的网格中时,它失败了。在这种情况下,它应该返回真值超过2000次。它永远不会因为其中的一个点而失败,它会让所有的点都失败。我已经确认,点在我期望的位置正确创建,多边形的顶点在我期望的位置。当失败时,最后一点的最后一个角度变量正好是双PI

我没有做任何多线程。我正在做的唯一可能“有趣”的事情就是与Excel进行COM互操作。这是在使用此算法的部分提交事务之后发生的,我确信我正在清理所有COM对象。在没有COM互操作部分的情况下,我无法再现故障,但我认为我还没有对其进行足够的测试,以获得足够的证据

有什么想法吗

bool IsInsidePolygon(Polyline polygon, Point3d pt)
    {
        int n = polygon.NumberOfVertices;
        double angle = 0;
        Point pt1, pt2;

        for (int i = 0; i < n; i++)
        {
            pt1.X = polygon.GetPoint2dAt(i).X - pt.X;
            pt1.Y = polygon.GetPoint2dAt(i).Y - pt.Y;
            pt2.X = polygon.GetPoint2dAt((i + 1) % n).X - pt.X;
            pt2.Y = polygon.GetPoint2dAt((i + 1) % n).Y - pt.Y;
            angle += Angle2D(pt1.X, pt1.Y, pt2.X, pt2.Y);
        }

        if (Math.Abs(angle) < Math.PI)
            return false;
        else
            return true;
    }

    public struct Point
    {
        public double X, Y;
    };

    public static double Angle2D(double x1, double y1, double x2, double y2)
    {
        double dtheta, theta1, theta2;

        theta1 = Math.Atan2(y1, x1);
        theta2 = Math.Atan2(y2, x2);
        dtheta = theta2 - theta1;
        while (dtheta > Math.PI)
            dtheta -= (Math.PI * 2);
        while (dtheta < -Math.PI)
            dtheta += (Math.PI * 2);
        return (dtheta);
    }
bool-IsInsidePolygon(多段线多边形,Point3d pt)
{
int n=多边形。顶点数;
双角度=0;
pt1、pt2点;
对于(int i=0;iMath.PI)
dtheta-=(Math.PI*2);
while(dtheta<-Math.PI)
dtheta+=(Math.PI*2);
返回(dtheta);
}
一些想法:

  • 浮点比较必须使用容差进行,这可能会导致任意结果,特别是当点位于多段线上时(point3d的注释相同,必须使用容差进行比较)

  • 可能多段线的最后一个点与第一个点位于同一位置,在这种情况下,无法计算角度(可能这就是为什么最后一个点会获得双pi值)。然后,您应该测试第一个点和最后一个点是否相等

  • 无论折线是顺时针还是逆时针,我不确定您的算法是否有效(我想是的)

  • 您可以将多段线转换为区域,并依赖于区域点包容方法

    • 另一种方法。 在多边形外创建一个“临时”点(找到最小X和Y,并使用X-1和Y-1创建一个点)。 然后在你的点和新的“临时”点之间划一条线。 检查此线是否与多边形相交-使用polyline.IntersectWith。 如果交叉点的数量是奇数-那么你的点在里面,如果交叉点的数量是偶数-那么你的点不在里面。 这对我很有用,希望对你也有帮助。 如果您在实现时发现问题,我可以给您发送一个示例代码。 当做
      Dobriyan Benov

      我使用了Kean Walmsley的一些代码将3d线条转换为2d线条。但请注意,以下情况(并非总是)正确:

      我在多段线上使用它时遇到了它,带有3d顶点。我最终使用了npt


      我发现该算法存在缺陷,我最终使用BREPAPI将其转换为一个区域。
      Point2d pt = lwp.GetPoint2dAt(i);
      Point2d npt = new Point2d(lwp.GetPoint3dAt(i).X, lwp.GetPoint3dAt(i).Y);
      
      pt == npt;