折线内点的算法莫名其妙地失败(AutoCAD)

时间:2013-05-13 22:07:44

标签: c# com autocad

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

我一直在对相同的51个多边形进行测试。 99%它将完美地工作。每隔一段时间,它会在一个或多个多边形上失败,返回假的超过2000点,我在折线的边界框内创建。当折线是一个简单的矩形并且所有点都分布在折线内的网格中时,我看到它失败了。在这种情况下它应该返回真实超过2000次。只有其中一个点永远都不会失败,它将全部失败。我已经确认正确地创建了点,我希望它们是正确的,并且多边形的顶点是我期望它们的位置。当它失败时,最后一个点的最后一个角度变量恰好是两倍PI。

我没有做任何多线程。我正在做的唯一可能“有趣”的事情是COM Interop with Excel。在使用此算法为部件提交事务之后,会发生这种情况,我确信我正在清理所有COM对象。如果没有COM Interop部分,我无法重现故障,但我认为我没有足够的测试来充分缺乏证据。

任何想法可能出错?

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);
    }

3 个答案:

答案 0 :(得分:1)

一些想法:

  • 浮点比较必须使用宽容来完成,这可能会导致任意结果,特别是在点位于折线上的情况下(对于point3d,它必须使用容差进行比较)

  • 也许折线的最后一个点与第一个点位于同一位置,在这种情况下,无法计算角度(这可能就是为什么你得到最后一个点的双pi值)。然后你应该测试第一个,最后一个点是等于。

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

  • 您可以将折线转换为区域并依赖区域点包含方法

答案 1 :(得分:1)

另一种方法。 做一个&#34;临时&#34;指向多边形外部(找到最小X和Y并用X-1和Y-1作一个点)。 然后在你的观点和新的&#34;临时&#34;之间划一条线。点。 检查此线是否穿过多边形 - 使用polyline.IntersectWith。 如果交叉点的数量是奇数 - 那么你的点在里面,如果交叉的数量是偶数 - 你的点不在里面。 这适合我,希望它也会帮助你。 如果您在实现此问题时遇到问题,我可以向您发送示例代码。 问候, 多布里扬·贝诺夫

答案 2 :(得分:0)

我使用Kean Walmsley的一些代码将3d线转换为2d线。但请注意,以下内容并非(始终)为真:

Point2d pt = lwp.GetPoint2dAt(i);
Point2d npt = new Point2d(lwp.GetPoint3dAt(i).X, lwp.GetPoint3dAt(i).Y);

pt == npt;

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

http://through-the-interface.typepad.com/through_the_interface/2007/04/iterating_throu.html