凸/凹多边形内的所有点 - 更好的方法?

时间:2017-05-25 12:05:16

标签: java algorithm

我需要列出具有给定坐标精度的特定多边形内的所有坐标,比如说1.这意味着,多边形边界的所有坐标都是整数。多边形可以是凸面或凹面。

我拥有边界的所有坐标coords[n][2]

以下是我如何解决问题:

为简单起见,我们假设多边形的第一个坐标为[0,0]

for (i = 1;; i++)

    for all points that lie on the lines: y = ±i, x = ±i, 

        check if the point lies inside the polygon.

    if no point lies on the polygon

        break;

我的方法几乎是一种蛮力的方法。是否有一个有效的算法来找出相同的?

1 个答案:

答案 0 :(得分:1)

最好的方法可能是使用在多边形上扫描扫描线的常用策略。将扫描线从最小y值垂直移动到最大y值;在每个y值处,您可以通过计算扫描线与跨越该y值的边界线的交点来计算x的间隔列表。 (由于扫描线是水平的,因此交叉点很容易计算。)

基本上,这个想法是:

  1. 创建一个活动边界线数组。这个数组最初是空的。

  2. 创建按y坐标排序的边界线端点数组。如果有两个具有相同y坐标的端点,则按x坐标对它们进行排序。每个端点出现两次(边界线的每一端一次);根据该行的另一个端点对两个匹配项进行排序。

  3. 现在将扫描线从最小y扫描到最大y。在排序的端点数组中出现的每个y值处,调整活动边界线列表,添加或删除列表中的边界线。新添加的行按x坐标顺序插入到列表中,以便列表始终从左到右。这样,每个交叉点都是内部和外部之间的过渡,因此作为成对的交叉点列表将是多边形内部点的开始和结束。

  4. 水平边界线有点烦人,它们的处理方式取决于您是否希望精确地在边界线上的点被视为多边形内部或外部。如果在内部考虑边界,您应该能够完全忽略水平线段。但请参见下文。

    虽然您已经说过多边形边界不是自相交的,但您可能需要担心量子化导致的自相交。如果边界顶点非常靠近边界线,则将所有端点四舍五入为整数值(量化)可能会消除微小间隙,从而导致看起来像是一个自交叉点。特别刺激的是几乎平行的近水平线:

                       A        B                         C
                       |___________________________________
                                ___________________________
                                |
    

    如果将这两条线量化为相同的y坐标,则最终会得到

                       A        B                         C
                       |  
                       .________._________________________.
                                |
    

    然后,如果忽略水平边界线,则不会将段BC报告为多边形的一部分。

    上述算法对凸边界和凹边界同样有效,甚至有多个边界,但如果边界自相交则失败。要处理自相交,您需要使用与Bentley-Ottmann algorithm类似的东西,这会将线交点添加到扫描线扫描中的“事件”列表中。 (在交叉点处,您必须反转线段的顺序以使水平扫描正确,并且还必须为重新排序的线段计算新的交叉点。)此外,您还需要更改简单的奇偶交叉点具有匝数计算的算法,其需要知道每个段是顺时针还是逆时针。虽然Bentley-Ottmann算法在理论上看起来很简单,但实际实现需要处理边缘情况,例如在同一点交叉的多条线,或者甚至在彼此之上折叠(可能由于量化,如上所述)。

相关问题