【问题标题】:Algorithm for points inside a polyline inexplicably fails (AutoCAD)折线内点的算法莫名其妙地失败(AutoCAD)
【发布时间】:2013-05-08 01:43:39
【问题描述】:

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

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

我没有做任何多线程。我正在做的唯一可能“有趣”的事情是 COM 与 Excel 的互操作。这是在使用该算法为部件提交事务之后发生的,我确信我正在清理我所有的 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);
    }

【问题讨论】:

    标签: c# com autocad


    【解决方案1】:

    我使用 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

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        【解决方案3】:

        一些想法:

        • 浮点比较必须使用公差进行,这可能会导致任意结果,尤其是在点位于折线上的情况下(point3d 的注释相同,必须使用公差进行比较)

        • 1234563然后你应该测试第一个点和最后一个点是否相等。
        • 我不确定你的算法是否有效,无论折线是顺时针还是逆时针(我认为是)

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

        【讨论】:

        • 我发现算法有缺陷,我确实使用 BREP API 将其转换为区域。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-03-12
        • 1970-01-01
        • 1970-01-01
        • 2012-05-19
        • 1970-01-01
        相关资源
        最近更新 更多